88  88. Step 14: Extending the functionality

At this point, you have a full-stack SaaS application with:

From here, you can refine the front end (i.e. Next.js) to your liking, add features, harden security and observability to take the app into production. Ideas to grow your SaaS:

You can also use this tutorial as a framework to help you develop a brand new different application from scratch.

88.1 Project Structure

Here’s a quick overview of the main folders and what you typically edit:

├── app/                     # Next.js app routes and pages
├── components/              # Reusable React UI components
├── hooks/                   # Client logic and Supabase integration
├── supabase/
│   ├── functions/           # Edge functions (backend logic)
│   └── migrations/          # Database schema and configurations
└── tests/
    └── integration/         # Integration test suite

To extend functionality:

  • UI changes:
    Update layout, pages, and routing in app/ and shared UI in components/.

  • Client logic:
    Modify data fetching, hooks, and client-side behavior in hooks/.

  • Backend logic:
    Add or update Edge Functions in supabase/functions/ for new APIs or integrations.

  • Database changes:
    Create new migration files in supabase/migrations/ to add tables, columns, or policies.

Practice Questions

Easy

Question 1 · Matching

Match each folder with what it holds.

Folder What it holds
1. app/ A. Reusable pieces of the user interface (React components)
2. components/ B. Migration files that define the database: tables, columns and policies
3. hooks/ C. The Next.js routes and pages
4. supabase/functions/ D. The integration test suite
5. supabase/migrations/ E. Client-side logic and the code that talks to Supabase
6. tests/integration/ F. Edge functions (back-end logic)

1 → C, 2 → A, 3 → E, 4 → F, 5 → B, 6 → D.

Question 2 · Short answer

According to the start of this page, the finished app already has six capabilities. Name four of them.

Any four of: authentication and user management; a Postgres database with row level security (RLS); file storage for images; AI-powered task labeling; subscription billing with Stripe; edge functions for serverless back-end logic.

Question 3 · True or false

The code in supabase/functions/ runs in the user’s web browser.

False. That folder holds the edge functions: back-end code that runs on Supabase’s servers. The parts users see and click on are built from app/, components/ and hooks/.

Question 4 · Multiple choice

The page calls the project a “full-stack SaaS application”. What does SaaS mean?

  1. Software as a Service: software people use over the internet, usually for a subscription fee
  2. Server and Application Storage System: a kind of database
  3. Secure Authentication as a Service: a login provider such as Google
  4. Static and Simple Site: a website with no back end

a. SaaS is software that customers use online instead of installing it, usually paying a subscription - which is what the Stripe subscription in this app supports. The other three are made-up expansions.

Medium

Question 5 · Short answer

For each change below, which folder would you mainly work in?

  1. Change how the box that shows a single task looks, everywhere it appears.
  2. Add a new “Reports” page with its own web address.
  3. Store a new yes/no value for each task, reminder_sent, in the database.
  4. Add back-end code that sends emails through an email service, using a secret API key.
  1. components/ - shared pieces of the user interface.
  2. app/ - pages and routing.
  3. supabase/migrations/ - a new migration file that adds the column.
  4. supabase/functions/ - a new edge function. The email service’s API key belongs in Supabase secrets, not in the code.

Question 6 · Multiple choice

You want every task to have a new estimated_minutes column. Following the page, what is the best way to make this change?

  1. Add the column by clicking around in the Supabase Table Editor
  2. Create a new migration file in supabase/migrations/ that adds the column, then push it to the database
  3. Add the column name to .env.local
  4. Add the column inside a React component in components/

b. A migration file records the change as code that is saved in Git, so the same change can be applied the same way to every copy of the database - a teammate’s, a test project, production. (You push it with npx supabase db push, as in the database step.) A change made by clicking (a) works once but leaves no record, so other copies of the database fall out of step. .env.local (c) holds settings, not the structure of the database, and React components (d) only display data.

Question 7 · Short answer

The app’s database uses row level security (RLS). In plain English, what does RLS do in this app, and what must you remember about RLS when a migration adds a brand-new table?

RLS is a set of rules inside the database that decides, row by row, who may see or change which data. For example, each user can see and edit only their own tasks, even though everyone’s tasks are stored in the same table. A new table needs its own RLS policies (a migration can add them, as the page says). Without the right policies, users either can’t use the new table at all, or - if RLS is left switched off - may be able to see each other’s data.

Hard

Question 8 · Long answer

The page says to create new migration files. Why shouldn’t you instead edit an old migration file, such as supabase/migrations/1_init_tasks.sql, that has already been applied to your database?

The database keeps a list of the migrations it has already run. When you push (npx supabase db push), only migrations that are not yet on that list are applied. If you edit a file that already ran, it won’t run again, so your change never reaches your database - while anyone who sets up the project from scratch later gets the edited version. The copies end up different. A new migration file is applied once, in order, everywhere. (Fixing a migration that failed and was never applied, as in the database step, is a different situation.)

Question 9 · Long answer

Plan the “email notifications for due tasks” idea. Using the folders on this page, describe what you would add or change, and where. A good answer covers at least three folders.

A model answer:

  • supabase/migrations/: a new migration that adds what you need to store - for example, whether a reminder was already sent for each task, or each user’s email preferences (plus RLS policies for any new table).
  • supabase/functions/: a new edge function that finds tasks that are due and sends the emails through an email service. The service’s API key is stored as a Supabase secret, never in the code. Something must run this function regularly (a scheduled job), because no user clicks a button to start it.
  • app/ and components/: a settings option where users can turn reminders on or off.
  • hooks/: the client logic that saves the user’s choice in Supabase.
  • tests/integration/: a test that checks that due tasks get a reminder.

Question 10 · Compare

The page suggests building a mobile app with React Native or Expo. Which parts of the current system could the mobile app reuse, and which part would you have to build again?

The back end can be reused: the same Supabase project with its sign-in system, its database (with the RLS rules), its storage bucket and its edge functions, including the AI labeling. The mobile app would simply talk to the same Supabase project. What you would build again is the front end - the screens and client logic, written with React Native or Expo instead of the Next.js code in app/, components/ and hooks/.

© 2025-2026 Y. Rosenthal. All rights reserved.