Process and decisions
Build Log
This page records how the site was built: what the brief asked for, the decisions behind it, how the work moved forward week by week, and what I actually checked before calling it finished. It is also the material I use to explain the project in the defence.
Against the brief
- At least four pages with working navigation. Fifteen routes, grouped into six sections. Every link is checked by a script that walks the whole site.
- Own content. Six long articles, three moments and one design note, all written from my own coursework and debugging sessions — sorting assignments, the Linux lab, the move between two computers, the performance investigation.
- Semantic, accessible markup. Landmarks, heading hierarchy, labeled controls, keyboard-operable menus, visible focus, reduced-motion support and AA contrast in both themes.
- Responsive layout. Tested at phone, tablet and desktop widths; the navigation, timetable, check-in calendar and photo wall all have dedicated small-screen layouts.
- At least one interactive element. The site goes well past one: a live clock, a pomodoro timer, a check-in tracker with calendar heat-map, an editable timetable, search and filters, a photo lightbox and a desktop pet with a state machine.
- Live at a real address. cxy0218-blog.pages.dev, with a GitHub Pages mirror.
- Git history showing the work develop. More than 90 commits on
mainbetween April and October, including this rewrite. - No server-side programming or database required. The site is a static export and all user data stays in the browser.
What is on the site
Fifteen routes, each with a reason to exist and something to do on it.
| Route | Purpose | Interactive |
|---|---|---|
| / | Home — Short introduction, latest writing, photo wall and dashboard. | Live clock, rotating carousel, music player, theme switch |
| /posts | Posts — Longer write-ups about things I built or got stuck on. | Search and tag filtering |
| /posts/[slug] | Article — One article with table of contents and reading progress. | Scroll spy, copy-button on code blocks |
| /chatter | Musings — Shorter, looser notes than the articles. | Filter by tag, mood badges |
| /timeline | Timeline — Everything I have published, in one chronological view. | Expandable timeline nodes |
| /local-posts | Local Drafts — Drafts written in the browser and stored only on this device. | Local save, open, delete |
| /courses | Courses — My weekly timetable for this semester. | Editable lessons, week switch |
| /resources | Resources — Study links I keep coming back to. | Category filters, add your own |
| /photowall | Photo Wall — Albums of screenshots and photos, with captions. | Lightbox with keyboard navigation |
| /moments | Moments — Short diary entries with a location and images. | Image lightbox, comments |
| /music | Music — What I listen to while coding. | Music player and previews |
| /checkin | Check-in — Time-block tracking with a monthly log. | Timer, calendar heat-map, export/import |
| /tree | Creative Workshop — Small 3D and canvas experiments. | Interactive 3D scenes |
| /about | About Me — Who I am and why the site exists. | Profile card, social links |
| /friends | Friends — Sites I read, and how to apply to be listed. | Friend-link cards |
The process, week by week
Commit counts come from git rev-list --count on the main branch. Commit messages use a prefix convention (feat, fix, content, chore) so the history reads as a list of decisions rather than a list of saves.
| Period | Commits | What happened |
|---|---|---|
| Apr 27 – May 20 | 35 | Started from a blog template, added LaTeX support, rebuilt the API layer and the launcher, and got a first version running locally. |
| Jun 8 – Jul 13 | 3 | Small fixes and license/attribution clean-up over the summer break. |
| Oct 14 – Oct 18 | 51 | The main build: pages and components, the desktop pet, check-in, accessibility fixes, performance work, Cloudflare Pages deployment and the local package for submission. |
| Oct 21 | this rewrite | Full English rewrite of the interface and articles, rebuilt navigation, and a final accessibility and responsiveness pass. |
| Oct 24 | polish pass | Type checking turned back on, reduced-motion support, sitemap/robots/RSS/manifest/Open Graph, phone asset loading cut by more than half, and dead components removed. |
The two quiet months are part of the record too. They are the summer break, and I would rather show an honest timeline — including the weeks when nothing happened — than back-date commits to look busier.
Decisions worth defending
Each of these was a choice between two reasonable options. This is the reasoning I would give if asked about it.
Licensed 30-second previews, not a pirated stream
The old player pointed at NetEase's free stream URL, which now redirects anonymous listeners to /404. The playlist is resolved once at build time through Apple's public iTunes API and played from its official 30-second previews. The trade-off is 30 seconds instead of a full track, but it is legal, it actually plays, and it needs no key or login.
Next.js App Router, exported as static files
The brief needs no server-side programming, so the site is a static export: plain HTML, CSS and JavaScript that can be hosted anywhere. The build produces the whole site ahead of time, which keeps it fast and cheap to host, and means the local package for grading is the same code that runs online.
Articles are Markdown files in the repository
Every post, moment and musing is a Markdown file next to the code. That keeps the writing in version control, so the git history also shows when each piece was written and edited, and there is no database or CMS to maintain. Comments in the code use the same approach.
Browser storage instead of a database
Timetable edits, study links, photo albums and check-in records live in localStorage. That satisfies "no database required" and keeps the site free to host, but the trade-off is that data belongs to one browser. Each of those pages therefore has export and import buttons, and the limitation is stated in the interface rather than hidden.
Self-hosted images and fonts
Photos are compressed to WebP and stored in the repository instead of being hot-linked from an image host, and fonts are self-hosted too. Nothing on the page depends on a third-party CDN, which makes the site work offline in the local package and removes a whole class of broken-image bugs.
One codebase, two hosts
Cloudflare Pages runs the main site, including a small Pages Function for the pet chat. GitHub Pages mirrors the same static build and demonstrates that the site still works with no server at all. A shared path helper keeps every asset URL correct when the site is served from a sub-directory.
Rebuilt navigation for the English version
The original navigation had twelve top-level items and a circular, drag-to-rotate menu on phones. It looked distinctive but was hard to use and impossible to operate with a keyboard. The rewrite groups the pages into six sections with accessible dropdowns, and replaces the circular menu with a standard drawer that traps focus, closes on Escape and restores focus to the trigger.
What I checked
The project is only finished when these pass. Most of them are automated in the repository under scripts/, so I can re-run them after any change.
- Every page is rendered by the production build and statically exported without errors; the build now type-checks the project instead of skipping TypeScript errors.
- All internal links, images, stylesheets and scripts return 200 — checked by following every link on every page with a script, not by clicking a few by hand.
- One main landmark and one h1 per page; headings run in order without skipping levels.
- Images carry meaningful alt text, or an empty alt when they are purely decorative.
- Icon-only buttons have accessible names; every form control has a visible label.
- Navigation works with the keyboard alone: Tab, Enter, Escape, and arrow keys inside menus.
- Focus is always visible, and the mobile drawer traps focus and restores it on close.
- The layout was tested at 1280px, 768px and 390px wide, including the timetable, check-in calendar, photo wall and navigation.
- Colors meet WCAG AA contrast in both light and dark themes, and heavy background effects are disabled on small screens and for visitors who prefer reduced motion.
- The HTML language is set to en, dates and numbers are formatted in English, and no Chinese text remains anywhere in the interface, articles or metadata.
- Reduced-motion mode removes every decorative animation (measured 113 animated elements down to 0) and skips the splash screen, while navigation and forms keep working.
- On a throttled 4G phone profile the home page went from 1.45 MB and 5.6 s LCP to 655 KB and 2.4 s; the pet no longer preloads its sprites on phones.
- SEO files are generated at build time: sitemap.xml, robots.txt, rss.xml, manifest.webmanifest, Open Graph/Twitter cards and JSON-LD.
Writing the English version
The course is taught in English, so the whole site now speaks English: the interface, the six articles, the moments, the project and album descriptions, the metadata, and the accessible names of icons. Translating was not a find-and-replace. English labels are longer than the Chinese ones, which broke the old twelve-item navigation on a laptop and made the circular mobile menu unusable, so the navigation was rebuilt as part of the rewrite.
I kept the meaning and the details — command names, complexity numbers, file paths, error messages — and rewrote the tone so it sounds like a student explaining their own work rather than a translated document. Screenshots in the articles were retaken from the English build, so the pictures match the text again.
Tools, and what I checked myself
I use AI tools the way the course describes: for drafting, refactoring and reviewing. For this rewrite, AI drafted the English for the interface and the articles, and helped rewrite the navigation. I read every changed page, corrected the wording where it did not sound like me, and re-ran the build and the audits above until they passed.
The mistakes the checks caught are the useful part of the record: leftover Chinese characters in aria labels, dates still formatted in Chinese, nav labels overflowing their buttons, a mobile drawer that did not return focus, and one heading level that skipped from h1 to h3. All of them are fixed in the history, and I can point to the commit for each.
What I would do next
- Replace browser-only drafts with a small exported file format, so a draft can move between devices without a database.
- Add automated visual regression tests for the timetable and check-in calendar, which are the two layouts most likely to break at odd widths.
- Keep the writing going: one article per topic I actually struggled with, instead of a burst of posts at the end.
Back to About Me or read the posts.