The page was a mock job posting: applicants, positions, benefits, responsibilities, a spec table and selection notes. That framing carried real wit, but it kept the warmest scenes at arm's length behind HR vocabulary. Every sentence carrying a personal fact is untouched — the dev job, Genshin and T1 Keria, the light novels, the three-year relationship, 162cm, the playlist, the whole appendix. Only the framing around them changed: - Retitled throughout: page title, OG and Twitter tags, wordmark. The site is now an open letter rather than a description and a CV. - "Ứng viên là ai?" becomes "Mình là ai?"; the cold open is a seat that has been empty a while rather than a vacancy; the CTA meets a person, not a candidate. - Scene 4 offers what he can give instead of listing entitlements, and loses the job-spec table whose three jokes only worked as a job spec. - Scene 5 drops "Trách nhiệm" for a smaller, warmer promise. - Scene 6 keeps its no-tests sentiment without the stress-test phrasing, and the climax speaks about the person he hopes to meet rather than a strong applicant. - The appendix is a few concrete things, not a dossier; the freshness stamp says he is still looking rather than that a position remains open. Also drops the office-parody joke, which pointed at a conceit that no longer exists, and restyles the numbered package as four unhurried lines so scene 4 keeps a shape of its own without reading as a compensation schedule.
2.8 KiB
Dating
A warm open letter from Tiến Nguyễn Minh to whoever comes along, told as a scroll-driven short film. Vietnamese only.
The page was originally framed as a mock job description and CV; that conceit was dropped in favour of a plainly romantic register, so avoid reintroducing recruiting language (ứng viên, vị trí, quyền lợi, trách nhiệm, tuyển chọn) when editing copy.
Structure
Single-page site: index.html at the repo root holds the whole story, told as
scenes and navigable via anchors:
#home— cold open, the vacant position#applicant— who the candidate is#honest— saying it straight#offer— what you get#shared— what you both protect#no-test— bonus points, and the written climax#closing— the connect beat#dossier— appendix, the detail table#end— end card
Features
- Light theme: warm ivory and terracotta-rose
- Dark theme: candlelit plum and rose-gold
- First visit follows the OS colour scheme; an explicit choice is persisted
- Compact emoji theme switch
- Vietnamese-only copy
Tech
- Plain HTML, CSS, and JavaScript — no framework, no build step
- GitHub Pages (classic, deploy from branch)
Motion tiers
Motion is a three-tier progressive enhancement. Any change must keep all three
working, and no [data-reveal] element may ever be left invisible:
- Film (
html.film-ready) — GSAP + ScrollTrigger + Lenis from a CDN, inassets/story-film.js. Activates only on ≥768px, with motion allowed, and only when the CDN libraries actually arrived in time. - Reveal (
html.js-ready:not(.film-ready)) — IntersectionObserver fade-and-rise inassets/story.js. This is what phones and reduced-motion visitors get. - Static — no JS, or a stalled CDN. A watchdog in the
index.htmlhead un-hides everything after 1200ms if no engine has claimed the page, so the first paint is never wordless.
Two ordering rules in story-film.js are load-bearing and commented there: pins
are created before reveals and carry refreshPriority: 1, and reveals are
per-beat and non-reversing.
Files
assets/styles.css— tokens, layout, components (both themes)assets/story.css/story.js— tier 2 revealassets/story-film.css/story-film.js— tier 1 filmassets/story-chrome.css/story-chrome.js— progress bar + active navassets/theme-switch.js— theme toggle (keep in sync with the head bootstrap)assets/freshness-stamp.js— "cập nhật [ngày]" from the GitHub commit date
Developing
No install needed. Open index.html directly, or serve the folder:
python -m http.server 8000
Then visit http://localhost:8000/.
Deploying
Classic GitHub Pages serves the main branch root directly — pushing to main
publishes the site. .nojekyll disables Jekyll processing.