diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for essence-of-live-coding-vivid
+
+## 0.2.5
+
+* Thank you, Miguel Negrão, for extensive support, suggestions, testing, and debugging!
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2021, Manuel Bärenz
+
+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 Manuel Bärenz nor the names of other
+      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/essence-of-live-coding-vivid.cabal b/essence-of-live-coding-vivid.cabal
new file mode 100644
--- /dev/null
+++ b/essence-of-live-coding-vivid.cabal
@@ -0,0 +1,36 @@
+name:               essence-of-live-coding-vivid
+version:            0.2.6
+synopsis: General purpose live coding framework - vivid backend
+description:
+  essence-of-live-coding is a general purpose and type safe live coding framework.
+  .
+  You can run programs in it, and edit, recompile and reload them while they're running.
+  Internally, the state of the live program is automatically migrated when performing hot code swap.
+  .
+  The library also offers an easy to use FRP interface.
+  It is parametrized by its side effects,
+  separates data flow cleanly from control flow,
+  and allows to develop live programs from reusable, modular components.
+  There are also useful utilities for debugging and quickchecking.
+  .
+  This package contains the backend for vivid, a Supercollider library.
+license:             BSD3
+license-file:        LICENSE
+author:              Manuel Bärenz
+maintainer:          programming@manuelbaerenz.de
+copyright:           2021 Manuel Bärenz
+category:            Sound
+build-type:          Simple
+cabal-version:       >=1.10
+extra-source-files: CHANGELOG.md
+
+library
+    exposed-modules:
+        LiveCoding.Vivid
+
+    build-depends:
+        base >= 4.7 && < 5
+      , vivid >= 0.5.2.0
+      , essence-of-live-coding >= 0.2.6
+    hs-source-dirs:   src
+    default-language: Haskell2010
diff --git a/src/LiveCoding/Vivid.hs b/src/LiveCoding/Vivid.hs
new file mode 100644
--- /dev/null
+++ b/src/LiveCoding/Vivid.hs
@@ -0,0 +1,110 @@
+{- | Support for [@vivid@](https://hackage.haskell.org/package/vivid),
+a Haskell library for [SuperCollider](https://supercollider.github.io/).
+
+With this module, you can create cells corresponding to synthesizers.
+
+The synthesizers automatically start and stop on reload.
+-}
+
+{-# LANGUAGE Arrows #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE StandaloneDeriving #-}
+module LiveCoding.Vivid where
+
+-- base
+import Data.Foldable (traverse_)
+import GHC.TypeLits (KnownSymbol)
+
+-- vivid
+import Vivid
+
+-- essence-of-live-coding
+import LiveCoding.Handle
+import LiveCoding
+
+{- | Whether a synthesizer should currently be running or not.
+
+Typically, you will either statically supply the value and change it in the code to start and stop the synth,
+or you can connect another cell to it.
+-}
+data SynthState
+  = Started
+  | Stopped
+  deriving (Eq)
+
+{- | A 'ParametrisedHandle' corresponding to one @vivid@/@SuperCollider@ synthesizer.
+
+Usually, you will want to use 'liveSynth' instead, it is easier to handle.
+-}
+vividHandleParametrised
+  :: (VividAction m, Eq params, VarList params, Subset (InnerVars params) args, Elem "gate" args)
+  => ParametrisedHandle (params, SynthDef args, SynthState) m (Maybe (Synth args))
+vividHandleParametrised = ParametrisedHandle { .. }
+  where
+    createParametrised (params, synthDef, Started) = Just <$> synth synthDef params
+    createParametrised (params, synthDef, Stopped) = defineSD synthDef >> pure Nothing
+
+    destroyParametrised _ synthMaybe = traverse_ release synthMaybe
+
+    -- Only the synth parameters changed and it's still running.
+    -- So simply set new parameters without stopping it.
+    changeParametrised (paramsOld, synthDefOld, Started) (paramsNew, synthDefNew, Started) (Just synth)
+      | paramsOld /= paramsNew && synthDefOld == synthDefNew = do
+          set synth paramsNew
+          return $ Just synth
+    -- Synthdef or start/stop state changed, need to release and reinitialise
+    changeParametrised old new synth = defaultChange createParametrised destroyParametrised old new synth
+
+deriving instance Data SynthState
+deriving instance KnownSymbol a => Data (I a)
+
+{- | Create a synthesizer.
+
+When you add 'liveSynth' to your live program,
+it will be started upon reload immediately.
+
+Feed the definition of the synthesizer and its current intended state to this cell.
+The input has the form @(params, sdbody, synthState)@.
+
+* A change in @params@ will reload the synthesizer quickly,
+  unless the types of the parameters change.
+* A change in the @sdbody :: 'SDBody' ...@ or the _types_ of the @params@ will 'release' the synthesizer and start a new one.
+* The input @synthState :: 'SynthState'@ represent whether the synthesizer should currently be running or not.
+  Changes in it quickly start or stop it.
+  * When it is started, @'Just' synth@ is returned, where @synth@ represents the running synthesizer.
+  * When it is stopped, 'Nothing' is returned.
+
+You have to use 'envGate' in your @sdbody@,
+or another way of gating your output signals
+in order to ensure release of the synths without clipping.
+
+For an example, have a look at the source code of 'sine'.
+-}
+liveSynth
+  :: ( VividAction m
+     , Eq params, Typeable params, VarList params
+     , Typeable (InnerVars params), Subset (InnerVars params) (InnerVars params)
+     , Elem "gate" (InnerVars params), Data params
+     )
+  => Cell (HandlingStateT m)
+       (params, SDBody' (InnerVars params) [Signal], SynthState)
+       (Maybe (Synth (InnerVars params)))
+liveSynth = proc (params, sdbody, synthstate) -> do
+  paramsFirstValue <- holdFirst -< params
+  handlingParametrised vividHandleParametrised -< (params, sd paramsFirstValue sdbody, synthstate)
+
+-- | Example sine synthesizer that creates a sine wave at the given input frequency.
+sine :: (VividAction m) => Cell (HandlingStateT m) Float ()
+sine = proc frequency -> do
+  liveSynth -<
+    (
+      ( 1 :: I "gate"
+      , 2 :: I "fadeSecs"
+      , I frequency :: I "freq"
+      )
+    , out (0 :: Int) [envGate ~* sinOsc (freq_ (V :: V "freq"))]
+    , Started)
+  returnA -< ()
