Building Apps with AILesson 51 of 87

Contents

Building Apps with AI

Lesson 51 of 87. Sign in to keep your place.

Module 6 · The parts that persist: data, accounts and files

Seed data, and the empty state nobody tested

7 min read

Two databases, two worlds

Your development database has your account, the three test bookings you made on Tuesday, and whatever the agent inserted while checking its work. It has never been empty since the first hour, and neither has your view of the app.

A new user’s world is a table with no rows. The dashboard they see first is the one you have not looked at since the project began, and a large share of “it works for me” reports are this: code written and checked against a full database, meeting an empty one.

Seeding on purpose

A seed script inserts known data into a development database so that a fresh clone, a reset, or a collaborator’s machine starts with something to look at:

TypeScript
// scripts/seed.ts
await db.insert(users).values([{ id: DEMO_USER, email: "demo@example.com" }]);
await db.insert(bookings).values(
  Array.from({ length: 40 }, (_, i) => ({
    userId: DEMO_USER,
    startsAt: addDays(new Date(), i - 20),
    status: ["pending", "confirmed", "cancelled"][i % 3],
  }))
);

Make it produce the awkward cases as well as the pretty ones: a booking in the past, one today, a cancelled one, a name with an apostrophe, a user with no bookings at all. The seed is the cheapest test data you will ever write, and the agent will use it too when it checks its own work.

Seed only development. The script should refuse to run if the connection string looks like production: a check on the hostname takes one line and has saved real data. A seed against production either fills a live app with demo@example.com or, in the common version where the script clears tables first, empties it.

Zero, one, many

Test every list at three sizes.

Zero. What does the page show? A generated page usually shows nothing, or crashes on rows[0].name. An empty state is a design decision: a sentence saying what will appear here and a button to make the first one. It is the first screen every new user sees, so it is the most-viewed screen you have.

One. Pluralisation (“1 bookings”), layouts that assumed a grid, summaries that divide by a count.

Many. Ten thousand rows through a page that renders all of them. Generated code selects everything and maps over it; at 40 rows it is instant, at 40,000 the page takes fifteen seconds and the browser tab freezes. The seed script can generate ten thousand rows in a loop in under a second, and then you see the problem before a user does. Pagination is the answer and a later lesson covers it.

The null in the middle

Between zero and one lives the row that exists with a field missing: a booking with no phone number, a user who signed up with Google and has no name. The nullable columns from the previous lesson each produce one of these, and the seed should include them, because null rendered on screen as the word “null” is what a user sees when nobody tested the row with the gap.

Copies of production are personal data

At some point somebody suggests loading a copy of the real database locally “to test with realistic data”. The realism is real; so is the fact that a copy of every customer’s name, email and history is now on a laptop, in an agent’s context window, possibly in a chat transcript.

If you need production shape, export it with the personal columns replaced: names from a word list, emails as user-1042@example.com, free text dropped. Tools exist for this, and a script the agent writes can do it in an afternoon. Then the copy is a copy of the shape and the volume, which is what you wanted, and not of the people.

The test accounts

Keep two accounts in development beyond your own: one with a lot of data and one with none. Sign in as the empty one before every release and click through the main path. It takes two minutes and it is the check that catches the blank dashboard, the crash on the first element, and the sentence that assumed you already had something.

The demo account is also what you hand to anybody testing the app, which means it must never be an account with a real person’s data behind it, and its password must not be the one you use anywhere else, because you will type it in front of people.

Every lesson here is open. Your progress is recorded once you pass the Building with AI exam.

Check your understanding

A dashboard page works for the developer but shows a blank white screen to a brand-new user. The console reports ‘Cannot read properties of undefined (reading 0)’. What is the most likely cause?

Pick the one you would defend. Your answer stays private.

Next lesson · 9 minSign-in, without writing it yourself

Stuck on something?Ask Beatriz, your AI tutor

How to cite: Addaly (2026) ‘Seed data, and the empty state nobody tested’, in Building Apps with AI. Edited by M. Mun. Addaly. Available at: https://addaly.com/learn/building-apps-with-ai/seed-data-and-the-empty-state (Accessed: 13 October 2026).