Work ch3ch3
platform

CH3CH3

A harm-reduction community for 5,489 substance areas — and Substrate, the passkey-only community engine underneath it.

CH3CH3.com is a global harm-reduction community: nested areas for every substance, family and meta topic, with posts, infinitely nested comments, voting and live presence on top. It runs on Substrate — a community-platform engine where nothing about CH3CH3 is hardcoded, so branding, taxonomy and copy are config and seed data. Passkeys are the only way in; there are no passwords to leak. The other half of the project is the content pipeline: an evidence-cited authoring rig that grounds every page on PubChem records, 21 CFR § 1308 schedule text and DEA seizure tables, and refuses to publish a page that overclaims safety. SvelteKit 5 + Postgres + Redis, shipped with one just recipe and under a second of downtime.

Last updateAug 29, 2026 PrimaryJavaScript
  • SvelteKit
  • Svelte 5
  • TypeScript
  • Node
  • PostgreSQL 14
  • Redis
  • SimpleWebAuthn
  • d3
  • sharp
  • Google Cloud Storage
  • Vite
  • just
  • nginx
CH3CH3 — A harm-reduction community for 5,489 substance areas — and Substrate, the passkey-only community engine underneath it.
CH3CH3 media
CH3CH3 media
CH3CH3 media
CH3CH3 media

CH3CH3.com is a harm-reduction community — honest information about substances, written for the people actually taking them, with a forum bolted to the same object tree rather than parked on a subdomain. Underneath it is Substrate, an engine built so that CH3CH3 is an instance of it and not the thing itself: areas, taxonomy, branding and copy are configuration and seed data, and a second community could be stood up against the same binary.

The engine

  • Passkeys only. WebAuthn is the entire front door — no password column, no reset-link theatre, nothing to phish. Account recovery runs over a verified email path instead.
  • Areas all the way down. Nested areas hold posts; posts hold comments nested without a depth limit; everything is votable and feeds an EXP system. Moderation and RBAC sit over the same tree, so a moderator's scope is a subtree rather than a checkbox.
  • Live presence over SSE — who is reading what, updating without a poll.
  • A node view at /graph: the whole area tree as a d3-force graph you can pan and zoom into, which turns out to be the fastest way to find anything in five thousand areas.
  • Per-user theming resolved on the server in hooks.server.ts, before the document ships. A skin applied after hydration means every light-mode reader eats a full-black flash on a cold load; this one never flashes.

The content pipeline

The harder half of the project isn't the forum, it's filling it without lying to anyone. Pages are authored against evidence and cited: PubChem records pinned by identity (a plausible record for the wrong molecule is the failure mode that bites — seven pages served a different compound before an end-to-end check learned to ask about the expansion of an abbreviation rather than the abbreviation), 21 CFR § 1308 schedule text, and the DEA's NFLIS seizure tables parsed straight out of the published PDFs.

Seizure watch alone carries 73 reporting periods back to 2000 and 66 published briefs, each one gated by a checker that fails the brief if any number or link in it doesn't appear in the underlying evidence. Where two official series disagree, the pipeline measured the sixteen overlapping years to decide which one wins rather than picking the newer file. Three different statistical bases are kept apart and never plotted on one axis, because two of them are not comparable and the page says so out loud.

Authored pages go through a panel that can reject them, and it mostly rejects for the right reason: absolute reassurance. A page claiming a substance has "no downside" doesn't ship.

What's on it

5,489 areas — 747 of them molecules across 81 families — 123 official posts and 268 evidence images at last count, plus a front-page news carousel of dated stories tracking scheduling actions as they land. Every authored page carries a visible "not yet human-reviewed" marker until a curator has read it; the honest constraint on this project is curator hours, not compute.

How it ships

SvelteKit with the Node adapter behind nginx, Postgres 14, Redis for presence and search indexing, uploads to Google Cloud Storage with sharp for derivatives. Deploy is one recipe — just ship "message" — which commits, pushes, builds, migrates and restarts with under a second of downtime, and there's a companion recipe whose only job is to prove that number.

Straight from the source

The project's own README.

Rendered in place — every link, image, and code block carried over from the repo. The page below is what a contributor would see opening the project for the first time.

Substrate

A community-platform engine — nested areas → posts → infinitely nested comments, passkey-only auth, RBAC, voting, EXP, live presence, per-user theming — and the evidence-cited content pipeline that fills it. Its first instance is ch3ch3.com, a global harm-reduction community. Nothing ch3ch3-specific is hardcoded: branding, taxonomy and copy are config and seed data.

SvelteKit (Svelte 5, adapter-node) · Postgres 14 · Redis · just + systemd + nginx.

Read this before running anything

This checkout is the production deployment. systemd substrate.service serves ch3ch3.com from build/ in this directory against db_substrate, and the project is developed directly on it by design. Do not run npm run dev here — it would point a dev server at the live database. Use just dev (dev DB + Redis index, via .env.development.local) and just dev-run "<cmd>" for anything that writes.

The loop

just dev                      # dev server on :5173 against db_substrate_dev
just dev-run "node scripts/e2e-<suite>.mjs"   # the E2E suites (never against prod — enforced)
just check                    # svelte-check, must be 0 errors
just ship "what changed"      # add + commit + push + build + migrate + restart (~1s downtime)

Every recipe is in the justfile with a comment saying which database it touches.

Gallery

The full set.

Build something like this

Want a tool like this for your shop?

We've shipped this kind of thing before. Twenty-minute intro call, no slides.