This article documents the technical structure of this website. It is not just a list of frameworks; it explains how the site brings together a personal homepage, portfolio, knowledge base, blog, gallery, and experimental tools inside one maintainable system.
In one sentence:
This is a Nuxt-based personal knowledge system and portfolio. Content is managed with Markdown and typed collections, pages are rendered with Vue components, a small server surface is provided by Nitro, and production builds output an SSR / Node server bundle with selected routes prerendered.
Frontend
The frontend is built with Nuxt 4 + Vue 3 and uses file-based routing. Core routes include:
/: home and profile entry./about: short profile./about-this-site: technical overview page./projectsand/projects/[slug]: project index and detail pages./conceptsand/concepts/[slug]: concept notes and local graph views./blog/posts,/blog/logs,/blog/crap: writing areas with different levels of polish./gallery: photo and media display./demo/*: interaction and visual experiments.
The UI layer is built with Nuxt UI, Tailwind CSS 4, custom Vue components, and Markdown content components. Heavier interactive modules such as maps, 3D scenes, Mermaid, Swiper, and Vue Flow are loaded on the client only where they are needed.
The frontend is less like a landing page and more like a long-lived tool surface: the home page is an entry point, article pages are for reading, project pages show deliverables, and concept pages connect ideas.
Content system
The content layer is based on Nuxt Content 3, with schemas defined in content.config.ts.
Main collections:
| Collection | Source | Purpose |
|---|---|---|
pages | content/*.md | Top-level pages |
projects | content/projects/*.md | Projects and portfolio entries |
concepts | content/concepts/*.md | Concept nodes and knowledge graph |
posts | content/blog/posts/*.md | Formal articles |
logs | content/blog/logs/*.md | Technical logs and process records |
crap | content/blog/crap/*.md | Lighter and less complete notes |
Each collection has a schema. For example, projects requires fields such as title, slug, summary, status, updated, and GitHub repo metadata; concepts includes state, relations, relatedProjects, and aliases.
This turns content into structured data rather than a loose pile of Markdown files. Pages query it with queryCollection() and render it with ContentRenderer.
Markdown pipeline
Markdown processing is configured in nuxt.config.ts under content.build.markdown.
It supports:
remark-gfmfor GitHub Flavored Markdown.remark-mathandrehype-katexfor math.remark-emoji.- Syntax highlighting for zsh, C/C++, Rust, Vue, TypeScript, JavaScript, JSON, Python, ASM, HTML, CSS, YAML, and more.
- Heading anchors for H1/H2/H3.
- TOC generation to depth 2.
There is also a custom rubyHook that runs before Content parsing, making ruby / furigana style annotations easier to write in Markdown.
Internationalization
Internationalization is handled by @nuxtjs/i18n. Current locales are:
enzh-CNja
Translation resources live in i18n/locales/, and navigation uses localePath(). Content files also carry lang metadata. For localized content, I group Markdown variants by the same slug, choose the best match for the current locale, and use English as a fallback.
The site does not force every article to exist in all three languages. Some writing is more natural in Chinese, some in Japanese, and some technical material works better in English.
Backend
Server-side capability is provided by Nitro / H3 under server/.
Current server entries include:
server/api/github/repo.get.ts: reads GitHub repository, release, and commit data so project pages can show live-ish open-source project status.server/routes/sitemap.xml.ts: generates the sitemap.server/utils/localGalleryUpload.ts: supports a local Gallery upload and import workflow.
The Gallery upload boundary is intentionally strict: it only works in import.meta.dev, only accepts localhost requests, returns 404 or 403 outside local development, and limits accepted file types.
Media pipeline
The Gallery media pipeline is the most backend-like part of this site.
Design goals:
- iPhone HEIC / Live Photo files can enter a local import workflow.
- Public display uses generated JPEG / MP4 assets.
- Original HEIC / MOV files are not uploaded by default.
- Public assets strip EXIF / QuickTime metadata, especially GPS.
- Cloudflare R2 is used as object storage.
I keep media upload as a local development tool instead of a production admin button because original photos often contain sensitive metadata. Local processing and explicit upload are easier to control.
Build and runtime
Package management uses pnpm, pinned to pnpm@9.15.9.
Common commands:
pnpm dev
pnpm build
pnpm preview
pnpm generate
pnpm lint
pnpm format:check
Production builds are created with nuxt build. Nuxt generates a client bundle, server bundle, and Nitro output. Current nitro.prerender.routes includes:
//zh-CN/ja/sitemap.xml
So the site is neither purely static nor fully dynamic. It is a hybrid: key entries can be prerendered, while content and APIs are still served by the Nuxt / Nitro runtime.
Hosting and observability
From the repository configuration, the confirmed runtime shape is Nuxt Nitro node-server.
Build output lives in .output/:
.output/public: public assets and prerendered output..output/server: Nitro server bundle..output/server/index.mjs: Node entrypoint.
Client-side analytics are handled by Vercel Analytics, injected in plugins/analytics.client.ts:
import { inject } from '@vercel/analytics'
Why this architecture
This architecture fits how I use the site:
- Markdown is good for long-term writing.
- Typed collections turn content into queryable data.
- Nuxt keeps content, components, interaction, and server routes in one project.
- Nitro provides a small backend surface without a separate API service.
- R2 fits media object storage while keeping uploads and metadata handling locally controlled.
- Locale metadata lets Chinese, Japanese, and English content coexist.
It is not the simplest blog architecture, but it keeps a personal profile, portfolio, knowledge base, experiment space, and media library inside one maintainable system.