Connecting it All
Introduction
Up to this point, we have successfully built two major pieces of our application: a React + Vite front end that provides users with an interactive experience and a Supabase back end that uses PostgreSQL to store and manage information. However, these two systems are still operating independently. Our front end can display information and respond to user interactions, but it cannot permanently save changes, while our Supabase database is ready to store information but has no connection to our application's interface. In this lesson, we will finally bring these two systems together to create our first Full-Stack Application. We will explore how RESTful APIs allow our front end to communicate with Supabase, why a dedicated API service layer helps keep our application organized, and how environment variables are used to configure that connection. Most importantly, we will learn how to orchestrate specialized Claude Code Sub-Agents to handle front-end and back-end responsibilities while preserving the functionality, design, and database structure we have already established. Our goal is to move beyond an application that simply looks functional and build one that can create, retrieve, update, and delete real information that persists beyond a browser session.
Lesson
What Do We Have?
Before we connect anything, it's worth being precise about what we're starting with on each side.
Your React + Vite frontend is currently a static site. It renders UI, manages local component state, and might even simulate CRUD with hardcoded arrays. But it has no memory — refresh the page and everything resets. Nothing is actually stored anywhere. It has zero awareness of your Supabase project.
Your Supabase backend is a fully capable dynamic system that's been running and waiting the whole time:
- A PostgreSQL database with your
usersandtaskstables already defined - A RESTful API powered by PostgREST, auto-generated from your schema, with endpoints ready to handle every CRUD operation
- API documentation auto-generated by Supabase and accessible from your project dashboard — it describes every endpoint, every filter, and every expected response for your specific schema
- API keys — a publishable (anon) key that is safe to use from client-side code
Everything on the Supabase side is ready. The only work left is on the client side: teaching your React application when and how to talk to Supabase.
The Full Stack Workflow
Once connected, every user action in your UI will trigger a chain of events that spans all three layers of your stack. Understanding this flow is essential — it's the mental model that will guide every feature you build from here on.
User Action (click "Add Task")
│
▼
React Component (calls a service function)
│
▼
API Service Layer (builds and sends the HTTP )
│
▼
Supabase PostgREST API (validates the request, checks the API key)
│
▼
PostgreSQL Database (executes INSERT, returns the new row)
│
▼
API Service Layer (receives the response)
│
▼
React Component (updates state → UI re-renders)
A few things to note about this flow:
Components never talk to the API directly. There is always a dedicated service layer in between. This keeps your components focused on UI and user interaction, and keeps all your Supabase-specific logic in one place. If your API URL or key ever changes, you update one file — not every component.
Every request is asynchronous. Network calls take time. Your UI must account for three possible states after initiating a request: loading (waiting for the response), success (data came back), and error (something went wrong). A real application always handles all three.
The database is the source of truth. After a successful write (POST, PATCH, DELETE), your UI should reflect what the database actually contains — either by using the response data returned from the request, or by re-fetching. Never assume the local state is correct without confirmation from the server.
Environment Variables
An environment variable is a value that is important to the fundamental operations of our application. These are all likely also secret values so they should always be hidden from our version control.
Your environment variables live in a .env file at the project root:
VITE_SUPABASE_URL=https://<your-project-id>.supabase.co
VITE_SUPABASE_ANON_KEY=<your-publishable-key>
Vite exposes environment variables prefixed with VITE_ to client-side code via import.meta.env. Any variable without that prefix is ignored by Vite and won't be available in your components.
In order for our Version Control to avoid keeping track of these secrets and not publishing them on Github or other resources we must add a .gitignore to our project telling it not to read .env.
Important: Add
.envto your.gitignorefile. Never commit API keys to version control — even public (anon) keys.
Leveraging Claude Code
At this point in your project, you have a functioning React + Vite application with an established UI and user experience. The changes ahead are entirely within the client-side codebase — no backend modifications, no database schema changes, no new tables. You're wiring up existing components to an existing API.
This is a well-defined task with a clear scope, and it's exactly the kind of work that Claude Code handles well when given the right context. You already have Claude Code running in your project. Rather than making these changes manually file by file, you're going to hand Claude Code a precise, structured prompt that gives it everything it needs to do this work correctly and safely.
Before opening Claude Code, we need to ensure we are in the correct location with the appropriate folder structure:
your-project/
├── .claude/
│ └── skills/
│ └── agents/
├── front-end/
├── supabase/
├── CLAUDE.md
├── README.md
└── ...
You'll notice there's now only one .claude directory holding all agents from front-end and supabase and all skills from both of those as well. This will give our main session the power to spawn sub-agents with all the tools they'll need to succeed.
The Prompt (in Opus/Fable)
My current front-end application is working as desired and I want to preserve the existing UI and user experience along with my supabase projects database structure. Now I would like to integrate these two projects as one (expose API endpoints and connect UI actions within the React app to the Supabase project) to create a full stack application.
I want you to use the subagents of front-end-agent and supabase-agent to communicate with one another to accomplish this task while using you as their main orchestrator for this task.
Do not change any fundamental functionality and/or data without my approval.
**DO NOT IMPLEMENT AUTHENTICATION NOR AUTHORIZATION PRINCIPLES**
Once the Sub-Agents return a completed action use both the Playwright MCP and the Supabase MCP to walk through the applications features yourself and test them out to ensure a successful integration.
What to expect from Claude Code's response:
Claude Code will not immediately start changing files. The prompt instructs it to analyze first and present a plan. You should expect:
- Architecture analysis — a summary of what components exist, which ones manage data, and what mock/local state they currently use
- Implementation plan — which files it intends to create (the service layer), which files it will modify (components), and how it plans to handle the
users/tasksrelationship - A question or clarification — if your schema has anything ambiguous (nullable foreign keys, missing constraints, naming inconsistencies), it will ask before proceeding
Review the plan before approving. If anything in the plan conflicts with your understanding of the application — a component it misidentified, a relationship it got wrong, a file it shouldn't touch — correct it in your reply before the code changes begin. This review step is the primary benefit of requiring the plan upfront.
Once you approve the plan, Claude Code will execute the changes, then deliver a summary of every modified file and any assumptions it made. Read the assumptions — they often surface decisions worth verifying.
Conclusion
Connecting our React application to Supabase represents one of the most important milestones in our development journey: transforming two independent systems into a working Full-Stack Application. We now understand how a user's interaction travels from a React component, through a dedicated API service layer, into Supabase's RESTful API, and ultimately reaches our PostgreSQL database, where information can be permanently stored and retrieved. We have also learned that successful integration requires more than simply making API requests. Our application must properly manage asynchronous operations, account for loading and error states, protect sensitive credentials, and treat the database as the source of truth. By organizing our project under a shared .claude directory and delegating specialized responsibilities to our front-end-agent and supabase-agent, we can use Claude Code as an orchestrator rather than relying on a single agent to manage every responsibility. Just as importantly, we remain responsible for reviewing implementation plans, approving meaningful changes, and verifying the completed integration through Playwright MCP and Supabase MCP. Moving forward, the applications we build will no longer be limited to temporary browser interactions. They will have the foundation necessary to manage real data, preserve user activity, and support increasingly sophisticated features, bringing us one step closer to developing complete, production-ready software.