Swiftpoint Hub — Documentation
This folder documents the Swiftpoint Hub website in full: what it is, how it is built, and how every part of it works. It was written by reading the source of t
This folder documents the Swiftpoint Hub website in full: what it is, how it is built, and how every part of it works. It was written by reading the source of the running application, not from memory — every factual claim in these files is traceable to a file in the repository, and nothing here describes a feature that is not implemented.
Swiftpoint Hub is an unofficial, non-commercial community hub for the Swiftpoint Z3 gaming mouse. It runs on its own server with no cloud dependency on Swiftpoint, stores .spcf profile files byte-for-byte as they were uploaded, and serves four browser tools, a forum with a ticket system, a guides site and a small amount of first-party analytics.
How this documentation is organised
The files are numbered so that they can be read in order if you want to, but almost nobody should. Pick the path that matches what you are trying to do:
| If you are… | Read |
|---|---|
| New here, and want to know what the site does | 01 Overview, 07 The tools gallery and profile gallery, 09 The forum and the ticket system |
| Want to write a guide | 11 The guides system, 12 The markdown reference, 13 The markdown blocks |
| Want to change code | 02 Project structure, 17 The data model, 18 The API reference, 21 Configuration and deployment, 22 Testing |
| Want the exact markdown syntax | 12 The markdown reference and 13 The markdown blocks |
Want to understand a .spcf file |
14 The .spcf format, then 24 Glossary |
| Are auditing the site | 15 Accounts and roles, 19 SEO and analytics, 20 Security and privacy |
| Hit a wall and want to know whether it is a known gap | 23 Known gaps |
| Do not recognise a word | 24 Glossary |
The complete file list
| # | File | What it answers |
|---|---|---|
| — | README | How this documentation is organised, and the three things that surprise everyone. |
| 01 | Overview: what this site is and does | The four tools, the content areas, the design principles visible in the code, and what the site deliberately is not. |
| 02 | Project structure: a file-by-file map | Every directory and file, what depends on what, the mount order in server.js, and where a new feature goes. |
| 03 | Pages and routes | Every URL the server answers, and which HTML file behind it. |
| 04 | The Profile Builder | How the three-panel .spcf editor works, and what the working draft in localStorage does. |
| 05 | The OLED pixel editor | The 64×32 1-bit editor: frames, layers, keyframes, onion skin, and the exports. |
| 06 | The .spcf checker |
The client-side profile viewer at /check, and why a file opened there never leaves the browser. |
| 07 | The tools gallery and the profile gallery | How profiles are listed, searched, filtered, sorted, voted on and commented on. |
| 08 | The walkthrough recorder | The .rec.json format, the recorder's admin gate, and the recordings admin page. |
| 09 | The forum and the ticket system | Categories, threads, posts, subscriptions, ticket statuses and the ticket trail. |
| 10 | Updates | The two update kinds, the accents, and the moderation rules around them. |
| 11 | The guides system | The docs/ tree, front matter, tags, ordering, the notes map, and writing guides from the admin panel. |
| 12 | The markdown reference | Every markdown construct that works, and the two engines that differ. |
| 13 | The markdown blocks | Each ::: block type, what it renders, and where it is allowed. |
| 14 | The .spcf format |
The header line, the RootProfile document shape, validation caps, and byte-exact storage. |
| 15 | Accounts, sign-in and roles | Discord OAuth2, the four permission levels, and the two sources of staff. |
| 16 | The admin panel | What the panel shows, what it can change, and the guides editor inside it. |
| 17 | The data model | Every table, its columns and the relations between them. |
| 18 | The API reference | Every /api/... endpoint, its method, guard and body. |
| 19 | SEO, social cards and analytics | Canonicals, OpenGraph, the sitemap, robots.txt, and the hashed-IP pageview counter. |
| 20 | Security and privacy | The CSP and other headers, the cookie settings, input cleaning, and the generated legal pages. |
| 21 | Configuration and deployment | Every environment variable, the nginx setup, the systemd restart, and the cache policy. |
| 22 | Testing | The node:test suite, what each group of test files protects, and the two helpers. |
| 23 | Known gaps | What is not built, what is deliberately limited, and the ideas that were left on the table. |
| 24 | Glossary | Every term used across this documentation, defined once, alphabetically. |
Conventions used in this documentation
-
Code, file paths, routes, environment variables and JSON are shown in fenced code blocks with a language tag, so they are read as literals and not as prose:
GET /profiles/hub -
:::block syntax — the custom markdown containers the two engines add — is shown as a code block rather than rendered, because the reader usually wants the source and not another box on the page:::: warning "Check the deactivation list" A trigger with no deactivation stays active until something stops it. ::: -
Reference data — statuses, kinds, roles, limits, headers — is always a markdown table, so it can be scanned, copied and diffed.
-
Verbatim source is quoted with
>and attributed to the file it came from, e.g.lib/forum.js. -
Verified against source on 2026-09-30. Every file in this folder was written by reading the repository on that date. Where a number is a limit or a setting, it is the value the code actually uses. Where something could not be verified from the source, it is left out rather than guessed.
The three things that surprise everyone
-
The site is entirely server-rendered, and there is not one inline script. The Content-Security-Policy sets
script-src 'self', so an inline<script>or anonclick=attribute would not run. Every page is a static HTML file with<script src="…">tags, and the client scripts only attach behaviour to markup that is already there. If a change you make does nothing, check first whether you reached for an inline handler — see 20 Security and privacy. -
There are two different markdown engines with different feature sets.
lib/docs/index.jsrenders the guides and supports Obsidian-style wikilinks, callouts, tabs, a link graph and a table of contents.lib/markdown.jsrenders forum posts, updates and comments, and its defining rule is that raw HTML is escaped rather than parsed, so a post cannot carry a<script>or a<form>at all. They share the:::block vocabulary but not the rest — see 12 The markdown reference. -
The OLED editor has no persistence at all. A reload loses the drawing: there is no localStorage draft, no session-restore, nothing. The Profile Builder, by contrast, writes its whole working document to
localStorageundersph:editor:draft(debounced by 600 ms) and reads it back on boot, because publishing requires a session and a failed sign-in must not cost an hour of binding choices. The two tools are inconsistent here deliberately — see 04 The Profile Builder and 05 The OLED pixel editor.
Back to the project README.