This project is a personal research blog for Subin Park (SOL1), migrated from Jekyll to Next.js (App Router). It features a minimal, "Apple-like" glassmorphic design, supports complex Markdown/LaTeX rendering, and is deployed via GitHub Actions.
- Framework: Next.js 14 (App Router, Static Export)
- Styling: Global CSS with Vanilla CSS Variables (Glassmorphism, Theming)
- Language: TypeScript
- Icons:
lucide-react - Markdown Engine:
remark(parse)remark-math(math syntax)rehype-katex(math rendering)rehype-highlight(code highlighting)rehype-slug(auto-generating IDs)
- Date Handling:
date-fns
src/app: App Router pages.page.tsx: Home page (intro, featured story, recent rows).posts/page.tsx: List of all posts.[...slug]/page.tsx: Dynamic blog post rendering.layout.tsx: Root layout (includes TopBar, Analytics, Katex CSS).globals.css: Global variables, resets, and dark mode overrides.
src/components:TopBar.tsx: Sticky navigation, social links, dark mode toggle.Footer.tsx: Shared footer columns.PostCard.tsx,PostRow.tsx,FeaturedHero.tsx: Post listing surfaces.PostsFilter.tsx: Client-side category filter for/posts.TOC.tsx: Table of Contents sidebar.
src/lib/markdown.ts: Core logic for reading_notes, parsing Frontmatter, Kramdown cleanup, and strict date sorting._notes: Source of truth for blog content (Markdown files).public/cv: Host forSubin_Park_CV.pdf..github/workflows/nextjs.yml: CI/CD pipeline.
- Variables: Defined in
globals.css(--glass-bg,--accent,--ink, category tints, etc.). - Dark Mode:
- Uses system preference on first load.
- Manual override supported via
data-theme='dark'|'light'attribute on<html>, toggled inTopBar.tsx.
- Layout:
- Home: Intro section, featured post, recent numbered rows.
- Posts: Filterable card grid, sorted by date (
dd-mm-yyyy).
- Math: Supports
$$...$$blocks and$..$inline via Katex. CSS is loaded inRootLayout. - Legacy Cleanup:
getPostDatainmarkdown.tsactively removes Kramdown-specific tags ({:toc},{:#id}) to prevent rendering errors. - Hidden Posts: Posts with
feed: hidein frontmatter are filtered out ingetSortedPostsData.
- Static Export:
output: 'export'innext.config.js. - GitHub Actions: Builds the project and uploads the
out/directory to GitHub Pages.
npm run dev
# Open http://localhost:3000Since we use static export:
npm run build
npx serve out
# Open http://localhost:3000 (or port shown)Next.js caches strictly. If you change a Markdown file and it doesn't appear in dev, try restarting the server. For production, the build process always generates fresh static HTML.
- Adding Posts: Just add
.mdfiles to_notes. - Updating CV: Replace
cv/Subin_Park_CV.pdf; local scripts copy it topublic/cv/Subin_Park_CV.pdf. - Navigation: Update
src/components/TopBar.tsx.
- The current redesign follows the design handoff at
/Users/bagsubin/Downloads/design_handoff_blog_redesign: Apple Newsroom-style typography, fixed glass top bar, text-only post cards, category filters, article TOC, and responsive About/404 pages. - Do not migrate or rewrite
_notesunless explicitly asked. The Next.js reader insrc/lib/markdown.tskeeps legacy Markdown paths and derives missing display metadata such as excerpts, reading time, fallback categories, and tags. - Post permalinks currently remain
/<_notes-relative-slug>for backward compatibility with the migrated Jekyll archive;/postsis the archive index, not the post-detail prefix.