Skip to Content
StatixFlow Next Docs
Content Editing

Content Editing

This is the page you’ll come back to most. Almost every copy change on the site is a one-file edit — you rarely need to touch a component.

The pattern

Each route has:

  1. A content file in content/*.tsx — a single typed object exporting all the copy, images, and links for that page.
  2. A thin page.tsx — imports the content object, spreads its fields as props into organism components, and wraps them in <SiteShell>.

Shared shapes (ImageAsset, StatCard, Testimonial, PricingTier, etc.) live in content/types.tsx and are reused across content files.

For example, content/home.tsx exports homeContent, an object with keys like hero, mandate, whyChooseUs, applications, testimonials, faq, and finalCta — one key per page section. app/home/page.tsx does nothing but read that object and pass each section’s slice into the matching organism:

app/home/page.tsx
export default function Page() { return ( <SiteShell footerVariant="full"> <HeroSection2 {...homeContent.hero} /> <StepsSection {...homeContent.mandate} /> <StatsSection {...homeContent.whyChooseUs} /> <PinnedShowcaseSection {...homeContent.applications} /> <CarouselSection {...homeContent.testimonials} /> <AccordionSection {...homeContent.faq} /> <CtaBanner heading={homeContent.finalCta.heading} body={homeContent.finalCta.body} ... /> </SiteShell> ); }

Worked example: change the home page headline

The hero heading lives in content/home.tsx, under hero.heading:

content/home.tsx
hero: { // ... heading: "Ship More. Profit always", body: "Use customer data to build great and solid product experiences that convert.", primaryCtaLabel: "Start a free trial", // ... }

Change the string, save, and the home page (app/home/page.tsx) picks it up — no component edit required. The same applies to every other section key (mandate.heading, testimonials.slides[n].quote, faq.items[n].content, and so on).

Worked example: add a brand-new route

To add a page that doesn’t exist yet (say, /careers):

  1. Define the shape — add any new field types to content/types.tsx if the page needs something not already modeled (most pages can reuse existing shapes like HeroContent, StatCard, AccordionItem).

  2. Create the content filecontent/careers.tsx, exporting a typed object the same way home.tsx does, including a meta: { title, description } block for generateMetadata/static metadata.

  3. Create the routeapp/careers/page.tsx:

    app/careers/page.tsx
    import type { Metadata } from "next"; import { SiteShell } from "@/components/templates/site-shell"; import { HeroSection2 } from "@/components/organisms/hero-section-2"; import { careersContent } from "@/content/careers"; export const metadata: Metadata = { title: careersContent.meta.title, description: careersContent.meta.description, }; export default function Page() { return ( <SiteShell footerVariant="full"> <HeroSection2 {...careersContent.hero} /> {/* compose whichever organisms this page needs */} </SiteShell> ); }
  4. Pick a footerVariant"full" for real site pages; "minimal" is reserved for the template’s own showcase page (see Component Architecture for what each does).

  5. Add a nav entry if the page should appear in the header/footer — see the nav block in content/site-wide.tsx.

Compose existing organisms wherever possible before reaching for a new component — see Component Architecture for the full inventory and when it’s actually appropriate to add something new.

Icons in content files

Where a content field needs an icon (e.g. about.tsx’s culture items, case-studies.tsx’s industry list), import the icon directly from lucide-react and assign the component itself — not a name string:

content/about.tsx
import { MapPin, type LucideIcon } from "lucide-react"; export interface CultureItem { icon: LucideIcon; title: string; body: string; } items: [ { icon: MapPin, title: "Remote-First", body: "..." }, // ... ] as CultureItem[],

The components that render these (IconFeatureCard, NumberedListItem, FeatureListSection) take the icon as a component prop and render it directly (e.g. <item.icon />) — there’s no name-to-component lookup to keep in sync. The one exception is case-study deliverables sourced from MDX frontmatter, which can’t hold a JS import; see Writing Articles for how those are resolved.

app/page.tsx vs app/home/page.tsx — don’t mix these up

This is the single most common point of confusion in the codebase:

  • app/page.tsx is the template’s own showcase/demo landing page — it uses content/showcase.tsx and is what you see when you first browse the repo. It is not meant to become your production home page.
  • app/home/page.tsx is the actual marketing home page for the site you’re building from this template — it uses content/home.tsx.

When someone asks you to edit “the home page,” confirm which one they mean before editing. For a real launch, you’ll typically end up either replacing app/page.tsx’s content with app/home/page.tsx’s, or redirecting / to /home, depending on how you want the site structured.

Last updated on