Skip to content

landing: migrate /blog and /blog/:slug to SSG (prerender + generateParams) #2961

@matheuspoleza

Description

@matheuspoleza

Context — follow-up from #2960 (blog at /blog).

The blog shipped in #2960 compiles all posts to HTML at build time (scripts/compile-blog-posts.tssrc/blog/.generated/manifest.ts) but renders routes at request time through the Cloudflare Worker. All post data is known before deploy — no auth, no cookies, no per-user state — so the blog is a textbook fit for Vertz SSG (https://docs.vertz.dev/guides/deploy/ssg).

Current declaration (packages/landing/src/app.tsx):

'/blog': { component: () => <BlogListPage /> },
'/blog/:slug': { component: () => <BlogPostPage /> },

Proposal.

'/blog': {
  component: () => <BlogListPage />,
  prerender: true,
},
'/blog/:slug': {
  component: () => <BlogPostPage />,
  prerender: true,
  generateParams: async () =>
    getAllPosts()
      .filter((p) => !p.meta.draft)
      .map((p) => ({ slug: p.meta.slug })),
},

Unknown to resolve first (spike).

The SSG docs state "Purely static pages have all <script> tags stripped". The blog has three interactive signal-driven components: reading-progress.tsx, tag-filter.tsx, toc.tsx. Confirm whether:

  1. SSG still ships the client bundle for pages that contain interactive components (island pattern), OR
  2. There is an opt-in/opt-out knob to keep the JS for those routes.

If neither, this issue is blocked on a framework gap and we file it separately.

Acceptance criteria.

  • Spike documented (comment here or short note in plans/): confirmed SSG behavior for interactive islands on prerendered routes.
  • /blog prerendered — dist/client/blog/index.html contains the list markup.
  • /blog/:slug prerendered for every non-draft post via generateParams.
  • Tag filter, reading-progress bar, and TOC still work in a deployed preview (manual check + screenshot).
  • JSON-LD + canonical tags present in the prerendered <head> — closes the deferral noted in the feat(landing): blog — dogfood Vertz stack at /blog [#2947] #2960 description ("SSR <head> injection for JSON-LD + canonical").
  • vtz test src/blog green.
  • Worker fallback for /blog/<unknown-slug> still returns the not-found UI.
  • Lighthouse run on a prerendered post vs. current SSR (attach before/after).

Related.

Does not block the #2960 merge. Pick up after blog is live.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions