Customization
How to customize the template for your product
This template is designed to be easily customized. Here are the key places to make it your own.
App Name & Description
Edit lib/constants.ts:
export const APP_NAME = "Your App Name";
export const APP_DESCRIPTION = "Your app description";This updates the header, sidebar, login page, and HTML metadata.
Logo & Favicon
The logo is in components/app-logo.tsx — a lightning bolt icon with the app name. To replace it:
- Logo icon: Replace the
LogoMarkSVG incomponents/app-logo.tsxwith your own, or swap it for anext/imageimport - Favicon: Replace
app/icon.svgwith your own SVG (oricon.png/favicon.ico). It currently matches the logo — accent-colored square with lightning bolt
The logo appears in the header, sidebar, login page, and checkout.
Footer Links
Edit components/landing/footer.tsx to update navigation links. Update LINKS in lib/constants.ts for the GitHub, terms, and privacy URLs:
export const LINKS = {
github: "https://github.com/your-org/your-repo",
terms: "/terms",
privacy: "/privacy",
};Hero Screenshot
The hero section in components/landing/hero.tsx has a placeholder where it says "Replace with a screenshot of your product". Replace the placeholder <div> with a next/image or a demo video:
<Image
src="/screenshot.png"
alt="Product screenshot"
width={1200}
height={675}
priority
/>Add your image to the public/ folder.
Branding / Accent Color
Admins can change the accent color from Dashboard → Settings → Branding. This updates all primary buttons and accents across the site.
You can also set the default accent color in app/globals.css:
:root {
--accent: #5b4cff;
--accent-foreground: #ffffff;
}Plans & Pricing
The plan system is data-driven from PLAN_METADATA in lib/constants.ts. To customize:
- Edit tiers — change names, descriptions, features in
PLAN_METADATA - Add/remove tiers — add or remove keys. The pricing page, setup wizard, plan gating, and config keys all adapt automatically
- Prices — set in your Whop Dashboard, synced automatically via the Whop API. You can manually sync from Dashboard → Settings → Pricing
- Billing intervals — set
billingIntervals: ["monthly"]on a plan to disable yearly. If no paid plan offers yearly, the pricing toggle disappears automatically - Free trials — set
trialDays: 7for display; configure the actual trial in your Whop Dashboard - Hide a tier — set
hidden: trueto keep a plan in the hierarchy (gating ranks, downgrade target) without showing it on pricing pages. Useful when you don't want to advertise a free tier but still need it as the unpaid landing state
Connect Whop plan IDs via the setup wizard at /setup or environment variables (pattern: NEXT_PUBLIC_WHOP_{PLAN_KEY}_PLAN_ID).
Plan visibility
Pricing pages only show tiers that are ready to sell. Once setup is complete, a paid tier with no Whop plan ID is hidden instead of rendering an unusable card — so if you only configure one paid tier, visitors see exactly one paid tier. Before setup completes, unconfigured tiers stay visible as placeholders so you can see what's left to wire up. The free tier is always shown (unless hidden) and links to sign-in when it has no Whop plan ID.
The pricing grid adapts to the visible count (1–4 columns), so any tier structure looks intentional.
Landing Page
The landing page renders sections in this order: Hero → Features → Testimonials → Pricing → CTA. All components are in components/landing/:
hero.tsx— Main headline, CTA buttons, and product screenshot placeholderfeatures.tsx— Feature grid (6 cards, 3 columns on desktop)testimonials.tsx— Social proof section (3-column card grid)pricing-cards.tsx— Pricing tiers with monthly/yearly togglecta.tsx— Closing call-to-action banner with accent glowheader.tsx— Navigation headerfooter.tsx— Footer links
Testimonials
Edit the testimonials array in components/landing/testimonials.tsx to replace the placeholder quotes with real customer feedback:
const testimonials = [
{
quote: "Your customer's testimonial here.",
name: "Customer Name",
role: "Role, Company",
},
// Add or remove entries — the grid adapts automatically
];Each card shows the first letter of the name as an accent-colored avatar. To use real profile images instead, replace the avatar <div> with an <Image> component.
CTA Section
The closing CTA in components/landing/cta.tsx mirrors the Hero's button style. Update the headline, description, and button links to match your product messaging.
Dashboard
The dashboard layout is in app/dashboard/layout.tsx with components in components/dashboard/:
sidebar.tsx— Navigation sidebarheader.tsx— Dashboard header with user menuactivity-feed.tsx— Recent activity log (placeholder data)upgrade-banner.tsx— Shown to free-tier usersreactivate-banner.tsx— Shown when subscription is pending cancellation
Activity Feed
The activity feed in components/dashboard/activity-feed.tsx shows recent account events on the dashboard overview. Replace the placeholder activities array with real data from your database:
const activities: Activity[] = [
{
type: "sign_in", // "sign_in" | "plan_change" | "setting" | "account"
description: "You signed in",
timestamp: new Date(),
},
// Add your own activity types and entries
];Each activity type has a distinct icon and color. To add new types, extend the ActivityType union and add cases to iconStyle() and ActivityIcon().
A matching ActivityFeedSkeleton is exported for use in Suspense boundaries.
Adding Pages
Public pages
Add to app/(marketing)/ — these share the landing page header and footer.
Protected pages
Add to app/dashboard/ — these are automatically protected by the dashboard layout's requireSession() call.
Documentation
Add .mdx files to content/docs/. They automatically appear in the docs sidebar. Use meta.json files in folders to control ordering.
Theme & Dark Mode
The template supports light and dark mode via CSS class toggling on the <html> element. Theme preference is stored in localStorage and respects the system setting by default.
CSS Custom Properties
All colors use CSS custom properties defined in app/globals.css. Override these to change the entire look:
:root {
--background: #ffffff;
--foreground: #0a0a0a;
--muted: #6b7280;
--border: #e5e7eb;
--card: #ffffff;
--surface: #f9fafb;
--accent: #5b4cff;
--accent-foreground: #ffffff;
}
.dark {
--background: #0a0a0a;
--foreground: #fafafa;
--muted: #a1a1aa;
--border: #27272a;
--card: #111111;
--surface: #1a1a1a;
--accent: #7b6fff;
--accent-foreground: #ffffff;
}Use them in Tailwind with the bracket syntax: bg-[var(--card)], text-[var(--muted)], border-[var(--border)].
Animations
Built-in animation classes with staggered delays:
animate-fade-in— opacity 0 → 1animate-slide-up— translate up + fade inanimate-scale-in— scale up + fade indelay-100throughdelay-500— stagger entrance animations
All animations respect prefers-reduced-motion.
Theme Toggle
The ThemeToggle component in the header lets users switch between light and dark. It's powered by the ThemeProvider in components/theme-provider.tsx.
Removing the Docs Site
If you don't need the built-in documentation:
- Delete
content/docs/andapp/docs/ - Delete
source.config.tsandmdx-components.tsx - Remove fumadocs dependencies from
package.json:pnpm remove fumadocs-core fumadocs-mdx fumadocs-ui @types/mdx - Remove the docs link from
components/landing/header-client.tsxandcomponents/landing/footer.tsx - Remove the
/api/searchroute (app/api/search/) - Remove
createMDXfromnext.config.ts
Removing the Activity Feed
If you don't want per-user activity tracking:
- Delete
lib/activity.tsandcomponents/dashboard/activity-feed.tsx - Remove the
<ActivityFeed />usage andgetRecentActivityimport fromapp/dashboard/page.tsx - Remove
logActivity/logActivityByWhopIdcalls fromapp/api/auth/callback/route.ts,app/api/webhooks/whop/route.ts,app/api/config/accent/route.ts, andapp/api/config/integrations/route.ts - Delete the
ActivityEventmodel (and theactivitiesrelation onUser) fromdb/schema.prisma, then runpnpm db:push
Removing Analytics
If you don't need the built-in analytics integrations (PostHog, Google Analytics, Plausible):
- Delete
lib/analytics.tsand remove thegetAnalyticsScript()usage fromapp/layout.tsx - Remove the analytics fields from
components/dashboard/integrations-settings.tsxandapp/api/config/integrations/route.ts - Remove
analytics_provider/analytics_idfromENV_MAPinlib/config.ts