Step 1: user registers for an account and is auto placed in the "Free" plan
Step 2: user logins and builds their map app
Step 3: user embeds their map app in their external website or app
-
Users can edit their map anytime on MapStuff.io/dashboard and updates will be auto shown wherever they have embedded their map app.
-
Upgrading plans can be done at anytime.
-
Downgrading is not possible yet.
- ReactJS (18.2) -- React Widgets for embeddable functionality
- NEXT.JS (13.0.7)
- NodeJS
- MongoDB App Services (formerly 'Realm')
- GraphQL
- Apollo
- Auth0
- Tailwind CSS, Tailwind UI, Headless UI
- Mapbox
- MongoDB Realm ( Used for connecting the app to the database )
- @auth0/nextjs-auth0 and realm custom JWT authorization. Right now we are not fetching from users collection we are just creating a valid jwt token to pass to realm custom JWT.
- We are using the Manually Specify Signing Keys HS256 Algorithm.
- We need to add first a signing key on realm. If we don't see a dropdown of the signing key, we need to create it first.
- Signing keys are stored on secrets of realm app. see image.png
- We are using JWK URI for the verification mode, the value for the JWK Uri field https://YOUR_DOMAIN/.well-known/jwks.json (example: https://mapstuff-dev.us.auth0.com/.well-known/jwks.json )
ON REGISTRATION WE ARE USING (API Key) provided on .env https://docs.mongodb.com/realm/web/authenticate#api-key
ON SIGN IN WE ARE USING (Custom JWT) from @auth0/nextjs-auth0 (https://www.npmjs.com/package/@auth0/nextjs-auth0) https://docs.mongodb.com/realm/web/authenticate#custom-jwt
- JWT_SIGNING_PRIVATE_KEY should be provided on .env. Get this from the realm app.
We are fetching the users subscription (for some UI conditions) from stripe API. this is another layer of security (eg. if we change the plan directly from stripe dashboard of a particular customer, it will reflect right away on users dashboard), and we can be sure that our stripe customer data is acurate.
-
React Home (https://react-select.com/home) - Multi and grouped dropdown for assigning tags to locations
-
Auth0 https://www.npmjs.com/package/@auth0/nextjs-auth0() - Package used for authentication
- @tailwindcss/ui
- @tailwindcss/typography
- @tailwindcss/colors
- @tailwindcss/forms
- @tailwindcss/aspect-ratio
- @tailwindcss/line-clamp
-
used for 'fetch'
-
used for all other CRUD operations
-
used for 'mutations' with array type field
-
used for filtering locations
For new features added to the map settings, always update the plans-acl collection and regenerate the schema.
Right now we have issue if we use next-link then route to a page that needs to fetch data from realm (ex. /apps/url-name). We can use this now for pages that dont need data fetching. like (apps/add)
Duplicate .env.example & rename to .env for dev and local development. See bitwarden entry for list of variables and values.
- Log in to MongoDB Atlas.
- Create a new project.
- Create database.
- Import collection.
- Create index. This is to ensure certain fields will have unique values.
- Users collection. Set the id and email to unique. Set username to unique and partial.
for email index https://trello-attachments.s3.amazonaws.com/5bb1fd4d0ffeab7f78c03779/60344c16323738134a5fe18d/ad55085285e8c0a07364bf4b5c0f1736/image.png for username index https://trello-attachments.s3.amazonaws.com/5bb1fd4d0ffeab7f78c03779/60344c16323738134a5fe18d/e084d5ed42a3c754b8b005d73c01c8c9/image.png
- Apps collection. Set the id and app_url to unique.
- Create a new Realm App. (Not sure if this is here or after creating new project.)
- Note App ID and add it to your .env
- Go to Deploy. Then, to Configuration.
- Disable Drafts
To link datasource, create collection (step 4), schema and rules.
Our database consists of 4 collections ["apps","locations","plans-acl","users"]. CREATE these 4 collections then import if we have existing data. (I think its okay if we use empty collection, as long as we copy the schema advance mode, if error lets do it basic mode..)
ADDING RULES AND SCHEMA ADVANCE MODE. From dev: I think this is the fastest way to add rules and schema if from scratch.
- Create Apps collection in Atlas.
- Copy /nosql_schema/apps-schema.json > paste it > save.
- Checking if success.
- Navigate to GraphQl then try to search "apps" https://trello-attachments.s3.amazonaws.com/5bb1fd4d0ffeab7f78c03779/60344c16323738134a5fe18d/d868364b088c4c8cc33d3a8a5594d411/image.png
- Repeat for the other collections
- locations using "/nosql_schema/locations-schema.json"
- plans-acl using "/nosql_schema/plans-acl-schema.json"
- users using "/nosql_schema/users-schema.json"
ADDING RULES AND SCHEMA BASIC MODE.
- Create apps collection.
- Import data for each collection but should have at least one data, so we can auto generate schema.
GENERATE SCHEMA - https://trello-attachments.s3.amazonaws.com/5bb1fd4d0ffeab7f78c03779/60344c16323738134a5fe18d/ddc9175be60a5824a246ae44a354476f/image.png
- Save
- Repeat for the other collections
- locations
- plans-acl
- users
Here's a sample when a schema is generated already.
For API key - user is not logged in (example: user registration, sign in, etc .. )
- In MongoDb, go to Authentication. Then, Authentication Providers
- Set API Keys to On.
- Create API Key. Note the key and add it to your .env. Save in BitWarden as well.
http://localhost:3000/api/auth/callback, https://mapstuff.io/api/auth/callback, https://mapstuff-io-68tmj.ondigitalocean.app/api/auth/callback
http://localhost:3000/, https://mapstuff.io/, https://mapstuff-io-68tmj.ondigitalocean.app/
http://localhost:3000/, https://mapstuff.io/, https://mapstuff-io-68tmj.ondigitalocean.app/
MongoDB
- Collection > Users
- Filter for the user you'd like to edit
{ email: '[email protected]' }
- Add a new field called:
role_id: 1
(Int32) - Update
Auth0
- User Management > User
- Click on the user
- Under the 'Details' tab > app_metadata add
"role": "Admin"
}```
## DNS
## SERVER
Setup a new App in Digital Ocean or the provider of your choice.
## CI/CD
1. Select repo
2. Select a branch
3. Check auto deploy changes
4. Set env variables (from env file, values in Bitwarden)
5. Set to HTTP Port to 3000
6. Choose plan
# To run app locally
1. Clone the repo
2. Switch to the given branch (ask your Project Manager for this branch)
3. Copy '.env.example' > '.env'
4. Open bitwarden entry 'dev.MapStuff.io | .env (Developer Edition)' and copy .env info
5. Run `yarn install --network-timeout 1000000`
6. Run `yarn run dev`
# User Role Management
## Set 'admin' role
### **MongoDB**
*No longer needed to manage roles
~~1. Collection > Users~~
~~2. Filter for the user you'd like to edit~~
~~```{ email: '[email protected]' }```~~
~~3. Add a new field called:~~
~~```role_id: 1``` (Int32)~~
~~4. Update~~
### **Auth0**
1. User Management > User
2. Click on the user
3. Under the 'Details' tab > app_metadata add
```
{
"role": "Admin"
}
```
# Access 'admin' pages locally
1. Look for this code:
```
if(!role.includes('Admin')) return <p>Access Denied</p>;
```
1. Comment it out to remove the 'admin' requirement
1. Code stuff!
1. Test. The link probably won't be in the navigation, but the page should still be accessible.
1. Don't forget to 'uncomment' before pushing your commits
# IMPORTING REQUIRED DATA
import DB/collection/plans-acl.json to plans-acl collection then add in the price_id directly into the collection
# Demo page
Demo page is using the following embed code to generate the map:
Dev environment
The app widget with the embed code and the map on the map settings are coming from different areas of the repo.
The mapbox.css files in both locations should be identical.
- This is the map that appears in the Map Settings /dashboard/map-settings page
- Files are located in /styles
- Edit the following files to reflect on the map
- mapbox.css
-
This is the map that is being generated by the embed code
-
Files are located in /public/widget
-
Go to the required CDN location (listed below depending on the environment).
- When updating the files, put the existing working files into the _previous-version folder as a backup.
- Upload the new files
- If the new files don't work, delete them and move the files you put in the "previous_version" folder into the widget folder
-
Copy these files in the CDN location.
-
close.svg
-
mapbox.css
-
mapbox2.js
-
marker.svg
-
plugins.js - check this file and update this URL in the file according to the environment you are updating
-
-
Purge the CDN files several times once uploaded
-
When these files are updated in the CDN, it will not trigger a deployment for the app (no reason to) but this should update the app still automatically with the changes in the file uploaded.
https://cloud.digitalocean.com/spaces/cinnamon/spaces/cinnamon/dev.mapstuff.io/widget
https://cloud.digitalocean.com/spaces/cinnamon/spaces/cinnamon/mapstuff.io/widget
All features are determined per plan in the CMS area of the site https://mapstuff.io/dashboard/admin/cms/plans
- Accepts xlsx or csv file
- Max number of locations is determined in the CMS page
- Only active locations count for the number of locations. If number of active locations is equal or more than the max locations,
- user cannot add a new location whether by manually adding or bulk upload.
- user cannot edit location from Unpublished to Published if publishing that location will exceed the max locations
Currently, this is set up for a Mapbox API key only.
Theme color applies to the sidebar (for listings) header and pop-up info window header.
The location name in the sidebar listings can also be edited but not part of the CMS.
Changeable map height.
- Currently not editable on the map settings area. Future feature.
- We have the marker.js file in the CDN
These are the styles from Mapbox: satellite, light, dark, streets, outdoors.
Create group of tags that are made into filters. Assign created tags to locations.
But working for admin accounts already.
Right way of adding the embed code from https://mapstuff.io/.
div id
will be in the template area while the script
will be in the script area. Update the data-app
if using a different account from MapStuff app.
<template>
<div>
<div id="map-mapstuff"></div>
</div>
</template>
<script lang="ts">
export default {
setup () {
useMeta({
script: [
{
hid: 'mapstuff',
src: 'https://cdn.gangnam.club/widget/plugins.js',
},
{
hid: 'mapstuff2',
src:'https://cdn.gangnam.club/widget/mapbox2.js',
'data-id': 'dev-store-locator-react',
'data-app': '[FROM MAPSTUFF]',
'data-key': '[FROM MAPSTUFF]'
}
]
})
}
}
</script>
-
Go to en.json and add the key that you want to add (ex. "header": "Header")
-
Go to the other .json file in the translation folder and add the key as well and the corresponding value
-
Go to the react component where you want to add the new key in the translation file and check if the
{ t } = useTranslation
is already existing, if not.- import the code below
import { useTranslation } from "react-i18next";
- Inside the component, add
const { t } = useTranslation();
- Add the translation key in the return of the component ex.
<button>{t('header')}</button>
- import the code below
- Create a new json file or copy the existing json files and then rename it to the new language
- Go to LanguageDropdown.js and and the language in the options, the value of the newly added language should be the filename of the translation file, for example, fr.json is the title of the new language, the you should add { value: "fr", label: "French" }, in the options dropdown
Demo page https://mapstuff.io/demo is using a MapStuff app from UAT. This means the data-key is from UAT as well. The js files are from https://cdn.gangnam.club/widget/ location.