https://github.com/cannlytics/cannlytics-website
The ๐ฅ Cannlytics Website ๐ provides people with information about Cannlytics, cannabis analytics, and boasts a cannabis data market ๐๏ธ
https://github.com/cannlytics/cannlytics-website
analytics cannabis cannabis-api cannabis-app cannabis-data cannabisapp data-marketplace django firebase metrc python statistics
Last synced: 4 days ago
JSON representation
The ๐ฅ Cannlytics Website ๐ provides people with information about Cannlytics, cannabis analytics, and boasts a cannabis data market ๐๏ธ
- Host: GitHub
- URL: https://github.com/cannlytics/cannlytics-website
- Owner: cannlytics
- License: mit
- Created: 2020-10-17T16:12:23.000Z (over 5 years ago)
- Default Branch: main
- Last Pushed: 2025-01-08T05:40:49.000Z (over 1 year ago)
- Last Synced: 2025-10-27T18:36:55.681Z (8 months ago)
- Topics: analytics, cannabis, cannabis-api, cannabis-app, cannabis-data, cannabisapp, data-marketplace, django, firebase, metrc, python, statistics
- Language: Python
- Homepage: https://cannlytics.com
- Size: 20.5 MB
- Stars: 5
- Watchers: 1
- Forks: 0
- Open Issues: 20
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
Simple, easy, cannabis analytics.
[](https://opensource.org/licenses/MIT)
[](https://pypi.org/project/cannlytics)
[](https://pypi.python.org/pypi/cannlytics/)
The ๐ฅ Cannlytics Website provides an aesthetic user interface for users to learn about Cannlytics and get set up with everything that they need to utilize Cannlytics to its fullest extent. This documentation explains the Cannlytics Website architecture and how to build, develop, and publish the website.
- [๐ฅ Introduction](#introduction)
- [๐ชด Installation](#installation)
- [๐๏ธ Architecture](#architecture)
- [๐ Development](#development)
* [Editing](#editing)
* [Running](#running)
* [Serving](#serving)
- [๐งช Testing](#testing)
- [๐ Publishing](#publishing)
The `cannlytics` package is the core module implementing cannabis analytics logic. The `cannlytics` module handles [database interactions](#data), [file management](#storage), [authentication and authorization](#authentication), traceability, data importing and exporting, and the logic for all workflows, such as certificate creation, item transfers, and publishing results. The `api` is the interface between the user application and the cannabis analytics logic of `cannlytics`. The `console` is the user application where user's can interface with the infrastructure, such as the database, and utilize the cannabis analytics logic. The `docs` provide information about the project and the `website` provides people with information about cannabis analytics. You can also use the `ai` to automatically collect, augment, and make inferences from data.
In brief, installation entails:
1. [Cloning the repository.](#cloning-the-repository)
2. [Setting your Firebase account credentials.](#setting-your-account-credentials)
3. [Installing project dependencies and development tools.](#installing-dependencies)
The best place to begin is to clone the repository and get a lay of the architecture.
```shell
git clone https://github.com/cannlytics/cannlytics.git
```
The architecture of the Cannlytics codebase is as follows.
```bash
โโโ .admin
โ โโโ tokens
โ โโโ your-firebase-service-account.json
โโโ .firebase
โ โโโ firestore.indexes # Available database queries.
โ โโโ firestore.rules # Database access control and data validation.
| โโโ storage.rules # File storage access control and validation.
โโโ ai
โ โโโ curation # Tools for automatically cleaning and augmenting data.
โ โโโ functions # Tools for automatically collecting data.
| โโโ inference # Tools for automatically making inferences from data.
โโโ api
โ โโโ {endpoint}
โ | โโโ {endpoint}.py # Implementation of specific API endpoints.
โ โโโ urls.py # Defined API endpoints.
| โโโ views.py # Implementation of general API endpoints.
โโโ cannlytics
โ โโโ auth # Core authentication logic.
โ โโโ ccrs # Interface to Washington State's traceability system.
โ โโโ charts # Crispy, ready-to-use charts.
โ โโโ data # Data logic, from wrangling to market.
โ โโโ firebase # Interface to Firebase.
โ โโโ lims # All laboratory information management (LIMS) logic.
โ โโโ metrc # Interface to the Metrc traceability system.
โ โโโ models # Defined models.
โ โโโ paypal # Interface to PayPal.
โ โโโ quickbooks # Interface to QuickBooks.
โ โโโ stats # Nifty, ready-to-use statistical models.
โ โโโ utils # General utility functions.
โ โโโ cannlytics.py # Core Cannlytics interface.
| โโโ requirements.txt # Package-specific requirements.
โโโ console
โ โโโ assets
โ | โโโ css # Stylesheets that will be minified and bundled.
โ | โโโ js # JavaScript that will be bundled into a `cannlytics.min.js` module.
โ โโโ core # Required Django configuration.
โ โโโ static/console # Static files, such as images and Excel templates.
โ โโโ templates/console # User interface templates.
โ โโโ templatetags # Custom Django template utility functions.
โ โโโ views # Implementation of user interfaces and their context.
โ | โโโ {view}.py # Views for specific purposes.
โ โโโ db.sqlite3 # Unused SQL database.
โ โโโ Dockerfile # Production configuration.
โ โโโ requirements.txt # Console-specific requirements.
โ โโโ settings.py # Django configuration.
โ โโโ state.py # Static text for certain pages and sections.
โ โโโ urls.py # Console navigation.
| โโโ webpack.config.js # Build configuration.
โโโ docs
โ โโโ {src} # Specific documentation.
โ โโโ theme # The style of the documentation site.
| โโโ Dockerfile # Documentation container configuration.
โโโ node_modules
โโโ public # Files hosted with Firebase hosting.
โโโ tests # Tests for all features and functionality.
โโโ tools # Administrative, developer, and data management tools.
โโโ website # A company website with the same structure as the `console`.
โโโ .env # Your secrets.
โโโ .firebasesrc # Firebase hosting sources.
โโโ .gitignore # Files not committed to GitHub.
โโโ firebase.json # Firebase configuration file.
โโโ manage.py # Django utility script.
โโโ mkdocs.yaml # Documentation configuration.
โโโ package.json # Node.js dependencies and scripts.
โโโ requirements.txt # All Python requirements.
โโโ setup.py # Python SDK configuration.
```
### 2. Installing project dependencies and development tools
You will need to install the following technologies when developing or creating an installation of Cannlytics. We recommend using the latest stable version of each piece of software whenever possible. Cannlytics has been tested with Python 3.9.
* [Python](https://www.python.org/psf/)
* [Docker](https://docs.docker.com/get-docker/)
* [Node.js](https://nodejs.org/en/about/)
The standard installation requires that you have an account with:
* [Firebase](https://firebase.google.com/)
* [Google Cloud Platform](https://cloud.google.com/gcp)
If you are developing Cannlytics, then you will need a couple extra tools:
* [Firebase Tools](https://firebase.google.com/docs/cli)
* [Google Cloud SDK](https://dl.google.com/dl/cloudsdk/channels/rapid/GoogleCloudSDKInstaller.exe)
We recommend using [Anaconda](https://docs.anaconda.com/anaconda/install/index.html) if you are developing Cannlytics so that you can create a virtual environment to test, develop, and use the Cannlytics Console in isolation and in a reproducible manner. After installing Anaconda, you can open a terminal and run the following commands to create a ready-to-go environment.
```bash
conda create --name cannlytics python=3.9
conda activate cannlytics
pip install -r requirements.txt
python manage.py migrate
npm install
```
> Note that `python manage.py migrate` creates a new `db.sqlite3` file if you do not have one already.
### 3. Setting your account credentials
For a standard setup, you will need to [create a Firebase account and a project](https://console.firebase.google.com/). We recommend choosing a project name that is in kebab-case, e.g. `your-lims`, so that you can safely use the project name in many places. Now, follow these steps to fill in your environment variables. When publishing, you will need to copy pertinent environment variables to a [Google Cloud Secret](https://codelabs.developers.google.com/codelabs/cloud-run-django/index.html?index=..%2F..index#4).
1. Create an `.env` file in your project's root directory. See `.env.example` for an example with all credentials.
2. Create a Django secret key:
```py
# tools/quickstart.py
from django.utils.crypto import get_random_string
# Generate a secret key for your project.
chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)'
generated_secret_key = get_random_string(50, chars)
print(generated_secret_key)
```
And save it in your `.env` file:
```bash
# .env
SECRET_KEY=xyz
```
3. [Create a Firebase web app](https://firebase.google.com/docs/web/setup). We recommend using the same namespace you chose for your project, e.g. `your-lims` or `your-lims-dev`, and setting up [Firebase Hosting](https://firebase.google.com/docs/hosting) with your app. Once you have created a Firebase web app, navigate to your Firebase project settings, find your Firebase App Config, and set your Firebase configuration in your `.env` file.
```bash
# .env
FIREBASE_API_KEY=xyz
FIREBASE_AUTH_DOMAIN=your-lims.firebaseapp.com
FIREBASE_DATABASE_URL=https://your-lims.firebaseio.com
FIREBASE_PROJECT_ID=your-lims
FIREBASE_STORAGE_BUCKET=your-lims.appspot.com
FIREBASE_MESSAGING_SENDER_ID=123
FIREBASE_APP_ID=123
FIREBASE_MEASUREMENT_ID=G-abc
```
4. If you wish to leverage Cannlytics' email capabilities, then set `EMAIL_HOST_USER` and `EMAIL_HOST_PASSWORD` environment variables in your `.env` file. It is recommended that you [create an app password](https://support.google.com/accounts/answer/185833/sign-in-with-app-passwords?hl=en) if you are using Gmail. After you have created your app password, set your email and app password as environment variables, `EMAIL_HOST_USER` and `EMAIL_HOST_PASSWORD` respectively.
```bash
# .env
EMAIL_HOST_USER=admin@your-company.com
EMAIL_HOST_PASSWORD=your-app-password
```
5. Finally, to facilitate Firebase management, create and download a service account and save the path to your service account as a `GOOGLE_APPLICATION_CREDENTIALS` environment variable. For accessing [secrets](https://cloud.google.com/secret-manager), you will need to grant your service key *Secret Manager Admin* permissions in [Cloud IAM Admin](https://console.cloud.google.com/iam-admin/iam). For your security, this configuration file needs to be kept in a safe place.
```bash
# .env
GOOGLE_APPLICATION_CREDENTIALS=path/to/your/service/account.json
```
6. Finish by creating a `.firebaserc` in the root directory with your [Firebase Hosting](https://firebase.google.com/docs/hosting) references. See `example.firebaserc` for an example.
You are now ready to develop!
The Cannlytics Console and Cannlytics Website are built with the [Django](https://www.djangoproject.com/) framework and generally follow a model-template-view (MTV) architectural pattern, where:
| Abstraction | Description |
|-|-|
| **Model** | The `cannlytics` package, Django, and all `assets`, such as JavaScript and CSS, that contain the core logic, which is provided to the views.|
| **Template** | Django HTML files that describe the display and how data are presented. |
| **View** | Python functions that control the model's logic, specify and provide data to templates, and manage user requests. [Django describes views](https://docs.djangoproject.com/en/3.1/intro/tutorial03/#write-views-that-actually-do-something) as follows: *"Your view can read records from a database, or not. It can use a template system such as Django's โ or a third-party Python template system โ or not. It can generate a PDF file, output XML, create a ZIP file on the fly, anything you want, using whatever Python libraries you want."* |
Cannlytics utilizes a number of [Google Cloud](https://console.cloud.google.com/) services, including:
| Service | Purpose |
|---------|---------|
| [Firebase](https://firebase.google.com/) | Cloud services, such as [dynamic links](https://firebase.google.com/docs/dynamic-links). |
| [Firebase Authentication](https://firebase.google.com/docs/auth) | User authentication. |
| [Firebase Firestore](https://firebase.google.com/docs/firestore) | NoSQL database for real-time data management. |
| [Firebase Storage](https://firebase.google.com/docs/storage) | File storage. |
| [Firebase Hosting](https://firebase.google.com/docs/hosting) | Console, website, and documentation hosting. |
| [Cloud Build](https://cloud.google.com/build) | Used to containerize the app. |
| [Cloud Registry](https://cloud.google.com/container-registry) | Used to upload the app to storage. |
| [Cloud Run](https://cloud.google.com/run) | Used to run the app as a stateless container. |
| [Cloud Storage](https://cloud.google.com/storage) | Used for console and website file storage. |
| [Cloud Secret Manager](https://cloud.google.com/secret-manager) | Used for storing configurations and keeping secrets secret. |
The [standard Cannlytics data models](https://firebasestorage.googleapis.com/v0/b/cannlytics.appspot.com/o/public%2Flims%2Fdiagrams%2Fcannlytics_standard_data_models_0_0_8.svg?alt=media&token=de8e81a9-6250-4aac-857e-3936d26b4f1b) and their default fields are shown below. Cannlytics data models are highly flexible and can contain fewer, different, or additional fields.

Development can happen in many avenues. Frequent, small scope pull requests are encouraged. Any contribution, even if it needs future polishing, helps build the project and advance cannabis science. In general;
1. [Create a fork](https://docs.github.com/en/github/getting-started-with-github/quickstart/fork-a-repo) of the repository.
2. [Edit the project](#edit) by improving the codebase in some manner. Be creative.
3. [Create a pull request](https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request) for your changes to be reviewed and merged into the project upon approval or for you to receive feedback on how your changes can be approved.
The table below lists available development commands.
| Command | Purpose |
|---------|---------|
| `start` | Start the complete website development environment. |
| `serve` | Serve the assets with `webpack-dev-server`. |
| `livereload` | Serve Django with `django-livereload-server`. |
| `dev` | Serve Django with `runserver`. |
| `build` | Build the assets for production with `webpack`. |
| `collectstatic` | Gather all of the Django static files into the `public` directory. |
| `container` | Build a container image for the app. |
| `cloud` | Run the container image in the cloud. |
| `deploy` | Direct requests to the running container image. |
| `publish` | Perform all publishing steps: `build`, `container`, `cloud`, and `deploy`.
All text material is either stored in JSON in `state.py` or written in Markdown in `docs` directories. See [`python-markdown` Extensions](https://python-markdown.github.io/extensions/) for more information on rendering Markdown. For help with storing static files, see [serving static files on App Engine](https://cloud.google.com/appengine/docs/standard/python3/serving-static-files). You can configure static files to be served from [Firebase Storage](https://firebase.google.com/docs/storage) instead of from [Firebase Hosting](https://firebase.google.com/docs/hosting) in `console/settings.py` or `website/settings.py`. If you modify assets, then you can gather all supporting files, located in each app's `static` directory, into the `public/static` directory with:
```shell
set PROJECT=website
python manage.py collectstatic --noinput
```
or
```shell
npm run collectstatic
```
The simplest way to run the app is to open a command line from the project's root directory, set a `PROJECT` environment variable, and run:
```shell
set PROJECT=website
python manage.py runserver
```
or
```shell
npm run dev
```
You can also leverage [django-livereload-server](https://github.com/tjwalch/django-livereload-server) for hot-reloading while you develop.
```shell
npm run start
```
Hot-reloading is an important tool of development. You can use `django-livereload-server`, which uses both [python-livereload](https://github.com/lepture/python-livereload) and [django-livereload](https://github.com/Fantomas42/django-livereload), for smooth reloading. You can install [django-live-reload-server](https://github.com/tjwalch/django-livereload-server) with:
```shell
pip install django-livereload-server
```
You can start hot-reloading by starting the `livereload` server:
```shell
set PROJECT=website
python manage.py livereload
```
In another console, you start the Django development server as usual:
```shell
set PROJECT=website
python manage.py runserver
```
You can build the static assets, JavaScript and CSS, utilizing [Webpack](https://webpack.js.org/). The JavaScript bundle is a JavaScript module and is callable from the user interface with the `cannlytics` namespace. You can run the build for development with:
```shell
webpack-dev-server --env production=False
```
or
```shell
npm run serve
```
It is an inconvenience to run multiple consoles, but a major convenience to have smooth hot-reloading. So, [`npm-run-all`](https://www.npmjs.com/package/npm-run-all) is used to run multiple servers in the same console for smooth development. When you are setup, you can run the project for development simply with:
```shell
npm run start
```
You can serve the built project from anywhere you desire. The default option is to serve the project from Google App Engine, outlined below in [publishing](#publishing). Below are general instructions for building and serving the project in a [Docker container image](https://docs.docker.com/get-started/02_our_app/#build-the-apps-container-image).
First, build the Docker container image:
```shell
# build docker image
docker build -t cannlytics .
```
You can register the container with:
```shell
# docker push to container registry.
docker push cannlytics
```
You can [run the application container](https://docs.docker.com/get-started/02_our_app/#start-an-app-container) locally with:
```shell
# run docker
docker run -dp 8080:8080 --env-file docker.env cannlytics
```
Finally, you can quickly run the container, or multiple containers, with:
```shell
# bring up containers
docker-compose up -d --build
# bring down
docker-compose down
# logs
docker-compose logs
```
Congratulations, you can now build and run Cannlytics just about anywhere! The sky is the limit.
You can check for errors detectable by Django with:
```shell
python manage.py check
```
You can run tests for a specific app with.
```shell
python manage.py test your_app_name
```
You can also build the platform in a docker container for your specific purposes:
```shell
docker build . --tag gcr.io/your-lims/cannlytics
gcloud auth configure-docker
docker push gcr.io/your-lims/cannlytics
```
Perusing the `tests` directory is actually a good place to find examples on how to use Cannlytics and can be a good place to begin your explorations.
See [the publishing guide](https://docs.cannlytics.com/developers/publishing/) for complete instructions on how to publish Cannlytics for production. The guide is based on the [Running Django on Cloud Run guide](https://cloud.google.com/python/django/run#windows). After setup, publishing is done with one command:
```shell
npm run publish
```
If you need to change accounts or projects, then you can use:
```shell
gcloud config set account `ACCOUNT`
gcloud config set project `PROJECT ID`
```
The build process contains three steps:
1. Containerize the app and upload it to Container Registry.
Build your container image using [Cloud Build](https://cloud.google.com/build) by running the following command from the directory containing the Dockerfile:
```shell
gcloud builds submit --tag gcr.io/your-lims/cannlytics
```
2. Deploy the container image to Cloud Run.
```shell
gcloud beta run deploy your-lims --image gcr.io/your-lims/cannlytics --region us-central1 --allow-unauthenticated --service-account=${GCS_SA}
```
3. Direct hosting requests to the containerized app.
This step provides access to this containerized app from a [Firebase Hosting] URL, so the app can generate dynamic content for the Firebase-hosted site.
```shell
firebase deploy --only hosting:production
```