Make it yours
Do these once, before your first feature.
Put it in your own repository
Section titled “Put it in your own repository”You can read the kit’s repository but not push to it. Keep the kit as a second remote, called
upstream, to take updates from:
git clone https://github.com/Michael-Guay/saas-stack.git my-productcd my-productgit remote rename origin upstreamgit remote add origin https://github.com/<you>/<my-product>.gitgit push -u origin mainMake the new repository private: the licence lets you build any number of products, not pass the kit on.
To take an update:
git fetch upstreamgit merge upstream/mainExpect conflicts in files you have both changed. They stay few when your features live in folders of their own, as in Add a resource.
Before you merge, read the new entries in the kit’s UPGRADING.md: what changed, and what
you have to do. Or ask your coding agent to “upgrade the kit”: the upgrade-kit skill does
the merge on a branch, follows those notes, and tells you what is left for you.
Name your product
Section titled “Name your product”The name is in five places, and the tagline beside it:
| Where | What it names |
|---|---|
packages/contracts/src/app.ts |
appConfig.name: the sidebar and every email |
packages/contracts/src/app.ts |
appConfig.tagline: one line beside sign-in and sign-up |
apps/web/index.html |
The browser tab, in <title> |
apps/site/src/config.ts |
The marketing site: name, tagline, description |
apps/mobile/app.json |
The mobile app: name, slug, scheme, store identifiers |
MAIL_FROM in .env |
Who your emails come from |
If you change the mobile app’s scheme, set MOBILE_SCHEME to the same value: the API accepts
sign-in from the app by it.
Replace favicon.svg in apps/web/public and apps/site/public too. In your own code, write
appConfig.name, never the name itself.
Change the colors and fonts
Section titled “Change the colors and fonts”The palette is warm paper and ink, with one accent color, --brand (marigold). Buttons and
other actions are --primary: ink on paper, and paper in dark mode, with
--primary-foreground on top. The accent marks things (meters, progress, the logo) and never
sits behind words. Headings use Instrument Sans set tight (the font-display class), as does text, and labels and code use JetBrains Mono.
The colors are in four places. Change them together:
| Where | What |
|---|---|
apps/web/src/styles.css |
The tokens, light and dark |
apps/site/src/styles/global.css |
The same tokens, for the site |
apps/mobile/src/theme.ts |
The same, as hex for React Native |
apps/api/src/mail/templates/layout.tsx |
The emails, which use light only |
The share images in apps/site/src/lib/og.ts and the favicons use them too. Every place the
look lives, logo and icons included, is in Change the design,
and the redesign skill changes them all at once.
Choose personal accounts or teams
Section titled “Choose personal accounts or teams”One setting, in packages/contracts/src/app.ts:
export const appConfig: AppConfig = { name: 'Acme', teams: false,};teams |
People get | Addresses |
|---|---|---|
false, as it comes |
An account of their own, straight into the app | /app/settings/billing |
true |
Workspaces they create and invite others to, with roles | /w/acme/settings/billing |
Either way, everything people create belongs to a workspace. With teams off, each person has one they never see. Build every feature against the workspace and it works in both modes: see Workspaces and teams.
You can start with false and turn teams on later: people keep their data, their addresses
change to /w/user-<id>/..., and old /app links stop working. Going from teams back to
personal accounts is not supported once people share workspaces. Turning teams on has not
been tested beyond reading the code.
Per-seat pricing only makes sense with teams on. See Charge for a feature.
Set your own secret
Section titled “Set your own secret”AUTH_SECRET signs session cookies. Everyone who has the kit knows the one in
.env.example, so generate yours:
openssl rand -base64 32Put it in .env. Changing it signs everyone out. Production needs another one again, and the
API refuses to start in production with the example value.
Start your product: describe it to your coding agent, and it plans what to build on the kit before it writes any code.