Shareable Module Factory Developer Documentation
Introduction - Shareable Modules
What is a shareable module? A shareable module is a self-contained piece of reusable code designed to be used across multiple Crowdbotics projects. Modules are structured as a set of files and folders, generally written in React Native and/or Django.
What are modules used for? Modules provide a robust, easy to use set of building blocks for many common features you’ll encounter building an application. Because they are reusable, modules provide a simple, clean way to avoid rewriting application code over and over again. Rather than rebuilding the same feature for every project, modules empower you to reuse code and save time so that you can focus on the more interesting parts of building software.
How can I use modules?
- To install a module in your project, start by clicking on the modules tab from the Storyboard panel of the Crowdbotics dashboard.
- Drag and drop a module onto your app.
- Once your module is on the storyboard, click and drag between the white dots to create a link between screens.
- Finally, click save on the top right to finalize your changes.
For some modules, that’s all the setup required. Your app should be ready following another deploy. Other, more involved modules may require further configuration. See the module’s README.md
files for more specific information.
Why write a module? If you’re working on multiple software projects, writing a module will allow you to save time and development cost by reusing module content across those projects. If you have to write a feature you know you’ll need to use again in future projects, that should probably be a module.
Use Cases Modules can be as simple as one page Terms and Conditions Screens, and as complex as you like. There is a healthy and continually expanding library of modules already available on the crowdbotics platform. Have a look at some of these modules to get a sense of what they can offer your future software projects:
- react-native-app-menu - automatically loads all the routes in your React Native app into a menu.
- react-native-login - Never write a login screen again! This module plays nicely with the built in django auth system for simple, out of the box user management. react-native-social-login supports several social based logins.
- react-native-chat - Add a simple chat interface to your app.
- django-articles & react-native-articles - separate front- and back-end modules that enable you to serve and display CRUD based article content. Supports images!
Writing a Module: An overview of the process:
Writing a shareable module is a multi-step process that includes the following steps:
- Forking the
crowdbotics/modules
repo and setting up your module’s file structure. - Writing your module code.
- Testing your module code in a demo project, which you can deploy on the web.
- Submitting your module for acceptance testing by Crowdbotics.
- Releasing your module for use in the Crowdbotics ecosystem.
Writing a Module, Part 1: Fork the code and set up your file structure.
- You’ll begin by forking the
crowdbotics/modules
repo. In addition to being where your module code will eventually live, this repo also contains useful utility commands and other module examples you can use as examples. https://github.com/crowdbotics/modules -
Begin writing your module code by creating a new folder within the
modules/modules
folder. You can confirm you are in the right directory by runningls
in the terminal. In the output, you should see a handful of other modules in this folder, for exampledjango-articles
,django-push-notifications
, etc. This folder you have just created will house your module code. You have two basic approaches you can use in creating a module:-
If your module will be purely Django or React Native code, make a new folder within the
modules/modules
repo that is prefixed with the appropriate name, eitherdjango-my-new-module
orreact-native-my-new-module
. For example, (run these commands from modules repository root):cd /modules/ && mkdir django-my-new-module
orcd /modules/ && mkdir react-native-my-new-module
-
If you need more flexibility for your module, or want to include both frontend and backend components, simply name your module folder without a prefix: (run this from the modules repo root again):
cd modules && mkdir my-new-module
Note that if you go with option B, you’ll need to create some additional folders within your newly created module directory. There’s an example of this in the Gotchas and Common Errors section below, though the best way to understand what you’ll need is to look at the
terms-and-conditions
orprivacy-policy
modules.
-
- Give your new module a
meta.json
. Specify aname
,description
, androot
path for your module here. You should create this within the folder you created in the previous step. Themeta.json
specifies the root install path for your module, relative to the top-level domain of the app that you are installing the module into. Here’s an examplemeta.json
for the Terms And Conditions app, which installs at the root directory level.
{
"title": "Terms and Conditions",
"description": "Terms and Conditions screen",
"root": "/"
}
And here’s the meta.json
for the django-articles
module, which is purely backend code. Note that since this is just backend, the root specifies the /backend/modules
folder, where django modules (which are also django apps, more on this below) are generally installed.
{
"title": "Articles (Django)",
"description": "Backend for the Articles module.",
"root": "/backend/modules"
}
Your meta.json
should always be in the root of your module folder. This file will not be installed in an app. The purpose of the meta.json
is that this is the main DSL mechanism we use for you as a modules author to specify options such as names, titles, and root paths.
Writing a Module, Part 2: Writing your Module Code
Modules can be as simple or as complex as you like. They can be made up of numerous new files and directories, or very few. Good modules are written to accomplish one thing, however complex that thing is, and they should be made as simple and reusable as possible. If you are writing a module, always keep in mind that future developers will use this module in a wide variety of contexts — hence, simplicity and reusability are key.
- There are example modules to look at in
modules/modules
. This is highly recommended, as it will give you some ideas about how modules function and are structured. - In particular,
modules/modules/django-articles
and andmodules/modules/react-native-articles
, which work together to provide a CRUD backend and frontend, are a great starting place for understanding how modules work. - These docs provide a guide on how to approach authoring a module, particularly a React Native module.
What kind of code/filetypes can I include in my module? You can include any filetype you’d like in a module. Generally speaking, your module will be made up of some combination of .py
, .js
, .json
, and .md
(for readme) files, as you will generally be writing python and React Native code in your modules. But you can also include other files, as needed. Should you, for instance, need static files, like images, or Terraform config files, like .tf
or .tf.json
, those may also be included.
A bit about Django:
Modules are Django Applications As of May 2021, all new backend modules will be structured as Django Applications. This means that backend modules can include their own migrations and configurations, and generally work like normal Django Applications. Purely frontend modules are unaffected by this change, and are still written in React native.
Modules should use PEP 8 style Your Django modules should conform to PEP 8 standards whenever possible, which includes using snake case (naming with an underscore). More here: https://www.python.org/dev/peps/pep-0008/
Namespacing and Configuring your Module Your module exists in the modules
namespace. This means that you need to define an
__init__.py
file, which should look something like this:
default_app_config = "modules.privacy_policy.apps.PrivacyPolicyConfig"
This file should point to another file you’ll need to add, apps.py
. This should look something like this:
from django.apps import AppConfig
class PrivacyPolicyConfig(AppConfig):
name = "modules.privacy_policy"
verbose_name = "Privacy Policy"
More information about Django apps can be found here (links to the 2.2 docs, but confirm you are using the same version of django as appears in the scaffold): https://docs.djangoproject.com/en/2.2/ref/applications/#configuring-applications
Writing a Module, Part 3: Testing your Module
After you’ve written your module, you can test it before submitting by creating a demo app and installing your module in there. You can then test by running the demo app locally or deploying it using the crowdbotics dashboard.
A demo app is a simple app that mirrors what you get when you start a new crowdbotics project: A Django backend and a React Native frontend, all combined in one folder with some configuration settings. This allows you to mimic the experience other developers will have when they install your module in their Crowdbotics app.
- Begin by running
npm run demo
within the rootmodules
folder. This will initialize a new demo app insidemodules/demo
. - You can now add your module to the demo app by using
npm run add <module-name>
. The module name is the same name as the folder you created in Part 1. If you have any problems with this step, check to make sure that yourmeta.json
is configured with the project root, and that your names match.- We also recommend installing the
[react-native-app-menu](http://react-native-app-menu)
app if you are testing a module that includes react-native, as this will give you an automatically populated app menu from which you can easily see all available routes—including your new module. - If you are working on a backend project, you can get a similar functionality by using the django management command
manage.py show_urls
. On docker, this can be run (in a seperate window from where you rundocker-compose up
) withdocker-compose exec web python3 manage.py show_urls
. You can also add the following to filter for module-related urls:…manage.py show_urls | grep
"
modules
"
- We also recommend installing the
- Try out your module inside the demo project. There are two basic ways to test your module within the demo project: locally or by deploying using the Crowdbotics dashboard. You can do both! Local testing may be a little bit quicker if you are already set up with the Crowdbotics scaffold and docker, though deploying using the Crowdbotics dashboard will allow you to test more network functionality.
- Running the app locally
- To run your app locally, first run
cd demo
after running thenpm run demo
andnpm run add <module>
commands above from the/modules
root directory. - To start the backend,
cd backend
and follow the instructions in thebackend/README.md
about setting up the app. Docker is recommended. - To start the frontend, follow the instructions in
demo/README.md
to run your app using the iOS or Android emulator.
- To run your app locally, first run
- Deploying the app using the Crowdbotics dashboard. Using the Crowdbotics dashboard, you can create a new project from a github repo. To do this, we’ll first create a repo for the demo app, then use the dashboard to deploy our app.
- Make sure you have initialized a demo app and added your module(s) using the
npm run demo
andnpm run add <module>
commands above. - Clone the git repo by finding the associated github repository in your app’s setting panel.
- Remove all the code generated in this repo. You will replace this with the code from
modules/demo
. After runningcd <path/to/your/new-project-repo>
, you can simply runrm -r *
- Copy your demo app into your newly empty project.
cp -r path/to/modules/demo path/to/your/new-project-repo
- Commit and push your changes to the remote repository.
- Deploy using the Crowdbotics dashboard.
- Once your app is deployed, you can use https://app.crowdbotics.com/dashboard/app/
/settings to generate admin credentials. You can then navigate to your app’s django admin panel by going to: .botics.co/admin/. API documentation is automatically generated and available at: .botics.co/api-docs/.
- Make sure you have initialized a demo app and added your module(s) using the
- Running the app locally
Writing a Module, Part 4: Submitting for Acceptance
After you’ve written and tested your module, it’s time to submit it for acceptance testing. Acceptance testing ensures that all modules on the Crowdbotics platform are functional, reusable, and conform to our quality standards.
Module Acceptance Criteria:
- The module must have a clear name and description.
- The module must work! We should be able to install, configure, and run your module using instructions in your
README.md
. - Speaking of
README
’s, Your module should contain at least one. YourREADME.md
should include a detailed description of what your module does, as well as complete instructions for configuration, installation, and usage. If you have both backend and frontend components in your module, each of those should have its ownREADME
. - Your module should be reusable. The purpose of modules is to easily share code, but for that to work, the code in your module should work in almost every case — and ideally be extensible enough to cover all cases.
Submitting your module
- One you’ve finished writing and testing your module, make sure you have all of your changes saved in the modules repository, i.e.
modules/modules/my-new-module
.- A common mistake is to make changes within your
modules/demo
project that you set up for testing in Part 3. Changes you make there will need to be imported back into the modules repo, which you can do manually or by copying your relevant module folders back into themodules
repo.
- A common mistake is to make changes within your
- Make sure your git fork is in sync with with the master branch. You may need to
git pull
orgit rebase
from the development branch. - Important! Within the modules repository, run **
npm run parse
. This command adds your module to themodules.json
script which is generated. We use this for some of our own config and testing. - Add your changes, commit them, and submit a PR against the
crowdbotics/modules
repository. - Your module has been submitted for acceptance testing! We will be in touch with next steps, if any, required for acceptance.
Writing a Module, Part 5: Release!
After your module passes acceptance testing, we will release it to the rest of our developer community. You will see your module listed on the Crowdbotics storyboard as a module available to install in any Crowdbotics project. Congratulations, and thank you for writing a Crowdbotics module!
Gotchas and Common Errors - Under Construction
[pipenv.exceptions.InstallError]: ['THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE. If you have updated the package versions, please update the hashes.
- This error pops up if your backend’s
Pipfile.lock
has gone out of date. This is fairly rare, but can happen from time to time. The easiest way to fix this is to runpipenv lock
from yourdemo/backend
folder to rebuild the Pipfile with the appropriate requirements and hashes.
- This error pops up if your backend’s
- Problems with running
npm run add
ornpm run parse
: If you experience issues running these commands, you likely have an issue with your file structure. Ensure you are using the following structure to save your files:- Backend:
$ modules/modules/my-module/backend/modules/my_module/(python code)
.- Migrations should be nested one folder deeper, e.g.:
modules/modules/my-module/backend/modules/my_module/migrations/0001_my-first-migration.py
- Migrations should be nested one folder deeper, e.g.:
- Frontend:
$ modules/modules/my-module/modules/my-module/(js code)
- Note that if you write a module with both backend and frontend components, your backend code will be nested one level deeper than your frontend code:
terms-and-conditions <-the root of your module code, eg. /modules/modules/my-module. ├── backend │ └── modules <-note that your backend code is nested one level deeper here. │ └── terms_and_conditions <- because this is django code, use snake case. │ ├── README.md │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ │ ├── 0001_terms_initial.py │ │ └── __init__.py │ ├── models.py │ ├── serializers.py │ ├── urls.py │ └── viewsets.py ├── meta.json <-this is where you set the root that you want your files installed to in the app. └── modules <-this is the folder, one level higher, for your FE code. └── terms-and-conditions <-because this is RN, use hypens here. ├── README.md ├── index.js ├── package.json └── styles.js
- Finally, make sure you have a
meta.json
here:$ modules/modules/my-module/meta.json
- Backend:
- Proper Casing: React Native uses hyphenated folder names, while Django uses snake case. Your top level module directory should also use hyphens. For example,
-
$ modules/modules/my-module/backend/modules/my_module/(python code)
. Note that the firstmy-module
folder is hyphenated. This is your top level module directory. -
Then, notice how the snake-cased
my_module
folder is specifically nested underbackend/modules
. -
However, for React Native, you use hyphens, for example:
$ modules/modules/my-module/modules/my-module/(js code)
. Note here that there are two identically named folders calledmy-module
. The top most folder stores all of your module code (if you are writing a module with both backend and frontend components), while the second folder stores only your RN code.
-