Coming soon page. Turn anything into living ASCII art.
Next.js App Router, TypeScript, no CSS framework. The imagery is a single
<canvas> per stage driven by the vendored glyph-raster engine, so there are no
image assets and nothing to load over the network.
yarn install
yarn dev
Yarn 4, nodeLinker: node-modules. There is deliberately no package-lock.json:
two lockfiles let the local tree and the deploy build drift apart. If port 3000
is busy, Next picks the next free one and prints it.
It runs with an empty environment. See below for what that means for the signup form.
The form posts to /api/subscribe, which resolves a provider at request time
from the environment and never exposes a key to the browser.
| Provider | When it is used |
|---|---|
kit |
KIT_API_KEY is set |
sendy |
the three SENDY_* vars are set |
console |
nothing is set |
console is the fallback so a clean checkout runs. It logs each address with a
loud warning and then discards it. The UI still shows success, because the
alternative is a form that looks broken in development. Do not launch that way.
To go live, copy .env.example to .env.local and set KIT_API_KEY.
The site talks to MailingProvider in src/lib/mailing/types.ts and nothing
else, so the swap is one env var. What the code cannot do for you:
src/lib/mailing/sendy.ts is written but has never run against a live install.
Test it against a throwaway list first.
Vercel. It detects Next.js and yarn with no config file.
Set KIT_API_KEY in the Vercel project’s environment variables, not in the
repo. Attach the domain in Vercel’s dashboard: the CNAME file in this repo is
a GitHub Pages artifact and is inert on Vercel, kept only so the Pages path
stays open.
src/app/api/subscribe/route.ts holds its counters in module memory. On Vercel
that memory is per lambda instance, so under real concurrency the global guard
becomes “100 per minute per instance”, which can collectively overshoot
Kit’s account-wide 120 per minute. It still does its main job of stopping a
single hammering client, and a coming soon form is unlikely to reach that
ceiling. If it ever does, move both counters to Vercel KV or Upstash; the
function signatures are already shaped for it.
src/
app/
api/subscribe/route.ts validation, per IP throttle, provider dispatch
globals.css the whole design, hand written
layout.tsx, page.tsx
components/
Hero.tsx full bleed cup, pointer and ripple interaction
MenuTiles.tsx the four sources
SignupForm.tsx
lib/
glyph-raster.js vendored engine, UMD, no dependencies
glyph-raster.d.ts hand written types for the parts used here
cup-field.ts the raymarched cup, a pure (u, v, t) field
density.ts cell size to column count
mailing/ provider seam: kit, sendy, console
document in its constructor, so this keeps it out of the server
render and out of the initial bundle.