Personal site for 申杰 / j3w1, presented as a working reinterpretation of the historical Manjaro i3
workstation preserved in j3w1/1w3j.
The page is not a picture of a window manager — it is one. Windows tile, split, float, resize, and close; the terminal runs commands over the site's own content; the status bar reads the visitor's own machine. It stays readable on a phone, and renders as one plain stacked document whenever the window manager cannot run.
The public site is a dependency-free GitHub Pages project: semantic HTML, CSS, vanilla ES modules,
and no runtime build step. Its seven workspaces are deep-linked at #home, #writing, #projects,
#photography, #books, #elsewhere, and #about; published entries add #writing/<slug>,
#photography/<slug>, and #books/<slug>.
Every published entry also has a real, crawlable page — /writing/<slug>/, /photography/<slug>/,
/books/<slug>/, plus /writing/, /photography/, /books/ — with its content as HTML, social
cards, and a link back into the desktop. Those paths are the canonical, shareable URLs; the hash
routes are how the desktop shows the same entries. sitemap.xml and the Atom feed.xml are
generated with them, and a path-shaped link that has no page (/about/, a mistyped slug) is
forwarded by 404.html into the desktop.
Identity, the projects table, the link list and the about buffers are data too:
content/site.json is authoritative, and npm run generate writes the marked
regions of index.html, wiki/index.html and 404.html from it, counts included.
Writing, reading notes, and photography are Git-managed. Authoritative Markdown lives in
content/; assets/data/content-index.json, the entry pages, the sitemap and
the feed are deterministic generated output, committed and checked by npm run check; the safe DOM
renderer is shared by the public workspaces and j3w1ctl preview, and the page generator mirrors it
(a browser test holds the two to byte-for-byte parity).
📖 The wiki is at https://j3w1.github.io/wiki/ — quick start, key points, every hotkey, the
terminal's commands, touch gestures, session and settings, privacy, and troubleshooting. It is
reachable from the site itself: the file manager's Places → Wiki entry on 1:home, the ? help
dialog, 6:elsewhere, the launcher's open wiki, or wiki in the terminal. Source: wiki/index.html.
The short version:
1–7switch workspace, or click the names in the bar. On a phone, swipe./opens the launcher — every command is reachable there without a keyboard shortcut.?shows the keys.Shift+E(or the power button in the bar) opens the session menu;0opens the same actions as the original config's system mode: lock, exit, switch user, suspend, hibernate, reboot, shut down. A reboot really reboots — systemd goes down, the machine boots, LightDM waits.
The desktop follows the original machine's dotfiles (j3w1/1w3j):
Source Code Pro, i3-gaps 14/−2, the Xresources palette, i3status's Chinese labels, dunst and dmenu's
colours, conky, an agnoster prompt, and the dotfiles themselves readable in the terminal
(cat ~/.config/i3/config). Where a browser cannot honestly supply a value the block is absent.
The palette's current contract is defined by
j3w1/theme, not by this repository. This site is a pinned
CSS-variable consumer of j3w1/theme@v1.1.0: it commits the verified export and generates its
legacy variable names from that copy. It never imports a moving branch, and there is no
synchronisation from the site back into the theme.
Nothing can be broken permanently: closed windows are only hidden, and reloading always restores the full desktop.
| Document | For |
|---|---|
| wiki/ | Visitors — how to use the site |
| wm-usage.md | The same guide in Markdown, for the repository |
| wm-architecture.md | How the window manager is built and why |
| wm-accessibility.md | The rules the implementation must obey |
| wm-development.md | Running it, testing it, extending it |
| j3w1ctl-architecture.md | The content management client and its backend |
From the repository root:
python -m http.server 8000Then open http://localhost:8000/#home.
The public site's own checks live at the repository root and need only development tooling — the site
itself has no runtime dependencies. The backend keeps its own suite under services/j3w1ctl-auth/.
npm ci # once: Playwright + generators
npm --prefix services/j3w1ctl-auth ci # once: the backend
npm test # tree maths, structure/accessibility contract, static security
npm run test:browser # the window manager in a real browser (PW_CHANNEL=msedge to use Edge)
npm --prefix services/j3w1ctl-auth test # backend
npm --prefix services/j3w1ctl-auth run test:browser # j3w1ctl client
npm run check # committed generated artifacts are currentnpm run test:all runs every suite. The same checks run in GitHub Actions on every push and pull request.
Opening the site with ?wm=selftest runs the pure layout assertions in the browser console.
The font is Source Code Pro as the Nerd Fonts build (SauceCodePro Nerd Font Mono), subset to the
glyphs the site uses and committed as ~39 KB of WOFF2 under assets/fonts/ by npm run generate;
the OFL license is included alongside. See docs/wm-architecture.md §8.
Cache busting is manual ?v= query strings. Every asset of the public shell — the stylesheets and
every script under assets/js/ — shares one token and is bumped as a unit — pinning only
boot.js would let a stale cached layout.js load against a fresh tree.js.
npm run bump-cache-token rewrites every reference (including dynamic imports, the wiki/,
admin/ and 404 pages, and the page generator); follow it with npm run generate, and redeploy
j3w1ctl-auth before the next browser publish. The contract test fails on a mixed set. content-renderer.js,
photo-viewer.js, and admin/j3w1ctl.js keep their own tokens and are bumped only when they change;
the j3w1ctl token in assets/js/site.js must always equal the one in admin/index.html.
Content can be added manually with the documented templates and CLI, or through the static /admin/
j3w1ctl client after its service URL is configured. The narrow Node 24/Fastify service under
services/j3w1ctl-auth/ runs as Vercel Functions and owns
authentication, validation, private temporary image staging, and atomic expected-head GitHub commits.
GitHub is the published-content database; Vercel Blob is staging only and the backend is not
permanent content storage.
In production, the service is source-bound to j3w1/j3w1.github.io@main; no browser or deployment
setting can select another publication target. j3w1ctl requires API protocol compatibility before
enabling authentication or mutation. Save draft remains browser-local, Preview does not publish, and
Publish performs one expected-head GitHub mutation with no automatic write retry. Photography sources
may be JPG, JPEG, PNG, or WebP; j3w1ctl creates full and thumbnail WebP files locally, stages only
those generated files in private Blob, and never uploads the original source.
Backend deployment is explicit: protected Preview, staged Production without domain assignment, then promotion of the exact accepted deployment. Automatic Git deployments are disabled. The previous DigitalOcean publisher is not a fallback.
The public page has no analytics and no backend. The status bar and neofetch read hardware
concurrency, device memory, connection type, battery, screen size, language, and time zone from the
visitor's own browser and transmit none of it. Where a browser does not expose a value it is left
absent rather than guessed. Layout, wallpaper, and preferences are stored in localStorage and never
leave the visitor's machine.