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.
A raw HTML button. No styles.
The API route receives the JSON.
Supabase saves the row.
If this chain works, the feature is "done." Everything else is just decoration.
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.
RLS
Row Level Security. The invisible wall.
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.
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
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.
Empty Response
Query succeeds but returns nothing. Classic RLS trap.
{ data: [], error: null }
→ Enable RLS policies or temporarily disable RLS to test.
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.
The Connect
Environment Vars
- →Create .env.local
- →Add Supabase URL & Anon Key
- →Restart your dev server
The Skeleton
Raw Form
- →Create a basic form
- →Connect `onSubmit` to your API
- →Use alert() for success/error
The Heartbeat
Live Data
- →Submit the form
- →Verify 200 OK in Network Tab
- →See row in Supabase
📋 Graduation Requirements
Environment
.env.local is configured and ignored by git.Logic
Data flows from Form → API → DB → UI.