Skip to main content
Week 03 • Track 04 • The Vision

Ugly But
Functional.

The "Walking Skeleton." We don't care about the paint yet. We care about the pulse. If the data hits the database and comes back, you have won.

The Mental Model

Bones First. Skin Later.

A "Walking Skeleton" is a vertical slice of your app that works from end-to-end but looks terrible.

1. The Trigger

A raw HTML button. No styles.

2. The Signal

The API route receives the JSON.

3. The Storage

Supabase saves the row.

If this chain works, the feature is "done." Everything else is just decoration.

The Skeleton
input...
SUBMIT
The Database

INSERT INTO users

VALUES (...)

Status: 201 Created

Sources of Truth

🌐

The Network Tab

The only thing that matters is the payload. If your button clicks but nothing happens in the Network tab, your code is broken. If the Network tab shows 500, the server is broken.

Name
Status
Type
Payload
create-user
200
fetch
{ email: "neo@matrix.com" }
🛡️

RLS

Row Level Security. The invisible wall.

Common Bug:"My query runs successfully but returns 0 rows."

This usually means RLS is on and you haven't written a policy to allow reading.

Trust the Dashboard.

Your UI might lie. Console logs might mislead you. But if you open Supabase and see the new row in the Table Editor, it is real.

  • 1Submit form in your "Ugly" app.
  • 2Switch tab to Supabase.
  • 3Hit Refresh on the Table.
Supabase Table Editor
idcreated_attitle
8f2a...Just nowMy New Song
1b4d...2 days agoDemo 1

The Validation

🏗️

1. Build It

Create the form. Bind the inputs to state. Don't style it. Just make it exist.

🧨

2. Break It

Try to submit empty data. Watch the error handling (or lack thereof). Fix the critical crashes.

🏁

3. Verify It

Submit valid data. Check the database. If the row appears, you move to Week 04.

The Error Log

500

Server Error

The API route crashed. Check your terminal for the stack trace.

Error: relation "users" does not exist

→ You forgot to create the table in Supabase.

0

Empty Response

Query succeeds but returns nothing. Classic RLS trap.

{ data: [], error: null }

→ Enable RLS policies or temporarily disable RLS to test.

401

Unauthorized

Your API key is wrong or missing from the request.

Invalid API key

→ Check .env.local and restart dev server after changes.

???

Silent Failure

Button clicks but nothing happens. No error, no network request.

// Check for these:

→ Missing await before async call

→ Form has no onSubmit handler

→ Button type is not "submit"

Common Patterns

Dead Ends

"I'll make it pretty first"

Then you spend 3 hours on CSS while the feature doesn't work.

"I trust my code works"

Always verify in the database. The UI can lie to you.

"I'll handle errors later"

At least console.log them. Silent failures waste hours.

"The Network tab is too complex"

Learn it. It's the only source of truth for API calls.

Clean Build

Function over form

An ugly working feature beats a pretty broken one every time.

Verify at every step

Console log the request. Check Network tab. Verify in Supabase.

One feature at a time

Get CREATE working before READ. Get READ working before UPDATE.

Celebrate the 200

When you see 200 OK and the row appears, you've won.

The Final Exam

Graduate from Week 03.

01

The Connect

Environment Vars

  • Create .env.local
  • Add Supabase URL & Anon Key
  • Restart your dev server
Goal: Establish the secure link
02

The Skeleton

Raw Form

  • Create a basic form
  • Connect `onSubmit` to your API
  • Use alert() for success/error
Goal: Functionality over aesthetics
03

The Heartbeat

Live Data

  • Submit the form
  • Verify 200 OK in Network Tab
  • See row in Supabase
Goal: Data persistence verified

📋 Graduation Requirements

Environment

.env.local is configured and ignored by git.

Logic

Data flows from Form → API → DB → UI.
End of PlaylistReturn to Studio