A trilingual static personal site for 李汶道 (DennySORA), targeting dennysora.me. Built with React, TypeScript, React Router prerendering, Vite and Tailwind CSS. The website supports 繁體中文, English and 日本語 on desktop and mobile. Every page sits in a Neovim-style workbench, Moonlit Vim: a tabline of buffers with search and language, a neo-tree file explorer, a winbar path, a lualine-style status line with real NORMAL/INSERT/VISUAL modes and Vim's command line, all on the semantic dark palette. Each page reads as an open Markdown buffer with line numbers; the chrome is made of real links and controls, and the document itself scrolls. The binding design system for every UI change is docs/DESIGN.md.
Use the Node version in .nvmrc and the pnpm version pinned in package.json. Dependencies are project-local.
pnpm install --frozen-lockfile
pnpm devThe development server binds to 127.0.0.1. Production preview and full validation:
pnpm verify
pnpm previewpnpm verify runs formatting, lint, strict type checks, unit tests, static generation with the Pagefind search index, and content/route/SEO/feed/artifact checks. The owner reviews visuals and interactions on the live site after an authorized release and reports issues; browser previews, screenshots and Playwright/axe are not routine publication blockers. pnpm test:e2e remains available for explicitly requested diagnostics and requires the configured Google Chrome. This verification workflow does not independently authorize any commit, push or deployment. Preview serves build/client at http://127.0.0.1:4173 with real 404 responses and no SPA fallback.
/{zh-hant,en,ja}/: the profile asREADME.md(logo, introduction and résumé), the blog (blog/, withblog/topics/<id>/,blog/tags/andblog/tags/<id>/), the note directories, and the project directories (projects/, with category folders such asprojects/tools/).about/forwards to the home page with its anchor. Migrated AI/video pages and the formerpapers/andresearch/entries return 404, without redirects.- The desktop Explorer and its mobile drawer retain a localized external link to Paper Daily. This is not a local route, a buffer tab or a home-page quick link; it does not restore migrated content or load third-party resources.
content/posts/<id>/:meta.jsonand language-specific Markdown, or reviewed static HTML fragments whenbodyFormatisstatic-html. Imported manuscripts retain their original filename and SHA-256; unknown authors are not inferred. Only valid published editions become routes, feeds or search entries. Imported static articles require all three reviewed editions before publication. Topic, content type and tags use the stable IDs incontent/taxonomy/. Empty blog taxonomy pages, including the tag index, are not published and return 404; the blog list remains available at its original URL. When a locale has no published articles, its blog tab and explorer folder are hidden, and the empty list is noindex and excluded from the sitemap and site search. Publishing an article restores those entries.src/lib/blog-tree.tssupplies real article folders and their shared route helpers; only populated folders appear. The password-manager and P2P architecture guides are drafts under the futureblog/security/andblog/network/folders.content/profile/profile.json: the structured profile shown on each language's home page. The Markdown files beside it retain the corresponding non-AI source content; the original versions remain in Git history.content/projects/projects.json: retained repository references. The home résumé now uses six owner-approved skill cards, with a direct link to the cryptography tutorial series; historical project sources remain intact.src/lib/project-pages.ts: project pages by category, with the languages each was written in. A page is published only in those languages (/{locale}/projects/tools/dgxtop/in all three languages, the dgxtop architecture and design write-up with translated captions and token-only diagrams); the folders are trilingual and say when a page has no edition in the reader's language. Screenshots live inassets/projects/<page>/and ship only when a page lists them. The former flat project page (/<locale>/projects/dgxtop/) and Privacy stay removed.data/comments.json: publicunconfigured,github-nativeor automatically loadedgiscusconfiguration. The sitewide integration covers localized home, blog/index/category/tag, article, note/index/folder, project/index/category and search pages; redirects and 404 pages are excluded. Typed content IDs—not translated titles, paths or search queries—share one discussion across languages. Recorded legacy numbers remain unchanged; new threads are created by giscus on the first comment or reaction. The widget usestransparent_darkand zh-TW/en/ja, with a GitHub fallback. Comments and the composer appear automatically as their section approaches the viewport. Reading requires no sign-in; posting uses GitHub sign-in, which may store a giscus session locally. A slow connection shows a nonfatal waiting hint rather than hiding the iframe; a later validated response can recover from an earlier error. See the setup and privacy boundary before enabling it.data/note-media.json: currently empty after the AI/video migration. The retained validator records any video and audio file a note streams from the owner's Hugging Face dataset (DennySORA/dennysora-site-media), pinned to a commit with its size and SHA-256. Content validation refuses media that is unrecorded, unpinned, autoplaying or loaded before the reader presses play.data/post-media.json: currently empty; the retained contract for article MP4 files in the same dataset, with a fixed commit, measured metadata and optional three-language WebVTT subtitles. Only registered media is emitted; videos stay out of the Pages artifact, while posters and validated subtitles stay same-origin.data/post-sections.json: currently empty; the ordered section groups and localized tab labels for long articles. It preserves heading deep links and shows all panels without JavaScript.data/brand-assets.jsonanddata/migration/: brand asset provenance (including the home page's logo derivatives), frozen heading anchors and the profile section migration map.scripts/: content validation, build finalization, search indexing, artifact checks and loopback preview.
The former blog repository was deleted, as confirmed by its owner. Its five known articles were not recovered. The three unrelated legacy URLs explain the missing source and are excluded from search and sitemap; the two AI article URLs have been removed. The two retained profile adaptations are unpublished, and the blog is empty until real posts are ready. Their former URLs show a no-index notice. Their source and immutable provenance remain in the migration manifest.
Study notes live separately under /{locale}/note/, filed in one folder tree. src/lib/note-tree.ts holds its structure (each folder's parent, icon and illustration, and the folder of every note), and a note's URL is its folder path plus its id; src/lib/note-tree.server.ts holds the folder names and introductions in all three languages. Folder pages show their subfolders as cards, then the notes filed directly in them. The owner reorganized the tree on 2026-10-12 without redirects, so the former /note/network/, /note/health/ and /note/other/photography/ paths now return 404. All six notes have complete Traditional Chinese, English and Japanese editions. Software / Networks / P2P (/{locale}/note/software/network/p2p/) covers P2P downloader architecture and traffic-correlation research. Health & medicine merges the former Medicine and Health folders: Medicines holds the pharmacology reference at /{locale}/note/medical/drugs/analgesics/, Pathology the brain/CNS tumor guide at /{locale}/note/medical/pathology/brain-cns-tumors/, and Daily care a lower-back care guide at /{locale}/note/medical/daily-care/lumbar-spine-care/, rechecked against OSHA, Mayo Clinic, NIAMS, MedlinePlus and NHS on 2026-10-12, with NHS's three tiers of warning signs. The owner retired the seven-part Japanese learning series and the old 140 mm fan evaluation on 2026-10-25. Their three-language article URLs and the Japan/Japanese folder URLs now return 404, with no replacement redirects. Hardware / Computers remains available for future notes. Other has no subfolders and holds a landscape photography guide at /{locale}/note/other/landscape-photography/, built on the author's own 31 photos (assets/notes/landscape-photography/, shipped byte-for-byte and only when the note shows them) with token-coloured guide overlays, local hyperfocal and ND calculators, and a 21-image GPT composition atlas whose generated images are labelled as generated in every edition and never presented as photos. The lower-back guide and the photography guide share one contract in src/lib/note-collections.ts; their localized copy lives in src/lib/note-collections.server.ts and reaches the page as loader data, so it never enters the client bundle. Directories, metadata, tags, search and local-tool messages use the selected language. Source-to-translation text pairs live in content/notes/translations/; content validation rejects missing, empty, duplicate or stale pairs, while preserving all source anchors, links and numeric data. Translation does not refresh the source’s dated findings or imply new testing or human expert review. The old analgesics URL forwards with its anchor preserved when JavaScript is enabled; without JavaScript, a complete no-index copy keeps every original section readable. Content fragments in content/notes/medical.html and content/notes/medical/pathology/brain-cns-tumors.html contain no scripts. Reference scenarios use native details controls so they also work without JavaScript. Every article and note shows subject tags directly below its title. Header tags open exact global tag-search results, combinable with keywords and content type; localized labels and controlled aliases are searchable. Explorer entries are named in the page's language with short names that are never cut off (full titles stay as tooltips and screen-reader text); when a row is wider than the Explorer, the tree scrolls sideways like a nowrap Vim window while the Explorer title stays put. Explorer folders start collapsed except the path to the current page, which each navigation opens again; without JavaScript every folder stays open. Its indentation follows neo-tree's defaults at any depth: rows sit on character cells of the code font, each level adds two cells so entries line up under their folder's icon, and files show │ or, for the last entry, └, with an ancestor's │ continuing while it has later siblings. The desktop Explorer can be collapsed and restored from the tabline; below 1100 px it opens as a dialog. There is no shared footer.
Only build/client is deployable. This personal website is the explicit exception to the owner's no-GitHub-CI policy. The GitHub Actions workflow runs build and deployment only on pushes to release, including merges into that branch. It builds the exact pushed commit and deploys the checked artifact from that run. Main pushes, pull requests and tags do not trigger it, and there is no scheduled or manual-dispatch trigger. Run pnpm verify locally before publishing. Commit source changes on main, then create or fast-forward release from the verified commit when publication is authorized; do not force-push over a diverged release branch. Pages must use GitHub Actions, and any github-pages environment protection must permit release through the owner's existing approval process. The custom domain remains dennysora.me; deployment publishes the checked static artifact, never the repository root.
See the design system, the Moonlit Vim redesign record, the writing and publication guide, the editor workbench redesign record, the UI/UX v2.1 delivery record, the original implementation record and its delivery evidence. Maintainer documentation is English here and Traditional Chinese in the process guide; the public UI and content remain trilingual.
The language-neutral / entry chooses the first supported browser language (Traditional Chinese, English or Japanese), with English for unsupported preferences. Explicit localized URLs and manual language links take precedence. No preference is stored. Without JavaScript, the root keeps its complete Traditional Chinese fallback and three-language navigation. The home front matter names 李汶道 as name and DennySORA as alias.