diff --git a/.coveragerc b/.coveragerc
index ca6673d7ceb288638ddfa315e48e32b8ab89f316..487f1adf655e3cc9f794178f300d0f21a7b3edcf 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -1,2 +1,2 @@
 [run]
-include = djangobower*
+include = django_yarnpkg*
diff --git a/.covio.yml b/.covio.yml
deleted file mode 100644
index 2dacb0ce732aeb226f72a33830dbbb9b2d174a80..0000000000000000000000000000000000000000
--- a/.covio.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-violations:
-  pep8: pep8 . --exclude='*migrations*,*settings*,*components*,*docs*'
-  sloccount: sloccount .
-  py_unittest: cat test_out
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index d23a42728d7a9b726e534eb59e18fcec1f35f855..72e99a6ce9245f8809188e1c1475664ea5e46168 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,3 +1,8 @@
+Version 6.0  (2019-12-07)
+=====================================================
+
+* Fork and port to yarnpkg
+
 Version 4.8  (2013-10-02)
 =====================================================
 
diff --git a/README.rst b/README.rst
index 72f4e5c05a8b530e51d5a1ed7ec7fa3ccd25373f..887b69b752ef4901f7998cdda32310d5870e4823 100644
--- a/README.rst
+++ b/README.rst
@@ -1,76 +1,65 @@
-Django-bower
-============
+Django-yarnpkg
+==============
 
-.. image:: https://travis-ci.org/nvbn/django-bower.png
-   :alt: Build Status
-   :target: https://travis-ci.org/nvbn/django-bower
-.. image:: https://coveralls.io/repos/nvbn/django-bower/badge.png?branch=develop
-   :alt: Coverage Status
-   :target: https://coveralls.io/r/nvbn/django-bower
-.. image:: https://pypip.in/v/django-bower/badge.png
-   :target: https://crate.io/packages/django-bower/
-.. image:: https://pypip.in/d/django-bower/badge.png
-   :target: https://crate.io/packages/django-bower/
+Easy way to use `yarnpkg <http://yarnpkg.com/>`_ with your `Django <https://www.djangoproject.com/>`_ project.
 
-Easy way to use `bower <http://bower.io/>`_ with your `Django <https://www.djangoproject.com/>`_ project.
+This is a fork of `django-bower <https://github.com/nvbn/django-bower>` by Vladimir Iakovlev.
 
-Bower is a package manager for the web. It offers a generic, unopinionated solution to the problem of front-end package management, while exposing the package dependency model via an API that can be consumed by a more opinionated build stack. There are no system wide dependencies, no dependencies are shared between different apps, and the dependency tree is flat.
-
-Read full documentation on `read-the-docs <https://django-bower.readthedocs.io/en/latest/>`_.
+Read full documentation on `read-the-docs <https://django-yarnpkg.readthedocs.io/en/latest/>`_.
 
 Installation
 ------------
 
-Install django-bower package:
+Install django-yarnpkg package:
 
 .. code-block:: bash
 
-    pip install django-bower
+    pip install django-yarnpkg
 
 Add django-bower to `INSTALLED_APPS` in your settings:
 
 .. code-block:: python
 
-    'djangobower',
+    'django_yarnpkg',
 
 Add staticfinder to `STATICFILES_FINDERS`:
 
 .. code-block:: python
 
-    'djangobower.finders.BowerFinder',
+    'django_yarnpkg.finders.NodeModulesFinder',
 
 Specify path to components root (you need to use an absolute path):
 
 .. code-block:: python
 
-    BOWER_COMPONENTS_ROOT = '/PROJECT_ROOT/components/'
+    NODE_MODULES_ROOT = os.path.join(BASE_DIR, 'node_modules')
 
 
-If you need, you can manually set the path to bower:
+If you need, you can manually set the path to yarnpkg:
 
 .. code-block:: python
 
-    BOWER_PATH = '/usr/bin/bower'
+    YARN_PATH = '/usr/bin/yarnpkg'
 
-You can see an example settings file in `example project <https://github.com/nvbn/django-bower/blob/master/example/example/settings.py>`_.
+You can see an example settings file in `example project <https://github.com/Natureshadow/django-yarnpkg/blob/master/example/example/settings.py>`_.
 
 Usage
 -----
 
-Specify `BOWER_INSTALLED_APPS` in settings, like:
+Specify `YARN_INSTALLED_APPS` in settings, like:
 
 .. code-block:: python
 
-    BOWER_INSTALLED_APPS = (
-        'jquery#1.9',
-        'underscore',
+    YARN_INSTALLED_APPS = (
+        'bootstrap@^4.4.1',
+        'underscore@^1.6.1',
     )
 
-Download bower packages with the management command:
+Download yarn packages with the management command:
 
 .. code-block:: bash
 
-    ./manage.py bower install
+    ./manage.py yarn install
 
 Add scripts in the template, like:
 
@@ -79,32 +68,26 @@ Add scripts in the template, like:
     {% load static %}
     <script type="text/javascript" src='{% static 'jquery/dist/jquery.js' %}'></script>
 
-In production you need to call `bower install` before `collectstatic`:
+In production you need to call `yarnpkg install` before `collectstatic`:
 
 .. code-block:: bash
 
-    ./manage.py bower install
+    ./manage.py yarn install
     ./manage.py collectstatic
 
-If you need to pass arguments to bower, like `--allow-root`, use:
-
-.. code-block:: bash
-
-    ./manage.py bower install -- --allow-root
-
-You can use `bower freeze` to receive `BOWER_INSTALLED_APPS` with fixed current versions:
+If you need to pass arguments to yarnpkg, like `--flat`, use:
 
 .. code-block:: bash
 
-    ./manage.py bower freeze
+    ./manage.py yarn install -- --flat
 
-You can call bower commands like `info` and `update` with:
+You can call yarnpkg commands like `info` and `update` with:
 
 .. code-block:: bash
 
-    ./manage.py bower info backbone
-    ./manage.py bower update
+    ./manage.py yarn info backbone
+    ./manage.py yarn update
 
 Python 3 support
 ----------------
-django-bower supports python 3.3+
+django-yarnpkg supports python 3.3+
diff --git a/djangobower/__init__.py b/django_yarnpkg/__init__.py
similarity index 100%
rename from djangobower/__init__.py
rename to django_yarnpkg/__init__.py
diff --git a/django_yarnpkg/conf.py b/django_yarnpkg/conf.py
new file mode 100644
index 0000000000000000000000000000000000000000..c4ea1701b4b0e1399bd3cce0b5bdad05c4528f1a
--- /dev/null
+++ b/django_yarnpkg/conf.py
@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*-
+from distutils.spawn import find_executable
+import os
+import sys
+from django.conf import settings
+
+__all__ = ['NODE_MODULES_ROOT', 'YARN_PATH']
+
+NODE_MODULES_ROOT = getattr(settings, 'NODE_MODULES_ROOT', os.path.abspath(os.path.dirname(__name__)))
+
+default_yarn_path = find_executable('yarn') or find_executable('yarnpkg')
+
+YARN_PATH = getattr(settings, 'YARN_PATH', default_yarn_path)
diff --git a/django_yarnpkg/context_processors.py b/django_yarnpkg/context_processors.py
new file mode 100644
index 0000000000000000000000000000000000000000..2b3fad5f64e92bf94d8b39fb816ad0a8a03bfc0c
--- /dev/null
+++ b/django_yarnpkg/context_processors.py
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+import os.path
+import json
+import six
+from django.conf import settings
+from django.utils.datastructures import OrderedSet
+
+
+def read_files():
+    for component in settings.YARN_INSTALLED_APPS:
+        component = component.split('#')[0]
+        try:
+            with open(os.path.join(
+                    settings.NODE_MODULES_ROOT,
+                    'node_modules',
+                    component,
+                    'package.json')) as package_json:
+                files = json.load(bower_json).get('files')
+                for f in files:
+                    yield '%s/%s' % (component, f)
+        except FileNotFoundError:
+            continue
+
+
+def node_modules(request):
+    return {
+        'node_modules': OrderedSet([f for f in read_files()]),
+    }
diff --git a/django_yarnpkg/exceptions.py b/django_yarnpkg/exceptions.py
new file mode 100644
index 0000000000000000000000000000000000000000..fd507a1183848323dfda71665e6982414d942446
--- /dev/null
+++ b/django_yarnpkg/exceptions.py
@@ -0,0 +1,10 @@
+from django.core.management.base import CommandError
+
+
+class YarnNotInstalled(CommandError):
+    """Custom command error"""
+
+    def __init__(self):
+        super(YarnNotInstalled, self).__init__(
+            "Yarn not installed, read instruction here - http://yarnpkg.com/",
+        )
diff --git a/djangobower/finders.py b/django_yarnpkg/finders.py
similarity index 52%
rename from djangobower/finders.py
rename to django_yarnpkg/finders.py
index 746cb6db6ad5e5a013315b448860536fd1a1a470..b3f8ff327f2b5979839f9b01e3a4faf6385dc3af 100644
--- a/djangobower/finders.py
+++ b/django_yarnpkg/finders.py
@@ -9,14 +9,14 @@ from . import conf
 import os
 
 
-class BowerFinder(FileSystemFinder):
-    """Find static files installed with bower"""
+class NodeModulesFinder(FileSystemFinder):
+    """Find static files installed with yarnpkg"""
 
     def __init__(self, apps=None, *args, **kwargs):
         self.locations = []
         self.storages = OrderedDict()
 
-        root = self._get_bower_components_location()
+        root = self._get_node_modules_location()
         if root is not None:
             prefix = ''
             self.locations.append((prefix, root))
@@ -25,13 +25,10 @@ class BowerFinder(FileSystemFinder):
             filesystem_storage.prefix = prefix
             self.storages[root] = filesystem_storage
 
-    def _get_bower_components_location(self):
+    def _get_node_modules_location(self):
         """
-        Return the bower components location, or None if one does not exist.
+        Return the node modules location, or None if one does not exist.
         """
-        # Bower 0.10 changed the default folder from 'components' to 'bower_components'.
-        # Try 'bower_components' first, then fall back to trying 'components'.
-        for name in ['bower_components', 'components']:
-            path = os.path.join(conf.COMPONENTS_ROOT, name)
-            if os.path.exists(path):
-                return path
+        path = os.path.join(conf.NODE_MODULES_ROOT, 'node_modules')
+        if os.path.exists(path):
+            return path
diff --git a/djangobower/management/__init__.py b/django_yarnpkg/management/__init__.py
similarity index 100%
rename from djangobower/management/__init__.py
rename to django_yarnpkg/management/__init__.py
diff --git a/django_yarnpkg/management/base.py b/django_yarnpkg/management/base.py
new file mode 100644
index 0000000000000000000000000000000000000000..f6b7dd1d24fa9dcc31dd667059641dbf91a10533
--- /dev/null
+++ b/django_yarnpkg/management/base.py
@@ -0,0 +1,27 @@
+from pprint import pformat
+from django.core.management.base import BaseCommand
+from django.conf import settings
+from ..yarn import yarn_adapter
+from ..exceptions import YarnNotInstalled
+
+
+class BaseYarnCommand(BaseCommand):
+    """Base management command with yarn support"""
+
+    requires_system_checks = False
+
+    # add fake .options_list for Django>=1.10
+    if not hasattr(BaseCommand, 'option_list'):
+        option_list = ()
+
+    def handle(self, *args, **options):
+        self._check_yarn_exists()
+        yarn_adapter.create_node_modules_root()
+
+    def _check_yarn_exists(self):
+        """Check yarn exists or raise exception"""
+        if not yarn_adapter.is_yarn_exists():
+            raise YarnNotInstalled()
+
+    def _install(self, args):
+        yarn_adapter.install(settings.YARN_INSTALLED_APPS, *args)
diff --git a/djangobower/management/commands/__init__.py b/django_yarnpkg/management/commands/__init__.py
similarity index 100%
rename from djangobower/management/commands/__init__.py
rename to django_yarnpkg/management/commands/__init__.py
diff --git a/djangobower/management/commands/bower.py b/django_yarnpkg/management/commands/yarn.py
similarity index 56%
rename from djangobower/management/commands/bower.py
rename to django_yarnpkg/management/commands/yarn.py
index b8779e99664049a27b5cdbbbd69f0addb4f8c581..5ea03c06ce0b14a53de7eb52ad47ab242b083c53 100644
--- a/djangobower/management/commands/bower.py
+++ b/django_yarnpkg/management/commands/yarn.py
@@ -1,13 +1,12 @@
-from ...bower import bower_adapter
-from ..base import BaseBowerCommand
+from ...yarn import yarn_adapter
+from ..base import BaseYarnCommand
 
 
-class Command(BaseBowerCommand):
+class Command(BaseYarnCommand):
     args = 'command'
-    help = 'Call bower in components root ({0}).'.format(
-        bower_adapter._components_root)
+    help = 'Call yarn in node modules root ({0}).'.format(
+        yarn_adapter._node_modules_root)
 
-    # for Django>=1.10
     def add_arguments(self, parser):
         parser.add_argument('command', nargs='*')
 
@@ -16,10 +15,8 @@ class Command(BaseBowerCommand):
         args = args or tuple(options.pop('command'))
         if self._is_single_command('install', args):
             self._install([])
-        elif self._is_single_command('freeze', args):
-            self._freeze()
         else:
-            bower_adapter.call_bower(args)
+            yarn_adapter.call_bower(args)
 
     def _is_single_command(self, name, args):
         return len(args) == 1 and args[0] == name
diff --git a/django_yarnpkg/management/commands/yarn_install.py b/django_yarnpkg/management/commands/yarn_install.py
new file mode 100644
index 0000000000000000000000000000000000000000..807eac47c6e1b7d12d36b10807d9d92160452209
--- /dev/null
+++ b/django_yarnpkg/management/commands/yarn_install.py
@@ -0,0 +1,10 @@
+from optparse import make_option
+from ..base import BaseYarnCommand
+
+
+class Command(BaseYarnCommand):
+    help = 'Install yarn apps'
+
+    def handle(self, *args, **options):
+        super(Command, self).handle(*args, **options)
+        self._install(args)
diff --git a/djangobower/models.py b/django_yarnpkg/models.py
similarity index 100%
rename from djangobower/models.py
rename to django_yarnpkg/models.py
diff --git a/django_yarnpkg/shortcuts.py b/django_yarnpkg/shortcuts.py
new file mode 100644
index 0000000000000000000000000000000000000000..1effce50fc43808439815c466df930846894d0d4
--- /dev/null
+++ b/django_yarnpkg/shortcuts.py
@@ -0,0 +1,9 @@
+import os, sys
+
+
+def is_executable(path):
+    """Check file is executable"""
+    if sys.platform == 'win32':
+        executable = os.access(path, os.X_OK) or path.lower().endswith(".cmd")
+        return os.path.isfile(path) and executable
+    return os.path.isfile(path) and os.access(path, os.X_OK)
diff --git a/djangobower/templatetags/__init__.py b/django_yarnpkg/templatetags/__init__.py
similarity index 100%
rename from djangobower/templatetags/__init__.py
rename to django_yarnpkg/templatetags/__init__.py
diff --git a/djangobower/templatetags/bower.py b/django_yarnpkg/templatetags/yarn.py
similarity index 80%
rename from djangobower/templatetags/bower.py
rename to django_yarnpkg/templatetags/yarn.py
index 6387e8882566ad55bc59c121cf442df9db1b580f..784717c1778aa0f0827632e093ea974f27ff260f 100644
--- a/djangobower/templatetags/bower.py
+++ b/django_yarnpkg/templatetags/yarn.py
@@ -24,13 +24,13 @@ script_template = template.Template(
 
 def tags(context, args, type):
     components = (
-        [arg for arg in args if arg in context['bower_components']]
-        if args else context['bower_components']
+        [arg for arg in args if arg in context['node_modules']]
+        if args else context['node_modules']
     )
     files = []
     for component in components:
         files.append(component)
-        context['bower_components'].remove(component)
+        context['node_modules'].remove(component)
     return {'files': [
         static.static(f)
         for f in files
@@ -39,10 +39,10 @@ def tags(context, args, type):
 
 
 @register.inclusion_tag(style_template, takes_context=True)
-def bower_styles(context, *args):
+def yarn_styles(context, *args):
     return tags(context, args, 'css')
 
 
 @register.inclusion_tag(script_template, takes_context=True)
-def bower_scripts(context, *args):
+def yarn_scripts(context, *args):
     return tags(context, args, 'js')
diff --git a/djangobower/test_settings.py b/django_yarnpkg/test_settings.py
similarity index 66%
rename from djangobower/test_settings.py
rename to django_yarnpkg/test_settings.py
index f932db5db3620544c176fe0cbb1c3a8fa9320d33..ca462cf2f7ecf26c84165c443c57e97e014f626f 100644
--- a/djangobower/test_settings.py
+++ b/django_yarnpkg/test_settings.py
@@ -8,21 +8,21 @@ TEST_PROJECT_ROOT = os.path.abspath(
 
 BASE_DIR = TEST_PROJECT_ROOT
 
-BOWER_COMPONENTS_ROOT = os.path.join(TEST_PROJECT_ROOT, 'bower_components')
+NODE_MODULES_ROOT = os.path.join(TEST_PROJECT_ROOT, 'node_modules')
 
-STATIC_ROOT = os.path.join(TEST_PROJECT_ROOT, 'bower_static')
+STATIC_ROOT = os.path.join(TEST_PROJECT_ROOT, 'yarnpkg_static')
 
 STATIC_URL = '/static/'
 
-BOWER_INSTALLED_APPS = (
+YARN_INSTALLED_APPS = (
     'jquery#1.9',
     'underscore',
 )
 
-SECRET_KEY = 'iamdjangobower'
+SECRET_KEY = 'iamdjangoyarnpkg'
 
 INSTALLED_APPS = (
-    'djangobower',
+    'django_yarnpkg',
 )
 
 DATABASES = {
diff --git a/djangobower/tests/__init__.py b/django_yarnpkg/tests/__init__.py
similarity index 100%
rename from djangobower/tests/__init__.py
rename to django_yarnpkg/tests/__init__.py
diff --git a/djangobower/tests/base.py b/django_yarnpkg/tests/base.py
similarity index 50%
rename from djangobower/tests/base.py
rename to django_yarnpkg/tests/base.py
index ca61152b33af9c699347b9c415d042dbc85a91df..b8e82a6faacc3ef72ab28c9c21aaf9f71da3c35f 100644
--- a/djangobower/tests/base.py
+++ b/django_yarnpkg/tests/base.py
@@ -1,37 +1,37 @@
 from django.conf import settings
 from django.test import TestCase
 from django.test.utils import override_settings
-from ..bower import bower_adapter
+from ..yarn import yarn_adapter
 import os
 import shutil
 
 
 try:
-    TEST_COMPONENTS_ROOT = os.path.join(
-        settings.TEST_PROJECT_ROOT, 'bower_components',
+    TEST_NODE_MODULES_ROOT = os.path.join(
+        settings.TEST_PROJECT_ROOT, 'node_modules',
     )
 except AttributeError:
-    TEST_COMPONENTS_ROOT = '/tmp/bower_components/'
+    TEST_NODE_MODULES_ROOT = '/tmp/node_modules/'
 
 
-@override_settings(BOWER_COMPONENTS_ROOT=TEST_COMPONENTS_ROOT)
-class BaseBowerCase(TestCase):
+@override_settings(NODE_MODULES_ROOT=TEST_NODE_MODULES_ROOT)
+class BaseYarnCase(TestCase):
     """Base bower test case"""
 
     def setUp(self):
-        bower_adapter.create_components_root()
+        yarn_adapter.create_node_modules_root()
 
     def tearDown(self):
-        self._remove_components_root()
+        self._remove_node_modules_root()
 
     def _remove_components_root(self):
         """Remove components root if exists"""
-        if os.path.exists(TEST_COMPONENTS_ROOT):
-            shutil.rmtree(TEST_COMPONENTS_ROOT)
+        if os.path.exists(TEST_NODE_MODULES_ROOT):
+            shutil.rmtree(TEST_NODE_MODULES_ROOT)
 
     def assertCountEqual(self, *args, **kwargs):
         """Add python 2 support"""
         if hasattr(self, 'assertItemsEqual'):
             return self.assertItemsEqual(*args, **kwargs)
         else:
-            return super(BaseBowerCase, self).assertCountEqual(*args, **kwargs)
+            return super(BaseYarnCase, self).assertCountEqual(*args, **kwargs)
diff --git a/djangobower/tests/test_finders.py b/django_yarnpkg/tests/test_finders.py
similarity index 62%
rename from djangobower/tests/test_finders.py
rename to django_yarnpkg/tests/test_finders.py
index 648829b78d2decb451b3347ececebd92cce5ac91..53378a5c2333641abff2bcf00e15f2fcfa1f8d03 100644
--- a/djangobower/tests/test_finders.py
+++ b/django_yarnpkg/tests/test_finders.py
@@ -1,10 +1,10 @@
 from django.core.files.storage import FileSystemStorage
 from django.test import TestCase
 
-from ..bower import bower_adapter
-from ..finders import BowerFinder
+from ..yarn import yarn_adapter
+from ..finders import NodeModulesFinder
 from .. import conf
-from .base import BaseBowerCase
+from .base import BaseYarnCase
 import os
 import os.path
 import shutil
@@ -33,26 +33,26 @@ class _MakeDirsTestCase(TestCase):
         self.created.append(name)
 
 
-class SimpleBowerFinderCase(_MakeDirsTestCase):
+class SimpleNodeModulesFinderCase(_MakeDirsTestCase):
     """
-    Simple BowerFinder tests, without any packages installed.
+    Simple YarnFinder tests, without any packages installed.
     """
 
     def test_list_nonexistent(self):
         """
-        When no Bower folder exists, just gracefully find nothing.
+        When no Yarn folder exists, just gracefully find nothing.
         """
-        finder = BowerFinder()
+        finder = NodeModulesFinder()
         self.assertEqual(finder.locations, [])
         self.assertEqual(finder.storages, {})
 
-    def test_list_existent(self, leaf_name='bower_components'):
+    def test_list_existent(self, leaf_name='node_modules'):
         """
-        If 'bower_components' exists, use it to to find files.
+        If 'node_modules' exists, use it to to find files.
         """
-        root = os.path.join(conf.COMPONENTS_ROOT, leaf_name)
+        root = os.path.join(conf.NODE_MODULES_ROOT, leaf_name)
         self.makedirs(root)
-        finder = BowerFinder()
+        finder = NodeModulesFinder()
 
         self.assertEqual(finder.locations, [('', root)])
 
@@ -64,32 +64,32 @@ class SimpleBowerFinderCase(_MakeDirsTestCase):
 
     def test_list_old_path(self):
         """
-        If only the old 'components' folder exists, use it instead.
+        If only the old 'node_modules' folder exists, use it instead.
         """
-        self.test_list_existent(leaf_name='components')
+        self.test_list_existent(leaf_name='node_modules')
 
     def test_list_both(self):
         """
-        If both folders exist, only 'bower_components' should be used.
+        If both folders exist, only 'yarn_node_modules' should be used.
         """
-        self.makedirs(os.path.join(conf.COMPONENTS_ROOT, 'components'))
-        self.test_list_existent(leaf_name='bower_components')
+        self.makedirs(os.path.join(conf.NODE_MODULES_ROOT, 'node_modules'))
+        self.test_list_existent(leaf_name='node_modules')
 
 
-class BowerFinderCase(BaseBowerCase):
-    """Test finding installed with bower files"""
+class NodeModulesFinderCase(BaseYarnCase):
+    """Test finding installed with yarn files"""
 
     def setUp(self):
-        super(BowerFinderCase, self).setUp()
-        bower_adapter.install(['jquery#1.9'])
-        self.finder = BowerFinder()
+        super(NodeModulesFinderCase, self).setUp()
+        yarn_adapter.install(['jquery@1.9'])
+        self.finder = NodeModulesFinder()
 
     def test_find(self):
         """Test staticfinder find"""
         test_path = os.path.join('jquery', 'jquery.min.js')
         path = self.finder.find(test_path)
         self.assertEqual(path, os.path.join(
-            conf.COMPONENTS_ROOT, 'bower_components', test_path,
+            conf.NODE_MODULES_ROOT, 'node_modules', test_path,
         ))
 
     def test_list(self):
diff --git a/django_yarnpkg/tests/test_yarn.py b/django_yarnpkg/tests/test_yarn.py
new file mode 100644
index 0000000000000000000000000000000000000000..44d404cfe7246fc1e53a2e19249c455804896ffa
--- /dev/null
+++ b/django_yarnpkg/tests/test_yarn.py
@@ -0,0 +1,129 @@
+from django.core.management import call_command
+from django.conf import settings
+from django.test import TestCase
+from six import StringIO
+from mock import MagicMock
+from ..yarn import yarn_adapter, YarnAdapter
+from .. import conf
+from .base import BaseYarnCase, TEST_NODE_MODULES_ROOT
+import os
+import shutil
+
+
+class YarnAdapterCase(TestCase):
+    """
+    YarnAdapter regression tests.
+    """
+
+    def test_create_node_modules_root_subdirs(self):
+        """
+        create_node_modules_root() creates missing intermediate directories.
+        """
+        if os.path.exists(TEST_NODE_MODULES_ROOT):
+            shutil.rmtree(TEST_NODE_MODULES_ROOT)
+
+        subdir = os.path.join(TEST_NODE_MODULES_ROOT, 'sub', 'dir')
+        adapter = YarnAdapter(conf.YARN_PATH, subdir)
+        adapter.create_node_modules_root()
+        self.assertTrue(os.path.exists(subdir))
+
+        shutil.rmtree(TEST_NODE_MODULES_ROOT)
+
+
+class YarnInstallCase(BaseYarnCase):
+    """Test case for yarn_install management command"""
+
+    def setUp(self):
+        super(YarnInstallCase, self).setUp()
+        self.apps = settings.YARN_INSTALLED_APPS
+        self._original_install = yarn_adapter.install
+        yarn_adapter.install = MagicMock()
+
+    def tearDown(self):
+        super(YarnInstallCase, self).tearDown()
+        yarn_adapter.install = self._original_install
+
+    def test_create_node_modules_root(self):
+        """Test create node_modules root"""
+        self._remove_node_modules_root()
+        call_command('yarn_install')
+
+        self.assertTrue(os.path.exists(TEST_NODE_MODULES_ROOT))
+
+    def test_install(self):
+        """Test install yarn packages"""
+        call_command('yarn_install')
+        yarn_adapter.install.assert_called_once_with(self.apps)
+
+
+class YarnExistsCase(BaseYarnCase):
+    """
+    Test yarn exists checker.
+    This case need yarn to be installed.
+    """
+
+    def setUp(self):
+        super(YarnExistsCase, self).setUp()
+        self._original_exists = yarn_adapter.is_yarn_exists
+
+    def tearDown(self):
+        super(YarnExistsCase, self).tearDown()
+        yarn_adapter.is_yarn_exists = self._original_exists
+
+    def test_if_exists(self):
+        """Test if yarn exists"""
+        self.assertTrue(yarn_adapter.is_yarn_exists())
+
+    def test_if_not_exists(self):
+        """Test if yarn not exists"""
+        adapter = YarnAdapter('/not/exists/path', TEST_NODE_MODULES_ROOT)
+        self.assertFalse(adapter.is_yarn_exists())
+
+    def _mock_exists_check(self):
+        """Make exists check return false"""
+        yarn_adapter.is_yarn_exists = MagicMock()
+        yarn_adapter.is_yarn_exists.return_value = False
+
+
+class YarnCommandCase(BaseYarnCase):
+    """Test case for ./manage.py yarn something command"""
+
+    def setUp(self):
+        super(YarnCommandCase, self).setUp()
+        self.apps = settings.YARN_INSTALLED_APPS
+        self._mock_yarn_adapter()
+
+    def _mock_yarn_adapter(self):
+        self._original_install = yarn_adapter.install
+        yarn_adapter.install = MagicMock()
+        self._orig_call = yarn_adapter.call_yarn
+        yarn_adapter.call_yarn = MagicMock()
+        self._orig_freeze = yarn_adapter.freeze
+        yarn_adapter.freeze = MagicMock()
+
+    def tearDown(self):
+        super(YarnCommandCase, self).tearDown()
+        yarn_adapter.install = self._original_install
+        yarn_adapter.call_yarn = self._orig_call
+        yarn_adapter.freeze = self._orig_freeze
+
+    def test_install_without_params(self):
+        """Test that yarn install without param identical
+        with yarn_install
+
+        """
+        call_command('yarn', 'install')
+        yarn_adapter.install.assert_called_once_with(
+            self.apps)
+
+    def test_install_with_params(self):
+        """Test yarn install <something>"""
+        call_command('yarn', 'install', 'jquery')
+        yarn_adapter.call_yarn.assert_called_once_with(
+            ('install', 'jquery'))
+
+    def test_call_to_yarn(self):
+        """Test simple call to yarn"""
+        call_command('yarn', 'update')
+        yarn_adapter.call_yarn.assert_called_once_with(
+            ('update',))
diff --git a/django_yarnpkg/yarn.py b/django_yarnpkg/yarn.py
new file mode 100644
index 0000000000000000000000000000000000000000..fa255471e27cdf1ae81a428dd37db76a2d1d500b
--- /dev/null
+++ b/django_yarnpkg/yarn.py
@@ -0,0 +1,58 @@
+from . import conf, shortcuts, exceptions
+from distutils.spawn import find_executable
+import os
+import subprocess
+import sys
+import json
+
+
+class YarnAdapter(object):
+    """Adapter for working with yarnpkg"""
+
+    def __init__(self, yarn_path, node_modules_root):
+        self._yarn_path = yarn_path
+        self._node_modules_root = node_modules_root
+
+    def is_yarn_exists(self):
+        """Check is bower exists"""
+        if shortcuts.is_executable(self._yarn_path)\
+                or find_executable(self._yarn_path):
+            return True
+        else:
+            return False
+
+    def create_node_modules_root(self):
+        """Create node modules root if need"""
+        if not os.path.exists(self._node_modules_root):
+            os.makedirs(self._node_modules_root)
+
+    def call_yarn(self, args):
+        """Call yarn with a list of args"""
+        proc = subprocess.Popen(
+            [self._yarn_path] + list(args),
+            cwd=self._node_modules_root)
+        proc.wait()
+
+    def install(self, packages, *options):
+        """Install packages from yarn"""
+        self.call_yarn(['add'] + list(options) + list(packages))
+
+    def _accumulate_dependencies(self, data):
+        """Accumulate dependencies"""
+        for name, version in data['dependencies'].items():
+            if version:
+                full_name = '{0}@{1}'.format(name, version)
+            else:
+                full_name = name
+
+            self._packages.append(full_name)
+            self._accumulate_dependencies(params)
+
+    def _parse_package_names(self, output):
+        """Get package names in yarn"""
+        data = json.loads(output)
+        self._packages = []
+        self._accumulate_dependencies(data)
+        return self._packages
+
+yarn_adapter = YarnAdapter(conf.YARN_PATH, conf.NODE_MODULES_ROOT)
diff --git a/djangobower/bower.py b/djangobower/bower.py
deleted file mode 100644
index 700554a7443862cdee40a0b9cc615b0e42ded637..0000000000000000000000000000000000000000
--- a/djangobower/bower.py
+++ /dev/null
@@ -1,80 +0,0 @@
-from . import conf, shortcuts, exceptions
-import os
-import subprocess
-import sys
-import json
-
-
-class BowerAdapter(object):
-    """Adapter for working with bower"""
-
-    def __init__(self, bower_path, components_root):
-        self._bower_path = bower_path
-        self._components_root = components_root
-
-    def is_bower_exists(self):
-        """Check is bower exists"""
-        if shortcuts.is_executable(self._bower_path)\
-                or shortcuts.which(self._bower_path):
-            return True
-        else:
-            return False
-
-    def create_components_root(self):
-        """Create components root if need"""
-        if not os.path.exists(self._components_root):
-            os.makedirs(self._components_root)
-
-    def call_bower(self, args):
-        """Call bower with a list of args"""
-        proc = subprocess.Popen(
-            [self._bower_path] + list(args),
-            cwd=self._components_root)
-        proc.wait()
-
-    def install(self, packages, *options):
-        """Install packages from bower"""
-        self.call_bower(['install'] + list(options) + list(packages))
-
-    def _accumulate_dependencies(self, data):
-        """Accumulate dependencies"""
-        for name, params in data['dependencies'].items():
-            meta = params.get('pkgMeta', {})
-            version = meta.get(
-                'version', meta.get('_resolution', {}).get('commit', ''),
-            )
-
-            if version:
-                full_name = '{0}#{1}'.format(name, version)
-            else:
-                full_name = name
-
-            self._packages.append(full_name)
-            self._accumulate_dependencies(params)
-
-    def _parse_package_names(self, output):
-        """Get package names in bower >= 1.0"""
-        data = json.loads(output)
-        self._packages = []
-        self._accumulate_dependencies(data)
-        return self._packages
-
-    def freeze(self):
-        """Yield packages with versions list"""
-        proc = subprocess.Popen(
-            [self._bower_path, 'list', '--json', '--offline', '--no-color'],
-            cwd=conf.COMPONENTS_ROOT,
-            stdout=subprocess.PIPE,
-        )
-        outs, errs = proc.communicate()
-        output = outs.decode(sys.getfilesystemencoding())
-
-        try:
-            packages = self._parse_package_names(output)
-        except ValueError:
-            raise exceptions.LegacyBowerVersionNotSupported()
-
-        return iter(set(packages))
-
-
-bower_adapter = BowerAdapter(conf.BOWER_PATH, conf.COMPONENTS_ROOT)
diff --git a/djangobower/conf.py b/djangobower/conf.py
deleted file mode 100644
index 40a9717100e19cf5b1b95f137b51021ceb55ef97..0000000000000000000000000000000000000000
--- a/djangobower/conf.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# -*- coding: utf-8 -*-
-import os
-import sys
-from django.conf import settings
-
-__all__ = ['COMPONENTS_ROOT', 'BOWER_PATH']
-
-COMPONENTS_ROOT = getattr(settings, 'BOWER_COMPONENTS_ROOT', os.path.abspath(os.path.dirname(__name__)))
-
-if sys.platform == 'win32':
-    default_bower_path = os.path.join(os.getenv("APPDATA"), 'npm', 'bower.cmd')
-else:
-    default_bower_path = 'bower'
-
-BOWER_PATH = getattr(settings, 'BOWER_PATH', default_bower_path)
diff --git a/djangobower/context_processors.py b/djangobower/context_processors.py
deleted file mode 100644
index 4bd7e47636bb8e2dec27f84984e56949a475e483..0000000000000000000000000000000000000000
--- a/djangobower/context_processors.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# -*- coding: utf-8 -*-
-import os.path
-import json
-import six
-from django.conf import settings
-from django.utils.datastructures import OrderedSet
-
-
-def read_mains():
-    for component in settings.BOWER_INSTALLED_APPS:
-        component = component.split('#')[0]
-        try:
-            with open(os.path.join(
-                    settings.BOWER_COMPONENTS_ROOT,
-                    'bower_components',
-                    component,
-                    'bower.json')) as bower_json:
-                main = json.load(bower_json).get('main')
-                if isinstance(main, six.string_types):
-                    yield '%s/%s' % (component, main)
-                elif isinstance(main, list):
-                    for m in main:
-                        yield '%s/%s' % (component, m)
-        except FileNotFoundError:
-            continue
-
-
-def bower_components(request):
-    return {
-        'bower_components': OrderedSet([main for main in read_mains()]),
-    }
diff --git a/djangobower/exceptions.py b/djangobower/exceptions.py
deleted file mode 100644
index f6d1e6087aac5d2a8ef4b5d63c9d6dcf89aedae4..0000000000000000000000000000000000000000
--- a/djangobower/exceptions.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from django.core.management.base import CommandError
-
-
-class BowerNotInstalled(CommandError):
-    """Custom command error"""
-
-    def __init__(self):
-        super(BowerNotInstalled, self).__init__(
-            "Bower not installed, read instruction here - http://bower.io/",
-        )
-
-
-class LegacyBowerVersionNotSupported(CommandError):
-    """Custom command error"""
-
-    def __init__(self):
-        super(LegacyBowerVersionNotSupported, self).__init__(
-            "Legacy bower versions not supported, please install bower 1.0+",
-        )
diff --git a/djangobower/management/base.py b/djangobower/management/base.py
deleted file mode 100644
index bac82337651efeef0b7617bbd205e71eec1c4637..0000000000000000000000000000000000000000
--- a/djangobower/management/base.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from pprint import pformat
-from django.core.management.base import BaseCommand
-from django.conf import settings
-from ..bower import bower_adapter
-from ..exceptions import BowerNotInstalled
-
-
-class BaseBowerCommand(BaseCommand):
-    """Base management command with bower support"""
-
-    requires_system_checks = False
-
-    # add fake .options_list for Django>=1.10
-    if not hasattr(BaseCommand, 'option_list'):
-        option_list = ()
-
-    def handle(self, *args, **options):
-        self._check_bower_exists()
-        bower_adapter.create_components_root()
-
-    def _check_bower_exists(self):
-        """Check bower exists or raise exception"""
-        if not bower_adapter.is_bower_exists():
-            raise BowerNotInstalled()
-
-    def _install(self, args):
-        bower_adapter.install(settings.BOWER_INSTALLED_APPS, *args)
-
-    def _freeze(self):
-        packages = list(bower_adapter.freeze())
-        packages.sort()
-        output = 'BOWER_INSTALLED_APPS = {0}'.format(
-            pformat(packages),
-        )
-        self.stdout.write(output)
diff --git a/djangobower/management/commands/bower_freeze.py b/djangobower/management/commands/bower_freeze.py
deleted file mode 100644
index ac89c7350d15163a0bb2ed04d98dd33389b6b085..0000000000000000000000000000000000000000
--- a/djangobower/management/commands/bower_freeze.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from ..base import BaseBowerCommand
-
-
-class Command(BaseBowerCommand):
-    help = 'Freeze bower apps'
-
-    def handle(self, *args, **options):
-        super(Command, self).handle(*args, **options)
-        self._freeze()
diff --git a/djangobower/management/commands/bower_install.py b/djangobower/management/commands/bower_install.py
deleted file mode 100644
index 816329824aec2f8eeb5803a87f37053605e9fab6..0000000000000000000000000000000000000000
--- a/djangobower/management/commands/bower_install.py
+++ /dev/null
@@ -1,45 +0,0 @@
-from optparse import make_option
-from ..base import BaseBowerCommand
-
-
-class Command(BaseBowerCommand):
-    help = 'Install bower apps'
-
-    # for Django<1.10
-    option_list = BaseBowerCommand.option_list + (
-        make_option('-F',
-                    action='store_true',
-                    dest='force',
-                    default=False,
-                    help='Force installation of latest package version on conflict'),
-        make_option('-R', '--allow-root',
-                    action='store_true',
-                    dest='allow-root',
-                    default=False,
-                    help='Allow installing bower packages even when user executing this script is root'),
-    )
-    # for Django>=1.10
-    def add_arguments(self, parser):
-        parser.add_argument('--force',
-                            '-F',
-                            action='store_true',
-                            dest='force',
-                            default=False,
-                            help='Force installation of latest package version on conflict')
-        parser.add_argument('--allow-root',
-                            '-R',
-                            action='store_true',
-                            dest='allow-root',
-                            default=False,
-                            help='Allow installing bower packages even when user executing this script is root')
-
-    def handle(self, *args, **options):
-        super(Command, self).handle(*args, **options)
-
-        if options.get('force'):
-            args = args + ("-F", )
-
-        if options.get('allow-root'):
-            args = args + ("--allow-root", )
-        
-        self._install(args)
diff --git a/djangobower/shortcuts.py b/djangobower/shortcuts.py
deleted file mode 100644
index f1bf112269403def3fafe54faef4bc775f60e643..0000000000000000000000000000000000000000
--- a/djangobower/shortcuts.py
+++ /dev/null
@@ -1,28 +0,0 @@
-import os, sys
-
-
-def is_executable(path):
-    """Check file is executable"""
-    if sys.platform == 'win32':
-        executable = os.access(path, os.X_OK) or path.lower().endswith(".cmd")
-        return os.path.isfile(path) and executable
-    return os.path.isfile(path) and os.access(path, os.X_OK)
-
-
-def which(program):
-    """
-    Find by path and check exists.
-    Analog of unix `which` command.
-    """
-    path, name = os.path.split(program)
-    if path:
-        if is_executable(program):
-            return program
-    else:
-        for path in os.environ["PATH"].split(os.pathsep):
-            path = path.strip('"')
-            exe_file = os.path.join(path, program)
-            if is_executable(exe_file):
-                return exe_file
-
-    return None
diff --git a/djangobower/tests/test_bower.py b/djangobower/tests/test_bower.py
deleted file mode 100644
index 75ee91064419ccabd050bf3d829ed2cb648094f7..0000000000000000000000000000000000000000
--- a/djangobower/tests/test_bower.py
+++ /dev/null
@@ -1,173 +0,0 @@
-from django.core.management import call_command
-from django.conf import settings
-from django.test import TestCase
-from six import StringIO
-from mock import MagicMock
-from ..bower import bower_adapter, BowerAdapter
-from .. import conf
-from .base import BaseBowerCase, TEST_COMPONENTS_ROOT
-import os
-import shutil
-
-
-class BowerAdapterCase(TestCase):
-    """
-    BowerAdapter regression tests.
-    """
-
-    def test_create_components_root_subdirs(self):
-        """
-        create_components_root() creates missing intermediate directories.
-        """
-        if os.path.exists(TEST_COMPONENTS_ROOT):
-            shutil.rmtree(TEST_COMPONENTS_ROOT)
-
-        subdir = os.path.join(TEST_COMPONENTS_ROOT, 'sub', 'dir')
-        adapter = BowerAdapter(conf.BOWER_PATH, subdir)
-        adapter.create_components_root()
-        self.assertTrue(os.path.exists(subdir))
-
-        shutil.rmtree(TEST_COMPONENTS_ROOT)
-
-
-class BowerInstallCase(BaseBowerCase):
-    """Test case for bower_install management command"""
-
-    def setUp(self):
-        super(BowerInstallCase, self).setUp()
-        self.apps = settings.BOWER_INSTALLED_APPS
-        self._original_install = bower_adapter.install
-        bower_adapter.install = MagicMock()
-
-    def tearDown(self):
-        super(BowerInstallCase, self).tearDown()
-        bower_adapter.install = self._original_install
-
-    def test_create_components_root(self):
-        """Test create components root"""
-        self._remove_components_root()
-        call_command('bower_install')
-
-        self.assertTrue(os.path.exists(TEST_COMPONENTS_ROOT))
-
-    def test_install(self):
-        """Test install bower packages"""
-        call_command('bower_install')
-        bower_adapter.install.assert_called_once_with(self.apps)
-
-
-class BowerFreezeCase(BaseBowerCase):
-    """Case for bower freeze"""
-
-    def setUp(self):
-        super(BowerFreezeCase, self).setUp()
-        bower_adapter.install(['jquery#1.9'])
-        bower_adapter.install(['backbone'])
-        bower_adapter.install(['underscore'])
-        bower_adapter.install(['typeahead.js'])
-        bower_adapter.install(['backbone-tastypie'])
-
-    def test_freeze(self):
-        """Test freeze"""
-        installed = [
-            package.split('#')[0] for package in bower_adapter.freeze()
-        ]
-        self.assertCountEqual(installed, [
-            'backbone', 'jquery',
-            'typeahead.js', 'underscore',
-            'backbone-tastypie',
-        ])
-
-    def test_no_newline_in_freeze(self):
-        """Test no newline in freezee"""
-        installed = bower_adapter.freeze()
-        for package in installed:
-            self.assertNotIn('\n', package)
-
-    def test_management_command(self):
-        """Test freeze management command"""
-        stdout = StringIO()
-        call_command('bower_freeze', stdout=stdout)
-        stdout.seek(0)
-        output = stdout.read()
-
-        self.assertIn('BOWER_INSTALLED_APPS', output)
-        self.assertIn('backbone', output)
-
-
-class BowerExistsCase(BaseBowerCase):
-    """
-    Test bower exists checker.
-    This case need bower to be installed.
-    """
-
-    def setUp(self):
-        super(BowerExistsCase, self).setUp()
-        self._original_exists = bower_adapter.is_bower_exists
-
-    def tearDown(self):
-        super(BowerExistsCase, self).tearDown()
-        bower_adapter.is_bower_exists = self._original_exists
-
-    def test_if_exists(self):
-        """Test if bower exists"""
-        self.assertTrue(bower_adapter.is_bower_exists())
-
-    def test_if_not_exists(self):
-        """Test if bower not exists"""
-        adapter = BowerAdapter('/not/exists/path', TEST_COMPONENTS_ROOT)
-        self.assertFalse(adapter.is_bower_exists())
-
-    def _mock_exists_check(self):
-        """Make exists check return false"""
-        bower_adapter.is_bower_exists = MagicMock()
-        bower_adapter.is_bower_exists.return_value = False
-
-
-class BowerCommandCase(BaseBowerCase):
-    """Test case for ./manage.py bower something command"""
-
-    def setUp(self):
-        super(BowerCommandCase, self).setUp()
-        self.apps = settings.BOWER_INSTALLED_APPS
-        self._mock_bower_adapter()
-
-    def _mock_bower_adapter(self):
-        self._original_install = bower_adapter.install
-        bower_adapter.install = MagicMock()
-        self._orig_call = bower_adapter.call_bower
-        bower_adapter.call_bower = MagicMock()
-        self._orig_freeze = bower_adapter.freeze
-        bower_adapter.freeze = MagicMock()
-
-    def tearDown(self):
-        super(BowerCommandCase, self).tearDown()
-        bower_adapter.install = self._original_install
-        bower_adapter.call_bower = self._orig_call
-        bower_adapter.freeze = self._orig_freeze
-
-    def test_install_without_params(self):
-        """Test that bower install without param identical
-        with bower_install
-
-        """
-        call_command('bower', 'install')
-        bower_adapter.install.assert_called_once_with(
-            self.apps)
-
-    def test_install_with_params(self):
-        """Test bower install <something>"""
-        call_command('bower', 'install', 'jquery')
-        bower_adapter.call_bower.assert_called_once_with(
-            ('install', 'jquery'))
-
-    def test_freeze(self):
-        """Test bower freeze command"""
-        call_command('bower', 'freeze')
-        bower_adapter.freeze.assert_called_once_with()
-
-    def test_call_to_bower(self):
-        """Test simple call to bower"""
-        call_command('bower', 'update')
-        bower_adapter.call_bower.assert_called_once_with(
-            ('update',))
diff --git a/docs/Makefile b/docs/Makefile
index 41b25a50fe635884a5af5bd421633eb1a8c7b8d5..fe36a6d6f9f9d722e717c5bd609d2b83a608bc6a 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -77,17 +77,17 @@ qthelp:
 	@echo
 	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
 	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
-	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/django-bower.qhcp"
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/django-yarnpkg.qhcp"
 	@echo "To view the help file:"
-	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/django-bower.qhc"
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/django-yarnpkg.qhc"
 
 devhelp:
 	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
 	@echo
 	@echo "Build finished."
 	@echo "To view the help file:"
-	@echo "# mkdir -p $$HOME/.local/share/devhelp/django-bower"
-	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/django-bower"
+	@echo "# mkdir -p $$HOME/.local/share/devhelp/django-yarnpkg"
+	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/django-yarnpkg"
 	@echo "# devhelp"
 
 epub:
diff --git a/docs/conf.py b/docs/conf.py
index 915d8fee6e66110f47ef8c6f71578ea5e151a981..f20dc831fb6a26e25650968f4ddc2a493bead0e4 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# django-bower documentation build configuration file, created by
+# django-yarnpkg documentation build configuration file, created by
 # sphinx-quickstart on Tue Jul 16 16:38:23 2013.
 #
 # This file is execfile()d with the current directory set to its containing dir.
@@ -40,17 +40,17 @@ source_suffix = '.rst'
 master_doc = 'index'
 
 # General information about the project.
-project = u'django-bower'
-copyright = u'2013, Vladimir Iakovlev'
+project = u'django-yarnpkg'
+copyright = u'2013, Vladimir Iakovlev; 2019, Dominik George'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # built documents.
 #
 # The short X.Y version.
-version = '4.7'
+version = '6.0'
 # The full version, including alpha/beta/rc tags.
-release = '4.8'
+release = '6.0'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
@@ -164,7 +164,7 @@ html_static_path = ['_static']
 #html_file_suffix = None
 
 # Output file base name for HTML help builder.
-htmlhelp_basename = 'django-bowerdoc'
+htmlhelp_basename = 'django-yarnpkgdoc'
 
 
 # -- Options for LaTeX output --------------------------------------------------
@@ -183,7 +183,7 @@ latex_elements = {
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title, author, documentclass [howto/manual]).
 latex_documents = [
-  ('index', 'django-bower.tex', u'django-bower Documentation',
+  ('index', 'django-yarnpkg.tex', u'django-yarnpkg Documentation',
    u'Vladimir Iakovlev', 'manual'),
 ]
 
@@ -213,7 +213,7 @@ latex_documents = [
 # One entry per manual page. List of tuples
 # (source start file, name, description, authors, manual section).
 man_pages = [
-    ('index', 'django-bower', u'django-bower Documentation',
+    ('index', 'django-yarnpkg', u'django-yarnpkg Documentation',
      [u'Vladimir Iakovlev'], 1)
 ]
 
@@ -227,8 +227,8 @@ man_pages = [
 # (source start file, target name, title, author,
 #  dir menu entry, description, category)
 texinfo_documents = [
-  ('index', 'django-bower', u'django-bower Documentation',
-   u'Vladimir Iakovlev', 'django-bower', 'One line description of project.',
+  ('index', 'django-yarnpkg', u'django-yarnpkg Documentation',
+   u'Vladimir Iakovlev', 'django-yarnpkg', 'One line description of project.',
    'Miscellaneous'),
 ]
 
diff --git a/docs/example.rst b/docs/example.rst
index 07a728f95024affc710e30cc10d3c5eaec36cd02..32cc45146e250c93f601a5c615f5f1d47bd7df3b 100644
--- a/docs/example.rst
+++ b/docs/example.rst
@@ -9,7 +9,7 @@ Prepare project with:
 .. code-block:: bash
 
     ./manage.py syncdb
-    ./manage.py bower_install
+    ./manage.py yarn install
 
 And run project with:
 
diff --git a/docs/index.rst b/docs/index.rst
index 69af97a85e5b50624871797420698568a2e26d81..1a5256c30beb73377d1a735c04df8f69a7147cf7 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1,18 +1,16 @@
-.. django-bower documentation master file, created by
+.. django-yarnpkg documentation master file, created by
    sphinx-quickstart on Tue Jul 16 16:38:23 2013.
    You can adapt this file completely to your liking, but it should at least
    contain the root `toctree` directive.
 
-Welcome to django-bower's documentation!
+Welcome to django-yarnpkg's documentation!
 ========================================
 
-Easy way to use `bower <http://bower.io/>`_ with your `django <https://www.djangoproject.com/>`_ project.
+Easy way to use `Yarn <http://yarnpkg.com/>`_ with your `django <https://www.djangoproject.com/>`_ project.
 
-Bower is a package manager for the web. It offers a generic, unopinionated solution to the problem of front-end package management, while exposing the package dependency model via an API that can be consumed by a more opinionated build stack. There are no system wide dependencies, no dependencies are shared between different apps, and the dependency tree is flat.
+Yarn is a package manager for the web. It offers a generic, unopinionated solution to the problem of front-end package management, while exposing the package dependency model via an API that can be consumed by a more opinionated build stack. There are no system wide dependencies, no dependencies are shared between different apps, and the dependency tree is flat.
 
-Bower runs over Git, and is package-agnostic. A packaged component can be made up of any type of asset, and use any type of transport (e.g., AMD, CommonJS, etc.).
-
-`View all packages available through Bower's registry. <http://sindresorhus.com/bower-components/>`_
+Yarn runs over Git, and is package-agnostic. A packaged module can be made up of any type of asset, and use any type of transport (e.g., AMD, CommonJS, etc.).
 
 Contents:
 
@@ -24,7 +22,7 @@ Contents:
    tests
    example
 
-`Visit django-bower github page. <https://github.com/nvbn/django-bower>`_
+`Visit django-yarnpkg github page. <https://github.com/Natureshadow/django-yarnpkg>`_
 
 
 
diff --git a/docs/installation.rst b/docs/installation.rst
index e0817390cbe31927f5f9df5b8fb1078edb6f42d9..637fcd688a1461b2ce090a33d9b17d2f10a7f6ca 100644
--- a/docs/installation.rst
+++ b/docs/installation.rst
@@ -2,43 +2,43 @@
 Installation
 ************
 
-Install `bower <http://bower.io/>`_ from npm:
+Install `Yarn <http://yarnpkg.com/>`_ from npm:
 
 .. code-block:: bash
 
-    npm install -g bower
+    npm install -g yarn
 
-And django-bower package:
+And django-yarnpkg package:
 
 .. code-block:: bash
 
-    pip install django-bower
+    pip install django-yarnpkg
 
 Add django-bower to `INSTALLED_APPS` in your settings:
 
 .. code-block:: python
 
-    'djangobower',
+    'django_yarnpkg',
 
 Add staticfinder to `STATICFILES_FINDERS`:
 
 .. code-block:: python
 
-    'djangobower.finders.BowerFinder',
+    'django_yarnpkg.finders.NodeModulesFinder',
 
-Specify path to components root (you need to use absolute path):
+Specify path to node modules root (you need to use absolute path):
 
 .. code-block:: python
 
-    BOWER_COMPONENTS_ROOT = '/PROJECT_ROOT/components/'
+    NODE_MODULES_ROOT = '/PROJECT_ROOT/node_modules/'
 
-If you need, you can manually set path to bower
+If you need, you can manually set path to yarn
 
 .. code-block:: python
 
-    BOWER_PATH = '/usr/bin/bower'
+    YARN_PATH = '/usr/bin/yarnpkg'
 
-Example settings file with django-bower:
+Example settings file with django-yarnpkg:
 
 .. code-block:: python
     :linenos:
@@ -68,12 +68,12 @@ Example settings file with django-bower:
 
     STATIC_URL = '/static/'
 
-    BOWER_COMPONENTS_ROOT = os.path.join(PROJECT_ROOT, 'components')
+    NODE_MODULES_ROOT = os.path.join(PROJECT_ROOT, 'node_modules')
 
     STATICFILES_FINDERS = (
         'django.contrib.staticfiles.finders.FileSystemFinder',
         'django.contrib.staticfiles.finders.AppDirectoriesFinder',
-        'djangobower.finders.BowerFinder',
+        'django_yarnpkg.finders.NodeModulesFinder',
     )
 
     SECRET_KEY = 'g^i##va1ewa5d-rw-mevzvx2^udt63@!xu$-&di^19t)5rbm!5'
@@ -101,10 +101,10 @@ Example settings file with django-bower:
 
     INSTALLED_APPS = (
         'django.contrib.staticfiles',
-        'djangobower',
+        'django_yarnpkg',
     )
 
-    BOWER_INSTALLED_APPS = (
+    YARN_INSTALLED_APPS = (
         'jquery',
         'underscore',
     )
diff --git a/docs/tests.rst b/docs/tests.rst
index 0b055159715acab76cc563722df4944d81489fcd..277353e052ab154e262b7fc0308ffc027d5f2ba2 100644
--- a/docs/tests.rst
+++ b/docs/tests.rst
@@ -2,7 +2,7 @@
 Running tests
 *************
 
-For running tests you need to install `django-bower` in development mode with:
+For running tests you need to install `django-yarnpkg` in development mode with:
 
 .. code-block:: bash
 
@@ -18,8 +18,6 @@ Now you can run tests with:
 
 .. code-block:: bash
 
-    django-admin.py test --settings=djangobower.test_settings djangobower
+    django-admin.py test --settings=django_yarnpkg.test_settings django_yarnpkg
 
 You can change test project root with `TEST_PROJECT_ROOT` environment variable. By default it is `/tmp`.
-
-You can show current tests status in `travis ci <https://travis-ci.org/nvbn/django-bower/>`_.
diff --git a/docs/usage.rst b/docs/usage.rst
index 80fe48c563493eb46c6892210288873c8bf74497..e7d33ba79652d4fad9edd55fa78fcf91fdb66396 100644
--- a/docs/usage.rst
+++ b/docs/usage.rst
@@ -2,20 +2,20 @@
 Usage
 *****
 
-Specifie `BOWER_INSTALLED_APPS` in settings, like:
+Specify `YARN_INSTALLED_APPS` in settings, like:
 
 .. code-block:: python
 
-    BOWER_INSTALLED_APPS = (
+    YARN_INSTALLED_APPS = (
         'jquery#1.9',
         'underscore',
     )
 
-Download bower packages with management command:
+Download yarn packages with management command:
 
 .. code-block:: bash
 
-    ./manage.py bower install
+    ./manage.py yarn install
 
 Add scripts in template, like:
 
@@ -24,28 +24,22 @@ Add scripts in template, like:
     {% load static %}
     <script type="text/javascript" src='{% static 'jquery/jquery.js' %}'></script>
 
-In production you need to call `bower install` before `collectstatic`:
+In production you need to call `yarn install` before `collectstatic`:
 
 .. code-block:: bash
 
-    ./manage.py bower install
+    ./manage.py yarn install
     ./manage.py collectstatic
 
-If you need to pass arguments to bower, like `--allow-root`, use:
+If you need to pass arguments to yarn, like `--flat`, use:
 
 .. code-block:: bash
 
-    ./manage.py bower install -- --allow-root
+    ./manage.py yarn install -- --flat
 
-You can use `bower freeze` to receive `BOWER_INSTALLED_APPS` with fixed current versions:
+You can call yarn commands like `info` and `update` with:
 
 .. code-block:: bash
 
-    ./manage.py bower freeze
-
-You can call bower commands like `info` and `update` with:
-
-.. code-block:: bash
-
-    ./manage.py bower info backbone
-    ./manage.py bower update
+    ./manage.py yarn info backbone
+    ./manage.py yarn update
diff --git a/example/example/settings.py b/example/example/settings.py
index 34b370c1dcc3cf3c391f0bc4874406496078aa16..f057a96625d6c755b38a830ee42f24f924ac9288 100644
--- a/example/example/settings.py
+++ b/example/example/settings.py
@@ -23,12 +23,12 @@ STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static')
 
 STATIC_URL = '/static/'
 
-BOWER_COMPONENTS_ROOT = os.path.join(PROJECT_ROOT, 'components')
+NODE_MODULES_ROOT = os.path.join(PROJECT_ROOT, 'node_modules')
 
 STATICFILES_FINDERS = (
     'django.contrib.staticfiles.finders.FileSystemFinder',
     'django.contrib.staticfiles.finders.AppDirectoriesFinder',
-    'djangobower.finders.BowerFinder',
+    'django_yarnpkg.finders.NodeModulesFinder',
 )
 
 SECRET_KEY = 'g^i##va1ewa5d-rw-mevzvx2^udt63@!xu$-&di^19t)5rbm!5'
@@ -56,10 +56,10 @@ TEMPLATE_DIRS = (
 
 INSTALLED_APPS = (
     'django.contrib.staticfiles',
-    'djangobower',
+    'django_yarnpkg',
 )
 
-BOWER_INSTALLED_APPS = (
+YARN_INSTALLED_APPS = (
     'jquery',
     'underscore',
 )
diff --git a/example/components/.gitkeep b/example/node_modules/.gitkeep
similarity index 100%
rename from example/components/.gitkeep
rename to example/node_modules/.gitkeep
diff --git a/example/templates/index.html b/example/templates/index.html
index 017d434b70d61ec6a2da6df18bfe7274f17cd81c..f6adfedacc8dada195b0ebabf9ed302c9095ccf4 100644
--- a/example/templates/index.html
+++ b/example/templates/index.html
@@ -2,7 +2,7 @@
 {% load static %}
 <html>
 <head>
-    <title>django-bower demo</title>
+    <title>django-yarnpkg demo</title>
     <script type="text/javascript" src='{% static 'jquery/dist/jquery.js' %}'></script>
     <script type="text/javascript" src='{% static 'underscore/underscore.js' %}'></script>
     <script type="text/javascript">
diff --git a/runtests.py b/runtests.py
index 274d5084e6b6773b22360f125ba87ef75a8bcbfc..115c8a2bff53282958543a071b4c3966e0f15722 100644
--- a/runtests.py
+++ b/runtests.py
@@ -4,7 +4,7 @@ import sys
 
 if __name__ == "__main__":
     os.environ.setdefault(
-        "DJANGO_SETTINGS_MODULE", 'djangobower.test_settings',
+        "DJANGO_SETTINGS_MODULE", 'django_yarnpkg.test_settings',
     )
 
     from django.core.management import execute_from_command_line
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index fa9fe18f50d479dd632d571764ebe2e5d83f9677..0000000000000000000000000000000000000000
--- a/setup.cfg
+++ /dev/null
@@ -1 +0,0 @@
-[egg_info]
diff --git a/setup.py b/setup.py
index d12142fd31fcdefc9b102a7495a3928692ddf3b6..bd6eeb311fbb806bb193d5b19729fef2c230c4af 100644
--- a/setup.py
+++ b/setup.py
@@ -1,11 +1,11 @@
 from setuptools import setup, find_packages
 
-version = '5.2.0'
+version = '6.0.0'
 
 setup(
-    name='django-bower',
+    name='django-yarnpkg',
     version=version,
-    description="Integrate django with bower",
+    description="Integrate django with yarnpkg",
     long_description=open('README.rst').read(),
     classifiers=[
         'Framework :: Django',
@@ -14,9 +14,9 @@ setup(
         'Programming Language :: Python :: 3',
     ],
     keywords='',
-    author='Vladimir Iakovlev',
-    author_email='nvbn.rm@gmail.com',
-    url='https://github.com/nvbn/django-bower',
+    author='Dominik George',
+    author_email='nik@naturalnet.de',
+    url='https://github.com/Natureshadow/django-yarnpkg',
     license='BSD',
     packages=find_packages(exclude=['example']),
     include_package_data=True,