main
Work in progress should not be readable by anyone who wanders in. CURTAIN=<secret> puts a contentless "Coming soon" card in front of every request — pages, APIs, the rotator, the link domains — with noindex headers and nothing that names the product or what it does. Opening the site once with ?k=<secret> drops a cookie that lifts it for that browser. Unsetting CURTAIN opens the site again, so this never has to be picked back out of the code. It sits at the very top of the request handler, ahead of the rotator and the link-domain sites, so there is no path around it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
LinkSpin marks: wordmark in every header, LinkSpin logo and icon files, split brand strings replaced
LinkSpin — site
Membership advertising with immutable on-chain settlement. Zero-dependency Node server (RM Circle pattern): static pages + JSON API + SSE ledger.
Architecture
server.js— http server: pages,/api/*,/join/<id>sponsor links, SSE feedchain.js— contract reader + persistent event indexer (free public RPCs)auth.js— SIWE wallet sign-in (EIP-4361), sessions in the volumeaccounts.js— site-side records only (free members, last-touch sponsor attribution, handles). The CHAIN is the source of truth for money/credits.public/— landing, live ledger, member area; no client libraries
Chain flip (rehearsal → mainnet)
Everything chain-specific lives in data/config.json (volume):
{contract, chainId, chainName, explorer, rpcs, deployBlock}.
Defaults point at the Amoy rehearsal deployment. Launch = deploy the
mainnet contract, wipe accounts.json/sessions.json/chain-index.json,
PATCH /api/admin/chain with the mainnet values, set rehearsal:false via
/api/admin/site. Same code, different config.
Run
PORT=3100 node server.js # DATA_DIR defaults to ./data
Admin API auth: Authorization: Bearer $ADMIN_PASSWORD.
Spec: ../CONTRACT-SPEC.md (v1.0.3-frozen). Contracts: ../contracts/.
Description
Languages
JavaScript
76%
HTML
19%
CSS
4.8%
Shell
0.2%