Skip to content

Commit 6670915

Browse files
authored
chore: adds ecommerce template (#2929)
1 parent 49f117e commit 6670915

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+12870
-0
lines changed

templates/ecommerce/.editorconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
root = true
2+
3+
[*]
4+
indent_style = space
5+
indent_size = 2
6+
charset = utf-8
7+
trim_trailing_whitespace = true
8+
insert_final_newline = true
9+
end_of_line = lf
10+
max_line_length = null

templates/ecommerce/.env.example

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
PORT=8000
2+
MONGODB_URI=mongodb://localhost/template-ecommerce
3+
PAYLOAD_SECRET=712kjbkuh87234sflj98713b
4+
PAYLOAD_PUBLIC_SERVER_URL=http://localhost:8000
5+
PAYLOAD_PUBLIC_SITE_URL=http://localhost:3000
6+
STRIPE_SECRET_KEY=
7+
PAYLOAD_PUBLIC_STRIPE_IS_TEST_KEY=true
8+
STRIPE_WEBHOOKS_ENDPOINT_SECRET=

templates/ecommerce/.eslintrc.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
root: true,
3+
extends: ['@payloadcms'],
4+
ignorePatterns: ['**/payload-types.ts'],
5+
}

templates/ecommerce/.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
build
2+
dist
3+
/media
4+
node_modules
5+
.DS_Store
6+
.env
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
**/payload-types.ts

templates/ecommerce/.prettierrc.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module.exports = {
2+
printWidth: 100,
3+
parser: "typescript",
4+
semi: false,
5+
singleQuote: true,
6+
trailingComma: "all",
7+
arrowParens: "avoid",
8+
};

templates/ecommerce/Dockerfile

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
FROM node:18.8-alpine as base
2+
3+
FROM base as builder
4+
5+
WORKDIR /home/node/app
6+
COPY package*.json ./
7+
8+
COPY . .
9+
RUN yarn install
10+
RUN yarn build
11+
12+
FROM base as runtime
13+
14+
ENV NODE_ENV=production
15+
ENV PAYLOAD_CONFIG_PATH=dist/payload.config.js
16+
17+
WORKDIR /home/node/app
18+
COPY package*.json ./
19+
20+
RUN yarn install --production
21+
COPY --from=builder /home/node/app/dist ./dist
22+
COPY --from=builder /home/node/app/build ./build
23+
24+
EXPOSE 3000
25+
26+
CMD ["node", "dist/server.js"]

templates/ecommerce/README.md

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
# Payload E-Commerce Template
2+
3+
A template for [Payload](https://github.com/payloadcms/payload) to power e-commerce businesses. This repo may have been created by running `npx create-payload-app` and selecting the "e-commerce" template or by cloning this template on [Payload Cloud](https://payloadcms.com/new/clone/blank).
4+
5+
Core features:
6+
7+
- [Pre-configured Payload Config](#how-it-works)
8+
- [Authentication](#users-authentication)
9+
- [Access Control](#access-control)
10+
- [Shopping Cart](#shopping-cart)
11+
- [Checkout](#checkout)
12+
- [Paywall](#paywall)
13+
- [Layout Builder](#layout-builder)
14+
- [SEO](#seo)
15+
16+
For details on how to get this template up and running locally, see the [development](#development) section.
17+
18+
## How it works
19+
20+
The Payload config is tailored specifically to the needs of an e-commerce business. It is pre-configured in the following ways:
21+
22+
### Collections
23+
24+
See the [collections documentation](https://payloadcms.com/docs/configuration/collections) for details on how to extend this functionality.
25+
26+
- #### Users (Authentication)
27+
28+
Users are auth-enabled and encompass both admins and customers based on the value of their `roles` field. Only `admin` users can access your admin panel to manage your store whereas `customer` can authenticate on your front-end to create [shopping carts](#shopping-cart) and place [orders](#orders) but have limited access to the platform. See [Access Control](#access-control) for more details.
29+
30+
For additional help, see the official [Auth Example](https://github.com/payloadcms/payload/tree/master/examples/auth/cms#readme) or the [authentication docs](https://payloadcms.com/docs/authentication/overview#authentication-overview).
31+
32+
- #### Products
33+
34+
Each product is linked to Stripe via a select field that is dynamically populated in the sidebar. This field fetches all available products in the background and displays them as options. Once a product has been selected, prices get automatically synced between Stripe and Payload. All products are layout-builder enabled so you can generate unique pages for each product using layout-building blocks, see [Layout Builder](#layout-builder) for more details. Products can also gate their content or digital assets behind a paywall, see [Paywall](#paywall) for more details.
35+
36+
- #### Orders
37+
38+
When an order is placed in Stripe, a webhook is fired that Payload listens for. This webhook creates a new order in Payload with the same data as the invoice. See the [Stripe section](#stripe) for more details.
39+
40+
- #### Pages
41+
42+
All pages are layout-builder enabled so you can generate unique layouts for each page using layout-building blocks, see [Layout Builder](#layout-builder) for more details.
43+
44+
- #### Media
45+
46+
This is the uploads-enabled collection used by products and pages to contain media, etc.
47+
48+
- #### Categories
49+
50+
A taxonomy used to group products together. Categories can be nested inside of one another, for example "Shirts > Red". See the official [Payload Nested Docs Plugin](https://github.com/payloadcms/plugin-nested-docs) for more details.
51+
52+
### Globals
53+
54+
See the [globals documentation](https://payloadcms.com/docs/configuration/globals) for details on how to extend this functionality.
55+
56+
- `Header`
57+
58+
The data required by the header on your front-end, i.e. nav links, etc.
59+
60+
- `Footer`
61+
62+
Same as above but for the footer of your site.
63+
64+
## Access control
65+
66+
Basic role-based access control is setup to determine what users can and cannot do based on their roles, which are:
67+
68+
- `admin`: They can access the Payload admin panel to manage your store. They can see all data and make all operations.
69+
- `customer`: They cannot access the Payload admin panel and have a limited access to operations based on their user (see below).
70+
71+
This applies to each collection in the following ways:
72+
73+
- `users`: Only admins and the user themselves can access their profile. Anyone can create a user but only admins can delete users.
74+
- `orders`: Only admins and the user who placed the order can access it. Once placed, orders cannot be edited or deleted.
75+
- `products`: Everyone can access products, but only admins can create, update, or delete them. Paywall-enabled products may also have content that is only accessible by users who have purchased the product. See [Paywall](#paywall) for more details.
76+
77+
For more details on how to extend this functionality, see the [Payload Access Control](https://payloadcms.com/docs/access-control/overview#access-control) docs.
78+
79+
## Shopping cart
80+
81+
Logged-in users can have their shopping carts saved to their profiles as they shop. This way they can continue shopping at a later date or on another device. When not logged in, the cart can be saved to local storage and synced to Payload on the next login. This works by maintaining a `cart` field on the `user`:
82+
83+
```ts
84+
{
85+
name: 'cart',
86+
label: 'Shopping Cart',
87+
type: 'object',
88+
fields: [
89+
{
90+
name: 'items',
91+
label: 'Items',
92+
type: 'array',
93+
fields: [
94+
// product, quantity, etc
95+
]
96+
},
97+
// other metadata like `createdOn`, etc
98+
]
99+
}
100+
```
101+
102+
## Stripe
103+
104+
Payload itself handles no currency exchange. All payments are processed and billed using [Stripe](https://stripe.com). This means you must have access to a Stripe account via an API key, see [Connect Stripe](#connect-stripe) for how to get one. When you create a product in Payload that wish to sell, it must be connected to a Stripe product by selecting one from the field in the product's sidebar. This field fetches all available products in the background and displays them as options, see [Products](#products) for more details. Once set, data is automatically synced between the two platforms in the following ways:
105+
106+
1. Stripe to Payload using [Stripe Webhooks](https://stripe.com/docs/webhooks):
107+
108+
- `invoice.created`
109+
- `invoice.updated`
110+
- `product.created`
111+
- `product.updated`
112+
- `price.updated`
113+
114+
1. Payload to Stripe using [Payload Hooks](https://payloadcms.com/docs/hooks/overview):
115+
- `user.create`
116+
117+
For more details on how to extend this functionality, see the the official [Payload Stripe Plugin](https://github.com/payloadcms/plugin-stripe).
118+
119+
## Checkout
120+
121+
A custom endpoint is opened at `/api/checkout` which initiates the checkout process. This endpoint creates a [`PaymentIntent`](https://stripe.com/docs/payments/payment-intents) with the items in the cart using the Stripe's [Invoices API](https://stripe.com/docs/api/invoices). First, an invoice is drafted, then each item in your cart is appended as a line-item to the invoice. The total price is recalculated on the server to ensure accuracy and security, and once completed, passes the `client_secret` back in the response for your front-end to finalize the payment.
122+
123+
## Paywall
124+
125+
Products can optionally gate content or digital assets behind a paywall. This will require the product to be purchased before it's resources are accessible. To do this, we add a `paywall` field to the `product` collection with `read` access control to check for associated purchases on each request. A `purchases` field is maintained on each user to determine their access which can be manually adjusted as needed.
126+
127+
```ts
128+
{
129+
name: 'paywall',
130+
label: 'Paywall',
131+
type: 'blocks',
132+
access: {
133+
read: checkUserPurchases,
134+
},
135+
fields: [
136+
// assets
137+
]
138+
}
139+
```
140+
141+
## Layout builder
142+
143+
Products and pages can be built using a powerful layout builder. This allows you to create unique layouts for each product or page. This template comes pre-configured with the following layout building blocks:
144+
145+
- Hero
146+
- Content
147+
- Media
148+
- Call To Action
149+
- Archive
150+
151+
## SEO
152+
153+
This template comes pre-configured with the official [Payload SEO Plugin](https://github.com/payloadcms/plugin-seo) for complete SEO control.
154+
155+
## Development
156+
157+
To spin up the template locally, follow these steps:
158+
159+
1. First clone the repo
160+
1. Then `cd YOUR_PROJECT_REPO && cp .env.example .env`
161+
1. Next `yarn && yarn dev` (or `docker-compose up`, see [Docker](#docker))
162+
1. Now `open http://localhost:8000/admin` to access the admin panel
163+
1. Create your first admin user using the form on the page
164+
165+
That's it! Changes made in `./src` will be reflected in your app—but your database is blank and your app is not yet connected to Stripe, more details on that [here](#stripe). You can optionally seed the database with a few products and pages, more details on that [here](#seed).
166+
167+
### Connect Stripe
168+
169+
To integrate with Stripe, follow these steps:
170+
171+
1. You will first need to create a [Stripe](https://stripe.com) account if you do not already have one.
172+
1. Retrieve your Stripe Secret Key from the Stripe admin panel and paste it into your `env`:
173+
```bash
174+
STRIPE_SECRET_KEY=
175+
```
176+
1. In another terminal, listen for webhooks:
177+
```bash
178+
stripe login # follow the prompts
179+
yarn stripe:webhooks
180+
```
181+
1. Paste the given webhook signing secret into your `env`:
182+
```bash
183+
STRIPE_WEBHOOKS_ENDPOINT_SECRET=
184+
```
185+
1. Reboot Payload to ensure that Stripe connects and the webhooks are registered.
186+
187+
See the official [Payload Stripe Plugin](https://github.com/payloadcms/plugin-stripe) for more details.
188+
189+
### Docker
190+
191+
Alternatively, you can use [Docker](https://www.docker.com) to spin up this template locally. To do so, follow these steps:
192+
193+
1. Follow [steps 1 and 2 from above](#development), the docker-compose file will automatically use the `.env` file in your project root
194+
1. Next run `docker-compose up`
195+
1. Follow [steps 4 and 5 from above](#development) to login and create your first admin user
196+
197+
That's it! The Docker instance will help you get up and running quickly while also standardizing the development environment across your teams.
198+
199+
### Seed
200+
201+
To seed the database with a few products and pages you can run `yarn seed`.
202+
203+
> NOTICE: seeding the database is destructive because it drops your current database to populate a fresh one from the seed template. Only run this command if you are starting a new project or can afford to lose your current data.
204+
205+
## Production
206+
207+
To run Payload in production, you need to build and serve the Admin panel. To do so, follow these steps:
208+
209+
1. First invoke the `payload build` script by running `yarn build` or `npm run build` in your project root. This creates a `./build` directory with a production-ready admin bundle.
210+
1. Then run `yarn serve` or `npm run serve` to run Node in production and serve Payload from the `./build` directory.
211+
212+
### Deployment
213+
214+
The easiest way to deploy your project is to use [Payload Cloud](https://payloadcms.com/new/import), a one-click hosting solution to deploy production-ready instances of your Payload apps directly from your GitHub repo. You can also deploy your app manually, check out the [deployment documentation](https://payloadcms.com/docs/production/deployment) for full details.
215+
216+
## Questions
217+
218+
If you have any issues or questions, reach out to us on [Discord](https://discord.com/invite/payload) or start a [GitHub discussion](https://github.com/payloadcms/payload/discussions).
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
version: '3'
2+
3+
services:
4+
5+
payload:
6+
image: node:18-alpine
7+
ports:
8+
- "3000:3000"
9+
volumes:
10+
- .:/home/node/app
11+
- node_modules:/home/node/app/node_modules
12+
working_dir: /home/node/app/
13+
command: sh -c "yarn install && yarn dev"
14+
depends_on:
15+
- mongo
16+
env_file:
17+
- .env
18+
19+
mongo:
20+
image: mongo:latest
21+
ports:
22+
- "27017:27017"
23+
command:
24+
- --storageEngine=wiredTiger
25+
volumes:
26+
- data:/data/db
27+
logging:
28+
driver: none
29+
30+
volumes:
31+
data:
32+
node_modules:

templates/ecommerce/nodemon.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"ext": "ts",
3+
"exec": "ts-node src/server.ts"
4+
}

0 commit comments

Comments
 (0)