Ecommerce Boilerplate
Configuration

Site Configuration

Single-file branding: names, contact, navigation, categories, locales, currencies, and theme.

Almost everything that makes the storefront yours lives in a single file: src/config/site.ts. Components read from this config instead of hardcoding copy, so rebranding the boilerplate is mostly an exercise in editing it.

This page reflects the values shipped in the boilerplate (the fictional "Kestrel Supply"). Every field name below matches the source exactly — change the values, keep the keys.

What the file exports

src/config/site.ts exports three runtime values plus several TypeScript interfaces that describe their shape.

ExportKindPurpose
siteConfigconst objectStore identity, contact, navigation, currencies, locales, and theme presets.
productCategoriesProductCategory[]The catalog's top-level categories.
productConfigconst objectThe boilerplate's own identity (name, url, tagline), kept separate so renaming your store does not rename the project you forked. Read by the /platform marketing page's nav and footer and by the /docs shell; delete those surfaces if you do not want them.
CurrencyConfiginterfaceShape of the base store currency (code, locale).
CurrencyOptioninterfaceA switchable currency (code, locale, rate, label).
LocaleOptioninterfaceA switchable UI locale (code, label).
ThemePresetinterfaceA brand color scheme as HSL triplets.
ProductCategoryinterfaceShape of one entry in productCategories.

siteConfig is declared as const, so its values are readonly and their literal types flow through the rest of the app — TypeScript will flag a typo in a category slug or a currency code at build time.

siteConfig

Identity

src/config/site.ts
export const siteConfig = {
  name: "Kestrel Supply",
  tagline: "Technology worth keeping",
  description:
    "Audio, wearables, and smart home gear, tested by our team before it reaches the shelf.",
  url: "https://ecommerce-boilerplate.com",
  // ...
} as const;
FieldTypeShipped valueNotes
namestring"Kestrel Supply"Store name shown in the header, footer, page titles, and emails.
taglinestring"Technology worth keeping"Short marketing line.
descriptionstring"Audio, wearables, and smart home gear, tested by our team…"Long description, used for SEO metadata and the OpenGraph/Twitter cards.
urlstring"https://ecommerce-boilerplate.com"Canonical site URL. Point this at your production domain.
src/config/site.ts
  contact: {
    email: "hello@example.com",
    phone: "+1 (555) 000-0000",
    address: "123 Commerce St, Suite 100, Springfield, USA",
  },
  links: {
    linkedin: "https://www.linkedin.com/company/your-company",
    instagram: "https://www.instagram.com/your-company",
    github: "https://github.com/nebulanollie/ecommerce-boilerplate",
  },
FieldShipped value
contact.email"hello@example.com"
contact.phone"+1 (555) 000-0000"
contact.address"123 Commerce St, Suite 100, Springfield, USA"
links.linkedin"https://www.linkedin.com/company/your-company"
links.instagram"https://www.instagram.com/your-company"
links.github"https://github.com/nebulanollie/ecommerce-boilerplate" (the boilerplate's own repo, used by the marketing landing and boilerplate bar)

Two navigation arrays drive the header and footer. Each item is a { label, href } pair — internal routes are plain paths and hash links (/#contact) jump to a section.

src/config/site.ts
  mainNav: [
    { label: "Products", href: "/products" },
    { label: "About", href: "/about" },
    { label: "Contact", href: "/#contact" },
  ],
  legalNav: [
    { label: "Privacy Policy", href: "/privacy-policy" },
    { label: "Terms of Service", href: "/terms-of-service" },
    { label: "Cookie Policy", href: "/cookie-policy" },
  ],
ArrayRendered inItems (label → href)
mainNavPrimary header/footer navigationProducts → /products, About → /about, Contact → /#contact
legalNavFooter legal linksPrivacy Policy → /privacy-policy, Terms of Service → /terms-of-service, Cookie Policy → /cookie-policy

Any internal href must point at a route that actually exists in the app — nothing validates these at build time.

Currencies

The store has one base currency (currency) and a list of currencies the shopper can switch into (currencies). Prices are stored in the base currency and converted for display by formatMoney in src/lib/money.ts.

src/config/site.ts
  currency: { code: "USD", locale: "en-US" } satisfies CurrencyConfig,
  currencies: [
    { code: "USD", locale: "en-US", rate: 1, label: "USD ($)" },
    { code: "EUR", locale: "de-DE", rate: 0.92, label: "EUR (€)" },
    { code: "GBP", locale: "en-GB", rate: 0.79, label: "GBP (£)" },
    { code: "JPY", locale: "ja-JP", rate: 155, label: "JPY (¥)" },
  ] satisfies CurrencyOption[],
  • currency (CurrencyConfig) is the single source of truth for how prices render across the storefront, admin, and emails: code is an ISO 4217 code and locale is a BCP 47 locale that drives number grouping and the currency symbol.
  • currencies (CurrencyOption[]) lists the switchable options. Each adds rate — the multiplier from the base currency — and label, the short text shown in the switcher.

The first entry in currencies must be the base currency with rate: 1 and must match siteConfig.currency. The shipped rates (0.92, 0.79, 155) are static demo values — wire a live FX feed before relying on them in production.

See Currency & pricing for how conversion and formatting work end to end.

Locales

src/config/site.ts
  defaultLocale: "en",
  locales: [
    { code: "en", label: "English" },
    { code: "es", label: "Español" },
  ] satisfies LocaleOption[],
FieldTypeShipped value
defaultLocalestring"en"
localesLocaleOption[]en → English, es → Español

Each LocaleOption has a code (a BCP 47 code that must also be registered in the src/lib/i18n dictionaries) and a native label for the switcher. The first entry is the default. Adding a language is a data change — drop in src/lib/i18n/<locale>.ts, register it in dictionaries, and add an entry here.

See Internationalization for the full "how to add a locale" walkthrough.

Theme presets

Brand colors live in the --brand* CSS variables in src/app/globals.css; the theme block mirrors and documents them so you can swap schemes from one place.

src/config/site.ts
  theme: {
    active: "default",
    presets: {
      default: {
        brand: "226 57% 21%",
        brandForeground: "210 40% 98%",
        brandAccent: "24.6 95% 53.1%",
        brandAccentForeground: "0 0% 100%",
      },
      emerald: {
        brand: "160 84% 20%",
        brandForeground: "150 40% 98%",
        brandAccent: "160 84% 39%",
        brandAccentForeground: "0 0% 100%",
      },
      violet: {
        brand: "263 60% 26%",
        brandForeground: "270 40% 98%",
        brandAccent: "262 83% 58%",
        brandAccentForeground: "0 0% 100%",
      },
    } satisfies Record<string, ThemePreset>,
  },

theme.active is informational only — the runtime source of truth is globals.css. Each preset is a ThemePreset whose four fields are space-separated HSL triplets ("H S% L%"), so a value drops straight into hsl(var(--brand)) with no conversion.

ThemePreset fieldMaps to CSS variableRole
brand--brandDeep brand color — headings, dark surfaces, primary brand buttons.
brandForeground--brand-foregroundReadable text/icon color on top of brand.
brandAccent--brand-accentVivid accent — primary CTA buttons and highlights.
brandAccentForeground--brand-accent-foregroundReadable text/icon color on top of brandAccent.
PresetLook
defaultDeep navy brand + vivid orange accent (ships out of the box).
emeraldGreen-forward alternative.
violetPurple-forward alternative.

To recolor the store, edit the --brand* values in src/app/globals.css — either directly or by pasting a preset's triplets onto them. globals.css also defines brand tokens inside the storefront and admin scopes, which is what decides how far a preset actually reaches; Branding & theming has the full picture.

productCategories

productCategories is an array of ProductCategory objects describing the catalog's top-level categories. They drive the header navigation, the hero, and the category cards, and their slug powers category filtering via /products?category=<slug>.

src/config/site.ts
export const productCategories: ProductCategory[] = [
  {
    name: "Audio",
    slug: "audio",
    icon: "/categories/audio.svg",
    image: "/categories/audio.svg",
    description:
      "Headphones, speakers, and studio gear engineered for rich, accurate sound.",
    secondaryDescription:
      "From everyday earbuds to reference monitors, our audio lineup covers listening, recording, and everything in between.",
    badges: ["Headphones", "Speakers", "Microphones"],
  },
  // ...five more
];

ProductCategory fields

FieldTypePurpose
namestringDisplay name shown in navigation and cards.
slugstringURL-safe identifier used in query strings: /products?category=<slug>.
iconstringSmall icon shown in the header navigation and hero.
imagestringLarger image shown on category cards.
descriptionstringShort marketing copy for the category card.
secondaryDescriptionstring (optional)Longer supporting copy for the category card.
badgesstring[]Example product types shown as badges on the category card.

Shipped categories

nameslugbadges
AudioaudioHeadphones, Speakers, Microphones
WearableswearablesSmartwatches, Fitness Trackers, Bands
Smart Homesmart-homeLighting, Plugs, Sensors, Hubs
CamerascamerasAction Cams, Security, Lenses
ComputingcomputingLaptops, Keyboards, Monitors, Storage
AccessoriesaccessoriesChargers, Cables, Cases

All shipped icon and image paths point at SVGs under public/categories/ (for example /categories/audio.svg). Replace these files, or point the fields at your own assets, to re-illustrate the categories.

Rebranding checklist

Set your identity. Update name, tagline, description, and url to your brand and production domain.

Fill in contact and social. Replace every value under contact and links with real details — these render in the footer and contact section.

Adjust navigation. Edit mainNav and legalNav so every href points at a route that exists in your app.

Define your catalog structure. Rewrite productCategories — set each name, slug, description, badges, and drop matching artwork into public/categories/. Keep slugs URL-safe; they appear in /products?category=<slug>.

Pick currencies and locales. Set the base currency, list switchable currencies (base first, rate: 1), and register your locales and defaultLocale alongside their i18n dictionaries.

Choose a color scheme. Apply a theme preset — or your own triplets — to the --brand* variables in src/app/globals.css.

None of this depends on Stripe, Resend, or a SQL backend — branding applies to the default quote-based store and does not change when you enable those later.

On this page