diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,6 @@
+# Revision history for minilight-lua
+
+## 0.1.0.0 -- 2020-05-10
+
+* First version.
+* Supports only limited API: translate, clip, text, picture
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 myuon
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/example/Main.hs b/example/Main.hs
new file mode 100644
--- /dev/null
+++ b/example/Main.hs
@@ -0,0 +1,33 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Main where
+
+import Control.Concurrent.MVar
+import Control.Lens
+import Control.Monad
+import Data.Maybe
+import MiniLight
+import MiniLight.Lua
+
+mainFile = "example/main.lua"
+
+main :: IO ()
+main = runLightT $ runMiniloop
+  (defConfig { hotConfigReplacement = Just "example", appConfigFile = Just "" })
+  initial
+  (const mainloop)
+ where
+  initial = do
+    comp <- registerComponent mainFile newLuaComponent
+    reload mainFile
+
+    return ()
+
+  mainloop :: MiniLoop ()
+  mainloop = do
+    ref <- view _events
+    evs <- liftIO $ tryReadMVar ref
+
+    let notifys = case evs of
+          Just evs -> mapMaybe asNotifyEvent evs
+          _        -> []
+    unless (null notifys) $ reload mainFile
diff --git a/minilight-lua.cabal b/minilight-lua.cabal
new file mode 100644
--- /dev/null
+++ b/minilight-lua.cabal
@@ -0,0 +1,56 @@
+cabal-version:       2.4
+-- Initial package description 'minilight-lua.cabal' generated by 'cabal
+-- init'.  For further documentation, see
+-- http://haskell.org/cabal/users-guide/
+
+name:                minilight-lua
+version:             0.1.0.0
+synopsis:            A binding library of minilight for Lua langauge.
+description:
+  This library provides a way to write minilight component in Lua language.
+-- bug-reports:
+license:             MIT
+license-file:        LICENSE
+author:              myuon
+maintainer:          ioi.joi.koi.loi@gmail.com
+-- copyright:
+category:            Graphics
+extra-source-files:  CHANGELOG.md
+
+source-repository head
+  type:     git
+  location: https://github.com/myuon/minilight-lua.git
+
+library
+  exposed-modules:
+    MiniLight.Lua
+    MiniLight.FigureDSL
+  -- other-modules:
+  -- other-extensions:
+  build-depends:
+    base ^>=4.13.0.0,
+    bytestring >= 0.10,
+    exceptions >= 0.10,
+    hslua >= 1.1,
+    linear >= 1.20,
+    minilight >= 0.5.0,
+    mtl >= 2.2,
+    sdl2 >= 2.4 && < 2.5,
+    text >= 1.2,
+    unix-time >= 0.4,
+  hs-source-dirs:      src
+  default-language:    Haskell2010
+  cpp-options: -Fsumtype
+
+executable example
+  -- other-modules:
+  -- other-extensions:
+  build-depends:
+    base ^>=4.13.0.0,
+    lens,
+    minilight >= 0.5.0,
+    minilight-lua,
+    mtl,
+  hs-source-dirs:      example
+  main-is:             Main.hs
+  default-language:    Haskell2010
diff --git a/src/MiniLight/FigureDSL.hs b/src/MiniLight/FigureDSL.hs
new file mode 100644
--- /dev/null
+++ b/src/MiniLight/FigureDSL.hs
@@ -0,0 +1,37 @@
+{-# LANGUAGE OverloadedStrings #-}
+module MiniLight.FigureDSL where
+
+import Control.Monad
+import qualified Data.Config.Font as Font
+import qualified Data.Text as T
+import Data.Word (Word8)
+import MiniLight
+import qualified SDL
+import qualified SDL.Vect as Vect
+import Foreign.Lua
+
+data FigureDSL
+  = Empty
+  | Translate (Vect.V2 Int) FigureDSL
+  | Clip (Vect.V2 Int) (Vect.V2 Int) FigureDSL
+  | Picture FilePath
+  | Text (Vect.V4 Word8) T.Text
+  deriving (Show, Read)
+
+instance Peekable FigureDSL where
+  peek = fmap read . peek
+
+instance Pushable FigureDSL where
+  push = push . show
+
+construct :: FigureDSL -> MiniLight (Maybe Figure)
+construct dsl = case dsl of
+  Empty           -> return $ Just emptyFigure
+  Translate p fig -> fmap (fmap (translate p)) $ construct fig
+  Clip p q fig ->
+    fmap (fmap (clip (SDL.Rectangle (Vect.P p) q))) $ construct fig
+  Picture path -> fmap Just $ picture path
+  Text color t -> do
+    font <- Font.loadFontFrom
+      $ Font.Config (FontDescriptor "IPAGothic" (FontStyle False False)) 24 0
+    fmap Just $ text font color t
diff --git a/src/MiniLight/Lua.hs b/src/MiniLight/Lua.hs
new file mode 100644
--- /dev/null
+++ b/src/MiniLight/Lua.hs
@@ -0,0 +1,116 @@
+{-# LANGUAGE OverloadedStrings #-}
+module MiniLight.Lua where
+
+import qualified Control.Monad.Caster as Caster
+import Control.Monad.Catch
+import Control.Monad.State hiding (state)
+import qualified Data.ByteString as BS
+import qualified Data.Component.Basic as Basic
+import Data.IORef
+import Data.Maybe
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as TLE
+import Data.UnixTime
+import qualified Foreign.Lua as Lua
+import Foreign.C.String
+import Foreign.Ptr
+import GHC.Generics (Generic)
+import Linear
+import MiniLight
+import MiniLight.FigureDSL
+import qualified SDL
+import qualified SDL.Vect as Vect
+
+data LuaComponentState = LuaComponentState {
+  mousePosition :: V2 Int
+} deriving (Eq, Show)
+
+data LuaComponent = LuaComponent {
+  expr :: String,
+  state :: LuaComponentState,
+  counter :: Int,
+  updatedAt :: UnixTime
+}
+
+data LuaComponentEvent
+  = SetExpr String
+
+instance EventType LuaComponentEvent where
+  getEventType (SetExpr _) = "set_expr"
+
+instance ComponentUnit LuaComponent where
+  figures comp = evalLuaComponent (expr comp) (state comp)
+
+  onSignal ev = execStateT $ do
+    lift $ Basic.emitBasicSignal ev (Basic.Config { Basic.size = V2 640 480, Basic.position = V2 0 0, Basic.visible = True })
+
+    case asSignal ev of
+      Just (SetExpr fs) -> do
+        t <- liftIO getUnixTime
+        modify $ \qc -> qc { expr = fs, counter = counter qc + 1, updatedAt = t }
+      _ -> return ()
+
+    case asSignal ev of
+      Just (Basic.MouseOver p) ->
+        modify $ \qc -> qc { state = (state qc) { mousePosition = p }, counter = counter qc + 1 }
+      _ -> return ()
+
+  useCache c1 c2 = updatedAt c1 == updatedAt c2
+
+newLuaComponent :: LuaComponent
+newLuaComponent = LuaComponent
+  { expr      = ""
+  , state     = LuaComponentState {mousePosition = 0}
+  , counter   = 0
+  , updatedAt = UnixTime 0 0
+  }
+
+evalLuaComponent
+  :: (HasLightEnv env, MonadIO m, MonadMask m)
+  => String
+  -> LuaComponentState
+  -> LightT env m [Figure]
+evalLuaComponent content state
+  | content == "" = return []
+  | otherwise = do
+    result <- liftIO $ Lua.run $ Lua.try $ do
+      Lua.openlibs
+      loadLib
+      st <- Lua.dostring $ TLE.encodeUtf8 $ T.pack content
+      case st of
+        Lua.OK -> Lua.callFunc "onDraw" ()
+        _      -> Lua.throwException $ "Invalid status: " ++ show st
+
+    case result of
+      Left  err -> Caster.err err >> return []
+      Right rs  -> liftMiniLight $ fmap catMaybes $ mapM construct rs
+
+reload
+  :: (HasLoaderEnv env, HasLightEnv env, HasLoopEnv env, MonadIO m, MonadMask m)
+  => T.Text
+  -> LightT env m ()
+reload path = do
+  fs <- liftIO $ readFile (T.unpack path)
+  path @@! SetExpr fs
+
+loadLib :: Lua.Lua ()
+loadLib = Lua.requirehs "minilight" $ do
+  Lua.create
+  Lua.addfunction "picture"   minilight_picture
+  Lua.addfunction "translate" minilight_translate
+  Lua.addfunction "text"      minilight_text
+ where
+  minilight_picture :: BS.ByteString -> Lua.Lua FigureDSL
+  minilight_picture cs = return $ Picture $ T.unpack $ TLE.decodeUtf8 cs
+
+  minilight_translate :: Int -> Int -> FigureDSL -> Lua.Lua FigureDSL
+  minilight_translate x y fig = return $ Translate (Vect.V2 x y) fig
+
+  minilight_text :: BS.ByteString -> (Int, Int, Int, Int) -> Lua.Lua FigureDSL
+  minilight_text cs (r, g, b, a) = return $ Text
+    ( Vect.V4 (fromIntegral r)
+              (fromIntegral g)
+              (fromIntegral b)
+              (fromIntegral a)
+    )
+    (TLE.decodeUtf8 cs)
