Problem
The landing-page header currently presents Blog as a disabled placeholder rather than a usable navigation destination. Fulling also has no /blog route, article content pipeline, or article-level SEO metadata, so the project has no first-party surface for explaining the product, publishing technical material, or building organic search visibility.
Current code context:
app/(landing)/_components/landing-client.tsx renders a disabled Blog, coming soon button.
- There is no
/blog or /blog/[slug] route.
- The repository has no MDX/content loader or external CMS integration.
app/layout.tsx only defines global title and description metadata.
- There is currently no blog-aware sitemap, canonical URL, Open Graph article metadata,
BlogPosting structured data, or RSS feed.
Proposed first iteration
Use repository-owned MDX content and statically rendered Next.js App Router pages. This keeps the public blog independent of authentication, databases, and new hosted services while the project is still maintained primarily through Git.
Suggested shape:
content/blog/*.mdx
app/(marketing)/blog/page.tsx
app/(marketing)/blog/[slug]/page.tsx
lib/blog/*
Each published post should expose validated metadata such as title, description, slug, publication/update dates, author, tags, cover image, draft state, and optional canonical URL.
A structured CMS such as Sanity can be evaluated later if Fulling needs non-developer editing, scheduled publishing, draft previews, or collaborative editorial workflows. The public URLs and content model should make that migration possible without changing published slugs.
Scope
- Replace the disabled landing-header Blog control with an accessible link to
/blog.
- Add a public blog index and individual post routes on the primary Fulling domain.
- Add a repository-owned MDX content loader with metadata validation and deterministic post ordering.
- Exclude drafts and future-dated posts from production output.
- Add an initial real article so the entry does not lead to an empty placeholder.
- Match the active design system in
docs/design.md and provide responsive reading layouts.
- Generate per-post title, description, canonical, Open Graph, and Twitter metadata.
- Emit
BlogPosting JSON-LD with author, dates, image, and canonical URL.
- Include published posts in the production sitemap with accurate
lastModified values.
- Provide an RSS or Atom feed.
- Ensure Vercel Preview deployments are not indexable while the production domain remains indexable.
Out of scope
- External CMS adoption or a migration UI.
- Google Ads, GA4, Google Tag Manager, or conversion tracking.
- Comments, memberships, newsletter delivery, or a site-wide search service.
- Bulk AI-generated SEO content.
Acceptance criteria
- Selecting Blog from the landing-page header navigates to a functional
/blog page.
/blog lists only published posts in reverse chronological order and links to stable article URLs.
- A production article renders correctly without client-side data fetching, authentication, database access, or new required environment variables.
- Every article has unique metadata, a canonical URL, social-preview metadata, and valid
BlogPosting JSON-LD.
- Published posts appear in the sitemap and feed; drafts and future posts do not.
- Preview deployment URLs are marked
noindex and do not become canonical URLs.
- The blog index and article layout work at supported desktop, tablet, and mobile widths and meet basic keyboard and semantic-heading accessibility expectations.
- Lint, tests, and the production build pass.
Follow-up direction
After the first content cluster is published, add Search Console verification and define a real product conversion before introducing paid acquisition or analytics tags. CMS adoption should be decided from editorial workflow needs rather than made a prerequisite for launching the blog.
Problem
The landing-page header currently presents Blog as a disabled placeholder rather than a usable navigation destination. Fulling also has no
/blogroute, article content pipeline, or article-level SEO metadata, so the project has no first-party surface for explaining the product, publishing technical material, or building organic search visibility.Current code context:
app/(landing)/_components/landing-client.tsxrenders a disabledBlog, coming soonbutton./blogor/blog/[slug]route.app/layout.tsxonly defines global title and description metadata.BlogPostingstructured data, or RSS feed.Proposed first iteration
Use repository-owned MDX content and statically rendered Next.js App Router pages. This keeps the public blog independent of authentication, databases, and new hosted services while the project is still maintained primarily through Git.
Suggested shape:
Each published post should expose validated metadata such as title, description, slug, publication/update dates, author, tags, cover image, draft state, and optional canonical URL.
A structured CMS such as Sanity can be evaluated later if Fulling needs non-developer editing, scheduled publishing, draft previews, or collaborative editorial workflows. The public URLs and content model should make that migration possible without changing published slugs.
Scope
/blog.docs/design.mdand provide responsive reading layouts.BlogPostingJSON-LD with author, dates, image, and canonical URL.lastModifiedvalues.Out of scope
Acceptance criteria
/blogpage./bloglists only published posts in reverse chronological order and links to stable article URLs.BlogPostingJSON-LD.noindexand do not become canonical URLs.Follow-up direction
After the first content cluster is published, add Search Console verification and define a real product conversion before introducing paid acquisition or analytics tags. CMS adoption should be decided from editorial workflow needs rather than made a prerequisite for launching the blog.