Skip to content
 
 

Repository files navigation

Cafe Compute Vending

Fork of dabit3/vending-machine, rebranded for Cafe Compute / Cerebras and hosted by Arca Computer.

Production Worker: vending at https://vending.arca.computer. This repo does not deploy. Chercán creates the D1 database and attaches secrets at deploy time.

A vending machine for Cafe Compute event credits. Admins create events with an eligible-email list and a pool of unique codes; attendees visit /<slug>, sign in, and receive a code if their email is on the list (idempotent — the same email always gets the same code).

Stack

  • Astro 7 with @astrojs/cloudflare (output: 'server')
  • Cloudflare Worker assets + on-demand routes (claim + admin)
  • D1 (vending) — schema in migrations/
  • No Convex, no Clerk, no Next.js, no KV/R2/Queues/Images bindings

House pattern matches arcacomputer/oss and clueside/site (workers_dev: false, preview_urls: false, custom domain outside auto workers.dev). Those sites are static; this app is not — claim and admin run on the Worker. / is also on-demand (not prerendered) so it can merge the live Luma calendar with D1 events.

Routes

  • / — Cerebras Cafe Compute directory (live Luma calendar + D1 events; Santiago is always listed)
  • /santiago — Cafe Compute Meetup: Santiago claim page (Luma: https://luma.com/cafecomputechile, 12 Sep 2026, host Luis Felipe Abarca / Felirami, venue TBA, approval-required)
  • /<slug> — claim page for an admin-created event
  • /sign-in — attendee or admin sign-in
  • /admin — create/list events
  • /admin/events/<id> — emails, codes, flagged review, stats
  • /admin/blacklist — app-wide email blacklist
  • /admin/admins — admin allowlist

Auth

Sessions are a signed httpOnly cookie. SESSION_SECRET is required (Worker secret / .dev.vars).

Attendee sign-in, in order:

  1. Email OTP if RESEND_API_KEY and MAIL_FROM are set — a one-time code is emailed.
  2. Else allowlist + Turnstile if TURNSTILE_SITE_KEY and TURNSTILE_SECRET_KEY are set — the email must already be on the event allowlist, and Turnstile must pass. This does not prove mailbox ownership (weaker threat model).
  3. Else allowlist-only (dev) — documented as unsafe for production. Set an email provider or Turnstile before going live.

Admin: D1 admins table. Empty list is bootstrap (first successful /admin sign-in becomes admin). After that, only listed emails get an admin session.

Environment

Copy .env.example to .dev.vars for local Wrangler. Do not commit secrets.

Name Required Purpose
SESSION_SECRET yes (prod) HMAC key for session cookies
RESEND_API_KEY no Send login codes via Resend
MAIL_FROM with Resend Verified from-address
TURNSTILE_SITE_KEY no Turnstile widget
TURNSTILE_SECRET_KEY with site key Turnstile verify

D1 is a binding (DB), not an env var. wrangler.jsonc has database_name: "vending" and a placeholder database_id. Replace the placeholder at deploy — do not create D1 from this PR.

Local

npm install
# optional: echo 'SESSION_SECRET=dev-only-not-for-prod' > .dev.vars
npm run dev          # astro dev (UI; D1 binding needs wrangler)
npx wrangler d1 migrations apply vending --local
npm run cf:dev       # wrangler dev — Worker + local D1
npm run build
npm run cf:dry-run

Adding a city

  1. Sign in at /admin (bootstrap if the admins table is empty).
  2. Create an event with a short slug (e.g. toronto) and optional Luma URL.
  3. Paste eligible emails and codes.
  4. Share https://vending.arca.computer/<slug>.

Santiago is seeded in migrations/0001_init.sql as slug santiago.

Wrangler

wrangler.jsonc: Worker name vending, compatibility_date 2026-08-26, workers_dev / preview_urls false, assets ./dist, D1 binding DB, route vending.arca.computer as a custom domain. No KV, R2, queues, or Images.

About

Dispense coupons and credits based on email address

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages