diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,3 @@
+## 0.1.0 (2023-04-12)
+
+- First release
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2023 Andrew Kane
+
+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/pgvector.cabal b/pgvector.cabal
new file mode 100644
--- /dev/null
+++ b/pgvector.cabal
@@ -0,0 +1,46 @@
+cabal-version:      3.0
+name:               pgvector
+version:            0.1.0
+synopsis:           pgvector support for Haskell
+description:        Adds the vector data type to postgresql-simple
+category:           Database
+homepage:           https://github.com/pgvector/pgvector-haskell
+license:            MIT
+license-file:       LICENSE.txt
+author:             Andrew Kane
+maintainer:         andrew@ankane.org
+build-type:         Simple
+extra-doc-files:    CHANGELOG.md
+
+source-repository head
+  type:     git
+  location: https://github.com/pgvector/pgvector-haskell.git
+
+source-repository this
+  type:     git
+  location: https://github.com/pgvector/pgvector-haskell.git
+  tag:      v0.1.0
+
+common warnings
+    ghc-options: -Wall
+
+library
+    import:           warnings
+    exposed-modules:  Pgvector
+    build-depends:
+        base >= 4.6 && < 4.19,
+        bytestring >= 0.10 && < 0.12,
+        postgresql-simple >= 0.6 && < 0.7
+    hs-source-dirs:   src
+    default-language: Haskell2010
+
+test-suite pgvector-test
+    import:           warnings
+    default-language: Haskell2010
+    type:             exitcode-stdio-1.0
+    hs-source-dirs:   test
+    main-is:          Main.hs
+    build-depends:
+        base,
+        pgvector,
+        postgresql-simple
diff --git a/src/Pgvector.hs b/src/Pgvector.hs
new file mode 100644
--- /dev/null
+++ b/src/Pgvector.hs
@@ -0,0 +1,26 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Pgvector (Vector (..)) where
+
+import qualified Data.ByteString.Char8 as BS
+import Database.PostgreSQL.Simple.FromField
+import Database.PostgreSQL.Simple.ToField
+
+data Vector = Vector [Float] deriving (Show)
+
+instance ToField Vector where
+    toField = toField . encodeVector
+
+instance FromField Vector where
+    fromField f mdat = do
+        typ <- typename f
+        if typ /= "vector"
+            then returnError Incompatible f ""
+            else case mdat of
+                Nothing  -> returnError UnexpectedNull f ""
+                Just dat -> return $! decodeVector (BS.unpack dat)
+
+encodeVector :: Vector -> String
+encodeVector (Vector v) = show v
+
+decodeVector :: String -> Vector
+decodeVector v = Vector (read v)
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,31 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Main where
+
+import Database.PostgreSQL.Simple
+import Pgvector
+
+main :: IO ()
+main = do
+    conn <- connectPostgreSQL "dbname=pgvector_haskell_test"
+    _ <- execute_ conn "CREATE EXTENSION IF NOT EXISTS vector"
+    _ <- execute_ conn "DROP TABLE IF EXISTS items"
+
+    _ <- execute_ conn "CREATE TABLE items (embedding vector(3))"
+
+    _ <- execute conn
+        "INSERT INTO items (embedding) VALUES (?)"
+        [Vector [1, 1, 1]]
+    _ <- execute conn
+        "INSERT INTO items (embedding) VALUES (?)"
+        [Vector [2, 2, 2]]
+    _ <- execute conn
+        "INSERT INTO items (embedding) VALUES (?)"
+        [Vector [1, 1, 2]]
+
+    let q = "SELECT embedding FROM items ORDER BY embedding <-> ? LIMIT 5"
+    forEach conn q [Vector [1, 1, 1]] $ \(Only embedding) ->
+        putStrLn $ show (embedding :: Vector)
+
+    _ <- execute_ conn "CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 1)"
+
+    putStrLn "Success"
