The first cut of /creative had ten track cards written straight into creative/page.tsx. It rendered the NAPA SEASON album, it looked right, and it was a trap. That page component held the content instead of reading it, and /creative is meant to hold a lot more than one album.
The plan for it is music, videos, the Suno series, and whatever medium comes after. If album one lives in the page component, so does album two, and by album ten the landing page is a wall of hardcoded cards that someone has to hand-edit every time anything ships. The version that worked for the first album was the version that could not survive the tenth.
The pattern was already in the building
/learning had solved this months earlier. A lesson is a content file. A loader reads the files. Status gating decides what is published. Adding a lesson means adding a file, and no page code changes. That is the whole shape, and it scales because the page never knows how many items exist.
So /creative got the same treatment, one level up. Each medium is now a static sibling under /creative/: music/ holds albums, videos/ holds an index, series/ holds the Suno programme. Each has content files, a loader, and status gating. Adding an album is adding a file at src/content/creative/music/<album>/. The page reads it. Nothing in the route gets touched.
NAPA SEASON became the first data-driven album to prove the loop: ten tracks in frontmatter, status: published, rendered at /creative/music/napa-season/ from the file rather than from the component. The held-back hardcoded version was superseded and deleted.
The landing page is a hub, not a feed
Making content data-driven solves maintenance. It does not, on its own, solve the firehose. A naive index that lists everything is still a bad front page once there are forty items across four mediums.
So the landing page shows a curated slice. Each medium gets a featured band (a few albums, a few videos, the series grid) and an “All →” link into that medium’s own index. The front page stays a short, editorial overview no matter how much sits behind it, and the depth lives one click down in the per-medium pages that are built to be long. Growth pushes into the indexes, not onto the front door.
The static-export tax
One constraint shaped the rollout. This site is a static export, and a static export refuses a dynamic route whose generateStaticParams() returns nothing:
Page "/creative/[series]" is missing "generateStaticParams()"
While every series is still upcoming, there are no params to generate, so the route cannot exist yet. Rather than ship an empty route or a fake param, the two series route components sit typechecked in a _route-templates/ folder and install into the app directory on the first real publish. The IA and the loaders are all in place; only the live route waits for content. The build emits the index pages and the published album today and no empty sub-routes.
The rule
The front page of a collection that is meant to grow should show a curated slice and a way in, never the whole collection. And the thing that makes that cheap is refusing to let any page component hold content. The moment the page reads files instead of listing items, the tenth album costs exactly what the first one did: one file, zero edits to the page.
One hardcoded album is not a bug. It is a perfectly reasonable first version. The mistake is only the one where you ship the second album the same way.

