├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── author.md
├── favicon.ico
├── index.md
├── package-lock.json
├── package.json
├── projects
├── api
│ ├── commands.md
│ ├── config.md
│ ├── data-design.md
│ ├── faq.md
│ ├── folder-structure.md
│ ├── index.md
│ ├── index.yml
│ └── technologies.md
├── apps
│ ├── TWA
│ │ ├── index.md
│ │ └── index.yml
│ ├── index.md
│ └── index.yml
├── cms
│ ├── commands.md
│ ├── config.md
│ ├── folder-structure.md
│ ├── index.md
│ ├── index.yml
│ └── technologies.md
├── doc
│ └── index.md
├── index.md
├── index.yml
└── website
│ ├── analytics.md
│ ├── build-strategy.md
│ ├── commands.md
│ ├── config.md
│ ├── faq.md
│ ├── folder-structure.md
│ ├── index.md
│ ├── index.yml
│ ├── payment.md
│ ├── pwa.md
│ ├── seo.md
│ ├── technologies.md
│ └── theme.md
├── retype.yml
└── static
├── appsco-splashscreens.png
├── favicon-generator.png
├── logo.png
├── product-properties-combo-product.png
├── product-properties-individual-product.png
└── pwa-builder.png
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text eol=lf
2 | *.png binary
3 | *.jpg binary
4 | *.jpeg binary
5 | *.ico binary
6 | *.icns binary
7 |
8 | # Web fonts are binary
9 | *.otf binary
10 | *.eot binary
11 | *.svg binary
12 | *.ttf binary
13 | *.woff binary
14 | *.woff2 binary
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | dist/
3 |
4 | # misc
5 | .DS_Store
6 | *.pem
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 OwnStore
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This project is part of OwnStore suite. Learn more here: https://ownstore.dev
2 |
3 | The suite contains the following projects:
4 | - [Website](https://github.com/OwnStoreOrg/ownstore-website)
5 | - [API](https://github.com/OwnStoreOrg/ownstore-api)
6 | - [CMS](https://github.com/OwnStoreOrg/ownstore-cms)
7 | - [Doc](https://github.com/OwnStoreOrg/ownstore-doc)
8 | - Apps
9 | - [TWA](https://github.com/OwnStoreOrg/ownstore-app-twa)
10 |
11 | **Note:** This project is a clone of a privately-managed repo by the author. The original repo has the complete Git tree, few additional technologies and a CI/CD setup. Changes are initially made in the private repo and then synced here through CLI commands. This is done for security reasons.
12 |
13 | Additional updates present in the original repos
14 | - Cypress (for end-to-end testing)
15 | - Storybook (for UI components explorer)
16 | - Docker files (for containerization)
17 | - Jest (for functional testing of business logic)
18 | - Local https setup for development (Eg. https://local.ownstore-demo.com)
19 | - AWS cloud migration (not pushed to prod yet)
20 | - Cloudflare as a CDN and custom name server (not pushed to prod yet)
21 | - Sub-domain for serving static files (not pushed to prod yet)
22 | - Algolia and ElasticSearch experiments for searching (not pushed to prod yet)
23 | - Sentry end-to-end tracking experiment (not pushed to prod yet)
24 | - Token-based color theming for dark mode and better DX support (not pushed to prod yet)
25 | - Modular folder structure
26 | - Native app with Flutter (Work in progress)
27 | - Kubernetes config to manage multiple app instances with ease (not pushed to prod yet)
28 | - Monitoring and alerting with Prometheus and Grafana (not pushed to prod yet)
29 | - Continuous deployment with GitHub actions, Docker, AWS and Kubernetes (not pushed to prod yet)
30 | - Lighhouse score checker for PRs through GitHub actions
31 |
32 |
--------------------------------------------------------------------------------
/author.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: Author
3 | icon: person
4 | ---
5 |
6 | Faiyaz (-looking for a change -)
7 |
8 | Few links to follow the author:
9 | - [LinkedIn](https://www.linkedin.com/in/faiyaz-s-413450118/)
10 | - [GitHub](https://github.com/yTakkar)
11 | - [Twitter](https://twitter.com/shtakkar)
12 | - [Email](mailto:www.shtakkar@gmail.com)
13 |
--------------------------------------------------------------------------------
/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OwnStoreOrg/ownstore-doc/d4df9c89aef1c4199e5c9739e76a81fb57591bbe/favicon.ico
--------------------------------------------------------------------------------
/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: Welcome
3 | icon: home
4 | order: 4
5 | ---
6 |
7 | OwnStore is a configurable online store for your bussiness. Can be customized according to your needs. Packed with bundle of modern web features and a easy-to-use UI for users.
8 |
9 | Few features:
10 | - Mobile-first rendering
11 | - Minimalistic UI
12 | - Advanced SEO practices
13 | - PWA enabled
14 | - Ready to incorporate in a webview for native apps
15 | - Contract based communication between layers
16 | - Advanced analytics for product and engineering folks :)
17 | - Easy-to-use CMS for admins
18 | - Secure user login and data management
19 | - Ultra-fast pages rendering (even for dynamic pages)
20 | - Highly configurable
21 | - 90+ average lighthouse score across all segments even for a full-fledged dynamic webapp like this
22 | - Advanced caching strategies at multiple layers from API to web
23 | - Smooth ordering and payment experience for users
24 | - Pattern-based engineering practices
25 | - Engineering practices from
26 | - [ESPNcricinfo](https://www.espncricinfo.com/)
27 | - [Disney+Hotstar](https://www.hotstar.com/)
28 | - [Proximity](https://www.proximity.tech/)
29 | - [Shaadi.com](https://www.shaadi.com/)
30 | - [Sangam.com](https://www.sangam.com)
31 | - [Delta Exchange](https://www.delta.exchange/)
32 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "own-store-doc",
3 | "version": "1.0.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "retypeapp": {
8 | "version": "1.10.0",
9 | "resolved": "https://registry.npmjs.org/retypeapp/-/retypeapp-1.10.0.tgz",
10 | "integrity": "sha512-TyGnSl1e29yXW42c5VXrkeXKHavkmaRjwQydlkZTdA2p8fHSKEQS7FGYW4OOSjK/tPQ1FTfX7lmogF+4KEZZ4g=="
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "own-store-doc",
3 | "version": "1.0.0",
4 | "description": "Summary",
5 | "private": true,
6 | "scripts": {
7 | "dev": "retype watch",
8 | "build": "retype build"
9 | },
10 | "keywords": [],
11 | "dependencies": {
12 | "retypeapp": "^1.10.0"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/projects/api/commands.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: Commands
3 | title: API Commands
4 | icon: gear
5 | order: 1
6 | ---
7 |
8 | Let's discuss the possible commands this project supports
9 |
10 | ## lint:fix
11 | This command will fix the linting issues. And report if not fixed.
12 |
13 | ```bash
14 | npm run lint:fix
15 | ```
16 |
17 | ## start:local
18 | Starts the server on `3001` port using `local` env.
19 |
20 | If both MySQL and Redis connections are successful, then you will see a `running...` message.
21 |
22 | ```bash
23 | npm run start:local
24 | ```
25 |
26 | ## start:prod
27 | Starts the server using `production` env.
28 |
29 | ```bash
30 | npm run start:prod
31 | ```
32 |
33 | ## build
34 | To build the project
35 |
36 | ```bash
37 | npm run build
38 | ```
39 |
40 | ## start
41 | This command can be used to start with build files. Note: You will have to pass the ENV to start.
42 | ```bash
43 | STORE_API_ENV=local npm run start
44 | STORE_API_ENV=production npm run start
45 | ```
46 |
--------------------------------------------------------------------------------
/projects/api/config.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: Config
3 | title: API Config and ENVs
4 | icon: note
5 | order: 2
6 | ---
7 |
8 | Before deep-diving into the app config, let's first through the ENVs.
9 |
10 | ## ENV
11 | This project has multiple environments and can be found under `/env` directory. These envs help us to develop, test and deploy. Currently, we have only 2:
12 | - `local` - For development
13 | - `production` - For production
14 |
15 | An ENV file contains values which you need to be different on different environments. For eg. You need a local DB connection while developing, but a prod connection for online users.
16 |
17 | ## Config
18 | App config can be found in `src/appConfig.ts` file.
19 |
20 | ### config.global
21 | Key | Description
22 | --- | ---
23 | `global.app` | Few app related information.
24 | `global.domain` | Domain. For eg. `your-store-api.herokuapp.com` OR `localhost:3000`
25 | `global.baseUrl` | Base URL. For eg. `https://your-store-api.herokuapp.com` or `http://localhost:3000`
26 | `global.clientOrigins` | A list of origins where API will be used. This is for security. Check the supported origins [here](http://localhost:3003/projects/api/faq/#which-origins-are-supported)
27 | `global.pageSectionItemsLimit` | A number to limit the count of items fetched for a section. For eg. If 15, then only 15 products will be returned for the `Products` section.
28 | `global.showDoc` | Control if you want to show swagger API doc.
29 |
30 | ### config.admin
31 | Key | Description
32 | --- | ---
33 | `admin.email` | Email of the admin. Used as a support email for swagger doc.
34 | `admin.cacheClearKey` | This key will be used when an admin tries to clear the redis cache. The operation will be validated against this key. **Very private**
35 | `admin.auth.key` | This key will be used to validate an admin from CMS. **Very private**
36 | `admin.auth.tokenSecret` | To prepare a unique and safe admin token with `admin.auth.key` for the CMS, a secret key is needed. **Very private**
37 | `admin.auth.tokenExpiry` | This controls how long the admin should stay logged in.
38 |
39 | ### config.errors
40 | Key | Description
41 | --- | ---
42 | `errors.report4xxErrors` | Set this to true if you want to report 4xx errors to Sentry.
43 |
44 | ### config.userAuth
45 | Key | Description
46 | --- | ---
47 | `userAuth.tokenSecret` | To prepare a unique and safe user token for users, a secret key is needed. **Very private**
48 | `userAuth.tokenExpiry.default` | This controls how long the user should stay logged in.
49 | `userAuth.tokenExpiry.extended` | This controls how long the user should stay logged in if they opt-in to `Remember me`.
50 |
51 | ### config.order
52 | Key | Description
53 | --- | ---
54 | `order.status` | There's a dependency in code for 2 order statuses: `RECEIVED` & `CANCELLED`. Map these statuses with correct DB ID here.
55 | `order.cancellationReasons` | This is a list of pre-defined reasons shown to users when they cancel the order.
56 |
57 | ### config.payment
58 | Key | Description
59 | --- | ---
60 | `payment.refundAmountPercent` | The amount in percentage of order total to refund.
61 | `payment.tax` | Total tax on cart total. First priority is given to `percent`. If null, considers 'flat' key.
62 | `payment.tax.percent` | Tax amount in percentage
63 | `payment.tax.flat` | Tax amount in flat number
64 | `payment.tax.decimalPrecision` | This controls the number of decimals after calculation of tax. For eg. 17.23491 => 17.23
65 | `payment.extraCharges` | Total extra charges on cart total. First priority is given to `percent`. If null, considers 'flat' key.
66 | `payment.extraCharges.percent` | Extra charge amount in percentage
67 | `payment.extraCharges.flat` | Extra charge amount in flat number
68 | `payment.extraCharges.decimalPrecision` | This controls the number of decimals after calculation of tax. For eg. 17.23491 => 17.23
69 | `payment.smallestCurrencyUnit` | Smallest currency unit to form 1 amount. For eg. 1 dollar = 100 cents, 1 rupee = 100 paisa. Used by Stripe to process payments.
70 | `payment.deliveryPriceMapping` | A mapping of [whenAmountAbove]: [deliveryPrice]. Should be in ascending order of whenAmountAbove.
71 |
72 | ### config.database
73 | Key | Description
74 | --- | ---
75 | `database.url` | DB connection URL. If provided, other credentials such host, password, etc.. will be ignored.
76 | `database.host` | DB host for connection
77 | `database.post` | DB post for connection
78 | `database.name` | DB name for connection
79 | `database.user` | DB user for connection
80 | `database.password` | DB password for connection
81 | `database.enableLogging` | If set to true, `TypeORM` logging will be enabled.
82 | `database.enableSync` | If set to true, any changes in models will be reflected in DB on save. Also if a table is not present in DB but present as a model, TypeORM will create one table. So DB and its tables are eligible for auto sync.
83 |
84 | ### config.cache
85 | Key | Description
86 | --- | ---
87 | `cache.redis` | Redis is used to cache data at service method level. This is done offload DB operations.
88 | `cache.redis.enabled` | To disable redis cache, set it to `false`
89 | `cache.redis.mode` | Redis mode (`standalone` / `cluster`). [Redis connection reference](https://github.com/luin/ioredis/blob/HEAD/API.md#Redis)
90 | `cache.redis.url` | Redis connection URL. IF provided, other credentials will be ignored. [Redis connection reference](https://github.com/luin/ioredis/blob/HEAD/API.md#Redis)
91 | `cache.redis.host` | [Redis connection reference](https://github.com/luin/ioredis/blob/HEAD/API.md#Redis)
92 | `cache.redis.port` | [Redis connection reference](https://github.com/luin/ioredis/blob/HEAD/API.md#Redis)
93 | `cache.redis.dbIndex` | [Redis connection reference](https://github.com/luin/ioredis/blob/HEAD/API.md#Redis)
94 | `cache.redis.password` | [Redis connection reference](https://github.com/luin/ioredis/blob/HEAD/API.md#Redis)
95 | `cache.redis.keyPrefix` | Used as a prefix for all Redis cache keys.
96 | `cache.redis.maxTtl` | How long the cache should be kept at max.
97 | `cache.httpResponse` | We have caching at HTTP response level too.
98 | `cache.httpResponse.enabled` | To disable HTTP response cache, set it to `false`
99 |
100 | ### config.allow
101 |
102 | There are 2 ways you can disable:
103 | - directly from project ENV files by setting the value as `false`
104 | - or expose these ENV variables separately and keep values here as blank. You can avoid a build with this approach and change will be applied immediately.
105 |
106 | Key | Description
107 | --- | ---
108 | `allow.newRegisterations` | Allow new registerations.
109 | `allow.newOrders` | Allow new orders.
110 |
111 | ### config.integrations
112 | Key | Description
113 | --- | ---
114 | `integrations.stripePayment` | Stripe is used to process payments
115 | `integrations.stripePayment.secretKey` | Get secret key from Stripe dashboard
116 | `integrations.sentryErrorReporting` | Sentry is used to monitor app health
117 | `integrations.sentryErrorReporting.enabled` | To disable this integration
118 | `integrations.sentryErrorReporting.dsn` | Get DSN from Sentry's dashboard
119 |
--------------------------------------------------------------------------------
/projects/api/data-design.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: Data Design
3 | title: API Data Design
4 | icon: cpu
5 | order: 4
6 | ---
7 |
8 | The database used here is MySQL. So let's go through each table and understand its responsibility.
9 |
10 | ## User
11 |
12 | User-related tables.
13 |
14 | ```mermaid
15 | graph LR;
16 | A[user] --> B(user_address)
17 | A --> C(user_login_history)
18 | A --> D(user_security_question_answer)
19 | A --> F(user_wish)
20 | A --> G(user_cart_item)
21 | ```
22 |
23 | Table | Responsibility
24 | --- | ---
25 | user | Holds user information such as `id`, `name`, etc...
26 | user_address | Holds user addresses. There can be multiple addresses associated with a user.
27 | user_login_history | Maintains a record of user logins.
28 | user_security_question_answer | Holds answers of user's selected security questions. Looks up to `security_question` for question reference.
29 | user_password_hint | Holds user's password hints. *This feature was deactivated due to security concerns.*
30 | user_wish | Holds user's product wishlist.
31 | user_cart_item | Holds user's cart products.
32 |
33 | ## Order
34 |
35 | Order-related tables.
36 |
37 | ```mermaid
38 | graph LR;
39 | A[order] --> B(order_status_history) --> C(order_status_type)
40 | A --> D(order_cancellation)
41 | ```
42 |
43 | Table | Responsibility
44 | --- | ---
45 | order_status_type | Holdes status list supported by an order. This is a lookup table. For eg.
RECEIVED
PROCESSING
DISPATCHED
DELIVERED
CANCELLED
You can add you own mapping here.
46 | order_status_history | Each order has a lifecycle from receiving an order to getting cancelled. This table maintains the very same lifecycle and uses status for it. Looks up to `order_status_type` for status reference.
47 | order | Holds all the information of an order. Few top-level data points:
Order summary such as `sale amount`, `retail amount`, `discount`, `total`, etc...
A snapshot of user's cart during order placement time.
User and their address.
Currency
Third party payment ID
Payment type (`CARD`, `WALLET`)
Status text
Cancellation ID (if any)
48 | order_cancellation | Holds order's cancellation reason.
49 |
50 | ## Catalogue
51 | Table | Responsibility
52 | --- | ---
53 | catalogue | All individual products are associated with a catalogue. This table holds catalogue information such `name`, `images`, etc...
54 |
55 | ## Product
56 | A product can be of 2 types:
57 | - Individual
58 | - Combo
59 |
60 | ### Individual Product
61 |
62 | 
63 |
64 | ```mermaid
65 | graph LR;
66 | A[individual_product] --> B(catalogue)
67 | A --> C(product_attribute) --> D(product_attribute_key)
68 | A --> E(product_brand)
69 | A --> F(product_tag)
70 | A --> G(product_feature_section)
71 | A --> H(products_relation)
72 | ```
73 |
74 | Table | Responsibility
75 | --- | ---
76 | individual_product | Holds individual product information. Few data points:
Basic information such `name`, `shortName`, `description`
SEO-related information such `seoTitle`, `seoDescription`, `seoKeywords`
Catalogue
Images (fetched from `image` table)
Brand
Other related products
Feature sections
Attributes
Tags
77 |
78 | ### Combo Product
79 | Combo products are made up of multiple products. For eg. A `Men winter suit` combo product can have the following product items
80 | - `Sweatshirt`
81 | - `Jacket`
82 | - `Beanie`
83 | - `Gloves `
84 |
85 | Combo products dont' have
86 | - catalogue
87 | - brand
88 |
89 | 
90 |
91 | ```mermaid
92 | graph LR;
93 | A[combo_product] --> B(combo_product_item)
94 | A --> C(product_attribute) --> D(product_attribute_key)
95 | A --> E(product_tag)
96 | A --> F(product_feature_section)
97 | A --> G(products_relation)
98 | ```
99 |
100 | Table | Responsibility
101 | --- | ---
102 | combo_product | Holds combo product information. Few data points:
Basic information such `name`, `shortName`, `description`
SEO-related information such `seoTitle`, `seoDescription`, `seoKeywords`
Images (fetched from `image` table)
Other related products
Feature sections
Attributes
Tags
103 | combo_product_item | Holds product items for a combo product.
104 |
105 | ### Product properties
106 |
107 | Table | Responsibility
108 | --- | ---
109 | product_attribute_key | A list of all attribute keys supported by the app. Few attribute key examples for a car:
Mileage
Color
Dimension
Variant
No. of seats
This is a lookup table.
110 | product_attribute | Maintains a list of all attributes for a **product**. Looks up to `product_attribute_key` for reference.
111 | product_brand | Holds the list of all the supported brands. This is a lookup table.
112 | product_tag | Holds tags for a product. Few tag examples:
Highly Rated
Verified
New
Trending
etc...
113 | product_feature_section | A feature section is an expandable section with some detailed information about a product. This table holds feature sections for a product.
114 | products_relation | This table holds product relations. A relation can have both individual and combo products.
115 |
116 | ## Section
117 | A section is a component which can have multiple items. There can be different types of sections.
118 | - Products section (For products)
119 | - Catalogues section (For catalogues)
120 | - Blogs section (For blogs)
121 | - Full-width slides section (For slides which will cover the full screen. Will be used as slides)
122 | - Strict-width slides section (For slides which will have 640x300 size. Will be used as slides)
123 | - USPs section (To showcase app USPs. **Note:** Max 4)
124 | - Procedures section (To showcase the process)
125 | - Customer feedbacks section (For displaying customer feedbacks)
126 | - Share section (For asking users to share the app)
127 | - Custom section (For rendering any custom section. Accepts raw HTML)
128 |
129 | For eg. If `type` of a section is `PRODUCTS`, it will lookup products from `section_product` table.
130 |
131 | ```mermaid
132 | graph LR;
133 | A[section] --> B(section_product) --> J(individual_product OR combo_product)
134 | A[section] --> C(section_catalogue) --> K(catalogue)
135 | A[section] --> D(section_blog) --> L(blog)
136 | A[section] --> E(section_slide)
137 | A[section] --> F(section_usp)
138 | A[section] --> G(section_procedure)
139 | A[section] --> H(section_customer_feedback)
140 | A[section] --> I(section_custom)
141 | ```
142 |
143 | Table | Responsibility
144 | --- | ---
145 | section | This is where all the sections are stored. Few data points:
Name
Title
SubTitle
Type (`PRODUCTS`, `CATALOGUES`, `BLOGS`, etc...). Used to decide the type of the section.
146 | section_product | Holds products for `Products` section
147 | section_catalogue | Holds catalogues for `Catalogues` section
148 | section_blog | Holds blogs for `Blogs` section
149 | section_slide | Holds slides for both `Full-width slides` and `Strict-width slides` sections.
150 | section_usp | Holds data for `USPs` section
151 | section_procedure | Holds data for `Procedures` section
152 | section_customer_feedback | Holds data for `Customer Feedbacks` section
153 | section_custom | Holds data for `Custom` section
154 |
155 | ## Page Sections
156 | You can use multiple sections on a page. Also you can override the default properties of a section such as `title`, `subTitle`, etc... only for a page.
157 |
158 | Table | Responsibility
159 | --- | ---
160 | section_page_home | Sections to show on home page
161 | section_page_explore | Sections to show on explore page
162 | section_page_error | Sections to show on error page
163 | section_page_individual_product | Sections to show on individual product page
164 | section_page_combo_product | Sections to show on combo product page
165 | section_page_search | Sections to show on search page
166 |
167 | ## Supported Regions
168 | **Note:** There's no validation of city-to-country mapping at system-level, so pls add cities only of the supported countries. For eg. don't add `Mumbai` if `India` country is not supported.
169 |
170 | Table | Responsibility
171 | --- | ---
172 | supported_country | Holds the list of countries the app supports.
173 | supported_city | Holds the list of cities the app supports. If the app is servicable only in `Mumbai`, then kindly add `India` as country and `Mumbai` as city.
174 |
175 | ## FAQ
176 | ```mermaid
177 | graph LR;
178 | A[faq_topic] --> B(faq)
179 | ```
180 |
181 | Table | Responsibility
182 | --- | ---
183 | faq_topic | Each FAQ is grouped with a topic such as `general`, `payment`, etc.. This table holds the very same topics.
184 | faq | All the FAQs are stored here with corresponding topic ID.
185 |
186 | ## HTML Pages
187 | Table | Responsibility
188 | --- | ---
189 | page_tn_c | Content for the `Terms and Conditions page`. Purely raw HTML.
190 | page_privacy_policy | Content for the `Privacy Policy page`. Purely raw HTML.
191 | page_refund_policy | Content for the `Refund Policy page`. Purely raw HTML.
192 |
193 | ## Others
194 | Table | Responsibility
195 | --- | ---
196 | currency | Holds currency supported by the product. There can be only 1 row.
197 | security_question | Holds all the security questions. This is a lookup table.
198 | blog | Holds all the information for a blog.
199 | image | This is a global table which holds all the dynamic images from product to slides. Few top-level data:
Image URL path (just the path, not the absolute URL. Base URL is added at consumer level.)
Dimensions
Size in bytes
200 |
201 |
202 |
--------------------------------------------------------------------------------
/projects/api/faq.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: FAQs
3 | title: API FAQs
4 | icon: question
5 | order: -1
6 | ---
7 |
8 | ## Which additional headers are supported?
9 | Apart from the standard HTTP headers, we accept a few more
10 |
11 | This mapping can be found in `src/app/constants/index.ts`
12 |
13 | ```ts
14 | export const VALID_EXTERNAL_HEADERS = {
15 | ACCESS_TOKEN: 'x-access-token',
16 | ADMIN_ACCESS_TOKEN: 'x-admin-access-token',
17 | SENTRY_TRACE: 'sentry-trace',
18 | RESPONSE_CACHE_TIME: `${appConfig.global.app.key.toLowerCase()}-cache-time`,
19 | }
20 | ```
21 |
22 | ## Which origins are supported?
23 |
24 | This list can be found in `src/appConfig.ts`.
25 |
26 | ```ts
27 | [
28 | 'http://localhost:3000', // website local
29 | 'http://localhost:3002', // cms local
30 | 'https://own-store-demo.vercel.app', // website prod
31 | 'https://own-store-demo-cms.vercel.app', // cms prod
32 | ]
33 | ```
34 |
35 | ## What are the supported cache TTLs?
36 |
37 | We have caching at 2 layers:
38 | - service
39 | - controller
40 |
41 | Service-level cache time should be 80% of controller's
42 |
43 | ```ts
44 | export const CACHE_MULTIPLIER = 0.8
45 |
46 | // Ideally service-level cache time should be 80% of controller's
47 | // in seconds
48 | export const SERVICE_CACHE_TTL = {
49 | LIVE: 30 * CACHE_MULTIPLIER,
50 | SHORT: 2 * 60 * CACHE_MULTIPLIER,
51 | DEFAULT: 5 * 60 * CACHE_MULTIPLIER,
52 | LONG: 10 * 60 * CACHE_MULTIPLIER,
53 | }
54 |
55 | // in seconds
56 | export const CONTROLLER_CACHE_TTL = {
57 | LIVE: 30,
58 | SHORT: 2 * 60,
59 | DEFAULT: 5 * 60,
60 | LONG: 10 * 60,
61 | }
62 | ```
63 |
--------------------------------------------------------------------------------
/projects/api/folder-structure.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: Folder Structure
3 | title: API Folder Structure
4 | icon: file-directory
5 | order: 3
6 | ---
7 |
8 | ## Directories
9 | A description of top-level directories.
10 |
11 | Directory | Description
12 | --- | ---
13 | `/env` | For ENV files.
14 | `/src/server` | Only for server related handling.
15 | `/src/server/controller` | Holds all the supported HTTP endpoints.
16 | `/src/app` | This directory has all app-related files.
17 | `/src/app/constants` | For app constants.
18 | `/src/app/contract` | A contract consumers will use for business logic.
19 | `/src/app/decorators` | We use few decorators to enhance a method without modifying its interface.
20 | `src/app/errors` | We have extended `Error` class for more custom handling.
21 | `src/app/models` | These are TypeORM models. Basically a representation of a MySQL table.
22 | `src/app/repositories` | Contains repositories which are used to perform DB operations through TypeORM.
23 | `src/app/services` | For all services.
24 | `src/app/transformers` | Holds methods which transform a data into a contract.
25 | `src/app/utils` | Contains both contextual as well as pure methods.
26 | `/dist` | For build files.
27 |
28 | ## Core Layers
29 | There are 5 core layers in this project and each layer has a responsibility.
30 | - Controller
31 | - Service
32 | - Repository
33 | - Model
34 | - Transformer
35 |
36 | ```mermaid
37 | %%{init: {} }%%
38 | graph LR
39 | A[Controller] --> B[Service]
40 | B[Service] --> C[Repository]
41 | C[Repository] --> D[Model] --> C --> B --> E[Transformer] --> B --> A
42 | ```
43 |
44 | Kindly go through this [blog](https://softwareontheroad.com/ideal-nodejs-project-structure/).
45 |
46 | ==- Controller
47 | Handles incoming request and only interacts with service.
48 | Can be found in `src/server/controller`
49 | ==-
50 |
51 | ==- Service
52 | These are pure methods and don't accept any global or contextual values/params. Their responsibility is to return the required data to any consumer not specifically just the controller. Services interact with
53 | - repositories for fetching data
54 | - transformers for tranforming data into a contract
55 |
56 | Can be found in `src/app/services`
57 | ==-
58 |
59 | ==- Repository
60 | Their responsibility is to do DB-related operations.
61 | Can be found in `src/app/repositories`
62 | ==-
63 |
64 | ==- Model
65 | Specifies DB table contract.
66 | Can be found in `src/app/models`
67 | ==-
68 |
69 | ==- Transformers
70 | Since each endpoint returns data in form of a contract, it is transformer's responsibility is to prepare that contract.
71 | Can be found in `src/app/transformers`
72 | ==-
73 |
--------------------------------------------------------------------------------
/projects/api/index.md:
--------------------------------------------------------------------------------
1 | This project is responsible for communicating with the database and exposes REST API endpoints. This is a dependancy of both user-facing website UI and CMS.
2 |
3 | - [Technologies](./technologies)
4 | - [Data Design](./data-design)
5 | - [Folder Structure](./folder-structure)
6 | - [Config](./config)
7 | - [Commands](./commands)
8 | - [FAQs](./faq)
9 |
--------------------------------------------------------------------------------
/projects/api/index.yml:
--------------------------------------------------------------------------------
1 | label: API
2 | icon: plug
3 | order: 3
4 |
--------------------------------------------------------------------------------
/projects/api/technologies.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: Technologies
3 | title: API Tech stack
4 | icon: rocket
5 | order: 5
6 | ---
7 |
8 | Top level technologies used in this project.
9 |
10 | === NodeJs
11 | To keep language consistent throughout all 3 projects, we decided to use JS here as well. [Ref](https://nodejs.org/en)
12 | ===
13 |
14 | === TypeScript
15 | Used for type safety, and creating a contract between consumers and the the service provider that is API. [Ref](https://www.typescriptlang.org)
16 | ===
17 |
18 | === HapiJs
19 | For better dev experience while building an HTTP server. [Ref](https://hapi.dev/)
20 | ===
21 |
22 | === Inversify
23 | For dependency injection. [Ref](https://www.npmjs.com/package/inversify)
24 | ===
25 |
26 | === TypeORM
27 | For communicating with MySQL database. [Ref](https://typeorm.io/#/)
28 | ===
29 |
30 | === Redis
31 | To cache response at service method level. [Ref](https://www.npmjs.com/package/ioredis)
32 | ===
33 |
--------------------------------------------------------------------------------
/projects/apps/TWA/index.md:
--------------------------------------------------------------------------------
1 | Using TWA, you can serve your PWA web application to users as an Android app. Learn more about about this [here](https://developer.chrome.com/docs/android/trusted-web-activity/).
2 |
3 |
4 | ## Setup
5 |
6 | ### Install
7 | We will be using [Bubblewrap](https://github.com/GoogleChromeLabs/bubblewrap) to generate our project. So first install it
8 | ```bash
9 | npm i -g @bubblewrap/cli
10 | ```
11 |
12 | ### Directory
13 | Create a directory to init
14 | ```bash
15 | mkdir ownstore-app-twa
16 | ```
17 |
18 | ### Initialize
19 | Now let's initialize our project with a manifest file. Using OwnStore's demo manifest as an example here.
20 | ```bash
21 | bubblewrap init --manifest=https://own-store-demo.vercel.app/json/manifest.json
22 | ```
23 |
24 | This command will install
25 | - JDK 8 if not found. I had to say for this.
26 | - Android SDK if not found. I had previously installed the SDK here: `/Users/faiyazshaikh/Library/Android/sdk`.
27 |
28 | You will also be asked with a few questions.
29 |
30 | ### Build
31 | Once the project is initialized, we can build and generate our APK.
32 | ```bash
33 | bubblewrap build
34 | ```
35 |
36 | You can also provide `----skipPwaValidation` to bypass PWA validation checks.
37 |
38 | ### Fingerprint
39 | Next step is to generate SHA256 fingerprints. Run this command
40 | ```bash
41 | keytool -printcert -jarfile app-release-signed.apk | grep SHA256
42 | ```
43 |
44 | Copy the output.
45 |
46 | ### Web asset linking
47 | Create a file named `/public/.well-known/assetlinks.json` in website project. This will be served as `/.well-known/assetlinks.json`. Paste the following content in this JSON file.
48 | ```json
49 | [{
50 | "relation": ["delegate_permission/common.handle_all_urls"],
51 | "target": {
52 | "namespace": "android_app",
53 | "package_name": "app.own_store_demo.twa",
54 | "sha256_cert_fingerprints": [
55 | ""
56 | ]
57 | }
58 | }]
59 |
60 | ```
61 |
62 |
63 | Go through this [doc](https://developer.chrome.com/docs/android/trusted-web-activity/quick-start/) for more detailed instructions.
64 |
--------------------------------------------------------------------------------
/projects/apps/TWA/index.yml:
--------------------------------------------------------------------------------
1 | icon: diamond
2 | order: 3
3 | expanded: false
4 |
--------------------------------------------------------------------------------
/projects/apps/index.md:
--------------------------------------------------------------------------------
1 | Mobile apps for OwnStore.
2 | - [TWA - Only Android](/projects/apps/twa/)
3 | - React Native (Coming soon)
4 | - Flutter (Coming soon)
5 |
--------------------------------------------------------------------------------
/projects/apps/index.yml:
--------------------------------------------------------------------------------
1 | icon: device-mobile
2 | order: 1
3 | expanded: false
4 |
--------------------------------------------------------------------------------
/projects/cms/commands.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: Commands
3 | title: CMS Commands
4 | icon: gear
5 | order: 1
6 | ---
7 |
8 | Let's discuss the possible commands this project supports
9 |
10 | ## sync:contract
11 | This command assumes both CMS and API projects are siblings. Syncs API contracts.
12 | ```bash
13 | npm run sync:contract
14 | ```
15 |
16 | ## lint
17 | This command analyze the codebase for any linting or formatting issues.
18 | ```bash
19 | npm run lint
20 | ```
21 |
22 | ## lint:fix
23 | Same as `lint` but fixes the issues
24 | ```bash
25 | npm run lint:fix
26 | ```
27 |
28 | ## start:local
29 | Starts the server on `3002` port using `local` env. Also syncs the contract.
30 | ```bash
31 | npm run start:local
32 | ```
33 |
34 | ## start:localprod
35 | Starts the server on `3002` port using `localproduction` env. Also syncs the contract.
36 | ```bash
37 | npm run start:localprod
38 | ```
39 |
40 | ## build
41 | Builds the entire project.
42 | ```bash
43 | npm run build
44 | ```
45 |
46 | ## start
47 | This command can be used to start with build files. Note: You will have to pass the ENV to start.
48 | ```bash
49 | STORE_CMS_ENV=local npm run start
50 | STORE_CMS_ENV=production npm run start
51 | ```
52 |
--------------------------------------------------------------------------------
/projects/cms/config.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: Config
3 | title: CMS Config and ENVs
4 | icon: note
5 | order: 2
6 | ---
7 |
8 | ## ENV
9 | CMS project currently supports 3 environments:
10 | - `local` - For development
11 | - `localproduction` - For development but with prod API
12 | - `production` - For production
13 |
14 | ## Config
15 | App config can be found in `config/appConfig.ts` file.
16 |
17 | ### config.global
18 | Key | Description
19 | --- | ---
20 | `global.app` | Few app related information.
21 | `global.domain` | Domain. For eg. `own-store-demo-cms.vercel.app` OR `localhost:3002`
22 | `global.baseUrl` | Base URL. For eg. `https://own-store-demo-cms.vercel.app` or `http://localhost:3002`
23 | `global.imageBaseUrl` | Cloudinary image base URL. For eg. `https://res.cloudinary.com/your-store/image/upload`. If you have mapped AWS S3 with Cloudinary, put that URL here. `imageBaseUrl + image path (from DB)` will render the image. **Note:** This is not for static images.
24 | `global.apiBaseUrl` | API base URL to connect to. For eg. `http://localhost:3001`.
25 | `global.webBaseUrl` | User-facing website URL. For eg. `http://localhost:3000` or `https://own-store-demo.vercel.app`.
26 | `global.redirectToIndexViewAfterUpdate` | Whenever an entity is successfuly updated, do you want to redirect to its index page? This flag controls exactly that.
27 | `global.redirectToIndexViewAfterDelete` | Whenever an entity is successfuly deleted, do you want to redirect to its index page? This flag controls exactly that.
28 | `global.paginationFetchLimit` | How many items should be shown be fetched and shown per page during pagination.
29 |
30 | ### config.order
31 | Key | Description
32 | --- | ---
33 | `order.recentOrders` | Config for recent orders page.
34 | `order.autoRefresh` | Enable auto refresh of new orders.
35 | `order.refreshIntervalInSeconds` | Control the refresh interval of recent orders.
36 |
37 | ### config.search
38 | Key | Description
39 | --- | ---
40 | `search.limit` | How many results should be fetched and shown on search pages?
41 |
42 | ### config.image
43 | Key | Description
44 | --- | ---
45 | `image.imageUploadDirectory` | While uploading images, a dropdown is shown to pick a directory. This mapping controls exactly the same.
46 |
47 | ### config.integrations
48 |
49 | #### config.integrations.cloudinary
50 | Config for Cloudinary integration.
51 |
52 | Key | Description
53 | --- | ---
54 | `integrations.cloudinary.cloudName` | Cloudinary clound name. Get this from dashboard. Eg. `your-store`.
55 | `integrations.cloudinary.uploadPresetName` | We are doing unsigned image upload, so we have to create a preset. Steps:
Navigate to Cloudinary console.
Scroll down to `Upload presets` section.
Create a preset and make sure it is `unsigned`.
56 |
57 | #### config.integrations.googleAnalytics
58 | For Google analytics integration.
59 |
60 | Key | Description
61 | --- | ---
62 | `integrations.googleAnalytics.enabled` | Use this flag to disable.
63 | `integrations.googleAnalytics.code` | GA code. Get this from dashboard.
64 |
--------------------------------------------------------------------------------
/projects/cms/folder-structure.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: Folder Structure
3 | title: CMS Folder Structure
4 | icon: file-directory
5 | order: 3
6 | ---
7 |
8 | Directory | Description
9 | --- | ---
10 | `/components` | Contains page-level as well as pure components.
11 | `/config` | Contains app-level config.
12 | `/constants` | For global constants.
13 | `/contract` | API contracts are stored here.
14 | `/env` | For ENV files.
15 | `/hooks` | Contains global React hooks.
16 | `/http` | Responsible for connecting with API.
17 | `/pages` | All NextJs pages are kept in this folder.
18 | `/public` | Has all the static files from fonts to images.
19 | `/scriptTemplates` | Contains script templates for for all HTML pages.
20 | `/styles` | Holds all styles-related SCSS files.
21 | `/utils` | Contains page-level as well as pure methods.
22 | `/.next` | Contains build files.
23 |
--------------------------------------------------------------------------------
/projects/cms/index.md:
--------------------------------------------------------------------------------
1 | This project is responsible for providing a UI to update database entries.
2 |
3 | - [Technologies](./technologies)
4 | - [Folder Structure](./folder-structure)
5 | - [Config](./config)
6 | - [Commands](./commands)
7 |
--------------------------------------------------------------------------------
/projects/cms/index.yml:
--------------------------------------------------------------------------------
1 | icon: pencil
2 | label: CMS
3 | order: 2
--------------------------------------------------------------------------------
/projects/cms/technologies.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: Technologies
3 | title: CMS Tech stack
4 | icon: rocket
5 | order: 5
6 | ---
7 |
8 | Top level technologies used in this project.
9 |
10 | === NextJs
11 | React framework for better dev experience, optimized build, etc... [Ref](https://nextjs.org/)
12 | ===
13 |
14 | === TypeScript
15 | Used for type safety. [Ref](https://www.typescriptlang.org)
16 | ===
17 |
18 | === TailwindCSS
19 | Utility-based CSS framework for faster prototyping. [Ref](https://tailwindcss.com/)
20 | ===
21 |
22 |
--------------------------------------------------------------------------------
/projects/doc/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: Documentation
3 | title: Documentation
4 | icon: paste
5 | ---
6 |
7 | This doc project is created with the help of Retype open-source project.
8 |
9 | Few links:
10 | - [Retype](https://retype.com/)
11 | - [Retype website code](https://github.com/retypeapp/retype)
12 |
--------------------------------------------------------------------------------
/projects/index.md:
--------------------------------------------------------------------------------
1 | So we have the following projects that enable this product to function
2 | - [API](/projects/api)
3 | - [CMS](/projects/CMS)
4 | - [Website](/projects/website)
5 | - [Documentation](/projects/doc)
6 |
--------------------------------------------------------------------------------
/projects/index.yml:
--------------------------------------------------------------------------------
1 | icon: package
2 | order: 3
3 | expanded: true
4 |
--------------------------------------------------------------------------------
/projects/website/analytics.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: Analytics
3 | title: Website Analytics
4 | icon: graph
5 | order: 0
6 | ---
7 |
8 | ## Google Analytics
9 | GA is added as part of an integration but can be disabled. E-Commerce events have also been added for advanced analytics.
10 |
11 | The following events have been added:
12 | ```ts
13 | LOGIN = 'login',
14 | LOGOUT = 'logout',
15 | SIGNUP = 'sign_up',
16 | SEARCH = 'search',
17 | VIEW_SEARCH_RESULTS = 'view_search_results',
18 | SHARE = 'share',
19 | VIEW_CART = 'view_cart',
20 | ADD_TO_CART = 'add_to_cart',
21 | REMOVE_FROM_CART = 'remove_from_cart',
22 | DELETE_CART_ITEM = 'delete_cart_item',
23 | ADD_TO_WISHLIST = 'add_to_wishlist',
24 | REMOVE_FROM_WISHLIST = 'remove_from_wishlist',
25 | MOVE_TO_CART = 'move_to_cart',
26 | BEGIN_CHECKOUT = 'begin_checkout',
27 | PURCHASE = 'purchase',
28 | FAILED_PAYMENT = 'failed_payment',
29 | ADD_ADDRESS = 'add_address',
30 | EDIT_ADDRESS = 'edit_address',
31 | DEACTIVATE_ADDRESS = 'deactivate_address',
32 | SELECT_ADDRESS_FOR_DELIVERY = 'select_address_for_delivery',
33 | SELECT_PRODUCT = 'select_content',
34 | VIEW_PRODUCT = 'view_item',
35 | PWA_INSTALL_SUCCESS = 'pwa_install_success',
36 | PWA_INSTALL_FAILED = 'pwa_install_failed',
37 | EXCEPTION = 'exception',
38 | CHANGE_PASSWORD = 'change_password',
39 | UPDATE_PASSWORD_HINT = 'update_password_hint',
40 | UPDATE_SECURITY_QUESTIONS = 'update_security_questions',
41 | ANSWER_SECURITY_QUESTIONS = 'answer_security_questions',
42 | RESET_PASSWORD = 'reset_password',
43 | EDIT_PROFILE = 'edit_profile',
44 | SCROLL_TO_TOP = 'scroll_to_top',
45 | ```
46 |
47 | Can be found in `app/constants/analytics.ts`.
48 |
49 |
--------------------------------------------------------------------------------
/projects/website/build-strategy.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: Build Strategy
3 | title: Website Build Strategy
4 | icon: container
5 | order: -2
6 | ---
7 |
8 | Since we use NextJs as a framework, we have used 3 build strategies here depending upon the use-case. Used strategies:
9 | - SSG (Static Generation)
10 | - CSR (Client-side Rendering)
11 | - SSR (Server-side Rendering)
12 |
13 | Kindly go through this article to [learn more](https://vercel.com/blog/nextjs-server-side-rendering-vs-static-generation) in detail.
14 |
15 | ## SSG
16 | This strategy enables us to build a dynamic page initially and update its content after an interval. This is much faster, widely adopted and optimized than other strategies. For eg. for a product page...
17 |
18 | There can be 1000+ products, so we will build 50 product pages initially and if user visits a page that is not built, NextJs will build the page on the fly, serve that page and update the build mapping so the next time you visit, you'll see a static page with no server lookup.
19 |
20 | Also we can define when an SSG page should be re-validated.
21 |
22 | ## CSR
23 | Initially a skeleton is served and once the page has finished loading, you will fetch the data and show a corresponding UI. CSR pages:
24 | - Account pages
25 |
26 | ## SSR
27 | This will build the page everytime you visit. SSR pages
28 | - Search results page
29 |
--------------------------------------------------------------------------------
/projects/website/commands.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: Commands
3 | title: Website Commands
4 | icon: gear
5 | order: 4
6 | ---
7 |
8 | Let's discuss the possible commands this project supports
9 |
10 | ## sync:contract
11 | This command assumes both CMS and API projects are siblings. Syncs API contracts.
12 | ```bash
13 | npm run sync:contract
14 | ```
15 |
16 | ## lint
17 | This command analyze the codebase for any linting or formatting issues.
18 | ```bash
19 | npm run lint
20 | ```
21 |
22 | ## lint:fix
23 | Same as `lint` but fixes the issues
24 | ```bash
25 | npm run lint:fix
26 | ```
27 |
28 | ## script:generate-manifest
29 | Generates a manifest file for the project.
30 | ```bash
31 | npm run script:generate-manifest
32 | ```
33 |
34 | ## start:local
35 | Starts the server on `3002` port using `local` env. Also syncs the contract.
36 | ```bash
37 | npm run start:local
38 | ```
39 |
40 | ## start:localprod
41 | Starts the server on `3002` port using `localproduction` env. Also syncs the contract.
42 | ```bash
43 | npm run start:localprod
44 | ```
45 |
46 | ## build
47 | Builds the entire project.
48 | ```bash
49 | npm run build
50 | ```
51 |
52 | ## build:analyze
53 | Builds the project and opens a UI to visualize the build size. Note: You will have to pass the ENV to start.
54 | ```bash
55 | STORE_WEB_ENV=production npm run build:analyze
56 | ```
57 |
58 | ## start
59 | This command can be used to start with build files. Note: You will have to pass the ENV to start.
60 | ```bash
61 | STORE_WEB_ENV=local npm run start
62 | STORE_WEB_ENV=production npm run start
63 | ```
64 |
--------------------------------------------------------------------------------
/projects/website/config.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: Config
3 | title: Website Config and ENVs
4 | icon: note
5 | order: 5
6 | ---
7 |
8 | ## ENV
9 | This project currently supports 3 environments:
10 | - `local` - For development
11 | - `localproduction` - For development but with prod API
12 | - `production` - For production
13 |
14 | ## Config
15 | App config can be found in `config/appConfig.ts` file.
16 |
17 |
18 | ### config.global
19 | Key | Description
20 | --- | ---
21 | `global.app` | Few app related information.
22 | `global.domain` | Domain. For eg. `own-store-demo.vercel.app` OR `localhost:3000`
23 | `global.baseUrl` | Base URL. For eg. `https://own-store-demo.vercel.app` or `http://localhost:3000`
24 | `global.assetBaseUrl` | Base URL of static assets. If you want to push your static assets (stored in `/public`) and build files generated by NextJs to a CDN, update this URL. If you have a CDN for production, this is how you will map:
`http://localhost:3000` - (On local)
`https://www.your-cdn.com` - (On production)
25 | `global.imageBaseUrl` | Cloudinary image base URL. For eg. `https://res.cloudinary.com/your-store/image/upload`. If you have mapped AWS S3 with Cloudinary, put that URL here. `imageBaseUrl + image path (from DB)` will render the image. **Note:** This is not for static images.
26 | `global.apiBaseUrl` | API base URL to connect to. For eg. `http://localhost:3001`.
27 | `global.infiniteScrollFetchLimit` | How many items should be shown be fetched and shown per page during infinite scroll.
28 | `global.scrollToTopDisplayThreshold` | When to show scroll-to-top UI.
29 | `global.minSecurityQuestions` | How many security questions should be shown to user to set?
30 | `global.openBlogsInNewTab` | Should blogs open in a new tab?
31 |
32 | ### config.seo
33 | Learn more [here](./seo.md)
34 |
35 | Key | Description
36 | --- | ---
37 | `seo.facebook.pageId` | Facebook page ID. For eg. `1223xxxx`. Get this from page settings.
38 | `seo.twitter.username` | Twitter page username.
39 |
40 | ### config.pwa
41 | Learn more [here](./pwa.md)
42 |
43 | Key | Description
44 | --- | ---
45 | `pwa.shortcuts[]` | Users can directly open a page through shortcuts. Few properties are required:
46 | `pwa.startUrl` | PWA's start URL. Eg. `/?utm_source=pwa&utm_medium=homescreen`
47 | `pwa.icons.maskable` | Set this to true if PWA icons can be masked. **Note:** Make sure icons can be masked before setting to true. Otherwise, the installability criteria will not be met. [Masked icons ref](https://web.dev/maskable-icon/)
48 | `pwa.preferNativeAppOverPWA` | If you have a native app in store and want the app to have a higher preference, set this to true.
49 |
50 | ### config.app
51 | Key | Description
52 | --- | ---
53 | `app.android` | Android app information
54 | `app.android.name` | App name.
55 | `app.android.id` | App ID. For eg. (`com.android.chrome`)
56 | `app.android.storeUrl` | Store URL for the app. For eg. (`https://play.google.com/store/apps/details?id=com.android.chrome`)
57 | `app.ios` | iOS app information
58 | `app.android.name` | App name.
59 | `app.android.id` | App ID. For eg. (`535886823`)
60 | `app.android.storeUrl` | Store URL for the app. For eg. (`https://apps.apple.com/in/app/google-chrome/id535886823`)
61 |
62 | ### config.search
63 | Key | Description
64 | --- | ---
65 | `search.placeholder.header` | Search placeholder on the header.
66 | `search.placeholder.page` | Search placeholder on the page.
67 | `search.sectionFetchLimit` | Results count to show for each section. For eg. if set 10, show 10 products, catalogues and combos.
68 |
69 | ### config.features
70 | Key | Description
71 | --- | ---
72 | `features.enableLandscapeMode` | Enable landscape mode.
73 | `features.enablePageTransition` | Enable transition when navigation changes.
74 | `features.enableScrollToTop` | Show scroll to top UI.
75 | `features.enablePWAPromotions` | Enable PWA promotions.
76 | `features.enableAppPromotions` | Enable app promotions.
77 | `features.enablePagesPrefetching` | If enabled, link pages will be prefetched. [Reference](https://web.dev/route-prefetching-in-nextjs/)
78 |
79 | ### config.build
80 | Learn more [here](./build-strategy.md)
81 |
82 | Key | Description
83 | --- | ---
84 | `build.pageRevalidateTimeInSec` | When should the pages be re-validated? This is mapping for each static page.
85 | `build.initialPageBuildCount` | For pages that are public and dynamic, how many versions should be built initially?
86 |
87 | ### config.integrations
88 |
89 | #### config.integrations.googleOneTapLogIn
90 | For Google one-tap login integration.
91 |
92 | Key | Description
93 | --- | ---
94 | `integrations.googleOneTapLogIn.enabled` | Use this flag to disable.
95 | `integrations.googleOneTapLogIn.code` | Get this code from your app's credentials page from Google cloud console.
96 |
97 | #### config.integrations.googleLogIn
98 | For Google login integration.
99 |
100 | Key | Description
101 | --- | ---
102 | `integrations.googleLogIn.enabled` | Use this flag to disable.
103 | `integrations.googleLogIn.code` | Get this code from your app's credentials page from Google cloud console.
104 |
105 | #### config.integrations.facebookLogIn
106 | For Facebook login integration.
107 |
108 | Key | Description
109 | --- | ---
110 | `integrations.facebookLogIn.enabled` | Use this flag to disable.
111 | `integrations.facebookLogIn.code` | Get this code from Facebook's developer page.
112 |
113 | #### config.integrations.stripePayment
114 | For Stripe payments integration.
115 |
116 | Key | Description
117 | --- | ---
118 | `integrations.stripePayment.code` | Stripe secret key. Get this from dashboard.
119 | `integrations.stripePayment.publicCode` | Stripe public key. Get this from dashboard.
120 |
121 | #### config.integrations.googleAnalytics
122 | For Google analytics integration.
123 |
124 | Key | Description
125 | --- | ---
126 | `integrations.googleAnalytics.enabled` | Use this flag to disable.
127 | `integrations.googleAnalytics.webCode` | GA code. Get this from dashboard.
128 |
129 | #### config.integrations.googleSiteVerification
130 | For site verification on Google search console.
131 |
132 | Key | Description
133 | --- | ---
134 | `integrations.googleSiteVerification.enabled` | Use this flag to disable.
135 | `integrations.googleSiteVerification.code` | Get this from search console.
136 |
137 | #### config.integrations.sentryErrorReporting
138 | For Sentry integration.
139 |
140 | Key | Description
141 | --- | ---
142 | `integrations.googleSiteVerification.enabled` | Use this flag to disable.
143 | `integrations.googleSiteVerification.dsn` | Get this from dashboard.
144 |
145 | #### config.integrations.imageTransformation
146 | Image transformation integration. For eg. if you use `Cloudinary` and want to use their transformation parameters.
147 |
148 | Key | Description
149 | --- | ---
150 | `integrations.imageTransformation.enabled` | Use this flag to disable.
151 | `integrations.imageTransformation.variants` | A mapping of app-specific key and transform parameters.
152 |
153 | ### config.company
154 | Key | Description
155 | --- | ---
156 | `company.name` | Legal company name.
157 | `company.contactNumber` | Company's contact number.
158 | `company.contactEmail` | Company's contact email.
159 | `company.address` | Company address.
160 | `company.socialLinks[]` | Company social links. Following properties are required:
type: Type of the icon ([Reference](./faq/#which-social-icons-are-supported))
url: Social URL
name: Name of the social platform
isExternal: Should this link open in a new tab?
161 |
162 | ### config.footer
163 | Key | Description
164 | --- | ---
165 | `footer.links` | Links to show on footer.
166 | `footer.copyrightText` | Copyright text on footer.
167 |
168 | ### config.share
169 | Key | Description
170 | --- | ---
171 | `share.section.title` | Title to show when user shares the app from section.
172 | `share.product.title` | Title to show when user shares the product. Dynamic keywords allowed: `PRODUCT_NAME` and `PRODUCT_URL`.
173 |
--------------------------------------------------------------------------------
/projects/website/faq.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: FAQs
3 | title: Website FAQs
4 | icon: question
5 | order: -3
6 | ---
7 |
8 | ## Which social icons are supported?
9 | ```ts
10 | [
11 | APPLE,
12 | ANDROID,
13 | ALIBABA,
14 | AMAZON,
15 | EMAIL,
16 | APPSTORE,
17 | BLOGGER,
18 | DISCORD,
19 | DRIVE,
20 | EBAY,
21 | FACEBOOK,
22 | GITHUB,
23 | GITLAB,
24 | MAIL,
25 | GOOGLE,
26 | GOOGLE_PLAY,
27 | INSTAGRAM,
28 | ITUNES,
29 | LINKEDIN,
30 | MEDIUM,
31 | PAYPAL,
32 | PHONE,
33 | PHOTOS,
34 | PINTEREST,
35 | QUORA,
36 | REDDIT,
37 | RSS,
38 | SINA_WEIBO,
39 | SLACK,
40 | SNAPCHAT,
41 | SPOTIFY,
42 | TELEGRAM,
43 | TIKTOK,
44 | TUMBLR,
45 | TWITCH,
46 | TWITTER,
47 | VIMEO,
48 | WECHAT,
49 | WHATSAPP,
50 | WIKIPEDIA,
51 | YELP,
52 | YOUTUBE,
53 | GLOBE,
54 | PWA,
55 | FORM,
56 | REFRESH,
57 | ]
58 | ```
59 |
60 | ## Which icon library is used?
61 | [Heroicons](https://heroicons.com/) is used.
62 |
63 | ## How can we check debug logs?
64 | We have added grouped logging using [debug](https://www.npmjs.com/package/debug) library. Let's take an example...
65 |
66 | To check `http` logs
67 | ```ts http/httpClient.ts
68 | const log = debug('http')
69 | ```
70 |
71 | - On CLI:
72 | Use `DEBUG` environment variable. For eg.
73 | ```bash
74 | DEBUG='http' npm run start:local
75 | ```
76 |
77 | - On Browser:
78 | Use `localStorage.debug` to control. For eg.
79 | ```js
80 | localStorage.debug = 'http'
81 | ```
82 |
--------------------------------------------------------------------------------
/projects/website/folder-structure.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: Folder Structure
3 | title: Website Folder Structure
4 | icon: file-directory
5 | order: 6
6 | ---
7 |
8 | Directory | Description
9 | --- | ---
10 | `/components` | Contains page-level as well as pure components.
11 | `/config` | Contains app-level config.
12 | `/constants` | For global constants.
13 | `/contract` | API contracts are stored here.
14 | `/env` | For ENV files.
15 | `/hooks` | Contains global React hooks.
16 | `/http` | Responsible for connecting with API.
17 | `/pages` | All NextJs pages are kept in this folder.
18 | `/public` | Has all the static files from fonts to images.
19 | `/scriptTemplates` | Contains script templates for for all HTML pages.
20 | `/styles` | Holds all styles-related SCSS files.
21 | `/utils` | Contains page-level as well as pure methods.
22 |
--------------------------------------------------------------------------------
/projects/website/index.md:
--------------------------------------------------------------------------------
1 | This is the user-facing website project.
2 |
3 | - [Technologies](./technologies)
4 | - [Folder Structure](./folder-structure)
5 | - [Config](./config)
6 | - [Commands](./commands)
7 | - [Theme](./theme)
8 | - [SEO](./seo)
9 | - [PWA](./pwa)
10 | - [Analytics](./analytics)
11 | - [Payment](./payment)
12 | - [Build Strategy](./build-strategy)
13 | - [FAQs](./faq)
14 |
--------------------------------------------------------------------------------
/projects/website/index.yml:
--------------------------------------------------------------------------------
1 | icon: globe
2 | label: Website
3 | order: 2
4 |
--------------------------------------------------------------------------------
/projects/website/payment.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: Payment
3 | title: Website Payment
4 | icon: shield-check
5 | order: -1
6 | ---
7 |
8 | Stripe is added as an integration for processing seamless payments. Integration is added at both website and API layer for security.
9 |
--------------------------------------------------------------------------------
/projects/website/pwa.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: PWA
3 | title: Website PWA
4 | icon: download
5 | order: 1
6 | ---
7 |
8 | PWA along with offline support is supported in this. There are 2 major components here
9 | - Service Worker
10 | - manifest.json
11 |
12 | # Service Worker
13 | A SW is file is required for PWA to initialize. We have a PWA file in `pwa/service-worker.js`. What does it do?
14 | - Caches all the static files
15 | - Caches the offline page (can be found here: `public/html/offline.html`). Also adds a strategy to show the same HTML file when there's no network.
16 |
17 | !!!
18 | Note: Whenever you make a change in `offline.html`, make sure to update the `VERSION` variable stored in `pwa/service-worker.js`. Else users will keep seeing an outdated offline page.
19 | !!!
20 |
21 | !!!
22 | Also note PWA is disabled on local ENVs
23 | - `local`
24 | - `localproduction`
25 | !!!
26 |
27 | A minified SW file is created while building the project using `pwa/service-worker.js` as a source file.
28 |
29 | ## Manifest
30 | We don't have a static manifest JSON file, because we want values such as theme color, name, summary, etc... to be fetched from config or theme file. Don't want to hardcode here. These values should be defined only once in their config files.
31 |
32 | We have a script which fetches values from config files and prepares a `manifest.json` under `public/json` directory. Before preparing the file, let's first go step-by-step and update the current config for your needs.
33 |
34 | ### Basic Information
35 | Config defined in `appConfig.ts` will be used as manifest's basic information. So this is covered.
36 |
37 | ### Logos
38 | Let's discuss how to add your PWA icons...
39 |
40 | We'll use a third-party online tool for this.
41 |
42 | - Go to [pwabuilder.com](https://www.pwabuilder.com/imageGenerator)
43 | - Upload your logo, update settings (if required) and download the generated zip file. Settings I used: 
44 | - Move contents of the downloaded folder except `icons.json` to our logos folder (`public/images/logos/`).
45 | - Copy everything of `icons.json` and paste in `public/json/manifest-icons.json` file.
46 | - Now we need to update the `src` property of each icon in `manifest-icons.json` file. Add `/images/logos/` at the beginning. For eg.
47 |
48 | ```git
49 | - windows10/SmallTile.scale-100.png
50 | + /images/logos/windows10/SmallTile.scale-100.png
51 | ```
52 |
53 | In the end, an icon object should look something like this...
54 | ```json
55 | {
56 | "src": "/images/logos/windows10/SmallTile.scale-100.png",
57 | "sizes": "71x71"
58 | }
59 | ```
60 |
61 | - You're all set now for logos.
62 |
63 | ### Favicons
64 | Let's discuss how to add your favicons using a third-party online tool.
65 |
66 | - Go to [favicon-generator.org](https://www.favicon-generator.org/)
67 | - Upload your logo and update settings (if required). Settings I used: 
68 | - Once processed, you'll be prompted with 2 resources:
69 | - A zip file with all the required favicons.
70 | - A code snippet.
71 | - Move all the contents of the downloaded file to `public/images/logos` folder. **Note:** Only move image files.
72 | - Copy the code snippet. Only copy the line which has `+` marked against it.
73 | ```git
74 | +
75 | +
76 | +
77 | +
78 | +
79 | +
80 | +
81 | +
82 | +
83 | +
84 | +
85 | +
86 | +
87 | -
88 | -
89 | +
90 | -
91 | ```
92 |
93 | - Now navigate to `scriptTemplates/meta.tsx`, you will find a function there named `AppIcons`. Paste the copied snippet. The function will now look something like this...
94 | ```tsx
95 | const AppIcons: React.FC = () => {
96 | return (
97 | <>
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 | >
113 | )
114 | }
115 | ```
116 |
117 | - At last, we need to update `href` attribute of each line. Observe the following diff...
118 | ```git
119 | -
120 | +
121 | ```
122 |
123 | What did we do in this diff?
124 | - Prefix href with `/images/logos`
125 | - Wrap the entire href value with `prepareAssetUrl` method.
126 | - Properly close the tag for JSX. Replaced `>` with `/>`.
127 |
128 |
129 | ### Splashscreens
130 | We'll use a third-party online tool here as well.
131 |
132 | - Goto [appsco.pe](https://appsco.pe/developer/splash-screens)
133 | - Upload your screen, and update settings (if required). Settings I used: 
134 | - Download the zip and move contents to `public/images/splashscreens` folder.
135 | - Copy the provided code snippet.
136 | - Navigate to `scriptTemplates/meta.tsx`, you will find a function there named `AppSplashScreens`. Paste the copied snippet. The function will now look something like this...
137 | ```tsx
138 | const AppSplashScreens: React.FC = props => {
139 | return (
140 | <>
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 | >
152 | )
153 | }
154 | ```
155 |
156 | - At last, we need to update `href` attribute of each line. Observe the following diff...
157 | ```git
158 | -
159 | +
160 | ```
161 |
162 | What did we do in this diff?
163 | - Prefix href with `/images`
164 | - Wrap the entire href value with `prepareAssetUrl` method.
165 |
166 | ### Screenshots
167 | You can also show screenshots to the user when they try to install the PWA. Here's how you can add your own:
168 | - Put your screenshots under `public/images/screenshots` folder.
169 | - Not define your screenshots in `public/json/manifest-screenshots.json` file. Eg.
170 | ```json
171 | {
172 | "src": "/images/screenshots/screenshot-1.png",
173 | "type": "image/png",
174 | "sizes": "750x1364"
175 | },
176 | ```
177 | You need to specify
178 | - screenshot location source
179 | - type of the image
180 | - image size
181 |
182 | Eventually the file should look something like this:
183 | ```json
184 | {
185 | "screenshots": [
186 | {
187 | "src": "/images/screenshots/screenshot-1.png",
188 | "type": "image/png",
189 | "sizes": "750x1364"
190 | }
191 | ]
192 | }
193 | ```
194 |
195 | You can add multiple screenshots.
196 |
197 | ### Generate manifest.json
198 | Now let's finally generate a manifest file for testing.
199 | ```bash
200 | STORE_WEB_ENV=local npm run script:generate-manifest
201 | ```
202 |
203 | !!!
204 | Note: Manifest file will be automatically generated whenever you
205 | - run the server locally for development
206 | - build the project
207 | !!!
208 |
209 | !!!
210 | Also note that the `public/json/manifest.json` file ignore by Git since it will generated automatically.
211 | !!!
212 |
--------------------------------------------------------------------------------
/projects/website/seo.md:
--------------------------------------------------------------------------------
1 | ---
2 | label: SEO
3 | title: Website SEO
4 | icon: codescan-checkmark
5 | order: 2
6 | ---
7 |
8 | App is very well optimized with industry-standard SEO practices. There are 2 layers for SEO:
9 | - AppSeo
10 | - Page-level SEO
11 |
12 | ## App SEO
13 | App SEO is basically the global file for everything related to SEO. Can be found in `app/components/seo/AppSeo.tsx`. This file contains
14 | - global values
15 | - incoming page-level values
16 |
17 | ## Page-level SEO
18 | Now each page can have few SEO entires that can be dynamic. For eg. title of a page can be dynamic.
19 |
20 | Each page has a method to prepare page-level SEO data. Can be found in `app/utils/seo`. Let's take home page as an example...
21 |
22 | If you goto `app/utils/seo/home.ts`, you will find a method returning few entries.
23 |
24 | ```ts
25 | // http://localhost:3000/
26 | export const prepareHomePageSeo = (): IAppSeoProps => {
27 | return {
28 | title: 'Home',
29 | description: 'Home',
30 | canonical: `${appConfig.global.baseUrl}${getHomePageUrl()}`,
31 | keywords: [''],
32 | }
33 | }
34 | ```
35 |
36 | Now these entries will be passed on to `AppSeo.tsx`, that component will create a final SEO package and dump at the head of the page.
37 |
38 | What else can a page SEO method return?
39 | ```ts
40 | title: string
41 | description: string
42 | canonical: string
43 | keywords: string[]
44 | noIndex?: boolean
45 | noFollow?: boolean
46 | openGraph?: {
47 | title?: string
48 | description?: string
49 | }
50 | twitter?: {
51 | card?: 'summary' | 'summary_large_image'
52 | title?: string
53 | description?: string
54 | }
55 | imageUrl?: string
56 | structuredData?: {
57 | breadcrumbList?: { [key: string]: any }
58 | FAQs?: { [key: string]: any }
59 | product?: { [key: string]: any }
60 | }
61 | ```
62 |
63 | Let's understand what these keys mean
64 |
65 | Key | Description
66 | --- | ---
67 | `title` | Title of the page
68 | `description` | Page description
69 | `canonical` | Page's canonical URL. Should be absolute.
70 | `keywords` | A list of keywords for the page.
71 | `noIndex` | Should the page be indexed? If no, set this to true.
72 | `noFollow` | Should the page be followed? If no, set this to true.
73 | `openGraph` | This is to control page's meta information for OpenGraph/Facebook. For eg. you might want page `title` to be different when link is previewed.
74 | `openGraph.title` | Title for OpenGraph.
75 | `openGraph.description` | Description for OpenGraph.
76 | `twitter` | This is to control page's meta information for Twitter. For eg. you might want page `title` to be different when link is previewed.
77 | `twitter.card` | Should the card be of default size or large? Possible values: `'summary' | 'summary_large_image'`
78 | `twitter.title` | Title for Twitter.
79 | `twitter.description` | Description for Twitter.
80 | `imageUrl` | A page can also have a image URL. For eg. on product page. Should be absolute.
81 | `structuredData` | By default, each page will have the following structured data: