This app provides core functionality necessary for most user-oriented, data-driven applications:
Built with React using create-react-app
's defaults
Built for major platforms
Cross-platform support via Capacitor with a few plugins
Written entirely in TypeScript
Code linting with ESLint
Unit tests with Jest
Thorough code documentation generated by TypeDoc
Logging with loglevel
Custom fonts
Images
Preliminary search engine support
robots.txt
sitemap.xml
Prerequisites for app store submissions
Scripts
version.json
for web updatesEnvironment variables
process.env.*
type definitions with examplesAdditional type definitions
JSONValue
, JSONObject
, and JSONArray
- Useful when specifying JSONprocess.env.*
API modules
axios
instanceUser interface (UI) components built with styled-components
button
elementdiv
using flex box CSS to center its contents both horizonally and verticallyError
instance as children, displayed only if there is an errorform
element with some helpful additionsheader
elementiframe
element which attempts to adjust its height depending on its contentsinput
element (plus consistent cross-browser datetime
support)textarea
elementselect
element, normalized to look the same for every major browserusePromise
hookspan
element to quickly color some text using the current theme
textarea
elementExtremely useful React hooks
useAsyncExtendedState
- Same as setState
but with an additional convenient extendState
function and the ability to accept promisesusePromise
- Manage and render the state of any Promise
status
- Pending, resolved, or rejectedpromise
- The Promise
instance itselfvalue
- The resolved valueerror
- The caught errorcancel
- Cancels the promisereset
- Resets the stateUtilities
Themes
Core application components
react-router
Layout components
Store component for shared application state as a composition of React hooks
useNotifications
- A hook which returns the state of the device/browser's push notifications with methods to enable or disable themuseTheme
- A hook which returns the current theme and a method to set the theme by keyuseUser
- A hook which returns the current user (if logged in) and methods to set or extend the user stateuseVersion
- A hook which returns an object describing the current and potentially new version state and a method to update the service worker, if applicablelocalState
- Saves/retrieves the state of some resource to/from localStorage
User components
User device components
The app's codebase is opinionated but adaptable to nearly any architecture/design pattern of choice.
Every module is either a pure function (possibly asynchronous), a plain object, or a composition of both, with every function signature and object interface defined using TypeScript.
The app follows a top-down approach designed to be as simple and easy to follow as possible, where application state is rendered, beginning with the route, as a composition of pure function components using either shared state or internal state managed by hooks. Most API functionality is achieved using CRUD (create, read, update, delete, query) abstractions plus utility functions.
Extensive test coverage and separation of concerns make it easy to update and maintain the app while ensuring that it always works as expected.
Modules are thoroughly documented and organized logically and predictably, with exports structured to work nicely with TypeDoc to help you naturally keep your app documentation up to date with less effort.
You will need:
The following are recommended:
Visual Studio Code - Comes with IntelliSense for modern JavaScript and TypeScript by default, plus automatic linting with a little extra setup.
ESLint Extension for VSCode - See the ESLint Setup section below for a step-by-step guide to installation and configuration.
Git - Included with OSX, Linux, and VSCode.
After installing Node, navigate to this directory in your terminal and run npm install
to install the app's dependencies and synchronize Capacitor. This will also automatically create .env
and .env-cmdrc.json
files with example values which you should update for your project and environment(s).
The full list of environment variables specific to the app can be found within the .env
file. For all of the various builds, the values in .env
are used as defaults, and we use env-cmd
to extend these variables per configuration specified within .env-cmdrc.json
. See src/types/process.env.d.ts
for the app's environment variables' type definitions and examples, and other modules will extend process.env
with definitions as needed.
Update the .env
and .env-cmdrc.json
files with any known values.
Any environment variables beginning with REACT_APP
will be included in your application bundle, visible to the public. Your app's environment variables should not include any private keys or credentials.
The app is initially branded as "Molecule". You should change this to match your app.
To quickly update the app's branding, use an IDE (e.g., VSCode) to find all instances of "molecule", "your-api", "your-app", and "Your App" within your app's project directory and replace each instance with your app's name, domain(s), email address(es), etc. It's probably a good idea to review each instance one by one.
It's easiest to start with an SVG (vector) image for your logo. If you do not already have a logo, you can find many premade free and open source vector images on the web.
Inkscape is recommended for editing vector images and saving them in an optimized format compatible with React. To overwrite the Logo.svg
file included with Molecule in a compatible format:
Open your logo in Inkscape.
Select "File -> Save As..."
Select "Optimized SVG" next to "Save as type".
Overwrite {your-app}/src/App/Logo.svg
.
It's also probably a good idea to save a copy using the Inkscape format for future editing, like we've done with
{your-app}/src/App/Logo.inkscape.svg
.
To generate your logos/icons and splash images, after replacing {your-app}/src/App/Logo.svg
with your vector image (using a transparent background), run the following in the terminal within your app's root directory:
npm run generate-images
This generates all of the images necessary (based on your SVG logo) for the web and mobile apps. Feel free to improve and replace the generated images as desired.
Molecule comes with Arimo, a sans serif font metrically compatible with the widely used Arial font.
To replace Arimo with your own choice of font:
Copy your font files to your app within the public/fonts
directory.
Update public/index.html
and replace all instances of "Arimo" within the @font-face
declaration with the your font's sources. It may require some customization depending on your particular font and how you intend to use it.
Molecule comes with a very generic Privacy Policy and Terms of Service so you have something to start from, but you will probably need to update them depending on your requirements. They exist in two separate locations.
So that you can link to them from app stores via e.g., https://app.your-app.com/privacy-policy.html
:
{your-app}/public/privacy-policy.html
{your-app}/public/terms-of-service.html
So that users can view them directly within the app:
{your-app}/src/App/PrivacyPolicy.tsx
{your-app}/src/App/TermsOfService.tsx
You should now be ready to start building your app!
Code linting is a great way to keep your code consistently clean and readable, which helps prevent silly mistakes.
Install the ESLint extension within VSCode by opening File (or "Code" on Mac) -> Preferences -> Extensions
, searching for "ESLint", and clicking the "Install" button.
Open File (or "Code" on Mac) -> Preferences -> Settings
, then click the settings icon in the upper right to open your VSCode user settings.json
file. Add the following settings:
{
"eslint.alwaysShowStatus": true,
"javascript.format.enable": false,
"typescript.format.enable": false,
"eslint.format.enable": true,
"eslint.lintTask.enable": true,
"eslint.validate": [
"javascript",
"typescript",
"javascriptreact",
"typescriptreact"
]
}
Create a .vscode/tasks.json
file at the root of the molecule-app
project directory if it does not already exist and add the following task:
{
"version": "2.0.0",
"tasks": [{
"label": "ESLint",
"type": "shell",
"problemMatcher": "$eslint-stylish",
"command": "npm run lint",
"windows": {
"command": "npm run lint"
}
}]
}
You should now have linting enabled within VSCode as you develop your app. You can view any problems by selecting the View -> Problems
menu.
For more information on customizing your ESLint configuration, visit ESLint.org.
npm install
Installs the necessary dependencies for the app and synchronizes Capacitor.
npm run write-dotenv-files
Writes the default .env
and .env-cmdrc.json
files to disk. This is run automatically after installation and you may want to set any variables you already have values for.
npm run generate-images
You can replace src/App/Logo.svg
with your own logo and run this command to generate icons and splash images for every platform.
To update the push notification icon for Android:
Open the project in Android Studio with npx cap open android
.
Open "File -> New -> Image Asset".
Choose "Notification Icons" under "Icon Type".
Name it ic_notification
.
Choose "Image" for "Asset Type".
Click the folder icon next to "Path" and select {your-app}/resources/icon.png
.
Click the "Finish" button.
npm run lint
Checks every JavaScript and TypeScript file within the project directory and returns warnings and/or errors for any line of code which doesn't meet our standards.
npm run lint-autofix
Automatically fixes all auto-fixable code based on our linting rules.
npm test
Launches the test runner in the interactive watch mode.
See the section about running tests for more information.
npm run docs
Uses TypeDoc to generate documentation from comments throughout the codebase. Open docs/index.html
to view the documentation.
npm start
Runs the app in the development mode with hot reloading enabled.
Open http://localhost:3000 to view it in the browser.
You will also see any lint errors in the console.
npm run server
Serves the production app (possibly locally), if necessary. Serves a production build on port 3333, proxying API requests to localhost, port 4000. Useful for testing production builds locally.
npm run snapshot-html
Uses react-snap to snapshot the initially rendered HTML to give web users something to see other than a blank page before they've downloaded the application JavaScript.
npm run build
Builds the app for production to the build
folder, optimized for best performance with minification and hashed filenames.
Also writes version.json
to the build
folder and snapshots the HTML.
npm run prebuild-capacitor
Same as npm run build
but configured for Capacitor.
This is run before building for each Capacitor platform.
npm run build-android
Builds the app in release mode for Android, using the production API,
then opens it in Android Studio with npx cap open android
.
npm run build-android-debug
Builds the app in debug mode for Android, using the production API,
then opens it in Android Studio with npx cap open android
.
npm run build-android-debug-local-api
Builds the app in debug mode for Android with the REACT_APP_API_ORIGIN
environment variable set to your local machine (https://10.0.2.2:4000), then opens it in Android Studio with npx cap open android
.
You will need to start your local API server with the HTTPS
environment variable set to true
so that it uses SSL - i.e., HTTPS=true npm run dev
.
npm run build-ios
Builds the app in release mode for iOS, using the production API,
then opens it in Xcode with npx cap open ios
.
npm run build-ios-debug
Builds the app in debug mode for iOS, using the production API,
then opens it in Xcode with npx cap open ios
.
npm run build-mac
Builds the app in release mode for Mac with Electron, using the production API.
You can find the resulting Mac installer at {your-app}/electron/dist
.
npm run build-mac-debug
Builds the app in debug mode for Mac with Electron, using the development API
then runs npx cap open @capacitor-community/electron
which should automatically start
the app, and restarts whenever you make changes within the electron
directory.
npm run build-linux
Builds the app in release mode for Linux with Electron, using the production API.
You can find the resulting Linux packages at {your-app}/electron/dist
.
npm run build-linux-debug
Builds the app in debug mode for Linux with Electron, using the development API.
The npx cap open @capacitor-community/electron
command doesn't seem to work for Linux,
so you'll need to run the AppImage found at {your-app}/electron/dist
.
npm run eject
Note: this is a one-way operation. Once you eject
, you can’t go back!
If you aren’t satisfied with the build tool and configuration choices, you can eject
at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except eject
will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
You don’t have to ever use eject
. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
npx cap ...
Run Capacitor CLI commands. See Capacitor's CLI documentation.
@capacitor/
- Cross platform support by Ionic.
@primer/octicons-react
- Open source SVG icons by GitHub.
@testing-library/*
- Utilities for testing React components and hooks.
@types/*
- Type definitions for popular libraries. See DefinitelyTyped for more information.
axios
- Handles API requests.
cordova-plugin-purchase
- Cross-platform support for in-app purchases.
env-cmd
- Loads sets of environment variables via .env-cmdrc.json
.
eslint
- Code linter. Helps ensure structured code.
if-env
- Used for preventing postinstall
scripts from running when CI=true
or NODE_ENV=production
.
jwt-decode
- Gets the session
object (userId
and deviceId
) from the authorization header.
loglevel
- Minimal logging library which helps with quickly switching between various levels of logging.
polished
- Create and mix colors.
quill
- Rich text editor.
react
- Using create-react-app
's defaults.
react-dom
- Renders React to the DOM.
react-router-dom
- Renders layouts depending on the route.
react-scripts
- Scripts included by create-react-app
for managing the React app.
react-snap
- Snapshots the initially rendered HTML to give web users something to see other than a blank page before they've downloaded the application JavaScript.
react-swipeable
- Used for detecting when the user overscrolls (swipes downward beyond the top of the page) so that we can possibly fetch new data.
styled-components
- Style React components with CSS.
typescript
- Necessary for TypeScript support.
web-vitals
- Included by create-react-app
for measuring performance.
axios-mock-adapter
- Utility for mocking axios
requests when testing.
http-server
- Serves the production app (possibly locally), if necessary.
icon-gen
- Generates the favicon.
open-cli
- Opens the docs after generation.
sharp
- Used for generating the icons and splash screens of various sizes based on the SVG logo.
typedoc
- Generates documentation from comments throughout the codebase.
If you haven't already, run npm run docs
to generate the app documentation.
You should be greeted with this same README plus navigation on the right. This navigation structure matches the project folder structure, based on each module's exports.
If the documentation did not automatically open for you, you can find it at
{your-app}/docs/index.html
.
For example, click the documentation's API
navigation link and you'll see that it expands to show the API
module's description and exports: resource
, authorization
, and client
. Take a look at src/API/index.ts
and you'll see the same comments and exports.
To create documentation like this as you build your app, include comments and exports using the same structure and run npm run docs
again to regenerate your documentation. There are formatting rules which you'll need to follow to generate the documentation the way you want, like including the @module
tagged comment at the very top of modules and ensuring there are no blank lines between certain comments and function/object definitions. Visit TypeDoc.org to learn more about how to write documentation alongside your code.
The app is primarily separated into API
, UI
, and App
component directories, plus a themes
directory and common hooks
and utilities
directories. Sets of type definitions usually exist as a file or directory alongside the logical grouping of modules/components.
Also see the capacitor
directory for managing cross-platform, Capacitor-related modules (plugins) specific to the app.
If you would rather use a different architecture, the existing code is designed to be adaptable. Concerns are as separated as possible while using pure, tested functions.
This section assumes you have a git repository for your app on either GitHub, GitLab, BitBucket, or another git provider supported by Netlify.
Log into Netlify (or sign up).
Click the New site from Git button.
Connect your git provider and choose your app's repository.
The default settings should work, so you should be able to immediately deploy the site.
Open the "Site settings" tab in Netlify.
Go to the "Environment" section under "Build & Deploy".
Click the "Edit variables" button and set the following environment variables:
NODE_ENV=production
NODE_VERSION=16
GENERATE_SOURCEMAP=false
REACT_APP_URL_SCHEME=com.your-app.app
REACT_APP_API_ORIGIN=https://api.your-app.com
- Use the same value you used for your API's API_ORIGIN
environment variable. Also make sure this is set in the production
section of {your-app}/.env-cmdrc.json
.
REACT_APP_WEB_ORIGIN=https://app.your-app.com
REACT_APP_VAPID_PUBLIC_KEY=yourvapidpublickey
- Use the same value you used for your API's VAPID_PUBLIC_KEY
environment variable. Also make sure this is set in {your-app}/.env
.
You'll set additional environment variables as needed when following the instructions for setting up features specific to your Molecule.
Your app will be automatically rebuilt and redeployed whenever you push a change to the master/main branch of your git repository. You can manually redeploy at any time by opening the "Deploys" tab selecting "Deploy site" using the "Trigger deploy" button on the right.
After your app has been built and deployed (published), you should be ready to try it out with your production API!
Netlify gives you a unique random URL as a Netlify subdomain for your app, but you'll probably want to use your own official domain.
Open the "Domain management" section of the "Site settings" tab for your app in Netlify.
Click the "Add custom domain" button under the "Custom domains" section.
Enter your app's domain and click "Verify".
If you already own the domain, you will need to follow Netlify's instructions to verify your domain. Or if it's an unregistered domain, you can register it through Netlify.
See Netlify's Custom domains documentation for more information on adding your domain.
It is recommended that you use Netlify's DNS, as it's easy to use and nice to manage it all in one place. It also greatly simplifies the process of adding SSL (HTTPS) to your web app.
After you've added your domain, scroll down to the "HTTPS" section of the "Domain management" page and ensure that SSL is enabled. If you've recently switched to Netlify's DNS, it could take some time for the changes to propagate before you're able to provision a TLS certificate, but from experience, it usually takes less than an hour.
See Netlify's HTTPS documentation for more information on enabling (and troubleshooting) SSL.
Note: You may need to update your API's environment variables to match your domain if it's different than what you originally set on your production API. You'll want to ensure the
APP_DOMAIN
andAPP_ORIGIN
environment variables are correct, otherwise the CORS configuration will not allow requests to be made from your web app.
If you're using a different DNS for your domain, you can skip this section. Refer to your domain's DNS provider's documentation.
To add your subdomain(s) to Netlify's DNS:
Open the "Domains" tab of your Netlify dashboard.
Click your domain.
Click the "Add new record" button under "DNS records".
Choose the "CNAME" record type.
If your desired subdomain is api.your-app.com
, enter api
for the name.
Your API host should provide a DNS target for you to use as the value.
Click the "Save" button.
Note: You may need to update both your app's and API's environment variables to match your domain if it's different than what you originally set. On the API side, you'll want to ensure the
API_ORIGIN
is correct. On the app side (in Netlify), you'll want to ensure theREACT_APP_API_ORIGIN
is correct.
Generated using TypeDoc