Repository: awesome-panel/panel-chemistry (language: python)

Issue:
ImportError: cannot import name 'string_types' from 'panel.util' 
When testing on panel 0.13.0rc5 I get

```bash
2022-04-07 21:06:14,769 Error running application handler <bokeh.application.handlers.script.ScriptHandler object at 0x0000029BC5655100>: cannot import name 'string_types' from 'panel.util' (c:\repos\private\awesome-panel\.venv\lib\site-packages\panel\util.py)
File 'ngl_viewer.py', line 15, in <module>:
from panel.util import lazy_load, string_types Traceback (most recent call last):
  File "c:\repos\private\awesome-panel\.venv\lib\site-packages\bokeh\application\handlers\code_runner.py", line 231, in run
    exec(self._code, module.__dict__)
  File "C:\repos\private\awesome-panel\awesome_panel\apps\py3dmol.py", line 4, in <module>
    from panel_chemistry.pane import Py3DMol
  File "c:\repos\private\awesome-panel\.venv\lib\site-packages\panel_chemistry\pane\__init__.py", line 6, in <module>
    from .ngl_viewer import NGLViewer
  File "c:\repos\private\awesome-panel\.venv\lib\site-packages\panel_chemistry\pane\ngl_viewer.py", line 15, in <module>
    from panel.util import lazy_load, string_types
ImportError: cannot import name 'string_types' from 'panel.util' (c:\repos\private\awesome-panel\.venv\lib\site-packages\panel\util.py)
```


Discussion / hints:
Hi :-) 

First of all thank you so much for your great pluggin =D
I wanted to use it with Panel 0.13 (because of the great new notification system) and I also face this bug. 
While digging arround I realise it could be fixed by changing in `ngl_viewer.py`
```python 
from panel.util import lazy_load, string_types
``` 
by 
```python
from panel.util import lazy_load
from six import string_types
```

I made the changes and create a pull request --> #24  :-)

Best regards,
Thibault.

Fix patch:
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 0000000..c4e8cc2
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,68 @@
+name: "🐛 Bug Report"
+description: Report something that does not work as expected
+labels: [
+  "bug", "TRIAGE"
+]
+body:
+  - type: textarea
+    id: description
+    attributes:
+      label: "Description"
+      description: Please enter an explicit description of your issue. Supplementary images or videos are much appreciated.
+      placeholder: Short and explicit description of your issue...
+    validations:
+      required: true
+  - type: textarea
+    id: reprod
+    attributes:
+      label: "Reproduction steps"
+      description: Please list the steps needed to reproduce the issue. . Supplementary images or videos are much appreciated.
+      placeholder: |
+        - Run `panel serve app.py` where `app.py` contains the code below
+        - Open http://localhost:5006/app
+        - Go to '...'
+        - Click on '....'
+        - See error
+    validations:
+      required: true
+  - type: textarea
+    id: requirements
+    attributes:
+      label: "Requirements"
+      description: Please list the relevant requirements including version numbers
+      placeholder: |
+        panel==0.14.0
+      render: bash
+    validations:
+      required: false
+  - type: textarea
+    id: code
+    attributes:
+      label: "Code"
+      description: A minimum, reproducible example, see https://stackoverflow.com/help/minimal-reproducible-example.
+      placeholder: |
+        import panel as pn
+
+        pn.extension()
+      render: python3
+    validations:
+      required: false
+  - type: textarea
+    id: logs
+    attributes:
+      label: "Logs"
+      description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
+      placeholder: |
+        2022-10-13 05:59:36,200 Starting Bokeh server version 2.4.3 (running on Tornado 6.2)
+        2022-10-13 05:59:36,212 Bokeh app running at: http://localhost:5006/script
+      render: bash
+    validations:
+      required: false
+  - type: textarea
+    id: additional
+    attributes:
+      label: "Additional Context"
+      description: Any other relevant information that might be helpful
+      placeholder: This is important to fix because...
+    validations:
+      required: false
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000..8f996c0
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,8 @@
+blank_issues_enabled: false
+contact_links:
+  - name: 📙 Usage Questions
+    url: https://discourse.holoviz.org/
+    about: Please ask questions about usage here
+  - name: 📈 Panel Issues
+    url: https://github.com/holoviz/panel/issues
+    about: Please raise Panel specific issues here
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
new file mode 100644
index 0000000..a8a2fe0
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -0,0 +1,48 @@
+name: "💡 Feature Request"
+description: Create a request for enhancing the project
+labels: [
+  "enhancement"
+]
+body:
+  - type: textarea
+    id: request
+    attributes:
+      label: "Request"
+      description: Provide a brief explanation of your request.
+      placeholder: Describe in a few lines your feature request
+    validations:
+      required: true
+  - type: textarea
+    id: motivation
+    attributes:
+      label: "Motivation"
+      description: . Provide motivation for your feature request.
+      placeholder: | 
+        Describe why your feature request is be relevant and important.
+        Supplementary images or videos are much appreciated.
+    validations:
+      required: true
+  - type: textarea
+    id: drawbacks
+    attributes:
+      label: "Drawbacks"
+      description: What are the drawbacks/impacts of your feature request ?
+      placeholder: Identify the drawbacks and impacts while being neutral on your feature request
+    validations:
+      required: false
+  - type: textarea
+    id: alternatives
+    attributes:
+      label: "Alternatives"
+      description: Provide any alternatives solutions you've considered.
+      placeholder: Describe alternative solutions while being neutral on your feature request
+    validations:
+      required: false
+  - type: textarea
+    id: additional
+    attributes:
+      label: "Additional Context"
+      description: Provide other information relevant for the feature request. Supplementary images or videos are much appreciated.
+      placeholder: Describe any other information that would be relevant including open questions
+    validations:
+      required: false  
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index e88f48d..c2dc577 100644
--- a/.gitignore
+++ b/.gitignore
@@ -128,7 +128,6 @@ dmypy.json
 # Pyre type checker
 .pyre/
 test_results
-panel_chemistry/node_modules
+src/panel_chemistry/node_modules
 .vscode
-panel_chemistry/.bokeh
-panel_chemistry/pane/py3dmol_viewer.py
+src/panel_chemistry/.bokeh
diff --git a/.isort.cfg b/.isort.cfg
deleted file mode 100644
index dd6b520..0000000
--- a/.isort.cfg
+++ /dev/null
@@ -1,1 +0,0 @@
-[settings]
diff --git a/.pylintrc b/.pylintrc
deleted file mode 100644
index 28d83ef..0000000
--- a/.pylintrc
+++ /dev/null
@@ -1,19 +0,0 @@
-[MASTER]
-load-plugins=pylint.extensions.mccabe
-
-[FORMAT]
-max-line-length=100
-
-[MESSAGES CONTROL]
-# bad-continuation: Pylint cannot handle valid indendation created by Black
-# duplicate-code: The _current_event and _past_event have some similar code. But it's ok.
-disable=bad-continuation,duplicate-code
-
-
-[DESIGN]
-max-parents=13
-
-[TYPECHECK]
-generated-members=REQUEST,acl_users,aq_parent,"[a-zA-Z]+_set{1,2}",save,delete
-ignored-modules=winreg
-
diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md
index 2a79fb6..6bf6b15 100644
--- a/DEVELOPER_GUIDE.md
+++ b/DEVELOPER_GUIDE.md
@@ -1,172 +1,81 @@
-# 🎁 For Contributers
+# ❤️ Developer Guide
 
-The structure of the project will be the same as the [panel-highcharts](https://github.com/marcskovmadsen/panel-highcharts) project and package until something else is decided. I.e. we use
-
-- [binder](https://mybinder.org/) to provide an easy to use environment for trying, learning, exploring and using the packing. [See MarcSkovMadsen/../binder](https://github.com/MarcSkovMadsen/panel-chemistry/tree/main/binder).
-- Python [Invoke](http://www.pyinvoke.org/) to easily run build, test etc tasks. [See MarcSkovMadsen/../tasks](https://github.com/MarcSkovMadsen/panel-chemistry/tree/main/tasks)
-  - This includes includes running isort, autoflake, black, pylint, mypy and pytest and making sure all test should pass before merging to main branch. This will keep the code and package working and maintainable.
-- Provide documentation via this README and an examples folder of notebooks. [See MarcSkovMadsen/../examples](https://github.com/MarcSkovMadsen/panel-chemistry/tree/main/examples)
-
-Maybe we also improve it further
-
-- Add CI/ CD on Github to build, test and deploy the package. (I have not tried this before)
-- Add various badges (I have not tried this before).
-- Add documentation on read the docs. But not for now in order to keep things simple.
+Welcome. We are so happy that you want to contribute.
 
 ## 🛠️ Prerequisites
 
-- conda
+- A `conda` environment.
+- [Git CLI](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git).
 
-Please note that you can also use pip. But then you will have to mess with getting node.js installed which might be a painful process
-if your are in some kind of constrained, enterprise environment.
+You can also use `pip` if you can get `node.js` installed.
 
-## 🏃 Installation
-
-```bash
-git clone https://github.com/marcskovmadsen/panel-chemistry
-cd panel-chemistry
-```
+## 📙 How to
 
-Create your virtual environment.
+Below we describe how to install and use this project for development.
 
-```bash
-conda create --name panel-chemistry
-```
+### 💻 Install for Development
 
-Activate your virtual environment. On Windows with Git Bash it can be done via
+To install for development you will need to create and activate a virtual environment
 
 ```bash
+conda create --name panel-chemistry python=3.9 nodejs
 conda activate panel-chemistry
 ```
 
-Install the `panel-chemistry` package for editing
+Then run
 
 ```bash
+git clone https://github.com/awesome-panel/panel-chemistry.git
+cd panel-chemistry
+pip install pip -U
 pip install -e .[all]
 ```
 
-install node.js
+This will install the
+[`awesome-panel-cli`](https://github.com/awesome-panel/awesome-panel-cli). You can see the available commands via
 
 ```bash
-conda install -c conda-forge nodejs
+pn --help
 ```
 
-## 📝 Invoke
-
-We use [Python Invoke](http://www.pyinvoke.org/) to easily run build, test etc tasks.
-
-You can learn more about the available options via `invoke --list`. Please note that invoke should run from the root of the project.
-
-The invoke tasks are defined in the [tasks](./tasks/__init__.py) module.
-
-### 🏗️ Build
-
-You can see the build commands via
+You can run all tests via
 
 ```bash
-$ invoke --list=build
-Available 'build' tasks:
-
-  .binder-image (.binder)           Builds the panel-chemistry binder image using jupyter-repo2docker
-  .bokeh-extensions (.extensions)   Builds the Bokeh extensions using Node.js
-  .python-package (.package)        Builds the panel-chemistry Python package
+pn test all
 ```
 
-For example to build the Bokeh extensions you can write
+Please run this command and fix any failing tests if possible before you `git push`.
 
-```bash
-invoke build.extensions
-```
-
-## 🧪 Tests
-
-To see the available options run
-
-```bash
-$ invoke --list=test
-Available 'test' tasks:
-
-  .all (.pre-commit, .test)   Runs isort, autoflake, black, pylint, mypy and pytest
-  .autoflake                  Runs autoflake to remove unused imports on all .py files recursively
-  .bandit                     Runs Bandit the security linter from PyCQA.
-  .black                      Runs black (autoformatter) on all .py files recursively
-  .isort                      Runs isort (import sorter) on all .py files recursively
-  .mypy                       Runs mypy (static type checker) on all .py files recursively
-  .pylint                     Runs pylint (linter) on all .py files recursively to identify coding errors
-  .pytest                     Runs pytest to identify failing tests
-```
-
-For example to run pytest you would run `invoke test.pytest`.
-
-All tests are also automatically run via [Github Actions](https://docs.github.com/en/actions) on Pull Requests and merges into the `main` branch. For more info checkout the [tests.yaml](.github/workflows/tests.yaml) configuration file.
-
-## 📒 Show
-
-You can your invoke to easily show Binder or Github for the active branch.
-
-You can also use invoke to `panel serve` and show the example notebooks.
-
-Checkout
-
-```bash
-$ invoke --list=show
-Available 'start' tasks:
-
-  .binder     Opens the current branch on Binder.
-  .examples   Panel serves the examples notebooks.
-  .github     Opens the current branch on Github.
-```
-
-## Pull Requests
-
-You are welcome to create Pull Requests on preliminary code.
-
-When you request a review please make sure all tests, i.e. make sure `invoke test.all` run successfully and without errors.
-
-Alternatively please just mention that not all tests pass, but you would still like a review and the reason why.
-
-## 🚢 Releasing a New Package
+### 🚢 Release a new package on Pypi
 
 Please make sure you have upgraded bokeh
 
 ```bash
-cd panel_chemistry
+cd src/panel_chemistry
 npm update @bokeh/bokehjs --save
 ```
 
-In the [VERSION](VERSION) and [package.json](panel_chemistry/package.json) files update the `version` number. Then run
+Update the version number in the [__init__.py](panel_chemistry/__init__.py) and
+[package.json](src/panel_chemistry/package.json) files.
 
-Please make sure all tests pass
+Then run
 
 ```bash
-invoke test.all
+pn test all
 ```
 
 Then you can build
 
 ```bash
-invoke build.extensions
-invoke build.package
+cd ..
+panel build panel_chemistry
+pn build package
 ```
 
 and upload
 
 ```bash
-python -m twine upload dist/*<VERSION>*
+pn release package <VERSION>
 ```
 
-to deploy the package 📦.
-
-If you want to upload to *Test Pypi* first you can do so by adding `--repository testpypi`.
-
-## 🎥 Videos
-
-**Click the image** to watch.
-
-### v.0.0.1 - Project Structure
-
-[![v.0.0.1 - Basic Project Structure](https://img.youtube.com/vi/2zvXTTo5NcI/maxresdefault.jpg)](https://youtu.be/2zvXTTo5NcI)
-
-### v.0.0.2 - Init Bokeh Extensions
-
-[![v0.0.2 - Init Bokeh Extensions](https://img.youtube.com/vi/6XVEIiP52UU/maxresdefault.jpg)](https://youtu.be/6XVEIiP52UU)
+to release the package 📦. To upload to *Test Pypi* first, you can add the `--test` flag.
diff --git a/LICENSE b/LICENSE
index 261eeb9..8a6ec56 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,201 +1,21 @@
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
+MIT License
+
+Copyright (c) 2021 Marc Skov Madsen
+
+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.
\ No newline at end of file
diff --git a/MANIFEST.in b/MANIFEST.in
index 137bcee..933d632 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,11 +1,10 @@
-graft panel_chemistry/dist
-include panel_chemistry/*.json
-include panel_chemistry/bokeh_extensions/*.ts
-include panel_chemistry/index.ts
-include panel_chemistry/py.typed
 include README.md
-include VERSION
 include LICENSE
+include src/panel_chemistry/py.typed
+graft src/panel_chemistry/dist
+include src/panel_chemistry/*.json
+include src/panel_chemistry/bokeh_extensions/*.ts
+include src/panel_chemistry/index.ts
 global-exclude *.ipynb_checkpoints/*
 global-exclude *.py[co]
 global-exclude *~
\ No newline at end of file
diff --git a/README.md b/README.md
index 01eed07..91264c0 100644
--- a/README.md
+++ b/README.md
@@ -1,54 +1,77 @@
+![Python Versions](https://img.shields.io/badge/python-3.7%20%7C%203.8%20%7C%203.9%20%7C%203.10-blue)
+![Style Black](https://warehouse-camo.ingress.cmh1.psfhosted.org/fbfdc7754183ecf079bc71ddeabaf88f6cbc5c00/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f64652532307374796c652d626c61636b2d3030303030302e737667)
+[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) 
+![Test Results](https://github.com/MarcSkovMadsen/panel-chemistry/actions/workflows/tests.yaml/badge.svg?branch=main)
+[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/awesome-panel/panel-chemistry/feature/binder)
+[![Follow on Twitter](https://img.shields.io/twitter/follow/MarcSkovMadsen.svg?style=social)](https://twitter.com/MarcSkovMadsen)
+[![LinkedIn](https://img.shields.io/badge/linkedin-%230077B5.svg?style=for-the-badge&logo=linkedin&logoColor=white)](https://www.linkedin.com/in/marcskovmadsen)
+
 # 🧪 Panel-Chemistry
 
-👨‍🔬📈🛠️🐍❤️
+We want to
+
+- make it super simple to do **exploratory data analysis** and develop high-quality
+[Panel](https://awesome-panel.org) **data apps** within the domain of **chemistry**.
+
+We provide
+
+- the `panel-chemistry` python package of chemistry components for Panel.
+- example notebooks and data apps.
+
+You can install and create a new *app* as simple as
+
+```bash
+pip install panel-chemistry
+```
+
+```python
+import panel as pn 
+from panel_chemistry.pane import NGLViewer # panel_chemistry needs to be imported before you run pn.extension()
 
-![Python Versions](https://img.shields.io/badge/python-3.6%20%7C%203.7%20%7C%203.8%20%7C%203.9-blue) ![Style Black](https://warehouse-camo.ingress.cmh1.psfhosted.org/fbfdc7754183ecf079bc71ddeabaf88f6cbc5c00/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f64652532307374796c652d626c61636b2d3030303030302e737667) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) ![Test Results](https://github.com/MarcSkovMadsen/panel-chemistry/actions/workflows/tests.yaml/badge.svg?branch=main) [![Follow on Twitter](https://img.shields.io/twitter/follow/MarcSkovMadsen.svg?style=social)](https://twitter.com/MarcSkovMadsen)
+pn.extension("ngl_viewer", sizing_mode="stretch_width", template="fast")
 
-The purpose of the `panel-chemistry` project is to make it really easy for you  to do **exploratory data analysis** and **build powerful data and viz tools** within the domain of **Chemistry** using [Python](https://www.python.org/) and [HoloViz Panel](https://panel.holoviz.org/).
+NGLViewer(object="1CRN", background="#F7F7F7", min_height=700, sizing_mode="stretch_both").servable()
+```
 
 ![Panel Chemistry Teaser](https://raw.githubusercontent.com/MarcSkovMadsen/panel-chemistry/main/assets/panel-chemistry-teaser.gif)
 
-Check out the `panel-chemistry` examples on **Binder**
+## ⭐ Support
 
-| Jupyter Notebook | Jupyter Labs | Panel Apps |
-| - | - | - |
-| [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/marcskovmadsen/panel-chemistry/HEAD?filepath=examples) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/marcskovmadsen/panel-chemistry/HEAD?urlpath=lab/tree/examples) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/marcskovmadsen/panel-chemistry/HEAD?urlpath=panel) |
+Please support [Panel](https://panel.holoviz.org) and
+[awesome-panel](https://awesome-panel.org) by giving the projects a star on Github:
 
-## 🏁 Background
+- [holoviz/panel](https://github.com/holoviz/panel).
+- [awesome-panel/awesome-panel](https://github.com/awesome-panel/awesome-panel).
 
-This project was started by the discussion [How to display JSME molecular editor with Panel?](https://discourse.holoviz.org/t/how-to-display-jsme-molecular-editor-with-panel/2306/12) in the [Panel Community Forum](https://discourse.holoviz.org/)
+Thanks
 
-## 🏃 Getting Started
+## ❤️ Contribute
 
-```bash
-pip install panel-chemistry
-```
+You can find *good first issues* in the [issue tracker](https://github.com/awesome-panel/panel-chemistry/issues). To get started check out the [DEVELOPER_GUIDE](DEVELOPER_GUIDE.md).
 
-or with `conda`
+I would love to support and receive your contributions. Thanks.
 
-```bash
-conda install -c conda-forge panel-chemistry
-```
+[![Hacktober Fest](https://github.blog/wp-content/uploads/2022/10/hacktoberfestbanner.jpeg?fit=1200%2C630)](https://github.com/awesome-panel/panel-chemistry/issues).
 
-Run the below in a Notebook or using `panel serve NAME_OF_SCRIPT.py`.
+## 📙 How to
 
-```python
-import panel as pn
-from panel_chemistry.widgets import JSMEEditor
+Below we describe how to install and use this project.
 
-pn.extension("jsme", sizing_mode="stretch_width")
-```
+### 🚀 Install for usage
 
-```python
-smiles="N[C@@H](CCC(=O)N[C@@H](CS)C(=O)NCC(=O)O)C(=O)O"
-editor = JSMEEditor(value=smiles, height=500, format="smiles")
+You can install the package with `pip`
 
-editor.servable()
+```bash
+pip install panel-chemistry
 ```
 
-![JSME Editor](https://raw.githubusercontent.com/MarcSkovMadsen/panel-chemistry/main/assets/panel-chemistry-example.png)
+or `conda`
 
-## 👩‍🏫 Examples
+```bash
+conda install -c conda-forge panel-chemistry
+```
+
+### 👩‍🏫 Explore the examples online
 
 Check out the `panel-chemistry` **reference guides** on **Binder**
 
@@ -59,26 +82,45 @@ Check out the `panel-chemistry` **reference guides** on **Binder**
 | PDBe_MolStar | [View](https://nbviewer.org/github/MarcSkovMadsen/panel-chemistry/blob/main/examples/reference/PDBe_MolStar.ipynb) | [View](https://github.com/MarcSkovMadsen/panel-chemistry/blob/main/examples/reference/PDBe_MolStar.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/marcskovmadsen/panel-chemistry/HEAD?filepath=examples/reference/PDBe_MolStar.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/marcskovmadsen/panel-chemistry/HEAD?urlpath=lab/tree/examples/reference/PDBe_MolStar.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/marcskovmadsen/panel-chemistry/HEAD?urlpath=panel/PDBe_MolStar) |
 | Py3DMol Pane | [View](https://nbviewer.org/github/MarcSkovMadsen/panel-chemistry/blob/main/examples/reference/Py3DMol.ipynb) | [View](https://github.com/MarcSkovMadsen/panel-chemistry/blob/main/examples/reference/Py3DMol.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/marcskovmadsen/panel-chemistry/HEAD?filepath=examples/reference/Py3DMol.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/marcskovmadsen/panel-chemistry/HEAD?urlpath=lab/tree/examples/reference/Py3DMol.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/marcskovmadsen/panel-chemistry/HEAD?urlpath=panel/Py3DMol) |
 
-## 💡 Inspiration
+### 👩‍🏫 Explore the examples locally
+
+Run
+
+```bash
+pip install pip -U
+pip install panel-chemistry[all]
+git clone https://github.com/awesome-panel/panel-chemistry.git
+cd panel-chemistry/examples
+```
+
+Then run
+
+```bash
+jupyter lab
+```
+
+or
+
+```bash
+panel serve reference/*.ipynb
+```
 
-- [Awesome Python Chemistry](https://github.com/lmmentel/awesome-python-chemistry)
-- [Dash Bio](https://dash.plotly.com/dash-bio)
-- [JSME Editor](https://jsme-editor.github.io) and [Test Page](https://jsme-editor.github.io/dist/JSME_test.html)
-- [3DMol.js](https://3dmol.csb.pitt.edu/) and [py3Dmol](https://colab.research.google.com/drive/1T2zR59TXyWRcNxRgOAiqVPJWhep83NV_?usp=sharing)
-- [RDKit](http://www.rdkit.org/)
-- [RDKit IPython Tools](https://github.com/apahl/rdkit_ipynb_tools)
+### 🏃 Serve a data app
 
-## 🎁 Contributing
+Add the below to a python file or notebook
+
+```python
+import panel as pn
+from panel_chemistry.widgets import JSMEEditor
 
-If you want to contribute reach out via [Github Issues](https://github.com/MarcSkovMadsen/panel-chemistry/issues) or in the Contributor Community Forum on Gitter: https://gitter.im/panel-chemistry/community#
+pn.extension("jsme", sizing_mode="stretch_width")
 
-For more details see the [Developer Guide](DEVELOPER_GUIDE.md)
+smiles="N[C@@H](CCC(=O)N[C@@H](CS)C(=O)NCC(=O)O)C(=O)O"
+editor = JSMEEditor(value=smiles, height=500, format="smiles")
 
-## FAQ
+editor.servable()
+```
 
-## 📰 Change Log
+Run `panel serve name_of_app.py` or `panel_serve name_of_notebook.ipynb`.
 
-- 0.0.12: Add PDBeMolstar component and py.typed file
-- 0.0.11: Add LICENSE and VERSION files to package. Now available on conda-forge
-- 0.0.10: Update to Panel 0.12.6.
-- 0.0.9: Add Py3DMol pane. Update to Panel 0.12.4.
+![JSME Editor](https://raw.githubusercontent.com/MarcSkovMadsen/panel-chemistry/main/assets/panel-chemistry-example.png)
diff --git a/VERSION b/VERSION
deleted file mode 100644
index 2e60e2a..0000000
--- a/VERSION
+++ /dev/null
@@ -1,1 +0,0 @@
-0.0.13
\ No newline at end of file
diff --git a/binder/postBuild b/binder/postBuild
index a0062f2..19d8d88 100644
--- a/binder/postBuild
+++ b/binder/postBuild
@@ -1,15 +1,13 @@
-panel build panel_chemistry
-pip install voila>=0.2.10 -U
-conda install -c conda-forge jupyter_contrib_nbextensions
+panel build src/panel_chemistry
+conda install -c conda-forge jupyter_contrib_nbextensions code-server
 jupyter nbextension enable codefolding/main
 jupyter nbextension enable collapsible_headings/main
 jupyter nbextension enable comment-uncomment/main
 jupyter nbextension enable hide_input/main
 jupyter nbextension enable scratchpad/main
 jupyter nbextension enable init_cell/main
-conda install -c conda-forge code-server
 code-server --install-extension ms-python.python
 SERVICE_URL=https://open-vsx.org/vscode/gallery ITEM_URL=https://open-vsx.org/vscode/item code-server --install-extension wesbos.theme-cobalt2
 SERVICE_URL=https://open-vsx.org/vscode/gallery ITEM_URL=https://open-vsx.org/vscode/item code-server --install-extension RandomFractalsInc.vscode-data-preview
 SERVICE_URL=https://open-vsx.org/vscode/gallery ITEM_URL=https://open-vsx.org/vscode/item code-server --install-extension RandomFractalsInc.geo-data-viewer
-SERVICE_URL=https://open-vsx.org/vscode/gallery ITEM_URL=https://open-vsx.org/vscode/item code-server --install-extension ritwickdey.liveserver
+SERVICE_URL=https://open-vsx.org/vscode/gallery ITEM_URL=https://open-vsx.org/vscode/item code-server --install-extension ritwickdey.liveserver
\ No newline at end of file
diff --git a/binder/requirements.txt b/binder/requirements.txt
index ae94bd3..82a6846 100644
--- a/binder/requirements.txt
+++ b/binder/requirements.txt
@@ -1,11 +1,14 @@
 -e .['all']
--e binder/jupyter-panel-apps-server/.
+colorcet
 holoviews
 hvplot
-colorcet
-pydeck
-pyecharts
-pyarrow
+jedi-language-server
+jupyter_bokeh
 jupyter_bokeh
 jupyter-vscode-proxy
 py3Dmol
+pyarrow
+pydeck
+pyecharts
+pyright
+voila
diff --git a/binder/start b/binder/start
index 87e49a0..428bcdb 100644
--- a/binder/start
+++ b/binder/start
@@ -1,5 +1,5 @@
 #!/bin/bash
-export BOKEH_ALLOW_WS_ORIGIN=hub.gke2.mybinder.org,notebooks.gesis.org
+export BOKEH_ALLOW_WS_ORIGIN=*.org
 echo '' >> panel/template/base.py
 echo 'BasicTemplate.param.site_url.default="./"' >> panel/template/base.py
 jupyter trust examples/*.ipynb
diff --git a/codecov.yml b/codecov.yml
deleted file mode 100644
index b6ee7c1..0000000
--- a/codecov.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-coverage:
-  status:
-    patch: off
-    project:
-      default:
-        target: auto
-        threshold: 0.5%
-
-comment:
-  require_changes: yes
diff --git a/mypy.ini b/mypy.ini
deleted file mode 100644
index f42c6dc..0000000
--- a/mypy.ini
+++ /dev/null
@@ -1,15 +0,0 @@
-[mypy]
-[mypy-invoke.*]
-ignore_missing_imports=True
-[mypy-setuptools.*]
-ignore_missing_imports=True
-[mypy-param.*]
-ignore_missing_imports=True
-[mypy-panel.*]
-ignore_missing_imports=True
-[mypy-bokeh.*]
-ignore_missing_imports=True
-[mypy-pyviz_comms.*]
-ignore_missing_imports=True
-[mypy-py3Dmol.*]
-ignore_missing_imports=True
diff --git a/panel_chemistry/bokeh_extensions/__init__.py b/panel_chemistry/bokeh_extensions/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pyproject.toml b/pyproject.toml
index 037585e..852789b 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,2 +1,101 @@
+[build-system]
+requires = ["setuptools",]
+build-backend = "setuptools.build_meta"
+[project]
+name = "panel-chemistry"
+description = "This purpose of this project ..."
+readme = "README.md"
+requires-python = ">=3.7"
+keywords = ["python", "holoviz", "panel", "dataviz", "dataapp"]
+license = {file = "LICENSE"}
+classifiers = [
+    "Programming Language :: Python :: 3.9"
+]
+dependencies = [
+    "hvplot",
+    "pandas",
+    "panel",
+]
+dynamic = ["version"]
+
+authors = [
+    {name = "awesome-panel"}
+]
+
+[project.optional-dependencies]
+dev = ["awesome-panel-cli"]
+all = ["jupyter", "jupyterlab", "awesome-panel-cli", "py3Dmol"]
+
+[project.urls]
+repository = "https://github.com/awesome-panel/panel-chemistry"
+
+[tool.setuptools.dynamic]
+version = {attr = "panel_chemistry.VERSION"}
+
 [tool.black]
-line-length = 100
\ No newline at end of file
+line-length = 100
+
+[tool.isort]
+profile = "black"
+src_paths = ["src", "tests"]
+
+[tool.pylint.main]
+py-version=3.9
+output-format = "colorized"
+max-attributes=12
+max-args=10
+
+[tool.pylint.format]
+max-module-lines = 1000
+max-line-length=100
+
+[tool.mypy]
+python_version = "3.9"
+namespace_packages = true
+explicit_package_bases = true
+mypy_path = "src"
+exclude = []
+
+[[tool.mypy.overrides]]
+module = [
+    "bokeh.*",
+    "holoviews.*",
+    "hvplot.*",
+    "param",
+    "pyviz_comms",
+    "py3Dmol",
+]
+ignore_missing_imports = true
+
+# https://github.com/pytest-dev/pytest/blob/main/pyproject.toml
+[tool.pytest.ini_options]
+minversion = "7.0"
+addopts = "-s"
+testpaths = ["tests"]
+junit_family = "legacy"
+python_files = ["tests.py","test_*.py"]
+markers = [
+    "unittest", # Small, isolated test
+    "integrationtest", # A test towards some external system or service. For example a database
+    "functionaltest", # Large potentially non-isolated test requiring access to external services
+    "slow", # A slow test. Skip normally. But run this when you have the time.
+    "skip_in_build_server", # Tests that should be skipped on the build server
+]
+filterwarnings=[
+    "ignore:the imp module is deprecated in favour of importlib.*:DeprecationWarning", 
+    "ignore:inspect.getargspec.*:DeprecationWarning"
+]
+
+[tool.coverage.run]
+omit=[]
+
+[html]
+directory="test_results/cov_html"
+skip_empty=true
+
+[tool.bandit]
+exclude_dirs = [".venv", "venv",]
+severity="high"
+
+[tool.bandit.assert_used]
+exclude = ["*_test.py", "test_*.py"]
\ No newline at end of file
diff --git a/script.py b/script.py
deleted file mode 100644
index 3708606..0000000
--- a/script.py
+++ /dev/null
@@ -1,15 +0,0 @@
-import panel as pn
-
-pn.extension()
-
-
-def f(x):
-    return pn.pane.Markdown(x, sizing_mode="stretch_width")
-
-
-layout = pn.interact(
-    f,
-    x="Hi there!",
-)
-layout.sizing_mode = "stretch_width"
-layout.servable()
diff --git a/setup.py b/setup.py
deleted file mode 100644
index cf79e03..0000000
--- a/setup.py
+++ /dev/null
@@ -1,100 +0,0 @@
-"""Setup file for the Panel Chemistry"""
-import pathlib
-from typing import List
-
-import setuptools
-
-with open("README.md", "r", encoding="utf-8") as fh:
-    long_description = fh.read()
-
-ROOT = pathlib.Path.cwd()
-VERSION = (ROOT / "VERSION").read_text(encoding="utf-8").strip()
-
-install_requires = [
-    "numpy",
-    "panel>=0.12.7,<0.14",
-    "bokeh>=2.4.2,<3.0",
-    "param>=1.12.1",
-]
-
-_recommended: List[str] = []
-
-_tests = [
-    "autoflake",
-    "invoke",
-    "isort",
-    "jupyter-repo2docker",
-    "mypy",
-    "pylint>=2.6.0",
-    "pytest",
-    "pytest-cov",
-    "rope",
-    "twine",
-    "wheel",
-    "codecov",
-]
-
-_examples = [
-    "notebook",
-    "jupyterlab",
-    "py3Dmol",
-]
-
-_doc: List[str] = []
-
-extras_require = {
-    "examples": _recommended + _examples,
-    "tests": _tests,
-    "recommended": _recommended,
-    "doc": _recommended + _doc,
-}
-
-extras_require["all"] = sorted(set(sum(extras_require.values(), [])))
-
-setuptools.setup(
-    name="panel-chemistry",
-    version=VERSION,
-    description="This package makes it easy to work with Chemistry using Python and HoloViz Panel",
-    long_description_content_type="text/markdown",
-    long_description=long_description,
-    author="Marc Skov Madsen et al.",
-    author_email="marc.skov.madsen@gmail.com",
-    platforms=["Windows", "Mac OS X", "Linux"],
-    license="Apache 2",
-    url="https://github.com/MarcSkovMadsen/panel-chemistry",
-    # My Project contains more folders/ packages but they should not be included
-    packages=setuptools.find_packages(include=["panel_chemistry", "panel_chemistry.*"]),
-    include_package_data=True,
-    classifiers=[
-        # I would like to indicate that this package is a package for the Panel framework
-        "License :: OSI Approved :: Apache Software License",
-        "Development Status :: 3 - Alpha",
-        "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.7",
-        "Programming Language :: Python :: 3.8",
-        "Programming Language :: Python :: 3.9",
-        "Programming Language :: Python :: 3.10",
-        "Operating System :: OS Independent",
-        "Intended Audience :: Developers",
-        "Intended Audience :: Education",
-        "Intended Audience :: Financial and Insurance Industry",
-        "Intended Audience :: Healthcare Industry",
-        "Intended Audience :: Information Technology",
-        "Intended Audience :: Legal Industry",
-        "Intended Audience :: Other Audience",
-        "Intended Audience :: Science/Research",
-        "Natural Language :: English",
-        "Topic :: Office/Business :: Financial",
-        "Topic :: Office/Business",
-        "Topic :: Scientific/Engineering :: Bio-Informatics",
-        "Topic :: Scientific/Engineering :: Chemistry",
-        "Topic :: Scientific/Engineering :: Information Analysis",
-        "Topic :: Scientific/Engineering :: Visualization",
-        "Topic :: Scientific/Engineering",
-        "Topic :: Software Development :: Libraries",
-    ],
-    python_requires=">=3.6",
-    install_requires=install_requires,
-    extras_require=extras_require,
-    tests_require=extras_require["tests"],
-)
diff --git a/src/panel_chemistry/__init__.py b/src/panel_chemistry/__init__.py
new file mode 100644
index 0000000..6c5c26c
--- /dev/null
+++ b/src/panel_chemistry/__init__.py
@@ -0,0 +1,5 @@
+"""The Panel Chemistry package makes it super simple to do **exploratory data analysis** and
+develop high-quality [Panel](https://awesome-panel.org) **data apps** within the domain of
+**chemistry**.
+"""
+VERSION = "0.0.13"
diff --git a/panel_chemistry/bokeh.ext.json b/src/panel_chemistry/bokeh.ext.json
similarity index 100%
rename from panel_chemistry/bokeh.ext.json
rename to src/panel_chemistry/bokeh.ext.json
diff --git a/panel_chemistry/__init__.py b/src/panel_chemistry/bokeh_extensions/__init__.py
similarity index 100%
rename from panel_chemistry/__init__.py
rename to src/panel_chemistry/bokeh_extensions/__init__.py
diff --git a/panel_chemistry/bokeh_extensions/index.ts b/src/panel_chemistry/bokeh_extensions/index.ts
similarity index 100%
rename from panel_chemistry/bokeh_extensions/index.ts
rename to src/panel_chemistry/bokeh_extensions/index.ts
diff --git a/panel_chemistry/bokeh_extensions/jsme_editor.py b/src/panel_chemistry/bokeh_extensions/jsme_editor.py
similarity index 100%
rename from panel_chemistry/bokeh_extensions/jsme_editor.py
rename to src/panel_chemistry/bokeh_extensions/jsme_editor.py
diff --git a/panel_chemistry/bokeh_extensions/jsme_editor.ts b/src/panel_chemistry/bokeh_extensions/jsme_editor.ts
similarity index 100%
rename from panel_chemistry/bokeh_extensions/jsme_editor.ts
rename to src/panel_chemistry/bokeh_extensions/jsme_editor.ts
diff --git a/panel_chemistry/bokeh_extensions/ngl_viewer.py b/src/panel_chemistry/bokeh_extensions/ngl_viewer.py
similarity index 100%
rename from panel_chemistry/bokeh_extensions/ngl_viewer.py
rename to src/panel_chemistry/bokeh_extensions/ngl_viewer.py
diff --git a/panel_chemistry/bokeh_extensions/ngl_viewer.ts b/src/panel_chemistry/bokeh_extensions/ngl_viewer.ts
similarity index 100%
rename from panel_chemistry/bokeh_extensions/ngl_viewer.ts
rename to src/panel_chemistry/bokeh_extensions/ngl_viewer.ts
diff --git a/panel_chemistry/index.ts b/src/panel_chemistry/index.ts
similarity index 100%
rename from panel_chemistry/index.ts
rename to src/panel_chemistry/index.ts
diff --git a/panel_chemistry/package-lock.json b/src/panel_chemistry/package-lock.json
similarity index 97%
rename from panel_chemistry/package-lock.json
rename to src/panel_chemistry/package-lock.json
index b7aed06..6f9a87c 100644
--- a/panel_chemistry/package-lock.json
+++ b/src/panel_chemistry/package-lock.json
@@ -1,16 +1,16 @@
 {
   "name": "panel_chemistry",
-  "version": "0.0.12",
+  "version": "0.0.13",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
-      "version": "0.0.12",
+      "name": "panel_chemistry",
+      "version": "0.0.13",
       "license": "Apache 2.0",
       "dependencies": {
-        "@bokeh/bokehjs": "^2.4.2"
-      },
-      "devDependencies": {}
+        "@bokeh/bokehjs": "^2.4.3"
+      }
     },
     "node_modules/@babel/runtime": {
       "version": "7.14.0",
@@ -21,9 +21,9 @@
       }
     },
     "node_modules/@bokeh/bokehjs": {
-      "version": "2.4.2",
-      "resolved": "https://registry.npmjs.org/@bokeh/bokehjs/-/bokehjs-2.4.2.tgz",
-      "integrity": "sha512-ynOO63suiYKtTxBBdfLRZIRRiAAeG5efjHWx0KIbMpWFPGCVwz9iYuJRQLob8TsbVdbCtDO91+DrQo/mK9iXZA==",
+      "version": "2.4.3",
+      "resolved": "https://registry.npmjs.org/@bokeh/bokehjs/-/bokehjs-2.4.3.tgz",
+      "integrity": "sha512-zORGCM+3A2if+owfH03QFCL4GdnkhZizMlGjjGekAOp7Hc4TRqH9rQolEKKaNov7pmIay/VAMjZX4pyMXYW+Ag==",
       "dependencies": {
         "@bokeh/numbro": "^1.6.2",
         "@bokeh/slickgrid": "~2.4.2702",
@@ -280,9 +280,9 @@
       "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
     },
     "node_modules/jquery-ui": {
-      "version": "1.13.0",
-      "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.13.0.tgz",
-      "integrity": "sha512-Osf7ECXNTYHtKBkn9xzbIf9kifNrBhfywFEKxOeB/OVctVmLlouV9mfc2qXCp6uyO4Pn72PXKOnj09qXetopCw==",
+      "version": "1.13.2",
+      "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.13.2.tgz",
+      "integrity": "sha512-wBZPnqWs5GaYJmo1Jj0k/mrSkzdQzKDwhXNtHKcBdAcKVxMM3KNYFq+iJ2i1rwiG53Z8M4mTn3Qxrm17uH1D4Q==",
       "dependencies": {
         "jquery": ">=1.8.0 <4.0.0"
       }
@@ -417,9 +417,9 @@
       }
     },
     "@bokeh/bokehjs": {
-      "version": "2.4.2",
-      "resolved": "https://registry.npmjs.org/@bokeh/bokehjs/-/bokehjs-2.4.2.tgz",
-      "integrity": "sha512-ynOO63suiYKtTxBBdfLRZIRRiAAeG5efjHWx0KIbMpWFPGCVwz9iYuJRQLob8TsbVdbCtDO91+DrQo/mK9iXZA==",
+      "version": "2.4.3",
+      "resolved": "https://registry.npmjs.org/@bokeh/bokehjs/-/bokehjs-2.4.3.tgz",
+      "integrity": "sha512-zORGCM+3A2if+owfH03QFCL4GdnkhZizMlGjjGekAOp7Hc4TRqH9rQolEKKaNov7pmIay/VAMjZX4pyMXYW+Ag==",
       "requires": {
         "@bokeh/numbro": "^1.6.2",
         "@bokeh/slickgrid": "~2.4.2702",
@@ -660,9 +660,9 @@
       "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
     },
     "jquery-ui": {
-      "version": "1.13.0",
-      "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.13.0.tgz",
-      "integrity": "sha512-Osf7ECXNTYHtKBkn9xzbIf9kifNrBhfywFEKxOeB/OVctVmLlouV9mfc2qXCp6uyO4Pn72PXKOnj09qXetopCw==",
+      "version": "1.13.2",
+      "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.13.2.tgz",
+      "integrity": "sha512-wBZPnqWs5GaYJmo1Jj0k/mrSkzdQzKDwhXNtHKcBdAcKVxMM3KNYFq+iJ2i1rwiG53Z8M4mTn3Qxrm17uH1D4Q==",
       "requires": {
         "jquery": ">=1.8.0 <4.0.0"
       }
diff --git a/panel_chemistry/package.json b/src/panel_chemistry/package.json
similarity index 70%
rename from panel_chemistry/package.json
rename to src/panel_chemistry/package.json
index aa5310b..2f39473 100644
--- a/panel_chemistry/package.json
+++ b/src/panel_chemistry/package.json
@@ -1,11 +1,10 @@
 {
   "name": "panel_chemistry",
-  "version": "0.0.12",
+  "version": "0.0.13",
   "description": "Panel extension for data analysis and data apps within the domain of Chemistry",
   "license": "Apache 2.0",
   "keywords": [],
   "dependencies": {
-    "@bokeh/bokehjs": "^2.4.2"
-  },
-  "devDependencies": {}
+    "@bokeh/bokehjs": "^2.4.3"
+  }
 }
diff --git a/panel_chemistry/pane/__init__.py b/src/panel_chemistry/pane/__init__.py
similarity index 100%
rename from panel_chemistry/pane/__init__.py
rename to src/panel_chemistry/pane/__init__.py
diff --git a/panel_chemistry/pane/ngl_viewer.py b/src/panel_chemistry/pane/ngl_viewer.py
similarity index 98%
rename from panel_chemistry/pane/ngl_viewer.py
rename to src/panel_chemistry/pane/ngl_viewer.py
index 15191a3..ca8c1d0 100644
--- a/panel_chemistry/pane/ngl_viewer.py
+++ b/src/panel_chemistry/pane/ngl_viewer.py
@@ -7,7 +7,6 @@
 Author: https://github.com/Jhsmit
 """
 
-from typing import Dict
 
 import param
 from panel import extension
@@ -92,7 +91,7 @@
 ]
 
 
-class NGLViewer(PaneBase):
+class NGLViewer(PaneBase):  # pylint: disable=too-many-ancestors
     """The [NGL Viewer](https://github.com/nglviewer/ngl) can be used
     to show and analyse pdb molecule structures"""
 
@@ -140,7 +139,7 @@ class NGLViewer(PaneBase):
 
     priority = None
 
-    _rename: Dict[str, str] = {}
+    _rename = {}
 
     _updates = True
 
diff --git a/panel_chemistry/pane/pdbe_molstar.py b/src/panel_chemistry/pane/pdbe_molstar.py
similarity index 99%
rename from panel_chemistry/pane/pdbe_molstar.py
rename to src/panel_chemistry/pane/pdbe_molstar.py
index c99922e..7e3d06d 100644
--- a/panel_chemistry/pane/pdbe_molstar.py
+++ b/src/panel_chemistry/pane/pdbe_molstar.py
@@ -30,7 +30,7 @@
 ]
 
 # See https://embed.plnkr.co/plunk/m3GxFYx9cBjIanBp for an example JS implementation
-class PDBeMolStar(ReactiveHTML):
+class PDBeMolStar(ReactiveHTML):  # pylint: disable=too-many-ancestors
     """PDBe MolStar structure viewer.
 
     Set one of `molecule_id`, `custom_data` and `ligand_view`.
diff --git a/panel_chemistry/pane/py3dmol_viewer.py b/src/panel_chemistry/pane/py3dmol_viewer.py
similarity index 94%
rename from panel_chemistry/pane/py3dmol_viewer.py
rename to src/panel_chemistry/pane/py3dmol_viewer.py
index b24279a..9ad7657 100644
--- a/panel_chemistry/pane/py3dmol_viewer.py
+++ b/src/panel_chemistry/pane/py3dmol_viewer.py
@@ -15,7 +15,8 @@
     # pylint: disable=invalid-name
     class py3Dmol(param.Parameterized):  # type: ignore
         """Dummy py3Dmol class"""
-        view = param.String('mock_view')  # allow to import the file
+
+        view = param.String("mock_view")  # allow to import the file
 
 
 def _clean_html(html):
@@ -53,7 +54,7 @@ class Py3DMol(pn.viewable.Viewer):
     """,
     )
 
-    def __init__(self, object: py3Dmol.view = None, **params): # pylint: disable=redefined-builtin
+    def __init__(self, object: py3Dmol.view = None, **params):  # pylint: disable=redefined-builtin
         """A Panel Pane to wrap the interactive py3Dmol/ 3Dmol.js viewer in your Panel Application.
 
         Check out
diff --git a/panel_chemistry/py.typed b/src/panel_chemistry/py.typed
similarity index 100%
rename from panel_chemistry/py.typed
rename to src/panel_chemistry/py.typed
diff --git a/panel_chemistry/tsconfig.json b/src/panel_chemistry/tsconfig.json
similarity index 100%
rename from panel_chemistry/tsconfig.json
rename to src/panel_chemistry/tsconfig.json
diff --git a/panel_chemistry/widgets/__init__.py b/src/panel_chemistry/widgets/__init__.py
similarity index 100%
rename from panel_chemistry/widgets/__init__.py
rename to src/panel_chemistry/widgets/__init__.py
diff --git a/panel_chemistry/widgets/jsme_editor.py b/src/panel_chemistry/widgets/jsme_editor.py
similarity index 98%
rename from panel_chemistry/widgets/jsme_editor.py
rename to src/panel_chemistry/widgets/jsme_editor.py
index 254843d..fdece4f 100644
--- a/panel_chemistry/widgets/jsme_editor.py
+++ b/src/panel_chemistry/widgets/jsme_editor.py
@@ -58,7 +58,7 @@
 # fmt: on
 
 
-class JSMEEditor(Widget):
+class JSMEEditor(Widget):  # pylint: disable=too-many-ancestors
     """The panel-chemistry JSME Molecule Editor enables you to draw and edit molecules using Python
     and Panel.
     It is a wrapper of the free javascript JSME Molecule Editor.
diff --git a/tasks/__init__.py b/tasks/__init__.py
deleted file mode 100644
index 3720738..0000000
--- a/tasks/__init__.py
+++ /dev/null
@@ -1,11 +0,0 @@
-"""Here we import the different task submodules/ collections"""
-from invoke import Collection
-
-from . import build, show, test
-
-# pylint: disable=invalid-name
-# as invoke only recognizes lower case
-namespace = Collection()
-namespace.add_collection(build)
-namespace.add_collection(show)
-namespace.add_collection(test)
diff --git a/tasks/build.py b/tasks/build.py
deleted file mode 100644
index 48efc06..0000000
--- a/tasks/build.py
+++ /dev/null
@@ -1,56 +0,0 @@
-"""Module of Invoke build tasks to be invoked from the command line. Try
-
-invoke --list=build
-
-from the command line for a list of all available commands.
-"""
-
-from invoke import task
-
-
-@task(aliases=["extensions"])
-def bokeh_extensions(command):
-    """Builds the Bokeh extensions using Node.js
-
-    Please note this requires Node.js>=14 to be installed
-    """
-    print(
-        """Builds the Bokeh extensions using Node.js
-
-Please note this requires Node.js>=14 to be installed
-=====================================================
-"""
-    )
-    command.run("panel build panel_chemistry", echo=True)
-
-
-@task(aliases=["package"])
-def python_package(command):
-    """Builds the panel-chemistry Python package
-
-    Remember to update the version number in the VERSION file!
-    """
-    print(
-        """Builds the panel-chemistry Python package
-
-Remember to update the version number in the VERSION file!
-=================================================
-"""
-    )
-    command.run("python setup.py sdist bdist_wheel", echo=True)
-
-
-@task(aliases=["binder"])
-def binder_image(command):
-    """Builds the panel-chemistry binder image using jupyter-repo2docker
-
-
-    Please note this does not work on Windows"""
-    print(
-        """Builds the panel-chemistry binder image using jupyter-repo2docker
-
-Please note this does not work on Windows
-=========================================
-"""
-    )
-    command.run("jupyter-repo2docker .", echo=True)
diff --git a/tasks/show.py b/tasks/show.py
deleted file mode 100644
index ce2cf43..0000000
--- a/tasks/show.py
+++ /dev/null
@@ -1,76 +0,0 @@
-"""Module of Invoke starts tasks to be invoked from the command line. Try
-
-invoke --list=start
-
-from the command line for a list of all available commands.
-"""
-
-from glob import glob
-from pathlib import Path
-from typing import List
-
-from invoke import task
-
-DONT_SERVE: List[str] = []
-
-
-def _get_active_branch_name():
-
-    head_dir = Path(".") / ".git" / "HEAD"
-    with head_dir.open("r", encoding="utf-8") as file:
-        content = file.read().splitlines()
-
-    for line in content:
-        if line[0:4] == "ref:":
-            return line.partition("refs/heads/")[2]
-    return "main"
-
-
-def _get_apps():
-    return [
-        app for app in glob("examples/reference/*.ipynb", recursive=True) if not app in DONT_SERVE
-    ]
-
-
-@task()
-def binder(command):
-    """Opens the current branch on Binder."""
-    print(
-        """
-Opens the current branch on Binder.
-=================================================
-"""
-    )
-    branch = _get_active_branch_name()
-    url = (
-        f"https://mybinder.org/v2/gh/MarcSkovMadsen/panel-chemistry/{branch}"
-        "?urlpath=lab/tree/examples"
-    )
-    command.run(f"python -m webbrowser {url}", echo=True)
-
-
-@task()
-def github(command):
-    """Opens the current branch on Github."""
-    print(
-        """
-Opens the current branch on Github.
-=================================================
-"""
-    )
-    branch = _get_active_branch_name()
-    url = f"https://github.com/MarcSkovMadsen/panel-chemistry/tree/{branch}"
-    command.run(f"python -m webbrowser {url}", echo=True)
-
-
-@task()
-def examples(command):
-    """Panel serves the examples notebooks."""
-    print(
-        """
-Panel serves the example notebooks.
-===================================
-"""
-    )
-    apps = _get_apps()
-    command.run(f"panel serve {' '.join(apps)} --auto --show", echo=True)


Test patch:
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index f7790d6..4b1f880 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -15,22 +15,28 @@ jobs:
     strategy:
       matrix:
         os: ['ubuntu-latest', 'macos-latest', 'windows-latest']
-        python-version: [3.7, 3.8, 3.9]
+        python-version: [3.7, 3.8, 3.9, '3.10']
         exclude:
           - os: windows-latest
-            python-version: 3.7
+            python-version: 3.8
           - os: windows-latest
             python-version: 3.9
+          - os: windows-latest
+            python-version: '3.10'
           - os: macos-latest
-            python-version: 3.7
+            python-version: 3.8
           - os: macos-latest
             python-version: 3.9
+          - os: macos-latest
+            python-version: '3.10'
 
     env:
       CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
       GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
       - uses: actions/checkout@v2
+        with:
+            fetch-depth: "1"
       - name: Set up Python ${{ matrix.python-version }}
         uses: actions/setup-python@v2
         with:
@@ -41,19 +47,27 @@ jobs:
           pip install -e .[all]
       - name: Run Pylint
         run: |
-          invoke test.pylint
+          pn test pylint
         if: always()
       - name: Run MyPy
         run: |
-          invoke test.mypy
+          pn test mypy
         if: always()
       - name: Run Pytest
         run: |
-          pytest tests --cov=panel_chemistry --cov-report html:test_results/cov_html
+          pn test bandit
         if: always()
-      - name: Upload Coverage
-        uses: actions/upload-artifact@v2
-        with:
-          name: code-coverage-report
-          path: test_results/cov_html
+      - name: Run Pytest
+        run: |
+          pn test pytest --report
         if: always()
+      - name: Upload Test Reports
+        uses: actions/upload-artifact@v3
+        with:
+          name: test-results
+          path: test_results/*.xml
+        if: always()      
+      - name: Upload coverage to Codecov
+        uses: codecov/codecov-action@v3
+        with:
+          files: test_results/coverage.xml
\ No newline at end of file
diff --git a/pytest.ini b/pytest.ini
deleted file mode 100644
index 85165b1..0000000
--- a/pytest.ini
+++ /dev/null
@@ -1,8 +0,0 @@
-[pytest]
-testpaths = tests
-junit_family=legacy
-python_files = tests.py test_*.py *_tests.py
-markers =
-    unittest: Small, isolated test
-    functionaltest: Large potentially non-isolated test requiring access to external services
-    slow: A slow test. Skip normally. But run this when you have the time.
\ No newline at end of file
diff --git a/tasks/test.py b/tasks/test.py
deleted file mode 100644
index c83626c..0000000
--- a/tasks/test.py
+++ /dev/null
@@ -1,177 +0,0 @@
-"""Module of Invoke test tasks for testing the CODE QUALITY to be invoked from the command line. Try
-
-invoke --list=test
-
-from the command line for a list of all available commands.
-"""
-
-from invoke import task
-
-
-@task()
-def bandit(command):
-    """Runs Bandit the security linter from PyCQA."""
-    print(
-        """
-Running Bandit the Python Security Linter
-to identify common security issues in Python code
-=================================================
-"""
-    )
-    command.run("bandit -r ./", echo=True)
-
-
-@task()
-def black(command):
-    """Runs black (autoformatter) on all .py files recursively"""
-    print(
-        """
-Running Black the Python code formatter
-=======================================
-"""
-    )
-    command.run("black .", echo=True)
-
-
-@task()
-def isort(command):
-    """Runs isort (import sorter) on all .py files recursively"""
-    print(
-        """
-Running isort the Python code import sorter
-===========================================
-"""
-    )
-    command.run("isort .", echo=True)
-
-
-@task
-def pytest(
-    command,
-    test_files="tests",
-    integrationtest=False,
-    test_results="test_results",
-    open_results=True,
-):
-    """Runs pytest to identify failing tests
-
-    Arguments:
-        command {[type]} -- Invoke command object
-
-    Keyword Arguments:
-        root_dir {str} -- The directory from which to run the tests
-        test_files {str} -- A space separated list of folders and files to test. (default: {'tests})
-        integrationtest {bool} -- If True tests marked integrationtest or functionaltest will be
-            run. Otherwise not. (default: {False})
-        test_results {string} -- If not None test reports will be generated in the test_results
-            folder
-        open_results {bool} -- If True test reports in the 'test_results' folder will be opened in
-            a browser
-
-    # Print running pytest
-    """
-    print(
-        """
-Running pytest the test framework
-=================================
-"""
-    )
-    # Build the command_string
-    command_string = f"pytest {test_files} --doctest-modules --cov=panel_chemistry"
-    if not integrationtest:
-        command_string += ' -m "not functionaltest and not integrationtest"'
-    if test_results:
-        # command_string += f" --junitxml={test_results}/test-results-api.xml"
-        command_string += f" --cov-report html:{test_results}/cov_html"
-
-    # Run the command_string
-    command.run(command_string, echo=True)
-
-    # Open the test coverage report in a browser
-    if test_results and open_results:
-        command.run("start test_results/cov_html/index.html")
-
-
-@task()
-def pylint(command, files="setup.py tasks panel_chemistry tests"):
-    """Runs pylint (linter) on all .py files recursively to identify coding errors
-
-    Arguments:
-        command {[type]} -- [description]
-        files {string} -- A space separated list of files and folders to lint
-    """
-    # https://stackoverflow.com/questions/22241435/pylint-discard-cached-file-state
-    # from astroid import MANAGER
-    # MANAGER.astroid_cache.clear()
-    print(
-        """
-Running pylint.
-Pylint looks for programming errors, helps enforcing a coding standard,
-sniffs for code smells and offers simple refactoring suggestions.
-=======================================================================
-"""
-    )
-    command_string = f"pylint {files}"
-    command.run(command_string, echo=True)
-
-
-@task
-def mypy(command, files="setup.py tasks panel_chemistry tests"):
-    """Runs mypy (static type checker) on all .py files recursively
-
-    Arguments:
-        command {[type]} -- [description]
-        files {string} -- A space separated list of files and folders to lint
-    """
-    print(
-        """
-Running mypy for identifying python type errors
-===============================================
-"""
-    )
-    command_string = f"mypy {files}"
-    command.run(command_string, echo=True)
-
-
-@task
-def autoflake(command):
-    """Runs autoflake to remove unused imports on all .py files recursively
-
-    Arguments:
-        command {[type]} -- [description]
-    """
-    print(
-        """
-Running autoflake to remove unused imports on all .py files recursively
-=======================================================================
-"""
-    )
-    # command.run("RUN rm -rf .mypy_cache/; exit 0")
-    command.run(
-        "autoflake "
-        "--imports=pytest,pandas,numpy,panel,holoviews,hvplot,plotly,urllib3,pathlib "
-        "--in-place --recursive .",
-        echo=True,
-    )
-
-
-@task(
-    pre=[isort, autoflake, black, pylint, mypy, pytest],
-    aliases=["pre_commit", "test"],
-    name="all",
-)
-def _all(command):  # pylint: disable=unused-argument
-    """Runs isort, autoflake, black, pylint, mypy and pytest
-
-    Arguments:
-        command {[type]} -- [description]
-    """
-    # If we get to this point all tests listed in 'pre' have passed
-    # unless we have run the task with the --warn flag
-    if not command.config.run.warn:
-        print(
-            """
-All Tests Passed Successfully
-=============================
-"""
-        )