diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for aztecs
+
+## 0.1.0.0 -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,29 @@
+Copyright (c) 2024, Matt Hunzinger
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of the copyright holder nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/aztecs.cabal b/aztecs.cabal
new file mode 100644
--- /dev/null
+++ b/aztecs.cabal
@@ -0,0 +1,62 @@
+cabal-version:   3.0
+name:            aztecs
+version:         0.1.0.0
+license:         BSD-3-Clause
+license-file:    LICENSE
+maintainer:      matt@hunzinger.me
+author:          Matt Hunzinger
+build-type:      Simple
+extra-doc-files: CHANGELOG.md
+synopsis:        A type-safe and friendly ECS for Haskell 
+description:     A type-safe and friendly ECS for Haskell 
+    exposed-modules:
+        Data.Aztecs
+        Data.Aztecs.Core
+        Data.Aztecs.Command
+        Data.Aztecs.Schedule
+        Data.Aztecs.System
+        Data.Aztecs.Storage
+        Data.Aztecs.Task
+        Data.Aztecs.Query
+        Data.Aztecs.World
+        Data.Aztecs.World.Archetypes
+        Data.Aztecs.World.Components
+
+    hs-source-dirs:   src
+    default-language: Haskell2010
+    ghc-options:      -Wall
+    build-depends:
+        base >=4 && <5,
+        async >=2,
+        containers >=0.7,
+        mtl >=2
+
+executable ecs
+    main-is:          ECS.hs
+    hs-source-dirs:   examples
+    default-language: Haskell2010
+    ghc-options:      -Wall
+    build-depends:
+        base >=4 && <5,
+        aztecs
+
+test-suite aztecs-test
+    type:             exitcode-stdio-1.0
+    main-is:          Main.hs
+    hs-source-dirs:   test
+    default-language: Haskell2010
+    ghc-options:      -Wall
+    build-depends:
+        base >=4 && <5,
+        aztecs
+
+benchmark aztecs-bench
+    type:             exitcode-stdio-1.0
+    main-is:          Iter.hs
+    hs-source-dirs:   bench
+    default-language: Haskell2010
+    ghc-options:      -Wall
+    build-depends:
+        base >=4 && <5,
+        aztecs,
+        criterion >=1
diff --git a/bench/Iter.hs b/bench/Iter.hs
new file mode 100644
--- /dev/null
+++ b/bench/Iter.hs
@@ -0,0 +1,45 @@
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeApplications #-}
+
+import Criterion.Main
+import Data.Aztecs
+import qualified Data.Aztecs.Query as Q
+import Data.Aztecs.System (runSystem)
+import qualified Data.Aztecs.System as S
+import qualified Data.Aztecs.World as W
+import Data.Foldable (foldrM)
+
+newtype Position = Position Int deriving (Show)
+
+instance Component Position
+
+newtype Velocity = Velocity Int deriving (Show)
+
+instance Component Velocity
+
+data S
+
+instance System IO S where
+  access = do
+    _ <- S.all $ do
+      Velocity y <- Q.read
+      Q.write (\(Position x) -> Position (x + y))
+    return ()
+
+runner :: World -> IO ()
+runner w = do
+  !_ <- runSystem @S w
+  return ()
+
+main :: IO ()
+main = do
+  !w <-
+    foldrM
+      ( \_ wAcc -> do
+          (_, wAcc') <- W.spawn (Position 0) wAcc
+          return wAcc'
+      )
+      W.newWorld
+      [0 :: Int .. 10000]
+  defaultMain [bench "iter" $ nfIO (runner w)]
diff --git a/examples/ECS.hs b/examples/ECS.hs
new file mode 100644
--- /dev/null
+++ b/examples/ECS.hs
@@ -0,0 +1,47 @@
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeApplications #-}
+
+module Main where
+
+import Control.Monad.IO.Class
+import Data.Aztecs
+import qualified Data.Aztecs.Command as C
+import qualified Data.Aztecs.Query as Q
+import qualified Data.Aztecs.System as S
+
+-- Components
+
+newtype Position = Position Int deriving (Show)
+
+instance Component Position
+
+newtype Velocity = Velocity Int deriving (Show)
+
+instance Component Velocity
+
+-- Systems
+
+data A
+
+instance System IO A where
+  access = S.command $ do
+    e <- C.spawn (Position 0)
+    C.insert e (Velocity 1)
+
+data B
+
+instance System IO B where
+  access = do
+    -- Update all entities with a `Position` and `Velocity` component.
+    positions <- S.all $ do
+      Velocity v <- Q.read
+      Q.write (\(Position p) -> Position (p + v))
+
+    liftIO $ print positions
+
+app :: Scheduler IO
+app = schedule @Startup @_ @A [] <> schedule @Update @_ @B []
+
+main :: IO ()
+main = runScheduler app
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,4 @@
+module Main (main) where
+
+main :: IO ()
+main = putStrLn "Test suite not yet implemented."
