diff --git a/.codeclimate.yml b/.codeclimate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..62b61057e8914c1b737cff0b15dae5c4750f8795
--- /dev/null
+++ b/.codeclimate.yml
@@ -0,0 +1,33 @@
+engines:
+  duplication:
+    enabled: true
+    config:
+      languages:
+        python:
+
+  fixme:
+    enabled: true
+  markdownlint:
+    enabled: true
+  pep8:
+    enabled: true
+exclude_paths:
+  - tests/**
+  - setup.py
+ratings:
+  paths:
+    - flask_minijson.py
+checks:
+  argument-count:
+    config:
+      threshold: 15
+  method-complexity:
+    config:
+      threshold: 50
+  method-count:
+    config:
+      threshold: 85
+  file-lines:
+    enabled: true
+    config:
+      threshold: 700
diff --git a/.coveragerc b/.coveragerc
new file mode 100644
index 0000000000000000000000000000000000000000..c9f2f50eae8000b5249e50b5a7d183e792bdf430
--- /dev/null
+++ b/.coveragerc
@@ -0,0 +1,8 @@
+[run]
+branch=1
+source=
+    rapid_minijson
+
+[report]
+exclude_lines=
+    pragma: no cover
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f999d70488e33bd38883bbee160632136629a394
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,53 @@
+language: python
+stages:
+  - name: test
+
+cache: pip
+before_script:
+  - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
+  - chmod +x ./cc-test-reporter
+  - ./cc-test-reporter before-build
+  - pip install -r requirements.txt
+  - pip install -U pytest-xdist pytest-cov pytest pytest-forked pluggy py
+  - python setup.py install
+jobs:
+  include:
+    - stage: test
+      python: "3.5"
+      script:
+        - pytest -n 8 --cov=flask_minijson
+      after_script:
+        - coverage xml
+        - ./cc-test-reporter after-build -t coverage.py --exit-code $TRAVIS_TEST_RESULT
+    - stage: test
+      python: "3.6"
+      script:
+        - pytest -n 8 --cov=flask_minijson
+      after_script:
+        - coverage xml
+        - ./cc-test-reporter after-build -t coverage.py --exit-code $TRAVIS_TEST_RESULT
+    - stage: test
+      python: "3.7"
+      script:
+        - pytest -n 8 --cov=flask_minijson
+      after_script:
+        - coverage xml
+        - ./cc-test-reporter after-build -t coverage.py --exit-code $TRAVIS_TEST_RESULT
+    - stage: test
+      python: "3.8"
+      script:
+        - pytest -n 8 --cov=flask_minijson
+      after_script:
+        - coverage xml
+        - ./cc-test-reporter after-build -t coverage.py --exit-code $TRAVIS_TEST_RESULT
+    - stage: test
+      python: "3.9"
+      script:
+        - pytest -n 8 --cov=flask_minijson
+      after_script:
+        - coverage xml
+        - ./cc-test-reporter after-build -t coverage.py --exit-code $TRAVIS_TEST_RESULT
+    - stage: test
+      python: "pypy3.5"
+      script:
+        - pytest -n 8
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000000000000000000000000000000000000..f9bd1455b374de796e12d240c1211dee9829d97e
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1 @@
+include requirements.txt
diff --git a/README.md b/README.md
index 370b2b4bead26024d3f7bc5b58b73e055c110ced..82ef322952cb29e793fc90a6b6ae0342cb726570 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,12 @@
 # flask-minijson
 An extension for Flask to allow clients to submit data using the application/minijson codec
+
+flask-json is required to be initialized before `FlaskMiniJSON`, in such a way:
+
+```python
+from flask_minijson import FlaskMiniJSON
+
+app = Flask(__name__)
+FlaskJSON(app)
+FlaskMiniJSON(app)
+```
diff --git a/flask_minijson.py b/flask_minijson.py
new file mode 100644
index 0000000000000000000000000000000000000000..5bdc93d411fb64d9d070ae4c9ddef97a8c45b2ae
--- /dev/null
+++ b/flask_minijson.py
@@ -0,0 +1,35 @@
+import typing as tp
+
+import minijson
+from flask import Flask
+from flask_json import JsonRequest
+
+
+class MiniJSONRequest(JsonRequest):
+    def get_json(self, force=False, silent=False, cache=True):
+        """
+        Return JSON data, if content type is application/minijson it will be loaded
+        via minijson, else it will be loaded the normal way.
+        """
+        if self.headers['Content-Type'] == 'application/minijson':
+            return minijson.loads(self.get_data())
+        else:
+            return super().get_json(force, silent, cache)
+
+
+class FlaskMiniJSON(object):
+    """Flask-MiniJSON extension class."""
+    def __init__(self, app: tp.Optional[Flask] = None):
+        self._app = app
+        self._error_handler_func = None
+        self._decoder_error_func = None
+        if app is not None:
+            self.init_app(app)
+
+    def init_app(self, app: Flask):
+        if 'json' not in app.extensions:
+            raise RuntimeError('flask-json must be initialized before MiniJSON!')
+        app.extensions['minijson'] = self
+
+        self._app = app
+        app.request_class = MiniJSONRequest
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..cf312031d81c1289f8b2108817f52e80ccd9e770
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,3 @@
+flask
+flask-json
+minijson
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..349e4946142e2aa8a630af798abb34c4c331120a
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,41 @@
+# coding: utf-8
+[metadata]
+version = 2.5a1
+name = flask-minijson
+long_description = file: README.md
+long_description_content_type = text/markdown; charset=UTF-8
+author = Piotr Maślanka
+license_files =
+    LICENSE
+author_email = piotr.maslanka@dronehub.ai
+description = A Flask extension to allow client's to submit data using the MiniJSON codec
+url = https://github.com/Dronehub/flask-minijson
+project_urls =
+	Code = https://github.com/Dronehub/flask-minijson
+	Issue tracker = https://github.com/Dronehub/flask-minijson/issues
+classifier =
+    Development Status :: 4 - Beta
+    Programming Language :: Python
+    Programming Language :: Python :: 3.5
+    Programming Language :: Python :: 3.6
+    Programming Language :: Python :: 3.7
+    Programming Language :: Python :: 3.8
+    Programming Language :: Python :: 3.9
+    Programming Language :: Python :: Implementation :: CPython
+    Programming Language :: Python :: Implementation :: PyPy
+    Operating System :: OS Independent
+    License :: OSI Approved :: MIT License
+    Topic :: Software Development :: Libraries
+
+[pycodestyle]
+max-line-length = 100
+
+[pep8]
+max-line-length = 100
+
+[bdist_wheel]
+universal = 0
+
+[options]
+python_requires = !=2.7.*,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*
+py_modules = flask_minijson
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000000000000000000000000000000000000..606849326a4002007fd42060b51e69a19c18675c
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,3 @@
+from setuptools import setup
+
+setup()
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tests/app.py b/tests/app.py
new file mode 100644
index 0000000000000000000000000000000000000000..4ca3ceb9aead517a68de1bce2b37f843b54ddfce
--- /dev/null
+++ b/tests/app.py
@@ -0,0 +1,19 @@
+from flask import Flask, request
+from flask_json import FlaskJSON, as_json
+from flask_minijson import FlaskMiniJSON
+
+app = Flask(__name__)
+FlaskJSON(app)
+FlaskMiniJSON(app)
+
+app.config['DEBUG'] = True
+app.config['TESTING'] = True
+
+
+@app.route('/v1', methods=['POST'])
+@as_json
+def example_point():
+    if request.get_json() == {'1': '2'}:
+        return {'status': 'ok'},
+    else:
+        return {'status': 'fail'}
diff --git a/tests/test_minijson.py b/tests/test_minijson.py
new file mode 100644
index 0000000000000000000000000000000000000000..bdbfe4ffdc8f759585a63b5fabce0ec5104d0813
--- /dev/null
+++ b/tests/test_minijson.py
@@ -0,0 +1,17 @@
+import unittest
+
+import minijson
+
+from tests.app import app
+
+
+class TestMiniJSON(unittest.TestCase):
+    def setUp(self):
+        self.client = app.test_client()
+
+    def test_minijson(self):
+        data = minijson.dumps({'1': '2'})
+        resp = self.client.post('/v1', data=data, headers={'Content-Type': 'application/minijson'})
+        self.assertEqual(resp.get_json(), {'status': 'ok'})
+        resp = self.client.post('/v1', json={'1': '3'})
+        self.assertEqual(resp.get_json(), {'status': 'fail'})