This repository holds the Next.js project powering a multi-tenant avalanche center website experience, using PayloadCMS v3 as a built-in CMS and Next.js app router for the front-end.
We use Next.js middleware to dynamically rewrite requests from subdomains of the test or production site or from existing web properties of avalanche centers, allowing us to serve many tenants from one domain.
We use sqlite for local development since it's simple, allows us to store seed and test data easily, and has few dependencies.
When working on the front-end, it's possible to start with a seeded database and be up and running with no effort by using the in-repo seed database.
When changes to the schema or seed data need to occur, simply start with a new database and use a backup to update the seed database.
Run pnpm bootstrap, which will create a new database file for you, add a boostrap@avy.com user, and grant them super-admin rights to three tenants. Then, run pnpm dev and start work straight away by logging in as that first user.
Run pnpm seed, which will create a new database file for you and add all the seed data. Then, run pnpm dev and start work straight away by logging in as any of the users defined in the seed corpus. If you've changed how the seed is done or the contents of some record, run pnpm reseed to incrementally update just the values that were changed.
You can also run the seed in standalone mode which doesn't spin up a Next.js dev server: pnpm seed:standalone. This should run a little faster than pnpm seed.
Start a new database with:
echo "DATABASE_URI=file:./dev.db" >> .env
sqlite3 dev.dbIn the database console, configure the database to use WAL mode with:
PRAGMA journal_mode=WAL;
.quit
Start the development server with
pnpm i
pnpm devTODO: add to password manager
You will need to add two keys to your .env file. Reach out to someone on the dev team.
In order to use tenant scoped subdomains on localhost you'll need to add the following to your /etc/hosts on macOS or C:\Windows\System32\drivers\etc\hosts on Windows:
127.0.0.1 dvac.localhost
127.0.0.1 nwac.localhost
127.0.0.1 sac.localhost
127.0.0.1 snfac.localhost
Once a database file is chosen and the development server is started, navigate to the admin panellocalhost:3000/admin and log in with password:admin@avy.com for a seeded site, or bootstrap the first user as necessary.
This repo uses Husky and lint-staged to run a pre-commit hook that affects staged files. Our pre-commit hook formats staged files before committing. The pnpm prepare script should be automatically run after pnpm install which will configure the pre-commit hook to run on git commit.
If the pre-commit hook isn't running on your commits you can manually run pnpm prepare.
Running the seed script may take a while - when reviewing a pull request, you can download the turso CLI, initialize the client and clone the preview database locally instead:
# branch names may have illegal characters for turso database names, hence the shell magic
branch="skuznets/some-feature-thing"; turso db shell "payloadcms-preview-${branch//[^a-z0-9\-]/x}" .dump | sqlite3 dev.dbThe email adapter for Payload is set up to use nodemailer locally and Resend in production.
For local development it is recommended to use a free mailtrap.io account and their email sandbox. Using this sandbox SMTP server will capture all emails sent from your local environment regardless of email address.
- Create a free account at https://mailtrap.io/register/signup
- Select email testing / sandbox during onboarding (not critical)
- After onboarding navigate to the "Sandbox" page in the left-hand nav
- Copy the SMTP credentials to their respective SMTP_ environment variables in your
.envfile. See.env.example.
You should use the customized ./src/utilities/email/sendEmail#sendEmail function because it adds our default replyTo address which we use for email receiving.
This repo on GitHub requires signed commits on the main branch.
To avoid an error when attempting to merge a PR on a feature branch into main, you should setup automatic commit signing:
- Generate a GPG key (or use an existing one with the same name and email as your GitHub account): GitHub guide
- Add your GPG key to your GitHub account: GitHub guide
- Configure git to use your GPG key: GitHub guide
Note: When configuring git to automatically sign commits you could leave out the --global flag if you only want to automatically sign commits in this repo, not all repos.
The application uses Vercel Edge Config for fast, globally distributed tenant lookups in middleware, with a cached API route as fallback.
The system operates with these priorities:
- Edge Config Lookup (primary) - Fast tenants lookup (~10ms globally)
- Cached API Route (fallback) - Database query with 5-minute cache when Edge Config fails
We have two edge config stores in Vercel:
-
For prod environment
avy-edge-config-prod -
For preview environments
avy-edge-config-previewNOTE: This should also be used for local dev. Our preview environments still use our seed script so these values should be in sync with our local environments. The preview edge config can updated manually in Vercel if you need additional tenants in your local env.
This repo is setup to use React Email for custom email development.
react-email allows us to use React components to develop emails. The ./src/emails directory stores our React emails and can be previewed using the react-email preview server.
Run pnpm email:dev to run the email server on http://localhost:3001.
Any file inside ./src/emails (except for inside the ./src/emails/_components dir) will be interpreted as an email. Passing PreviewProps to the default export will render the email on the preview server with those props.
You likely won't use pnpm email:build or pnpm email:export. The primary method of using these emails is through the render utility. See ./src/utilities/email/generateInviteUserEmail.tsx for an example.
See our revalidation docs.