diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,7 @@
+# Changelog
+
+## 0.1.0.0 (2026-02-01)
+
+- Initial release
+- TypeScript instances for all Pandoc AST types
+- Uses Pandoc's native `t`/`c` JSON format
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 Sridhar Ratnakumar
+
+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/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,40 @@
+# pandoc-typescript
+
+TypeScript type generation for Pandoc AST types.
+
+## Overview
+
+This package provides TypeScript instances for Pandoc's AST types (`Block`, `Inline`, `Pandoc`, etc.) using [aeson-typescript](https://hackage.haskell.org/package/aeson-typescript).
+
+## JSON Format
+
+Pandoc's native `ToJSON` uses short keys for efficiency:
+- `"t"` for tag (constructor name)
+- `"c"` for contents (constructor arguments)
+
+For example, a paragraph block serializes as:
+```json
+{"t": "Para", "c": [{"t": "Str", "c": "Hello"}]}
+```
+
+The generated TypeScript types match this format.
+
+## Usage
+
+```haskell
+import Text.Pandoc.Definition.TypeScript (pandocTsDeclarations)
+import Data.Aeson.TypeScript.TH (formatTSDeclarations)
+
+main :: IO ()
+main = putStrLn $ formatTSDeclarations pandocTsDeclarations
+```
+
+## Generated Types
+
+The types are currently generated to `frontend/src/components/markdown/types.ts` via the `generate-types` executable.
+
+**TODO:** Encapsulate the generated TypeScript file within this package (perhaps as a build artifact or embedded resource).
+
+## Note
+
+This package uses base (not Relude) to minimize dependencies.
diff --git a/pandoc-typescript.cabal b/pandoc-typescript.cabal
new file mode 100644
--- /dev/null
+++ b/pandoc-typescript.cabal
@@ -0,0 +1,33 @@
+cabal-version:   3.4
+name:            pandoc-typescript
+version:         0.1.0.0
+synopsis:        TypeScript type generation for Pandoc AST types
+homepage:
+  https://github.com/srid/imako/tree/master/backend/pandoc-typescript
+
+license:         MIT
+license-file:    LICENSE
+author:          Sridhar Ratnakumar
+maintainer:      srid@srid.ca
+category:        Text
+build-type:      Simple
+extra-doc-files:
+  CHANGELOG.md
+  README.md
+
+common warnings
+  ghc-options: -Wall
+
+library
+  import:             warnings
+  exposed-modules:    Text.Pandoc.Definition.TypeScript
+  default-extensions: OverloadedStrings
+  build-depends:
+    , aeson
+    , aeson-typescript
+    , base              >=4 && <5
+    , pandoc-types
+    , text
+
+  hs-source-dirs:     src
+  default-language:   GHC2021
diff --git a/src/Text/Pandoc/Definition/TypeScript.hs b/src/Text/Pandoc/Definition/TypeScript.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/Definition/TypeScript.hs
@@ -0,0 +1,239 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+{- |
+TypeScript instances for Pandoc AST types.
+
+Provides TypeScript type generation for Pandoc's Block/Inline and all
+dependent types.
+
+== JSON Format
+
+Pandoc's native ToJSON uses short keys for efficiency:
+
+- @"t"@ for tag (constructor name)
+- @"c"@ for contents (constructor arguments)
+
+For example, a paragraph block serializes as:
+
+@{"t": "Para", "c": [{"t": "Str", "c": "Hello"}]}@
+
+The generated TypeScript types match this format, using @t@ and @c@ as
+discriminator and content fields respectively.
+
+== Circular Types
+
+Some types reference each other: Inline contains @Cite [Citation] [Inline]@,
+Citation contains @[Inline]@ fields, Block contains @Note [Block]@.
+These use manual TypeScript instances to break the dependency cycle.
+-}
+module Text.Pandoc.Definition.TypeScript (
+  pandocTsDeclarations,
+)
+where
+
+import Data.Aeson (defaultOptions)
+import Data.Aeson.TypeScript.Internal (TSDeclaration (..), TSField (..))
+import Data.Aeson.TypeScript.TH (TypeScript (..), deriveTypeScript)
+import Data.Proxy (Proxy (..))
+import Data.Text (Text)
+import Text.Pandoc.Definition hiding (Attr, ColSpec, ListAttributes, Target)
+
+-- ===========================================================================
+-- Manual TypeScript instances for circular types
+-- These types reference each other: Inline contains Cite [Citation] [Inline]
+--                                   Citation contains [Inline] fields
+--                                   Block contains [Inline] and Note [Block]
+-- ===========================================================================
+
+instance TypeScript Inline where
+  getTypeScriptType _ = "Inline"
+  getTypeScriptDeclarations _ =
+    [ TSTypeAlternatives
+        "Inline"
+        []
+        [ "{ t: 'Str'; c: string }"
+        , "{ t: 'Emph'; c: Inline[] }"
+        , "{ t: 'Underline'; c: Inline[] }"
+        , "{ t: 'Strong'; c: Inline[] }"
+        , "{ t: 'Strikeout'; c: Inline[] }"
+        , "{ t: 'Superscript'; c: Inline[] }"
+        , "{ t: 'Subscript'; c: Inline[] }"
+        , "{ t: 'SmallCaps'; c: Inline[] }"
+        , "{ t: 'Quoted'; c: [QuoteType, Inline[]] }"
+        , "{ t: 'Cite'; c: [Citation[], Inline[]] }"
+        , "{ t: 'Code'; c: [Attr, string] }"
+        , "{ t: 'Space' }"
+        , "{ t: 'SoftBreak' }"
+        , "{ t: 'LineBreak' }"
+        , "{ t: 'Math'; c: [MathType, string] }"
+        , "{ t: 'RawInline'; c: [Format, string] }"
+        , "{ t: 'Link'; c: [Attr, Inline[], Target] }"
+        , "{ t: 'Image'; c: [Attr, Inline[], Target] }"
+        , "{ t: 'Note'; c: Block[] }"
+        , "{ t: 'Span'; c: [Attr, Inline[]] }"
+        ]
+        Nothing
+    ]
+
+instance TypeScript Citation where
+  getTypeScriptType _ = "Citation"
+  getTypeScriptDeclarations _ =
+    [ TSInterfaceDeclaration
+        { interfaceName = "Citation"
+        , interfaceGenericVariables = []
+        , interfaceMembers =
+            [ TSField False "citationId" "string" Nothing
+            , TSField False "citationPrefix" "Inline[]" Nothing
+            , TSField False "citationSuffix" "Inline[]" Nothing
+            , TSField False "citationMode" "CitationMode" Nothing
+            , TSField False "citationNoteNum" "number" Nothing
+            , TSField False "citationHash" "number" Nothing
+            ]
+        , interfaceDoc = Nothing
+        }
+    ]
+
+instance TypeScript Block where
+  getTypeScriptType _ = "Block"
+  getTypeScriptDeclarations _ =
+    [ TSTypeAlternatives
+        "Block"
+        []
+        [ "{ t: 'Plain'; c: Inline[] }"
+        , "{ t: 'Para'; c: Inline[] }"
+        , "{ t: 'LineBlock'; c: Inline[][] }"
+        , "{ t: 'CodeBlock'; c: [Attr, string] }"
+        , "{ t: 'RawBlock'; c: [Format, string] }"
+        , "{ t: 'BlockQuote'; c: Block[] }"
+        , "{ t: 'OrderedList'; c: [ListAttributes, Block[][]] }"
+        , "{ t: 'BulletList'; c: Block[][] }"
+        , "{ t: 'DefinitionList'; c: [Inline[], Block[][]][] }"
+        , "{ t: 'Header'; c: [number, Attr, Inline[]] }"
+        , "{ t: 'HorizontalRule' }"
+        , "{ t: 'Table'; c: [Attr, Caption, ColSpec[], TableHead, TableBody[], TableFoot] }"
+        , "{ t: 'Figure'; c: [Attr, Caption, Block[]] }"
+        , "{ t: 'Div'; c: [Attr, Block[]] }"
+        ]
+        Nothing
+    ]
+
+instance TypeScript Pandoc where
+  getTypeScriptType _ = "Pandoc"
+  getTypeScriptDeclarations _ =
+    [ TSInterfaceDeclaration
+        { interfaceName = "Pandoc"
+        , interfaceGenericVariables = []
+        , interfaceMembers =
+            [ TSField False "blocks" "Block[]" Nothing
+            , TSField False "meta" "Meta" Nothing
+            ]
+        , interfaceDoc = Nothing
+        }
+    ]
+
+instance TypeScript Meta where
+  getTypeScriptType _ = "Meta"
+  getTypeScriptDeclarations _ =
+    [TSTypeAlternatives "Meta" [] ["Record<string, MetaValue>"] Nothing]
+
+instance TypeScript MetaValue where
+  getTypeScriptType _ = "MetaValue"
+  getTypeScriptDeclarations _ =
+    [ TSTypeAlternatives
+        "MetaValue"
+        []
+        [ "{ tag: 'MetaMap'; contents: Record<string, MetaValue> }"
+        , "{ tag: 'MetaList'; contents: MetaValue[] }"
+        , "{ tag: 'MetaBool'; contents: boolean }"
+        , "{ tag: 'MetaString'; contents: string }"
+        , "{ tag: 'MetaInlines'; contents: Inline[] }"
+        , "{ tag: 'MetaBlocks'; contents: Block[] }"
+        ]
+        Nothing
+    ]
+
+-- ===========================================================================
+-- TH-derived TypeScript instances for non-circular types
+-- ===========================================================================
+
+$(deriveTypeScript defaultOptions ''Alignment)
+$(deriveTypeScript defaultOptions ''ListNumberStyle)
+$(deriveTypeScript defaultOptions ''ListNumberDelim)
+$(deriveTypeScript defaultOptions ''CitationMode)
+$(deriveTypeScript defaultOptions ''MathType)
+$(deriveTypeScript defaultOptions ''QuoteType)
+$(deriveTypeScript defaultOptions ''Format)
+$(deriveTypeScript defaultOptions ''ColWidth)
+$(deriveTypeScript defaultOptions ''RowSpan)
+$(deriveTypeScript defaultOptions ''ColSpan)
+$(deriveTypeScript defaultOptions ''RowHeadColumns)
+$(deriveTypeScript defaultOptions ''Cell)
+$(deriveTypeScript defaultOptions ''Row)
+$(deriveTypeScript defaultOptions ''Caption)
+$(deriveTypeScript defaultOptions ''TableHead)
+$(deriveTypeScript defaultOptions ''TableBody)
+$(deriveTypeScript defaultOptions ''TableFoot)
+
+-- Type aliases for Pandoc
+type Attr = (Text, [Text], [(Text, Text)])
+type Target = (Text, Text)
+type ListAttributes = (Int, ListNumberStyle, ListNumberDelim)
+type ColSpec = (Alignment, ColWidth)
+
+instance TypeScript Attr where
+  getTypeScriptType _ = "Attr"
+  getTypeScriptDeclarations _ =
+    [TSTypeAlternatives "Attr" [] ["[string, string[], [string, string][]]"] Nothing]
+
+instance TypeScript Target where
+  getTypeScriptType _ = "Target"
+  getTypeScriptDeclarations _ =
+    [TSTypeAlternatives "Target" [] ["[string, string]"] Nothing]
+
+instance TypeScript ListAttributes where
+  getTypeScriptType _ = "ListAttributes"
+  getTypeScriptDeclarations _ =
+    [TSTypeAlternatives "ListAttributes" [] ["[number, ListNumberStyle, ListNumberDelim]"] Nothing]
+
+instance TypeScript ColSpec where
+  getTypeScriptType _ = "ColSpec"
+  getTypeScriptDeclarations _ =
+    [TSTypeAlternatives "ColSpec" [] ["[Alignment, ColWidth]"] Nothing]
+
+-- ===========================================================================
+-- Exports
+-- ===========================================================================
+
+-- | All Pandoc TypeScript declarations
+pandocTsDeclarations :: [TSDeclaration]
+pandocTsDeclarations =
+  mconcat
+    [ getTypeScriptDeclarations (Proxy @Attr)
+    , getTypeScriptDeclarations (Proxy @Target)
+    , getTypeScriptDeclarations (Proxy @ListAttributes)
+    , getTypeScriptDeclarations (Proxy @ColSpec)
+    , getTypeScriptDeclarations (Proxy @Alignment)
+    , getTypeScriptDeclarations (Proxy @ListNumberStyle)
+    , getTypeScriptDeclarations (Proxy @ListNumberDelim)
+    , getTypeScriptDeclarations (Proxy @CitationMode)
+    , getTypeScriptDeclarations (Proxy @MathType)
+    , getTypeScriptDeclarations (Proxy @QuoteType)
+    , getTypeScriptDeclarations (Proxy @Format)
+    , getTypeScriptDeclarations (Proxy @ColWidth)
+    , getTypeScriptDeclarations (Proxy @RowSpan)
+    , getTypeScriptDeclarations (Proxy @ColSpan)
+    , getTypeScriptDeclarations (Proxy @RowHeadColumns)
+    , getTypeScriptDeclarations (Proxy @Cell)
+    , getTypeScriptDeclarations (Proxy @Row)
+    , getTypeScriptDeclarations (Proxy @Caption)
+    , getTypeScriptDeclarations (Proxy @TableHead)
+    , getTypeScriptDeclarations (Proxy @TableBody)
+    , getTypeScriptDeclarations (Proxy @TableFoot)
+    , getTypeScriptDeclarations (Proxy @Meta)
+    , getTypeScriptDeclarations (Proxy @MetaValue)
+    , getTypeScriptDeclarations (Proxy @Citation)
+    , getTypeScriptDeclarations (Proxy @Inline)
+    , getTypeScriptDeclarations (Proxy @Block)
+    , getTypeScriptDeclarations (Proxy @Pandoc)
+    ]
