diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,6 @@
+# Change Log
+
+
+## v1.0.0.0
+
+* Initial package release.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,26 @@
+Copyright 2019 Pavan Rikhi
+
+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 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/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,30 @@
+# ISO 3166-2:CA Province/Territory Codes
+
+[![Build Status](https://travis-ci.org/prikhi/ca-province-codes.svg?branch=master)](https://travis-ci.org/prikhi/ca-province-codes)
+
+
+This is a Haskell package that provides a data type for Canadian ISO 3166-2
+Province and Territory codes, as well as functions for converting codes into
+their English subdivision names.
+
+
+## Building
+
+Use `stack` to build this for local development:
+
+```sh
+stack build --pedantic --test --haddock --file-watch 
+```
+
+
+## Prior Art
+
+The API for this package is based off of the
+[state-codes](https://hackage.haskell.org/package/state-codes) and
+[iso3166-country-codes](https://hackage.haskell.org/package/iso3166-country-codes)
+packages.
+
+
+## License
+
+BSD-3, exceptions available.
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/ca-province-codes.cabal b/ca-province-codes.cabal
new file mode 100644
--- /dev/null
+++ b/ca-province-codes.cabal
@@ -0,0 +1,59 @@
+cabal-version: 1.12
+
+-- This file has been generated from package.yaml by hpack version 0.31.1.
+--
+-- see: https://github.com/sol/hpack
+--
+-- hash: fa6a6e709df152c56ccdfe32e761e672424ef03f0ec97a3621280f24430f4503
+
+name:           ca-province-codes
+version:        1.0.0.0
+synopsis:       ISO 3166-2:CA Province Codes and Names
+description:    This package contains a @Code@ data type containing each Canadian Province and Territory, as well as functions for converting from and to the English subdivision names.
+category:       Data
+homepage:       https://github.com/prikhi/ca-province-codes#readme
+bug-reports:    https://github.com/prikhi/ca-province-codes/issues
+author:         Pavan Rikhi
+maintainer:     pavan.rikhi@gmail.com
+copyright:      2019, Pavan Rikhi
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+extra-source-files:
+    README.md
+    CHANGELOG.md
+
+source-repository head
+  type: git
+  location: https://github.com/prikhi/ca-province-codes
+
+library
+  exposed-modules:
+      Data.CAProvinceCodes
+  other-modules:
+      Paths_ca_province_codes
+  hs-source-dirs:
+      src
+  ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints
+  build-depends:
+      aeson >=1 && <2
+    , base >=4.7 && <5
+    , text >=1 && <2
+  default-language: Haskell2010
+
+test-suite ca-province-codes-test
+  type: exitcode-stdio-1.0
+  main-is: Spec.hs
+  other-modules:
+      Paths_ca_province_codes
+  hs-source-dirs:
+      test
+  ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
+  build-depends:
+      QuickCheck
+    , aeson >=1 && <2
+    , base >=4.7 && <5
+    , ca-province-codes
+    , hspec
+    , text >=1 && <2
+  default-language: Haskell2010
diff --git a/src/Data/CAProvinceCodes.hs b/src/Data/CAProvinceCodes.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/CAProvinceCodes.hs
@@ -0,0 +1,103 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-| The "Data.CAProvinceCodes" module is used for enumerating, and
+rendering the <https://en.wikipedia.org/wiki/ISO_3166-2:CA ISO 3166-2:CA>
+codes for Canadian Provinces and Territories.
+
+It is meant to be qualified when imported:
+
+@
+import qualified Data.CAProvinceCodes as CAProvinces
+@
+
+-}
+module Data.CAProvinceCodes
+    ( Code(..)
+    , all
+    , toName
+    , fromName
+    , isProvince
+    , isTerritory
+    )
+where
+
+import           Data.Aeson                     ( ToJSON
+                                                , FromJSON
+                                                )
+import qualified Data.Text                     as T
+import           GHC.Generics                   ( Generic )
+import           Prelude                 hiding ( all )
+
+
+{-| A Canadian Province/Territory Code from
+<https://en.wikipedia.org/wiki/ISO_3166-2:CA ISO 3166-2:CA>.
+-}
+data Code
+    = AB -- ^ Alberta
+    | BC -- ^ British Columbia
+    | MB -- ^ Manitoba
+    | NB -- ^ New Brunswick
+    | NL -- ^ Newfoundland And Labrador
+    | NS -- ^ Nova Scotia
+    | NT -- ^ Northwest Territories
+    | NU -- ^ Nunavut
+    | ON -- ^ Ontario
+    | PE -- ^ Prince Edward Island
+    | QC -- ^ Quebec
+    | SK -- ^ Saskatchewan
+    | YT -- ^ Yukon
+    deriving (Show, Read, Eq, Enum, Bounded, Generic)
+
+instance ToJSON Code
+instance FromJSON Code
+
+
+{-| A list of every Province/Territory Code. -}
+all :: [Code]
+all = enumFrom minBound
+
+
+{-| Render a `Code` to it's English name. -}
+toName :: Code -> T.Text
+toName c = case c of
+    AB -> "Alberta"
+    BC -> "British Columbia"
+    MB -> "Manitoba"
+    NB -> "New Brunswick"
+    NL -> "Newfoundland And Labrador"
+    NS -> "Nova Scotia"
+    NT -> "Northwest Territories"
+    NU -> "Nunavut"
+    ON -> "Ontario"
+    PE -> "Prince Edward Island"
+    QC -> "Quebec"
+    SK -> "Saskatchewan"
+    YT -> "Yukon"
+
+
+{-| Parse a `Code` from an English name. This is case-insensitive.
+-}
+fromName :: T.Text -> Maybe Code
+fromName n = case T.toLower n of
+    "alberta"                   -> Just AB
+    "british columbia"          -> Just BC
+    "manitoba"                  -> Just MB
+    "new brunswick"             -> Just NB
+    "newfoundland and labrador" -> Just NL
+    "nova scotia"               -> Just NS
+    "northwest territories"     -> Just NT
+    "nunavut"                   -> Just NU
+    "ontario"                   -> Just ON
+    "prince edward island"      -> Just PE
+    "quebec"                    -> Just QC
+    "saskatchewan"              -> Just SK
+    "yukon"                     -> Just YT
+    _                           -> Nothing
+
+{-| Does the `Code` denote a Province? -}
+isProvince :: Code -> Bool
+isProvince = not . isTerritory
+
+{-| Does the `Code` denote a Territory? -}
+isTerritory :: Code -> Bool
+isTerritory = (`elem` [NT, NU, YT])
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,28 @@
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+import           Data.Aeson                     ( encode
+                                                , decode
+                                                )
+import qualified Data.CAProvinceCodes          as CAProvinces
+import qualified Data.Text                     as T
+import           Test.Hspec
+import           Test.QuickCheck
+
+-- brittany-disable-next-binding
+main :: IO ()
+main = hspec $ do
+    describe "all" $
+        it "contains all enumerations" $
+            CAProvinces.all `shouldBe` [minBound .. maxBound]
+    describe "toName" $
+        it "is idempotent with fromName" $ property $
+            \c -> (CAProvinces.fromName . CAProvinces.toName) c == Just c
+    describe "fromName" $
+        it "is case-insensitive" $ property $
+            \c -> (CAProvinces.fromName . T.toUpper . CAProvinces.toName) c == Just c
+    describe "Aeson instance" $
+        it "is idempotent" $ property $
+            \c -> (decode . encode) c == Just (c :: CAProvinces.Code)
+
+
+instance Arbitrary CAProvinces.Code where
+    arbitrary = elements CAProvinces.all
