diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,5 @@
+# Revision history for asciichart
+
+## 1.0.0 -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2018 Fabian Beuke
+
+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,27 @@
+# asciichart
+[![License: MIT](https://img.shields.io/badge/License-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT)
+[![Build Status](https://travis-ci.org/madnight/asciichart.svg?branch=master)](https://travis-ci.org/madnight/asciichart)
+
+ASCII line charts in terminal ╭┈╯. Console line charts in pure Haskell.  
+This is a Haskell port of the Javascript library [kroitor/asciichart](https://github.com/kroitor/asciichart). Free for any usage (MIT License).
+
+![](example.png)
+
+## Usage
+```bash
+cabal install asciichart
+```
+
+```haskell
+import Data.Text.Chart (plot)
+
+main :: IO ()
+main = plot [1..20]
+```
+
+For more examples e.g. sinus wave see [examples folder](https://github.com/madnight/asciichart/tree/master/examples).
+
+## References
+
+Full credits to [kroitor](https://github.com/kroitor/) the inventor of asciichart for the terminal.  
+This is only a simple port for the Haskell community.
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/asciichart.cabal b/asciichart.cabal
new file mode 100644
--- /dev/null
+++ b/asciichart.cabal
@@ -0,0 +1,54 @@
+name:                asciichart
+version:             1.0.0
+synopsis:            Line charts in terminal
+license:             MIT
+license-file:        LICENSE
+author:              Fabian Beuke
+maintainer:          mail@beuke.org
+homepage:            https://github.com/madnight/asciichart
+bug-reports:         https://github.com/madnight/asciichart/issues
+copyright:           (c) 2018-Present Fabian Beuke
+category:            Text
+build-type:          Simple
+extra-source-files:  ChangeLog.md, README.md
+cabal-version:       >=1.10
+tested-with:         GHC == 7.8
+                   , GHC == 7.10
+                   , GHC == 8.0.1
+                   , GHC == 8.2.2
+                   , GHC == 8.4.1
+description:
+  Line charts in terminal ╭┈╯. Haskell port of kroitor/asciichart.
+  .
+  @
+    import Data.Text.Chart (plot)
+    .
+    main :: IO ()
+    main = plot [1..20]
+  @
+  .
+
+source-repository head
+  type: git
+  location: git://github.com/madnight/asciichart.git
+
+library
+  exposed-modules:     Data.Text.Chart
+  build-depends:       base >=3.0 && <5
+                     , array >=0.5 && <0.6
+  hs-source-dirs:      src
+  ghc-options:         -Wall
+  default-language:    Haskell2010
+
+test-suite test
+    type:              exitcode-stdio-1.0
+    main-is:           Test.hs
+    hs-source-dirs:    test
+    ghc-options:       -Wall
+    default-language:  Haskell2010
+    build-depends:     base
+                     , asciichart
+                     , random
+                     , silently
+                     , raw-strings-qq
+                     , hspec == 2.*
diff --git a/src/Data/Text/Chart.hs b/src/Data/Text/Chart.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Text/Chart.hs
@@ -0,0 +1,100 @@
+{-# LANGUAGE CPP #-}
+
+module Data.Text.Chart
+    ( plot
+    , plotWith
+    , options
+    , height
+    ) where
+
+import Control.Monad (forM_)
+import Data.Array.IO (newArray, IOArray, getElems, writeArray)
+import Data.Char     (isSpace)
+import Data.List     (unfoldr, dropWhileEnd)
+import Text.Printf   (printf)
+
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative ((<$>))
+#endif
+
+data Options =
+  Options { height :: Int }
+
+-- default options
+options :: Options
+options =
+  Options { height = 14 }
+
+newArray2D :: Integer -> Integer -> IO (IOArray (Integer, Integer) String)
+newArray2D dimX dimY = newArray ((0,0), (dimX, dimY)) " "
+
+splitEvery :: Int -> [a] -> [[a]]
+splitEvery n = takeWhile (not . null) . unfoldr (Just . splitAt n)
+
+plot :: [Integer] -> IO ()
+plot = plotWith options
+
+pad :: Integral a => [a] -> Int
+pad series =
+  let floats = fromIntegral <$> series
+      toStr :: [Float] -> [String]
+      toStr = fmap (printf "%0.2f")
+  in  maximum $ length <$> toStr floats
+
+plotWith :: Options -> [Integer] -> IO ()
+plotWith options series = do
+
+    -- variables and functions
+    let min' = minimum series
+    let max' = maximum series
+    let range = abs $ max' - min'
+    let offset' = 3
+    let height' = height options
+    let ratio = fromIntegral height' / fromIntegral range :: Float
+    let min2 = fromIntegral min' * ratio
+    let max2 = fromIntegral max' * ratio
+    let rows = round $ abs $ max2 - min2
+    let width = length series + 3
+    let pad' = pad series
+
+    -- array creation
+    arr <- newArray2D rows (toInteger width)
+    let write arr [x] [y] = writeArray arr (x, y)
+    let result = write arr
+
+    -- axis and labels
+    forM_ [min2..max2] $ \y -> do
+            let label = fromInteger max' - (y - min2)
+                      * fromInteger range / fromIntegral rows
+            result [round(y - min2)] [maximum [offset' - 5, 0]] $
+                   printf ("%"++ show pad' ++".2f") label
+            result [round(y - min2)] [offset' - 1] $
+                   if y == 0 then "┼" else "┤"
+
+    -- initial value
+    let first = fromInteger (head series) * ratio - min2
+    result [round(fromInteger rows - first)] [offset' - 1] "┼"
+
+    -- plot the line
+    forM_ [0..(length series - 2)] $ \x' -> do
+        let x = toInteger x'
+        let offset'' = x + offset'
+        let y0 = round (fromInteger (series !! (x' + 0)) * ratio) - round min2
+        let y1 = round (fromInteger (series !! (x' + 1)) * ratio) - round min2
+        if y0 == y1 then
+            result [rows - y0] [offset''] "─"
+        else do
+            result [rows - y1] [offset''] $
+                   if y0 > y1 then "╰" else "╭"
+            result [rows - y0] [offset''] $
+                   if y0 > y1 then "╮" else "╯"
+            let start = minimum [y0, y1] + 1
+            let end = maximum [y0, y1]
+
+            forM_ [start..(end - 1)] $ \y ->
+                result [rows - y] [offset''] "│"
+
+    -- print the results
+    elements <- getElems arr
+    let result = splitEvery (width + 1) elements
+    forM_ result $ putStrLn . dropWhileEnd isSpace . concat
diff --git a/test/Test.hs b/test/Test.hs
new file mode 100644
--- /dev/null
+++ b/test/Test.hs
@@ -0,0 +1,148 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE QuasiQuotes #-}
+
+import Control.Monad       (forM_, replicateM)
+import Data.Text.Chart     (plot, plotWith, options, height)
+import System.IO.Silently
+import System.Random       (randomRIO)
+import Test.Hspec
+import Text.RawString.QQ
+
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative ((<$>))
+import Data.Monoid         (mempty)
+#endif
+
+randomList :: Int -> IO [Integer]
+randomList = ($ randomRIO (-99999, 99999)) . replicateM
+
+test0 :: IO ()
+test0 = plotWith options {height = 5} ([1..6] ++ [6,5..1])
+
+test0Output :: String
+test0Output = tail [r|
+6.00 ┤    ╭─╮
+5.00 ┤   ╭╯ ╰╮
+4.00 ┤  ╭╯   ╰╮
+3.00 ┤ ╭╯     ╰╮
+2.00 ┤╭╯       ╰╮
+1.00 ┼╯         ╰
+|]
+
+test1 :: IO ()
+test1 = plotWith options {height = 8} wave
+  where wave = round . (5 *) . sin . (/ 120) . (pi *) . (4 *) <$> [0..60]
+
+test1Output :: String
+test1Output = tail [r|
+ 5.00 ┤          ╭────────╮
+ 3.75 ┤       ╭──╯        ╰──╮
+ 2.50 ┤  ╭────╯              ╰────╮
+ 1.25 ┤╭─╯                        ╰─╮
+ 0.00 ┼╯                            ╰╮                            ╭
+-1.25 ┤                              ╰─╮                        ╭─╯
+-2.50 ┤                                ╰────╮              ╭────╯
+-3.75 ┤                                     ╰──╮        ╭──╯
+-5.00 ┤                                        ╰────────╯
+|]
+
+test2 :: IO ()
+test2 = plotWith options {height = 2} wave
+  where wave = round . (5 *) . cos . (/ 30) . (pi *) . (4 *) <$> [0..30]
+
+test2Output :: String
+test2Output = tail [r|
+ 5.00 ┼──╮         ╭────╮         ╭──
+ 0.00 ┼  ╰──╮    ╭─╯    ╰──╮   ╭──╯
+-5.00 ┤     ╰────╯         ╰───╯
+|]
+
+test3 :: IO ()
+test3 = plot $ take 51 $ cycle [-8975789655001, 6755678990773]
+
+test3Output :: String
+test3Output = tail [r|
+ 6755679000000.00 ┤╭╮╭╮╭╮╭╮╭╮╭╮╭╮╭╮╭╮╭╮╭╮╭╮╭╮╭╮╭╮╭╮╭╮╭╮╭╮╭╮╭╮╭╮╭╮╭╮╭╮
+ 5632002400000.00 ┤││││││││││││││││││││││││││││││││││││││││││││││││││
+ 4508326300000.00 ┤││││││││││││││││││││││││││││││││││││││││││││││││││
+ 3384649700000.00 ┤││││││││││││││││││││││││││││││││││││││││││││││││││
+ 2260973600000.00 ┤││││││││││││││││││││││││││││││││││││││││││││││││││
+ 1137297000000.00 ┤││││││││││││││││││││││││││││││││││││││││││││││││││
+   13620478000.00 ┤││││││││││││││││││││││││││││││││││││││││││││││││││
+-1110055600000.00 ┤││││││││││││││││││││││││││││││││││││││││││││││││││
+-2233731600000.00 ┤││││││││││││││││││││││││││││││││││││││││││││││││││
+-3357408800000.00 ┤││││││││││││││││││││││││││││││││││││││││││││││││││
+-4481085000000.00 ┤││││││││││││││││││││││││││││││││││││││││││││││││││
+-5604761000000.00 ┤││││││││││││││││││││││││││││││││││││││││││││││││││
+-6728438000000.00 ┤││││││││││││││││││││││││││││││││││││││││││││││││││
+-7852114000000.00 ┤││││││││││││││││││││││││││││││││││││││││││││││││││
+-8975790000000.00 ┼╯╰╯╰╯╰╯╰╯╰╯╰╯╰╯╰╯╰╯╰╯╰╯╰╯╰╯╰╯╰╯╰╯╰╯╰╯╰╯╰╯╰╯╰╯╰╯╰╯╰
+|]
+
+btcChart :: [Float]
+btcChart =
+    [2591.22,2720.08,2723.58,3255,3445.28,4382.74,4159.46,4137.67           ] ++
+    [4387.46,4630.73,4631.69,4638.1,4188.84,3686.9,3897,3777.29,4208.56     ] ++
+    [4394.64,4322.75,4772.97,5640.13,5595.23,6013.23,5733.9,6140.53,7030    ] ++
+    [6958.21,6570.31,6598.77,7776.94,8230.69,9326.59,9916.54,11616.85       ] ++
+    [16057.14,17178.1,19343.04,16454.72,13975.44,14428.76,13412.44,16937.17 ] ++
+    [14439.47,14188.78,11141.25,11522.86,11137.24,11158.39,8827.63,7700.39  ] ++
+    [8556.61,9477.84,10396.63,9830.43,10313.08,11019.52,10709.53,8787.16    ] ++
+    [8196.9,8196.02,8712.89,8138.34,6844.32,7417.89,6896.28,6939.55,8357.04 ] ++
+    [8273.74,8938.3,8978.33                                                 ]
+
+test4 :: IO ()
+test4 = plot $ round <$> btcChart
+
+test4Output :: String
+test4Output = tail [r|
+19343.00 ┤                                   ╭╮
+18146.43 ┤                                   ││
+16949.86 ┤                                  ╭╯╰╮  ╭╮
+15753.28 ┤                                 ╭╯  │  ││
+14556.72 ┤                                 │   ╰─╮│╰─╮
+13360.14 ┤                                 │     ╰╯  │
+12163.57 ┤                                ╭╯         │╭╮
+10967.00 ┤                                │          ╰╯╰─╮   ╭╮╭──╮
+ 9770.43 ┤                              ╭─╯              │  ╭╯╰╯  │           ╭
+ 8573.86 ┤                             ╭╯                ╰╮╭╯     ╰────╮   ╭──╯
+ 7377.29 ┤                        ╭─╮╭─╯                  ╰╯           ╰───╯
+ 6180.71 ┤                   ╭────╯ ╰╯
+ 4984.14 ┤    ╭╮ ╭────╮  ╭───╯
+ 3787.57 ┤  ╭─╯╰─╯    ╰──╯
+ 2591.00 ┼──╯
+|]
+
+check :: IO a -> String -> IO ()
+check test out = do
+    (output, _) <- capture test
+    output `shouldBe` out
+
+main :: IO ()
+main = hspec $ do
+
+    describe "Test 0" $
+      it "{height = 5} ([1..6] ++ [6,5..1])" $
+        check test0 test0Output
+
+    describe "Test 1" $
+      it "{height = 8} sin wave" $
+        check test1 test1Output
+
+    describe "Test 2" $
+      it "{height = 2} mini cos wave" $
+        check test2 test2Output
+
+    describe "Test 3" $
+      it "very large numbers" $
+        check test3 test3Output
+
+    describe "Test 4" $
+      it "bitcoin chart" $
+        check test4 test4Output
+
+    describe "Test 5" $
+      it "500 random charts" $
+      forM_ [1..500] . const $ do
+        randLen <- randomRIO (2, 140)
+        plot =<< randomList randLen
