Skip to content
← Back to the app

How to use Waiting Lists

Waiting Lists

Deploy your own waiting-list service, connect a signup form, confirm an address and export subscribers.

Free to read. You can explore the guide before buying the app.

On this page

Waiting Lists is source code for a service you deploy in your own Cloudflare account. It includes an administrator dashboard, signup endpoints, confirmation emails, CSV exports and a command-line client. Your purchase does not include a hosted subscriber service.

Install the source

Connect GitHub in Polar after purchase and accept the invitation. Clone the customer repository. You need Node.js 22.12 or later.

From the repository root:

npm ci
npm run check
npm test

The repository README documents the individual Cloudflare resources and settings. Start with its Configuration and Deployment sections when preparing a real installation.

Configure your installation

For local work, copy the settings template:

cp .dev.vars.example .dev.vars

Set your admin username and password hash. ADMIN_PASSWORD_HASH is the lowercase SHA-256 digest of a strong password. Use different random secrets of at least 32 bytes for SESSION_SECRET and SUBSCRIBER_TOKEN_SECRET. Configure your Turnstile keys and the allowed login hostnames.

Keep .dev.vars outside Git. It contains credentials, rather than public project settings.

The reference deployment needs the following resources in your Cloudflare account:

ResourcePurpose
WorkerRuns the application and scheduled cleanup
D1 databaseStores lists, subscriptions, consent and admin data
Turnstile widgetProtects administrator login
Rate-limit bindingsLimit login and signup requests
Email Service senderSends confirmation and removal links
Queue and email event subscriptionReport delivery outcomes

Replace the placeholders in wrangler.jsonc with your resource names and IDs. Set APP_URL to the service’s HTTPS origin. Set EMAIL_FROM and the allowed sender binding to your onboarded sender address. Use your production hostname in TURNSTILE_HOSTNAMES.

Update the product name, consent-version identifier, email branding and /privacy notice for your own service. The default source still includes the original waitinglists.dev branding.

For production, store ADMIN_USERNAME, ADMIN_PASSWORD_HASH, SESSION_SECRET, SUBSCRIBER_TOKEN_SECRET and TURNSTILE_SECRET as Worker secrets. Do not place them in the public vars section.

Run and deploy

Prepare the local database and start the application:

npm run db:migrate:local
npm run dev

Open the URL shown by Astro and visit /login. Local rendering and database checks do not establish that real confirmation email works; that needs the configured sender and production bindings.

After configuring your own Cloudflare resources and secrets, apply remote migrations and deploy:

npm run db:migrate:remote
npm run deploy

You can alternatively connect the repository to Cloudflare Workers Builds using the build and deployment commands in its README. Keep a D1 backup before migrations or upgrades.

Create and connect a list

Sign in at /login and create a list called Garden Planner. Add the exact origins of the pages that will collect addresses, such as https://garden.northstar.example. Replace that fictional origin with your own website.

An origin includes the scheme and hostname, and the port when applicable. The www and non-www versions are different origins. Add each one you use.

Open the list’s detail page and copy its generated HTML or JavaScript integration. The public endpoint accepts exactly two subscriber fields, email and explicit consent. Use the generated form with consent wording describing the messages people will receive and a link to your privacy notice.

Do not put an administrator API key in the public form. The public signup endpoint and private management API serve different purposes.

Test confirmation

Submit an address you control from an allowed website origin. The endpoint gives a generic accepted response, including for an address already confirmed. It does not promise that email has been delivered.

Open the confirmation email, follow its link and press the confirmation button. Only then should the subscriber appear as confirmed and become available to normal exports. The extra button avoids treating an email scanner’s link visit as consent.

Confirmation links expire after 24 hours. Test the removal link too. Check the dashboard’s delivery status if the message is deferred, bounced, rejected or fails.

Use the CLI

Open /admin/agent, create an API key and copy it when shown. On macOS, configure the CLI from the clipboard without typing the key into shell history:

pbpaste | npm run waitinglists -- configure --key-stdin --api-url https://lists.northstar.example/api/v1

Replace the fictional origin with your deployed service. Omit --api-url for the default local server.

Create a list and save its non-secret link in .waitinglists.json:

npm run waitinglists -- init --name 'Garden Planner' --origin https://garden.northstar.example

Run that command only when you want a new list. Inspect existing lists first with npm run waitinglists -- lists. Use show LIST_ID or integration LIST_ID to work with an existing one.

Export confirmed addresses from the linked list:

npm run waitinglists -- export --format universal --output garden-planner-subscribers.csv

Other formats are archive, sendy, kit and mailchimp. The CLI refuses to overwrite an existing export and creates it with owner-only permissions. Preserve consent evidence and use addresses for the purpose subscribers accepted.

Data and troubleshooting

The normal CLI credentials are in ~/.config/waitinglists/credentials.json, outside the repository. Treat exports and D1 backups as private subscriber data.

An origin error means the form’s exact origin is missing from the list settings. A 401 from the private API means the key is invalid or revoked. “No list ID supplied” means the current directory is not linked; pass a list ID or use the linked project directory.

Scheduled cleanup removes expired pending requests and confirmed subscriptions after the retention limit, which is 24 months in the included implementation. Keep that job, the privacy notice and your operational process consistent when customizing the service.