Scaffold Next.js app with content pipeline and core pages#12
Open
Scaffold Next.js app with content pipeline and core pages#12
Conversation
Comprehensive plan covering content pipeline, app router structure, component architecture, CSS modules strategy, and testing approach. https://claude.ai/code/session_01R5awpyXidcUMHNPPVAsLvA
Each component gets its own directory with colocated .tsx, .module.css, .test.tsx, and index.ts barrel export. https://claude.ai/code/session_01R5awpyXidcUMHNPPVAsLvA
Complete migration of benward.uk from Jekyll to Next.js 15 with App Router. Library layer (lib/): - content.ts: Post loading from Jekyll _posts, Markdown + Textile rendering - posts.ts: Post enrichment (clean URLs, GitHub links, auto-titles) - archives.ts: Year/month archive grouping with pagination - base60.ts: NewBase60 encoding for shortlinks - romans.ts: Roman numeral conversion for footer copyright - dates.ts: Timezone-preserving date formatting - tag-id.ts: RFC 4151 tag URI generation for Atom feed Components (components/): - Each in own subdirectory with colocated .tsx, .module.css, .test.tsx, index.ts - BlogPostLayout, ArchiveYearLayout, ArchiveMonthLayout, ArticleLayout - Cover, PostSummary, Share, ArchiveNavigation, TwitterMeta, Scripts, etc. - Full microformat fidelity (h-entry, h-card, h-feed, h-geo) Routes (app/): - /blog/[slug]: Blog posts with prev/next navigation - /[year] and /[year]/[month]: Archive pages - /about, /network, /feeds: Static pages from Jekyll content - /feed.atom: Atom feed route handler with shortlinks - /robots.txt, /sitemap.xml, /humans.txt: Metadata route handlers - .html -> clean URL redirects in next.config.ts CSS decomposed from single sixthree.css into: - lib/global.css: Variables, resets, typography, microformat classes - Per-component CSS Modules Config in config/site.ts, not lib/. 77 tests passing across 11 test suites. Next.js build compiles successfully. https://claude.ai/code/session_01R5awpyXidcUMHNPPVAsLvA
- Markdown post (top-5-2017): verifies frontmatter parsing, canonical URL, geo data, tags, enriched properties, date formatting matching Jekyll strftime, shortlink generation, tag URI, and rendered HTML (including raw HTML passthrough for iframes/figures) - Textile post (simple_microformats): verifies textile rendering, atomid preservation, pre-2018 domain switching, timezone preservation - humans.txt: line-by-line structure match against Jekyll template 128 tests passing across 13 suites. https://claude.ai/code/session_01R5awpyXidcUMHNPPVAsLvA
Replaces the Jekyll-generated short.yaml mapping file with a native Next.js route that resolves base60-encoded shortlink IDs to post URLs. - lib/shortlinks.ts: decodeBase60, buildShortlinkMap, resolveShortlink - app/s/[id]/route.ts: redirects to canonical or clean URL - Posts with canonical URLs (e.g. bff.fm) redirect there directly https://claude.ai/code/session_01R5awpyXidcUMHNPPVAsLvA
- Replace jest, ts-jest, ts-node, jest-environment-jsdom with vitest - Add @vitejs/plugin-react for JSX support in tests - Replace jest.config.ts and tsconfig.test.json with vitest.config.ts - Remove CSS mock files (vitest handles CSS modules natively) - Update all 14 test files with vitest imports - 135 tests passing across 14 suites https://claude.ai/code/session_01R5awpyXidcUMHNPPVAsLvA
Runs vitest suite in the nextjs directory on pull requests and pushes to main. https://claude.ai/code/session_01R5awpyXidcUMHNPPVAsLvA
Install npm-check-updates with upgrade scripts for dependency management. Upgrade major versions: @types/node ^22→^25, typescript ^5→^6, next ^15→^16. All 135 tests pass. https://claude.ai/code/session_01R5awpyXidcUMHNPPVAsLvA
@types/node@25 targets Node 25 which isn't LTS. Our runtime and CI both use Node 22, so the types should match. https://claude.ai/code/session_01R5awpyXidcUMHNPPVAsLvA
Update @types/node to ^24 and CI workflow to node-version: 24. https://claude.ai/code/session_01R5awpyXidcUMHNPPVAsLvA
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR establishes the foundation for migrating benward.uk from Jekyll to Next.js (App Router) with TypeScript. The new Next.js application reads content directly from the existing Jekyll
_posts/directory without duplication, implements a complete content rendering pipeline, and includes core pages and components with comprehensive test coverage.Key Changes
Project Structure
nextjs/directory alongside existingjekyll/directoryContent Pipeline (
lib/)content.ts: Post loading, YAML frontmatter parsing, and rendering (Markdown via unified/remark/rehype, Textile via textile-js)posts.ts: Post enrichment (clean URLs, GitHub source links, excerpt generation, title auto-generation for Tumblr imports)archives.ts: Archive index generation with year/month grouping and navigationdates.ts: Timezone-preserving date formatting (keeps ISO 8601 strings to preserve original offsets)base60.ts: NewBase60 encoding for shortlink generationshortlinks.ts: Shortlink resolution mapping base60 IDs back to post URLstag-id.ts: RFC 4151 tag URI generation for Atom feedromans.ts: Roman numeral conversion for archive headersPages & Routes
app/page.tsx: Homepage with recent postsapp/blog/[slug]/page.tsx: Individual blog post pagesapp/[year]/page.tsx: Year archive pagesapp/[year]/[month]/page.tsx: Month archive pagesapp/about/page.tsx,app/feeds/page.tsx,app/network/page.tsx: Static pagesapp/feed.atom/route.ts: Atom feed generationapp/s/[id]/route.ts: Shortlink redirect handlerapp/humans.txt/route.ts,app/robots.txt/route.ts,app/sitemap.xml/route.ts: SEO/metadata routesComponents
BlogPostLayout: Blog post template with metadata, sharing, and navigationArchiveYearLayout,ArchiveMonthLayout: Archive page templatesPostSummary: Post preview cardArchiveNavigation: Previous/next period navigationCover,ArticleLayout: Page templatesShare,TwitterMeta,Identity,Profiles,Scripts: Metadata and utility componentsTesting
Static Assets
Notable Implementation Details
../jekyll/_posts/at runtimedynamic = "force-dynamic"— no static exporthttps://claude.ai/code/session_01R5awpyXidcUMHNPPVAsLvA