Skip to content

Repository files navigation

con-sign

E-ink "door sign" for hotel rooms at furry conventions. Roommates show their fursonas, handles, and rough whereabouts; passersby see a sanitized view; QR + per-roommate passcode unlocks more.

Production: cons.social.

Stack

  • Frontend — SvelteKit 2 + Svelte 5 (runes), TypeScript, Vite, @sveltejs/adapter-cloudflare. Deploys to Cloudflare Pages on the apex; Pencil mockups source the design.
  • Backend — Cloudflare Worker (Hono, TypeScript), routed at cons.social/api/*.
  • Database — Cloudflare D1 (SQLite at the edge).
  • Sessions — Cloudflare KV (for revocation).
  • Rate limiting — Workers Rate Limiting binding + Cloudflare zone rule + Turnstile after repeated failures. No IP-based blocking (hotel NAT).
  • E-ink device — dumb HTTP client, fetches a server-rendered image with a bearer token. Hardware-agnostic.
  • Cons list — daily cron sync of the furrycons.com ICS feed.

Repo layout

apps/
  worker/        Cloudflare Worker — API, visitor flow, device sign render,
                 ICS cron. See apps/worker/README.md for setup.
  web/           Pencil.dev frontend (placeholder; toolchain TBD).
packages/
  shared/        Zod schemas + the privacy projection (projectRoommate).
                 The contract the UI imports.
docs/
  mockups/       Pencil.dev .pen files (open via the Pencil app + MCP).
PLAN.md          Canonical design doc — schema, auth, API surface, scope.
                 Read this before re-deriving any architectural decision.

Screens

Mockups live in docs/mockups/pencil-new.pen (open via the Pencil app). The design system frame defines a monochrome ink-on-paper palette shared between the e-ink panel and the web UI.

  • E-Ink panel (800×480) — Sign Render, Unpaired (shows pairing code), Token Revoked.
  • Visitor (mobile) — Locked list, Passcode Sheet, Unlocked detail.
  • Login — Desktop and Mobile, each with a BSky-disabled launch variant (Telegram-only until BSky OAuth lands).
  • Setup Wizard — Pick a Con → Name Room → Invite Roommates → All Set.
  • Admin — Dashboard, Roommate Editor (Desktop + Mobile), Device Pairing flow, Paired Devices settings.

Privacy tiers

Each field on a roommate has a minimum tier required to see it:

  • guest — anyone who scanned the room QR (proof-of-presence at the door).
  • personal — entered that roommate's per-roommate passcode.
  • private — admin / the roommate themselves. Default for new fields.

Unlocks are additive across roommates and rotation-aware (rotating a passcode invalidates only that roommate's unlock).

Develop

pnpm install
pnpm -r test          # 54+ tests, Miniflare pool
pnpm -r typecheck
pnpm -r build

Per-package scripts:

  • apps/workerpnpm --filter @con-sign/worker dev (Wrangler local). Setup, secrets, and D1/KV provisioning live in apps/worker/README.md.
  • apps/web — SvelteKit Pages app (pnpm --filter @con-sign/web dev). Dev server proxies /api/* to a locally-run Worker.
  • packages/shared — pure TS, no build step (consumed via workspace main).

Deployment

  • Worker deploys via the GitHub Actions workflow under .github/.
  • Pages project con-sign owns the apex; the Worker is bound to cons.social/api/* (see apps/worker/wrangler.toml).

Status

Live at https://cons.social — Coming Soon splash is the first page; the rest of the UI lands incrementally.

Backend is end-to-end working: BlueSky + Telegram login, per-roommate passcodes, room/roommate CRUD, visitor unlock + cookie projection, daily ICS sync (151 cons live), pair-code device bootstrap (firmware UUID is the bearer; admin types a 6-char OTP shown on the panel; one endpoint dispatches unpaired/paired/revoked render), audit log of admin actions, and a security pass covering rate limiting, TOCTOU race in claim, CSRF Origin enforcement, JWKS rotation, and an audit trail (see docs/security-todo.md for the resolved items + remaining designed-as-accepted notes).

Frontend (SvelteKit) is scaffolded and shipping pages: splash is live; /login is next. First hardware target picked: TRMNL — see docs/devices/trmnl/PLAN.md. Server-side PNG render is now live (?fmt=png on the device endpoint, rasterized via resvg-wasm and edge-cached for 60 s); the TRMNL adapter endpoints (Mode B BYOS) are the next backend step.

See PLAN.md, docs/api.md, and git log for the latest.

About

Convention door signs

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages