diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,3 @@
+# 0.1
+
+* Builds with GHC 8.6.5, GHC 8.8.2, GHCJS 8.6.0.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,26 @@
+Copyright (c) 2020, Renzo Carbonara. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+2. 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.
+
+3. Neither the name of the author 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/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,20 @@
+# serialise-uuid
+
+Encode and decode UUID values in CBOR
+using [uuid-types](
+https://hackage.haskell.org/package/uuid-types
+), [cborg](
+https://hackage.haskell.org/package/cborg
+) and [serialise](
+https://hackage.haskell.org/package/serialise
+).
+
+# Development
+
+* Build all with `nix-build`.
+
+* Build with some GHC or GHCJS version with `nix-build -A $xxx`, where `$xxx` is
+  one of `ghc865`, `ghc883`, `ghcjs86`.
+
+* Enter a development environment with `nix-shell -A $xxx.env`, where `$xxx` is
+  one of `ghc865`, `ghc883`, `ghcjs86`.
diff --git a/lib/Codec/CBOR/UUID.hs b/lib/Codec/CBOR/UUID.hs
new file mode 100644
--- /dev/null
+++ b/lib/Codec/CBOR/UUID.hs
@@ -0,0 +1,36 @@
+module Codec.CBOR.UUID (encode, decode) where
+
+import qualified Codec.Serialise as Ser
+import qualified Codec.CBOR.Encoding as Ser (Encoding, encodeTag)
+import qualified Codec.CBOR.Decoding as Ser (Decoder, decodeTag)
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.UUID.Types as UUID
+
+-- | Encoded according to [draft-bormann-cbor-tags-oid-06](https://tools.ietf.org/html/draft-bormann-cbor-tags-oid-06).
+--
+-- 19 bytes consisting of @0xd8@, @0x25@, @0x50@, and the 16 raw bytes of the
+-- UUID in network order. For example, the UUID @8b0d1a20-dcc5-11d9-bda9-0002a5d5c51b@ is
+-- encoded as @"\\xd8\\x25\\x50\\x8b\\x0d\\x1a\\x20\\xdc\\xc5\\x11\\xd9\\xbd\\xa9\\x00\\x02\\xa5\\xd5\\xc5\\x1b"@.
+encode :: UUID.UUID -> Ser.Encoding
+encode = \u ->
+  Ser.encodeTag 0x25 <>
+  Ser.encode (BL.toStrict (UUID.toByteString u))
+{-# INLINABLE encode #-}
+
+-- | Decode according to [draft-bormann-cbor-tags-oid-06](https://tools.ietf.org/html/draft-bormann-cbor-tags-oid-06).
+--
+-- 19 bytes consisting of @0xd8@, @0x25@, @0x50@, and the 16 raw bytes of the
+-- UUID in network order. For example, the UUID @8b0d1a20-dcc5-11d9-bda9-0002a5d5c51b@ is expected to be
+-- encoded as @"\\xd8\\x25\\x50\\x8b\\x0d\\x1a\\x20\\xdc\\xc5\\x11\\xd9\\xbd\\xa9\\x00\\x02\\xa5\\xd5\\xc5\\x1b"@.
+decode :: Ser.Decoder s UUID.UUID
+decode = do
+  tag <- Ser.decodeTag
+  case tag of
+    0x25 -> do
+      bs <- Ser.decode
+      case UUID.fromByteString (BL.fromStrict bs) of
+        Nothing -> fail "UUID"
+        Just x -> pure x
+    _ -> fail "UUID"
+{-# INLINABLE decode #-}
+
diff --git a/lib/Codec/Serialise/UUID.hs b/lib/Codec/Serialise/UUID.hs
new file mode 100644
--- /dev/null
+++ b/lib/Codec/Serialise/UUID.hs
@@ -0,0 +1,24 @@
+-- | This module offers an orphan 'Ser.Serialise' instance for 'UUID.UUID'.
+--
+-- Import as follows:
+--
+-- @
+-- import Codec.Serialise.UUID ()
+-- @
+module Codec.Serialise.UUID () where
+
+import qualified Codec.Serialise as Ser
+import qualified Data.UUID.Types as UUID
+
+import qualified Codec.CBOR.UUID
+
+-- | Encoded according to [draft-bormann-cbor-tags-oid-06](https://tools.ietf.org/html/draft-bormann-cbor-tags-oid-06).
+--
+-- 19 bytes consisting of @0xd8@, @0x25@, @0x50@, and the 16 raw bytes of the
+-- UUID in network order. For example, the UUID @8b0d1a20-dcc5-11d9-bda9-0002a5d5c51b@ is
+-- encoded as @"\\xd8\\x25\\x50\\x8b\\x0d\\x1a\\x20\\xdc\\xc5\\x11\\xd9\\xbd\\xa9\\x00\\x02\\xa5\\xd5\\xc5\\x1b"@.
+instance Ser.Serialise UUID.UUID where
+  encode = Codec.CBOR.UUID.encode
+  {-# INLINE encode #-}
+  decode = Codec.CBOR.UUID.decode
+  {-# INLINE decode #-}
diff --git a/serialise-uuid.cabal b/serialise-uuid.cabal
new file mode 100644
--- /dev/null
+++ b/serialise-uuid.cabal
@@ -0,0 +1,50 @@
+cabal-version: 2.4
+name: serialise-uuid
+version: 0.1
+license: BSD-3-Clause
+license-file: LICENSE
+extra-source-files: README.md CHANGELOG.md
+author: Renzo Carbonara
+maintainer: renλren.zone
+copyright: Copyright (c) Renzo Carbonara 2020
+category: Data
+build-type: Simple
+synopsis: Encode and decode UUID values in CBOR using uuid-types, cborg and serialise.
+description: Encode and decode UUID values in CBOR using uuid-types, cborg and serialise.
+homepage: https://gitlab.com/k0001/serialise-uuid
+bug-reports: https://gitlab.com/k0001/serialise-uuid/issues
+tested-with:
+  GHC == 8.6.0,
+  GHC == 8.6.5,
+  GHC == 8.8.2
+
+library
+  hs-source-dirs: lib
+  ghc-options: -Wall -Werror=incomplete-patterns -O2
+  ghcjs-options: -Wall -Werror=incomplete-patterns -O3
+  default-language: Haskell2010
+  exposed-modules:
+    Codec.Serialise.UUID
+    Codec.CBOR.UUID
+  build-depends:
+    cborg,
+    base ==4.*,
+    bytestring,
+    serialise,
+    uuid-types,
+
+test-suite test
+  default-language: Haskell2010
+  type: exitcode-stdio-1.0
+  hs-source-dirs: test
+  main-is: Main.hs
+  build-depends:
+    base,
+    bytestring,
+    serialise,
+    serialise-uuid,
+    tasty,
+    tasty-hunit,
+    tasty-quickcheck,
+    uuid-types,
+
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,49 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module Main
+  ( main,
+  )
+where
+
+import qualified Codec.Serialise as Ser
+import Codec.Serialise.UUID ()
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.UUID.Types as UUID
+import qualified Test.Tasty as Tasty
+import Test.Tasty.HUnit ((@?=), testCase)
+import Test.Tasty.QuickCheck ((===), Gen, arbitrary, forAll, testProperty)
+import qualified Test.Tasty.Runners as Tasty
+
+main :: IO ()
+main =
+  Tasty.defaultMainWithIngredients
+    [ Tasty.consoleTestReporter,
+      Tasty.listingTests
+    ]
+    tt
+
+tt :: Tasty.TestTree
+tt =
+  Tasty.testGroup
+    "serialise-uuid"
+    [ testProperty "round trip" $ forAll genUUID $ \u ->
+        Right u === Ser.deserialiseOrFail (Ser.serialise u),
+      testProperty "expected format" $ forAll genUUID $ \u ->
+        Ser.serialise u === "\xd8\x25\x50" <> UUID.toByteString u,
+      testProperty "expected length" $ forAll genUUID $ \u ->
+        BL.length (Ser.serialise u) === 19,
+      testCase "00000000-0000-0000-0000-000000000000" $
+        Ser.serialise UUID.nil @?= "\xd8\x25\x50\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      testCase "8b0d1a20-dcc5-11d9-bda9-0002a5d5c51b" $
+        let Just u = UUID.fromString "8b0d1a20-dcc5-11d9-bda9-0002a5d5c51b"
+         in Ser.serialise u @?= "\xd8\x25\x50\x8b\x0d\x1a\x20\xdc\xc5\x11\xd9\xbd\xa9\x00\x02\xa5\xd5\xc5\x1b"
+    ]
+
+genUUID :: Gen UUID.UUID
+genUUID =
+  UUID.fromWords
+    <$> arbitrary
+    <*> arbitrary
+    <*> arbitrary
+    <*> arbitrary
