diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,27 @@
+Shpadoinkle Debug aka S11 Debug
+Copyright © 2020 Isaac Shapira
+All rights reserved.
+
+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 Shpadoinkle 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 OWNER 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 @@
+# Shpadoinkle Debug
+
+[![Goldwater](https://gitlab.com/fresheyeball/Shpadoinkle/badges/master/pipeline.svg)](https://gitlab.com/fresheyeball/Shpadoinkle)
+[![BSD-3](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
+[![built with nix](https://img.shields.io/badge/built%20with-nix-41439a)](https://builtwithnix.org)
+[![Hackage](https://img.shields.io/hackage/v/Shpadoinkle-debug.svg)](https://hackage.haskell.org/package/Shpadoinkle-debug)
+[![Hackage Deps](https://img.shields.io/hackage-deps/v/Shpadoinkle-debug.svg)](http://packdeps.haskellers.com/reverse/Shpadoinkle-debug)
+[![Hackage CI](https://matrix.hackage.haskell.org/api/v2/packages/Shpadoinkle-debug/badge)](https://matrix.hackage.haskell.org/#/package/Shpadoinkle-debug)
+
+This package exposes some useful debugging functions for tracing the state of Shpadoinkle applications as they change over time. It exposes 2 type classes currently.
+
+```haskell
+class LogJS (c :: Type -> Constraint) where
+  logJS :: c a => a -> JSM ()
+
+class LogJS c => Trapper c where
+  trapper :: c a => JSContextRef -> a -> a
+```
+
+These are intended to by used with `TypeApplications`, so you can choose the means of conversion before passing to `console.log`. For example:
+
+```haskell
+main :: IO ()
+main = runJSorWarp 8080 $ do
+  ctx <- askJSM
+  simple runParDiff initial (view . trapper @ToJSON ctx) getBody
+```
+
+Will log all state by first encoding to JSON with Aeson, then then logging with `JSON.parse` so the browser console has the nice native display. If we change it to `trapper @Show ctx` it will use the `Show` instance instead.
+
diff --git a/Shpadoinkle-debug.cabal b/Shpadoinkle-debug.cabal
new file mode 100644
--- /dev/null
+++ b/Shpadoinkle-debug.cabal
@@ -0,0 +1,42 @@
+cabal-version: 1.12
+
+-- This file has been generated from package.yaml by hpack version 0.32.0.
+--
+-- see: https://github.com/sol/hpack
+--
+-- hash: e9e30937de9b5d1c02c02b329830272b9305e6d17612fa256c2a54fff3f8381d
+
+name:           Shpadoinkle-debug
+version:        0.0.0.1
+synopsis:       Debugging tools for Shpadoinkle applications.
+description:    Shpadoinkle tooling is a work in progress. But some useful functions have already emerged. This repo centeralizes these functions, and will house future work on more robust tooling, such as time travel debugging.
+category:       Web
+author:         Isaac Shapira
+maintainer:     fresheyeball@protonmail.com
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+extra-source-files:
+    README.md
+    CHANGELOG.md
+
+source-repository head
+  type: git
+  location: https://gitlab.com/fresheyeball/Shpadoinkle.git
+
+library
+  exposed-modules:
+      Shpadoinkle.Debug
+  other-modules:
+      Paths_Shpadoinkle_debug
+  hs-source-dirs:
+      ./.
+  ghc-options: -Wall -Wcompat -fwarn-redundant-constraints -fwarn-incomplete-uni-patterns -fwarn-tabs -fwarn-incomplete-record-updates -fwarn-identities
+  build-depends:
+      aeson
+    , base >=4.12.0 && <4.16
+    , jsaddle >=0.9.7 && <0.20
+    , lens
+    , text
+    , unliftio
+  default-language: Haskell2010
diff --git a/Shpadoinkle/Debug.hs b/Shpadoinkle/Debug.hs
new file mode 100644
--- /dev/null
+++ b/Shpadoinkle/Debug.hs
@@ -0,0 +1,60 @@
+{-# LANGUAGE AllowAmbiguousTypes  #-}
+{-# LANGUAGE ConstraintKinds      #-}
+{-# LANGUAGE ExtendedDefaultRules #-}
+{-# LANGUAGE KindSignatures       #-}
+{-# LANGUAGE OverloadedStrings    #-}
+{-# LANGUAGE ScopedTypeVariables  #-}
+{-# LANGUAGE TypeApplications     #-}
+{-# OPTIONS_GHC -fno-warn-type-defaults #-}
+
+
+module Shpadoinkle.Debug
+  ( LogJS (..)
+  , Trapper (..)
+  , askJSM
+  ) where
+
+
+import           Control.Lens
+import           Data.Aeson                  (ToJSON, encode)
+import           Data.Kind
+import           Data.Text
+import           Data.Text.Lazy              (toStrict)
+import           Data.Text.Lazy.Encoding
+import           Language.Javascript.JSaddle
+import           System.IO.Unsafe            (unsafePerformIO)
+
+
+default (Data.Text.Text)
+
+
+class LogJS (c :: Type -> Constraint) where
+  logJS :: c a => a -> JSM ()
+
+instance LogJS ToJSON where
+  logJS a = do
+    console <- jsg "console"
+    json <- jsg "JSON"
+    parsed <- json ^. js1 "parse" (toStrict . decodeUtf8 $ encode a)
+    () <$ console ^. js1 "log" parsed
+
+instance LogJS Show where
+  logJS a = do
+    console <- jsg "console"
+    () <$ console ^. js1 "log" (pack $ show a)
+
+instance LogJS ToJSVal where
+  logJS a = do
+    console <- jsg "console"
+    () <$ console ^. js1 "log" (toJSVal a)
+
+
+class LogJS c => Trapper c where
+  trapper :: c a => JSContextRef -> a -> a
+  trapper ctx x = unsafePerformIO $ runJSM (x <$ logJS @c x) ctx
+  {-# NOINLINE trapper #-}
+
+
+instance Trapper ToJSON
+instance Trapper Show
+instance Trapper ToJSVal
