What to Customize
A map of the DirectoryLaunch codebase by upgrade cost — what is free to change, what will conflict when you merge a release, and what you should leave alone.
Everything here is yours to edit. But some edits cost you nothing at upgrade time and others cost you a merge conflict every release. Knowing which is which up front is the difference between a five-minute update and an afternoon.
Free — costs you nothing, ever
These never conflict, because they aren't in code you and we both edit.
| What | Where | How |
|---|---|---|
| Colours, typography, radius, shadows | Database | /admin/design → Theme |
| FAQ questions and answers | config/faq.config.ts | Edit the config, never the page |
| Terms, privacy, cookies | config/legal.config.ts | Edit the config, never the page |
| Card & page layouts, homepage sections | Database | /admin/design → Layout |
| Map projection & lighting | Database | /admin/design → Map |
| Categories, spheres, listings | Database | /admin |
| Blog posts | Database | /admin/blog |
| Sponsors, promotions, social proof | Database | /admin/advertising, /admin/social-proof |
Anything you can change from the admin panel is stored in your Supabase project. Merges cannot touch it.
Protected — yours, kept automatically
Listed in .gitattributes with merge=ours. Once you've run pnpm setup:upstream, an
upstream merge keeps your version of these with no conflict at all:
- config/
- site.config.ts — brand, tagline, URLs, logos, contacts, socials, SEO
- platform.config.ts — which vertical you run
- features.config.ts — feature flags
- plans.config.ts — pricing tiers, Stripe price IDs
- directory.config.ts — page size, sorting, seed categories
- marketing.config.ts — ad banner copy
- pricing.config.ts — the cards on /pricing (prices come from plans.config.ts)
- faq.config.ts — every question on /faq, and the words its JSON-LD emits
- legal.config.ts — the terms, privacy and cookie copy
- help.config.ts — the cards on /help
- advertising.config.ts — sponsor & promotion pricing
- ai.config.ts / claims.config.ts / local-seo.config.ts / map.config.ts / quotes.config.ts / store.config.ts
- storage.config.ts — upload destination, size limits, image compression
- places.config.ts — Google Places scan and import rules
- payments.config.ts / email.config.ts / analytics.config.ts / i18n.config.ts
- messages/
- en.json — UI translations
- public/assets/ — logos, favicon, OG image
Keeping your version used to mean not getting new keys we add — a flag or a setting
introduced by a release was simply absent from the file the merge kept. Since 2.0.0 (and for
every config since 3.0.0) each one is wrapped in defineX({ ... }) and layers over
config/defaults/: your values win, and keys you have never set resolve to ours.
After merging a release that says so, run pnpm fix:configs --apply — the wrapper cannot
arrive on its own, and lib/config-guard.ts fails the typecheck until it is there.
Helpers that used to be exported from these files — getPlan, resolveCheckoutMode,
planSeesLeadContact, isFreemailDomain, hasRegionTier — moved to lib/ in 3.0.0. They
were code living in files a merge keeps your copy of, so a fix to them could never reach you.
Import them from @/lib/* (the table is in UPGRADING.md); edit the configs for data only.
ownership.json lists every path with the reason it is yours or ours. .gitattributes is
generated from it, and pnpm check:ownership fails CI when the two disagree. config/database.config.ts
is deliberately core — there is one legal value, so keeping your copy could only withhold
a provider we added.
Will conflict — edit freely, expect a merge
Real code that you may well need to change, and that we also change. This is normal git; the
changelog marks these releases [ui] so you see them coming, and git rerere means a
conflict you resolve once stays resolved.
| File | Why you'd edit it |
|---|---|
app/(marketing)/faq/page.tsx | Layout only — the questions moved to config/faq.config.ts |
app/(marketing)/pricing/page.tsx | Layout only — the cards moved to config/pricing.config.ts |
app/(marketing)/terms/page.tsx | Layout only — the copy moved to config/legal.config.ts |
app/(marketing)/privacy/page.tsx | Layout only — the copy moved to config/legal.config.ts |
app/(marketing)/help/page.tsx | Layout only — the cards moved to config/help.config.ts |
components/layout/Header.tsx, Footer.tsx | Nav links, footer columns |
app/globals.css | Only for the pre-login default look — colours belong in /admin/design |
components/shared/DirectoryLaunchBadge.tsx | The "Built with DirectoryLaunch" badge — delete it and its two call sites if you don't want it |
terms, privacy and cookies ship as example text, not legal advice. Since 2.0.0 that
text is inherited from config/defaults/legal.defaults.ts rather than copied into your
config, so our corrections reach you — but it has still never been reviewed by a lawyer for
your business. To take a document over, copy it out of the defaults file into
config/legal.config.ts and edit it there; from then on it is yours in full. The operator
named in the terms comes from siteConfig.legal.entity, and that section stays omitted while
it is empty.
Leave alone — take our version
Change these and every release becomes a manual merge, with no upside: the behaviour you want is almost always reachable through config or the admin panel instead.
- lib/ — business logic, Supabase layer, validations, payments
- app/api/ — every API route
- components/ui/ — Base UI primitives
- middleware.ts
- next.config.ts
- supabase/ — schema and migrations
- types/
Need behaviour that isn't there? Add a file rather than editing one. A new route under
app/(marketing)/, a new component in components/, a new helper in lib/ — new files never
conflict, because we don't have a version of them.
The rule, in one line
Configure what you can, add new files where you must, and edit shared files only when there's
no alternative. Then pnpm upgrade:check will keep telling you your merges are clean.