Skip to main content
Week 03 • Track 03 • The Process

Mock It
'Til You Make It.

Stop waiting for the backend. Hardcode your success. Build the UI with fake data first to isolate bugs, then swap the signal when the lines are clear.

The Mental Model

Isolate the Variable.

When the speakers buzz, you don't rewrite the song. You check the cable. In dev, if your app breaks, is it the UI or the Data?

1

The Mock Phase: Build the UI using a static array. If it breaks here, it's a React bug.

2

The Swap Phase: Replace the array with a fetch call. If it breaks here, it's a Database bug.

// The Golden Rule

"Never debug UI logic and Data fetching logic at the same time."

📄Static
☁️DB
User Interface

The Studio

Crucial
TypeScript Interface

Sign the Contract.

Before writing fake data OR real code, define what the data looks like. This is your contract. If the Mock signs it, and the Database signs it, the Swap will be instant.

Why this matters:

  • Autocompletes your fake data for you.
  • Errors red if your DB returns the wrong shape.
  • Documentation for your future self.

// types/index.ts

export interface Track {

id: string;

title: string;

artist: string;

bpm: number;

is_active: boolean;

tags: string[];

}

// The component doesn't care source

function Player({ track }: { track: Track })

Step 1
🛠️

The Mock

A simple file. No async, no await, no loading states. Instant feedback.

data.ts

import { Track } from "@/types";

export const mockTracks: Track[] = [

{

id: "1",

title: "Bassline",

artist: "System",

bpm: 128,

is_active: true,

tags: ["House"],

},

];

Step 2
📡

The Real

The component expects `Track[]`. It doesn't care if it came from memory or Supabase.

api.ts

import { Track } from "@/types";

export async function getTracks(): Promise<Track[]> {

const { data } = await supabase

.from('tracks')

.select('*');

return data as Track[];

}

The Swap

🚧

Phase 1: Hardcoded

Import directly from your data file. No waiting.

// page.tsx

import { mockTracks } from "@/lib/data";

export default function Page() {

// Just pass the array

return <TrackList items={mockTracks} />

}

🚀

Phase 2: Fetched

Change the import to the API function. Add await.

// page.tsx

import { getTracks } from "@/lib/api";

export default async function Page() {

// Fetch the data

const tracks = await getTracks();

return <TrackList items={tracks} />

}

The State Machine

Mock data is instant. Real data takes time. When you swap, you need to handle the waiting.

Loading

if (loading) {

return <Skeleton />

}

Show a placeholder while fetching.

Error

if (error) {

return <ErrorMsg />

}

Show a message if the fetch fails.

Success

return (

<TrackList

items={data}

/>

)

Render the UI with real data.

Pro tip: With mocks, you skip loading/error states entirely. Add them only when you swap to real data.

Common Patterns

Signal Distortion

"I'll fetch data from day one"

Now every bug could be UI OR backend. Good luck debugging.

"I don't need types"

Then your mock and real data will have different shapes. Swap will fail.

"I'll handle loading states later"

Your app will flash blank screens. Users will think it's broken.

"My mock data is just [1, 2, 3]"

Lazy mocks hide bugs. Use realistic data with edge cases.

Clean Signal

Types first, always

Define the interface. Mock signs it. Real signs it. Swap is instant.

Realistic mock data

Include long titles, empty arrays, missing images. Find bugs early.

One swap at a time

Don't replace all mocks at once. Swap one endpoint, test, repeat.

Keep mocks around

Comment out, don't delete. Quick rollback when the API breaks.

The Exercises

Set the stage for the database.

01

The Contract

Define TypeScript

  • Create types/index.ts
  • Look at your Napkin Flow (Track 08)
  • Write interfaces for your data
  • Export them
Goal: Strict types prevent future headaches
02

The Mock

Static File

  • Create lib/mock-data.ts
  • Import your Interface
  • Fill it with perfect, ideal data
  • Include edge cases (long titles, etc)
Goal: A reliable test source
03

The Prop Drill

Pass it Down

  • Import mock data in your Page
  • Pass it to your Components
  • Verify the UI looks good
  • Do not fetch yet. Just render.
Goal: Validated UI before backend work

📋 Quick Reference Cheatsheet

Type Definition

interface User { id: string }

Mock Data

const users: User[] = [...]

Supabase Typecast

data as User[]