Deeve Technologies
Client workWeb Application

EarlyBird, Next.js Waitlist App

A minimalist waitlist application built with Next.js, TypeScript, and Supabase, deployed on Vercel. A single-purpose signup page with privacy-first data handling: emails stored in one Supabase row with row-level security, hashed IPs for...

ClientDeeve Technologies
RoleFull-stack developer
Year2026
TypeWeb Application
Updated23 Sep 2026
Earlybird
Overview

EarlyBird is a quiet, design-led waitlist tool. Next.js and TypeScript on Vercel, Supabase for storage.

Built around the idea that a waitlist should promise almost nothing and be trusted with the address.

Built with
Next.jsSupabaseTypeScriptVercel
The problem

What was in the way

Most waitlist tools are marketing platforms wearing a signup form.

They treat an email address as the start of a drip campaign. You sign up to hear when something launches and you receive a welcome sequence, a founder story, a survey and three nudges before the product exists.

Some products want the opposite. Capture interest, promise almost nothing, and be trusted. That is a different product with a different shape, and the existing tools cannot be configured into it because the campaign machinery is the point of them.

There is a second problem underneath. A pre-launch signup form is the first thing anyone sees of a product, and it is usually the least considered page the team will ever ship. It says more about the product than the team intends.

What I built

Five parts, each with a reason

A single purpose signup page

Editorial, no noise. One thing to do on the page.

No feature list, no roadmap, no social proof from a product that has not launched. A waitlist page arguing hard for a product nobody can evaluate is asking to be distrusted.

A three principle promise, stated on the page

One email when something ships. No drip campaigns. One click unsubscribe.

This is the actual product. The form is trivial, the commitment is not, and stating it explicitly is what makes someone give a real address rather than a throwaway one.

Putting it on the page also constrains what the product can become later, which is the point of writing it down.

Hashed IPs for spam control

Abuse prevention without retaining identifiable data.

This is the trade most signup forms get wrong in the other direction: they log the raw address indefinitely because it was easier, and then hold a table of IPs they never intended to keep. A salted hash supports rate limiting and duplicate detection without storing anything that identifies a person.

Why it is listed

Partly to show range beyond PHP into the React and serverless stack.

Mostly because the decisions in it are small and defensible: store the minimum, enforce the boundary at the database, say what you will do with the address, and then do only that.

Privacy-first storage

Each signup is a single Supabase row with row level security enabled.

The data boundary is enforced at the database rather than in application code. A query that forgets a condition returns nothing rather than returning the list, which is the correct failure mode for a table of email addresses.

One row, no profile, no enrichment, no tracking. There is nothing to leak beyond the address the person knowingly gave.

How it was built

The engineering underneath

Next.jsTypeScript with Supabase for storage, deployed on Vercel
StaticThe page costs nothing to serve and makes no database round trip for a visitor who never signs up
RLSThe anonymous key can insert and cannot read, so the public key in the browser cannot retrieve the list

Next.js with TypeScript, Supabase for storage, deployed on Vercel.

The page is statically generated with the form posting to a route handler, so the page itself costs nothing to serve and there is no database round trip for a visitor who never signs up.

Validation runs on the server. Client-side validation is a convenience for the person filling the form and no kind of control, because anything the browser checks can be bypassed by not using the browser.

Supabase row level security is doing real work here rather than being enabled and forgotten. The anonymous key can insert and cannot read, which means the public key shipped to the browser cannot be used to retrieve the list.

Next.js with TypeScript, Supabase with row level security, deployed to Vercel.

Next.jsSupabaseTypeScriptVercel
More work

Projects like this

All projects
Why it matters for your project

I build software, and I measure whether it works.

The same questions I research are the ones I ask on client builds: is it reliable, is it fast, is it easy to use, and is it secure. Those four drove satisfaction in my ICT portal study, and they shape how I scope and test every project.