Site Config
Single source of truth for brand name, domain, logos and contact info — propagates to header, footer, SEO tags, emails and OG images.
Why this matters
Site config is the one file that touches every page. Change name here and your <title> tags, header logo alt text, footer copyright, OG images, transactional emails, robots.txt and sitemap.xml all update — no manual hunting through 40 components. Get it wrong and you ship a directory with mismatched branding in three places, broken share previews on Twitter, and emails that go out under the wrong domain.
This page is the field-by-field reference, the minimal example, and the gotchas. If you're spinning up a new directory, edit this file first — before you touch any feature config or layout. Everything else inherits from here.
File: config/site.config.ts
This is the first file you'll edit. Everything in it — name, tagline, URL, contact emails — propagates across the whole site: header, footer, SEO tags, emails, Open Graph images.
All fields
| Field | Type | What it controls |
|---|---|---|
name | string | Your brand name. Shows in the header, page titles, emails. |
tagline | string | One-line pitch. Shows under the hero and in OG tags. |
description | string | Longer SEO description for meta tags. |
url | string | Canonical URL. Pulled from NEXT_PUBLIC_APP_URL env by default. |
logo.light | string | Path to logo shown on light backgrounds. |
logo.dark | string | Path to logo shown on dark backgrounds. |
favicon | string | Path to favicon. |
ogImage | string | Path to default Open Graph image (1200×630). |
social.twitter | string | Twitter/X handle or full URL. |
social.github | string? | GitHub link (optional). |
social.discord | string? | Discord invite link (optional). |
contact.email | string | Main contact email (shown in footer, About). |
contact.supportEmail | string | Support email for user help requests. |
contact.privacyEmail | string | Privacy/GDPR contact email. |
footer.copyright | string | Footer copyright text. |
footer.description | string | Footer tagline shown below the copyright. |
refParameter | string | UTM/ref param added to outbound links (e.g. ?ref=yourbrand). |
keywords | string[] | SEO keywords for meta tags. |
language | string | Primary language (en, ru, …). |
locale | string | Locale code (en_US, en_GB, …). |
themeColor | string | HEX color for browser UI (mobile address bar). |
Minimal example
export const siteConfig: SiteConfig = {
name: 'ToolFinder',
tagline: 'Discover the best developer tools',
description: 'A curated directory of tools, libraries, and services for developers.',
url: process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000',
logo: {
light: '/assets/logo.svg',
dark: '/assets/logo-white.svg',
},
favicon: '/assets/favicon/favicon.ico',
ogImage: '/assets/og-image.png',
social: {
twitter: '@toolfinder',
},
contact: {
email: 'hello@toolfinder.dev',
supportEmail: 'support@toolfinder.dev',
privacyEmail: 'privacy@toolfinder.dev',
},
footer: {
copyright: `© ${new Date().getFullYear()} ToolFinder. All rights reserved.`,
description: 'A curated directory of developer tools.',
},
refParameter: 'toolfinder',
keywords: ['developer tools', 'SaaS directory', 'programming'],
language: 'en',
locale: 'en_US',
themeColor: '#000000',
};Replacing logos and images
Drop your files into public/assets/ using the same filenames the config references (logo.svg, logo-white.svg, favicon.ico, og-image.png). No code changes needed.
See Branding for sizes and best practices.
When to restart the server
- Changes to
name,tagline,contact, etc. — hot-reload handles it. - Changes to
url(when also changingNEXT_PUBLIC_APP_URL) — restart the dev server to pick up the env var.
A real-world walkthrough: spinning up a new directory in 30 minutes
You bought craft-tools.directory for a directory of woodworking software. The 30-minute setup:
- Open
config/site.config.ts. Replacenamewith'CraftTools'. Updatetagline,description,contact.*,keywords,themeColor. Save. - Drop your logo SVG into
public/assets/logo.svg(andlogo-white.svgfor dark mode). Drop a 1200×630 OG image intopublic/assets/og-image.png. Drop a favicon intopublic/assets/favicon/. Filenames must match what's in config. - Set
NEXT_PUBLIC_APP_URL=https://craft-tools.directoryin Vercel env vars (production) andhttp://localhost:3000in.env.local(dev). - Run
pnpm dev. Verify the header logo, page title, footer text. Open a project page → confirm the<title>is[Project Name] | CraftTools. - Set up
keywordscarefully: 5–8 niche terms, not generic ones.['woodworking software', 'CAD for furniture', 'wood-cutting plans', 'workshop tools']beats['software directory', 'tools', 'apps'].
The whole setup takes 20–30 minutes. After that, every page on the site has correct branding, correct meta tags, correct emails, and correct OG share previews — without you touching any other file.
Common pitfalls
- Using
process.env.NEXT_PUBLIC_APP_URLwithout a fallback. If the env var is missing in a build,urlbecomesundefined, breaking canonical tags and OG image absolute URLs. Always provide a literal fallback in the config:process.env.NEXT_PUBLIC_APP_URL || 'https://yourdomain.com'. - Forgetting to update
languageandlocalefor non-English directories. They default toen/en_US. If you ship in Russian, setlanguage: 'ru',locale: 'ru_RU'— Google uses these to decide language relevance. - Setting
themeColorto your brand's vibrant colour. Mobile address-bar colour bleeds into the URL for users; vibrant colours look gaudy. Use a darker, muted version of your brand (your sidebar/footer dark colour usually works). - Mismatching
social.twitterformats. Use@handlefor the bare handle; the OG meta tags expect that format. If you put a full URL, the Twitter card may not render correctly. - Hardcoding the year in
footer.copyright. Use${new Date().getFullYear()}so the year auto-updates on the next deploy. Year-stale footers are a tiny but visible "this site is abandoned" signal.
FAQ
Should I store the logo in public/assets/ or in public/?
public/assets/ is the convention here, and the config defaults reference that path. Keeping all branding in one folder makes rebrands easier — drop new files in, one folder, no git ls-files | grep logo archaeology.
Can I A/B test the tagline?
Yes — wrap the tagline render with a feature flag or split-test middleware. The config file is the default; you can override the rendered value at runtime. Most operators don't bother — the tagline is rarely the conversion bottleneck.
Does Google use description from this file or per-page descriptions?
Per-page descriptions if set; falls back to description from this file otherwise. Project pages, blog posts and category pages typically generate their own descriptions; static pages (privacy, about) inherit from here.
With AI
Rebrand config/site.config.ts with these values:
Brand:
- name: "{brand name}"
- tagline: "{60-char one-liner}"
- description: "{150-char SEO description}"
Contact:
- email: "{hello@yourdomain.com}"
- supportEmail: "{support@yourdomain.com}"
- privacyEmail: "{privacy@yourdomain.com}"
Social (use full URLs or @handle where noted; omit any I didn't provide):
- twitter: "{@handle}"
- github: "{https://github.com/org\}"
- discord: "{https://discord.gg/xxxx\}"
Footer:
- copyright: "{© YEAR Brand. All rights reserved.}"
- description: "{short footer tagline}"
SEO:
- refParameter: "{slug for ref query param}"
- keywords: [{5 niche keywords}]
- language: "{en|ru|es|...}"
- locale: "{en_US|ru_RU|...}"
- themeColor: "{hex color for mobile browser UI}"
Preserve the existing SiteConfig type structure. Don't touch logo/favicon/ogImage paths.