Knock docs

Reading the index…

Host the Human Club

The Human Club is a Next.js app with a libSQL database. Run it on Vercel with Turso, or on any server that runs Node.

Markdown

The Human Club is Knock's demo site: petitions and fundraisers for humans only, where each human signs a petition once. It's apps/bouncer in getknock/knock, a Next.js app that checks knocks in its own functions with @knock-dev/verify and keeps its records in a libSQL database. A copy of your own is a whole club of its own, with its own petitions, fundraisers and members.

What you need

  • A checkout of getknock/knock and Bun.
  • A database: a Turso database for Vercel or any host that runs more than one copy of the club, or a SQLite file on a server that runs one.
  • An origin for it, such as https://club.example, served on HTTPS.

Try it on your machine

Shell
bun install
cd apps/bouncer
bun run dev

The club is at http://localhost:3001 and keeps its records in human-club.db beside it. In development, knocks go through the Door at http://localhost:3000: run the Console and Door's dev server too (bun run dev in apps/door), or set NEXT_PUBLIC_DOOR=https://door.getknock.dev to use Knock's.

On Vercel, with Turso

  1. Make the database. With the Turso CLI, signed in:

    Shell
    turso db create human-club
    turso db show human-club --url      # libsql://…
    turso db tokens create human-club   # its token

    The club makes its tables itself, the first time it opens the database.

  2. Make the project. In Vercel, import your copy of getknock/knock and set the Root Directory to apps/bouncer. apps/bouncer/vercel.json sets the rest: the install runs at the repo's root, because the club uses Knock's packages from the same workspace, then bun run build.

  3. Set its environment variables, for Production: TURSO_DATABASE_URL and TURSO_AUTH_TOKEN from step 1, and CLUB_ORIGIN set to the club's address. The rest are in Settings.

  4. Deploy, then add your domain to the project. If the domain changes, change CLUB_ORIGIN with it and deploy again.

Preview deployments have addresses of their own, and the club takes knocks only for CLUB_ORIGIN. To try one, give previews a domain in Vercel, set CLUB_ORIGIN to it for the Preview environment, and give them a database of their own, so tests stay out of the real club.

On your own server

Shell
bun install
cd apps/bouncer
NEXT_PUBLIC_DOOR=https://door.example bun run build
CLUB_ORIGIN=https://club.example \
TURSO_DATABASE_URL=file:/var/lib/human-club/club.db \
PORT=3001 \
bun run start

Put it behind a proxy that serves HTTPS, as for knockd, and keep it running with systemd or the like. A SQLite file works for one copy of the club. If you run more than one, they must share a database: use Turso, with libsql://… and its token.

Settings

NEXT_PUBLIC_ settings are read when the club is built. The rest are read when it runs.

SettingDefaultWhat it does
CLUB_ORIGINnone: needed in productionThe club's origin, exactly as browsers send it, such as https://club.example. Wedgies sign for it, and the club takes no knock signed for another. In development, the address the request came to.
TURSO_DATABASE_URLfile:human-club.dbThe database: libsql://… for Turso, or file:… for a SQLite file. Needed on Vercel.
TURSO_AUTH_TOKENnoneTurso's token for that database.
NEXT_PUBLIC_DOORKnock's, https://door.getknock.dev; in development, http://localhost:3000The Door knocks go through: Knock's, or your own.
CLUB_ETH_RPChttps://ethereum-rpc.publicnode.comA mainnet RPC: for ENS, and to check gifts.
CLUB_WORLD_RPChttps://worldchain-mainnet.g.alchemy.com/publicA World Chain RPC: for bindings.
CLUB_STRICToffWhether a binding must be final first: off, on (safe) or finalized. Strict mode explains.
CLUB_MAX_BINDING_DAYS365How old a binding's World ID proof may be, in days.
CLUB_KNOCK_BINDINGKnock'sThe KnockBinding whose bindings count. Only for a network of your own.

Use your own RPCs for a club people use: the public ones are rate-limited, and the checks believe what they say. Its RPCs says more.

What it keeps

For each human who has knocked: their nullifier, their Wedgie's name, and when they came. Then what they started, signed and gave, with their name beside it only where they chose to show it, and the gifts' transactions. A session is a random token in a cookie, which the club keeps only as a hash, for two weeks.

Nothing else: no email addresses, no IP addresses, no analytics. Whoever holds the database can see which nullifier did what, so keep its token as you'd keep a password.