Aller au contenu principal

Customization

Make HeartCo your own: name, colors, emails, sidebar, legal pages.

Branding

File: src/lib/config/branding.ts

All brand configuration is centralized in the APP_CONFIG object. Every value is configurable via an environment variable:

Identity

PropertyDefaultEnvironment variable
NameHeartCoNEXT_PUBLIC_APP_NAME
Short nameHCNEXT_PUBLIC_APP_SHORT_NAME
Tagline"Launch your SaaS in 1 week"NEXT_PUBLIC_APP_TAGLINE
Description"The production-ready SaaS boilerplate..."NEXT_PUBLIC_APP_DESCRIPTION
URLhttp://localhost:3000NEXT_PUBLIC_APP_URL
Domainheartco.frNEXT_PUBLIC_APP_DOMAIN

Emails

PropertyDefaultEnvironment variable
Primary emailhello@heartco.frNEXT_PUBLIC_APP_EMAIL
Supportsupport@heartco.frNEXT_PUBLIC_SUPPORT_EMAIL
No-replynoreply@heartco.frNEXT_PUBLIC_NOREPLY_EMAIL

Colors

PropertyValueUsage
Primary#6366f1 (Indigo)Buttons, links, accents
Secondary#8b5cf6 (Violet)Gradients, secondary elements

Social networks

Configurable via APP_CONFIG.social: twitter, linkedin, github, discord, instagram, youtube (empty by default).

Legal information

PropertyEnvironment variable
Company nameNEXT_PUBLIC_COMPANY_NAME
Registration numberNEXT_PUBLIC_REGISTRATION_NUMBER
VAT numberNEXT_PUBLIC_VAT_NUMBER
AddressNEXT_PUBLIC_COMPANY_ADDRESS

Customization example

To rebrand the app as "MySaaS":

NEXT_PUBLIC_APP_NAME="MySaaS"
NEXT_PUBLIC_APP_SHORT_NAME="MS"
NEXT_PUBLIC_APP_TAGLINE="The all-in-one solution for your business"
NEXT_PUBLIC_APP_DOMAIN="mysaas.com"
NEXT_PUBLIC_APP_EMAIL="contact@mysaas.com"
NEXT_PUBLIC_SUPPORT_EMAIL="support@mysaas.com"
NEXT_PUBLIC_NOREPLY_EMAIL="noreply@mysaas.com"
NEXT_PUBLIC_COMPANY_NAME="MySaaS Inc."

Tailwind and theming

Main file

src/styles/globals.css contains the CSS tokens and the Tailwind v4 configuration.

Semantic CSS tokens

HeartCo uses CSS custom properties for the light and dark themes:

:root {
  --background: ...;
  --foreground: ...;
  --primary: ...;
  --primary-foreground: ...;
  --secondary: ...;
  --card: ...;
  --border: ...;
  --ring: ...;
  /* ... */
}
 
.dark {
  --background: ...;
  --foreground: ...;
  /* ... dark variants */
}

Custom colors

:root {
  --color-brand: #6366f1;
  --color-deep-navy: #0d1b2a;
  --color-ai-blue: ...;
  --color-ai-cyan: ...;
}

Dark mode

Dark mode is handled by next-themes. Always use the semantic CSS tokens, never hardcoded colors:

// ✅ Correct — uses the tokens
<div className="bg-background text-foreground border-border">
 
// ❌ FORBIDDEN — hardcoded colors
<div className="bg-white text-gray-900 border-gray-200">

Class merging

Use cn() (clsx + tailwind-merge) to merge classes:

import { cn } from "~/lib/utils";
 
<button className={cn(
  "px-4 py-2 rounded-md",
  variant === "primary" && "bg-primary text-primary-foreground",
  variant === "outline" && "border border-input",
  className
)} />

Navigation (Sidebar)

File: src/lib/navigation/nav-config.ts

Structure

The sidebar is organized into 8 sections with semantic colors:

SectionColorIcon
DashboardIndigoLayoutDashboard
AI CopilotVioletSparkles
SalesEmeraldUsers
InvoicingAmberReceipt
FinanceSkyTrendingUp
OperationsOrangeWrench
TeamTealUserCog

Editing an item

To change the label, icon or path of a module:

// src/lib/navigation/nav-config.ts
{
  id: "crm",
  label: "My CRM",         // ← Change the label
  path: "/dashboard/crm",
  icon: Target,             // ← Change the icon (Lucide)
  badge: "core",
  moduleId: "MODULE_CRM",
}

Footer items

3 fixed items at the bottom of the sidebar:

  • Marketplace/dashboard/marketplace
  • Help/help
  • Settings/dashboard/parametres

Badges

BadgeDisplayUsage
coreModule included in the plan
addonPaid badgeOptional paid add-on module
verticalVertical badgeVertical module (construction)
tag: NEW"NEW" pillNew module
tag: BETA"BETA" pillModule in beta

Legal pages

Important: the 5 legal pages provided are generic templates. You must replace their content with your own texts before going to production. A warning banner (showBoilerplateDisclaimer) is displayed until you customize the content.

The legal pages live in the src/app/(legal)/ route group:

PagePathFile
Terms of Use/cgusrc/app/(legal)/cgu/page.tsx
Terms of Sale/cgvsrc/app/(legal)/cgv/page.tsx
Legal notice/mentions-legalessrc/app/(legal)/mentions-legales/page.tsx
Cookie policy/politique-cookiessrc/app/(legal)/politique-cookies/page.tsx
Privacy policy/politique-confidentialitesrc/app/(legal)/politique-confidentialite/page.tsx

Customization

  1. Open each file and replace the text content with your real legal terms
  2. Dynamic legal information (company name, address, registration number) is pulled from APP_CONFIG.legal — configure it via the NEXT_PUBLIC_LEGAL_* environment variables
  3. To remove the warning banner, drop the showBoilerplateDisclaimer prop from the component
  4. Have your texts reviewed by a lawyer before going to production

Email templates

Folder: src/lib/emails/templates/

6 ready-to-use lifecycle templates:

TemplateTriggerDescription
email-verification.tsSign-upVerification link (24h)
trial-welcome.tsTrial startWelcome + 3 features to try
trial-reminder-7days.tsTrial D-7Reminder with an upgrade incentive
trial-reminder-2days.tsTrial D-2Urgent conversion reminder
trial-expired.tsTrial endUsage stats + paid plans
newsletter-onboarding.tsSign-up D+3Per-feature personalized tips

Customizing a template

The templates use Resend with inline HTML. To edit one:

  1. Open the template file in src/lib/emails/templates/
  2. Edit the HTML, the texts, the colors
  3. Dynamic variables (name, link, etc.) are passed as parameters

Reminder templates

Payment reminders (src/lib/emails/relances.ts) use substitution variables:

VariableDescription
{{clientName}}Client name
{{invoiceNumber}}Invoice number
{{amount}}Amount due
{{dueDate}}Due date
{{daysPastDue}}Days overdue
{{orgName}}Organization name
{{signature}}Configured signature

Recipes

Four classic customization operations, ready to paste.

1. Rename the "HeartCo" brand to "MySaaS"

The brand is centralized in apps/web/src/lib/config/branding.ts and exposed via the NEXT_PUBLIC_APP_* environment variables. Golden rule: always use APP_CONFIG.name in code, never a hardcoded "HeartCo".

  1. Update .env (or the Vercel variables in prod):
NEXT_PUBLIC_APP_NAME="MySaaS"
NEXT_PUBLIC_APP_DOMAIN="mysaas.com"
NEXT_PUBLIC_APP_URL="https://app.mysaas.com"
  1. Search for any residual hardcoded references (rare — fix if found):
# With ripgrep
rg -i "heartco" apps/web/src --type ts --type tsx
  1. Files to inspect manually (may contain the name outside APP_CONFIG):
    • apps/web/src/lib/config/branding.ts (centralizes the brand)
    • Legal pages apps/web/src/app/(legal)/*.tsx (to be customized anyway)
    • Email templates apps/web/src/lib/emails/templates/ (inline HTML, signature, footer)

2. Replace the logo

The logo is served from apps/web/public/ (3 SVG files: logo.svg, logo-dark.svg, logo-mark.svg).

  1. Replace the 3 SVG files with your own (same names, same target dimensions)
  2. If the format differs (PNG/JPG), edit apps/web/src/components/layout/logo.tsx to point to the new path
  3. On Vercel production, redeploy to invalidate the CDN cache

3. Change the primary color

The brand color is a CSS token in apps/web/src/styles/globals.css. Every component using bg-primary, text-primary, border-primary inherits it automatically.

/* apps/web/src/styles/globals.css */
:root {
  --color-brand: #YOUR_COLOR;  /* Replace #6366f1 */
}

Instant hot reload in dev (pnpm dev), pnpm build required in prod.

4. Disable a sidebar module without removing it

See the full procedure in 05-modules.md — in short:

  1. Open apps/web/src/lib/navigation/nav-config.ts
  2. Comment out the item in the children array of the relevant section
  3. The tRPC router can stay in place — it simply becomes unreachable from the sidebar

◀ Payments · Contents · Security ▶