External APIs and Data Handling

  • Explain how web applications upload data to cloud storage
  • Differentiate between cloud file storage and cloud database storage
  • Understand what Supabase is and how to set up your own cloud storage
  • A Supabase project with a database to store stakeholder feedback
  • Updated Founder’s Toolkit where stakeholder feedback is stored in Supabase database, with ability to add/edit/delete records
  • Students have completed previous technical units working on Founder’s Toolkit

From Local Storage to Cloud Storage

Your Founder’s Toolkit has been growing with each unit. You’ve built modules for feedback collection, stakeholder tracking, and AI-powered analysis. These tools are helping you develop your business idea while at the same time, helping you understand how to adapt to your idea.

All your data currently lives in localStorage.

But there’s a limitation that becomes a problem as soon as you try to work with others or use your app outside your current GitHub codespace. 

Successful apps that serve real users need data that:

Data Persists

Users can trust you with their information

Works across Devices

People switch between browsers, computers, phones, etc.

Enables Collaboration

Business and development teams like yours need to share information 

Can  Grow and Scale

What works for 1 user must work for 1,000

This unit is your first step into cloud storage. You’ll update your Founder’s Toolkit so data stored in localStorage will now be safely stored in the cloud, and accessible from anywhere. More importantly, you’ll learn patterns that apply to other situations for storing data in the cloud.

Cloud Storage

Cloud storage can be considered in two main ways, and understanding the difference helps you make the right choice for different types of data.

For now, we will focus on database storage.

Choosing a Cloud Storage Service

There are many cloud storage options available. Here’s how the most popular ones to compare for someone starting to build their MVP.

Service

Setup Complexity

Free Tier

Pricing After Free Tier

Best For

Supabase

Simple

  • 500MB database storage
  • 1GB file storage
  • Generous API limits
  • Unlimited API requests*

$25/month

  • Startups building MVPs
  • Learning SQL
  • Apps needing auth + database

Firebase

Simple

  • 1GB file storage
  • 1GB database storage
  • Generous API limits
  • Real-time sync included
  • Pay-as-you-go ($0.18/GB storage, $0.06/GB downloads)

  • Google ecosystem
  • Real-time apps
  • Mobile apps
  • Beginners (simpler than SQL)

MongoDB Atlas

Medium

  • 512MB database storage
  • Shared cluster
  • Limited connections

$9/month (dedicated cluster)

  • NoSQL databases
  • Flexible data schemas
  • Document-based storage
  • Scaling large datasets

Amazon Web Services/ Google Cloud Platform

Complex

  • Limited (varies by service)
  • 12-month trials available
  • Often requires credit card

Variable (highly depends on usage)

  • Enterprise applications
  • Need full infrastructure control
  • Advanced scaling requirements
  • Teams with DevOps expertise

For this lesson, we’re using Supabase storage.

Why Supabase?

  • No complex setup or credit card required
  • A generous free tier that actually works for MVPs. Some “free tiers” are so limited they’re essentially just trials. As of January 22, 2026 Supabase gives you 1GB of storage and unlimited API requests per month for free.  That’s enough to build, test, and even soft-launch your MVP without worrying about surprise bills. As your startup grows, Supabase offers options that scale with your needs.
  • One platform for your entire backend storage
  • Supabase isn’t just for MVPs. Today, companies with millions of users run on Supabase, so your skills here will be directly transferable beyond.  

You’ll need to create a Supabase account and project and get an API key, similar to Google AI Studio and Hugging Face. The concepts are the same: You’re setting up access to an external service that your app will communicate with.

The difference is that Supabase will become a more central part of your infrastructure. While Gemini handles one specific task, which is the aII analysis, Supabase can handle your storage, database, and potentially user authentication. It’s basically setting the entire foundation for your app.

Security

It is important to consider security when creating and using cloud storage. Supabase allows you to set up levels of security for different roles in your app. At a basic level, turning on RLS (Row Level Security) is like locking the front door. Without it, your database is an open book. Once locked, we have to create specific ‘digital keys’ for different groups. For our Founder’s Toolkit, we want to let stakeholders to enter their own feedback directly. But we don’t want to give them (and anyone who opens our app) the ability to view, edit, or delete records in the database. But we do need team members to have full access. So we will set up 2 levels of permissions for our database. 

We are implementing two distinct roles:

  • Stakeholders (Anonymous): Public access to Insert records. They can contribute, but they cannot change history.
  • The Team (Authenticated): Secure access via email and password. This ‘Admin’ level grants full power to Create, Read, Update, and Delete (CRUD) records to keep the toolkit organized.
ACTIVITY 1

Create Your Supabase Account and Project

Estimated Time: 15 minutes

You will create a Supabase account and project, set up your Stakeholders table, and get an API key to access the table from your app.

  1. Go to supabase.com to create an account
  2. Click to sign up. We recommend signing up with your GitHub account to keep things organized.
  1. Once signed up, click to create a New Project .
  2. Enter your project name.
  3. Create a strong password or click “generate a password to create one automatically”.
  4. Store this password in a safe place as you will need it for direct database access.
  5. Select your organization (the free version may only allow one organization and will show you a default organization).
  6. Select a Region that’s closest to you and your users. This affects performance since data stored closer to them will load faster.
  7. Under Security Options:
    • Keep the default  “Data API + Connection String” because it gives you more flexibility and simplicity when using their API or connecting directly to the database
    • Keep the default  “Use public schema for Data API”. This is a standard setup that works for most apps.  The “dedicated API schema” option is for advanced security needs that you do not need right now.
  8. Click to create a new project and wait for it to complete (1-2 minutes)
supabase new project interface

We are going to create a table in our database for our stakeholder feedback.

  1. Under Build out your database, click the Table Editor button.
  2. Click Create a table.
  3. Name the table Stakeholders, and give it a description.
  4. Supabase starts the table with an id and a timestamp, called created_at. Keep those columns as it is useful to have an id for each row in the table, and could be helpful to know when those rows are added to the table.
  5. What else do we need to add? Look back at your Stakeholder Tracker tab in your Founder’s Toolkit. The form includes, name, type, and key feedback. Add those 3 columns, and set the type to text.
  6. Click to save the table.
  1. In the Table Editor, click on the 3 dots next to your Stakeholder table and click on View Policies.
getting to policies in supabase
  1. RLS should be enabled. If it isn’t, Enable RLS (Row Level Security). This allows you to set exactly who has access to tables in your database and app. 
  2. Click Create Policy to configure a RLS policy for your team.
  3. In the next window, 
    1. Type Team Access for Policy Name. 
    2. Select ALL for Policy Command.
    3. For Target Roles, in the dropdown, choose authenticated.
    4. After using, type true.
    5. After with check, type true.
    6. Click Save Policy.

This allows authenticated users (the team) full read/write/delete access to the table. 

setting supabase rls policy
  1. Add another policy (Create Policy again), this time for the Stakeholders.
    This will allow stakeholders to directly add feedback through the app. This time:

    1. Type Stakeholder Access for Policy Name. 
    2. Select INSERT for Policy Command.
    3. For Target Roles, in the dropdown, choose anon.
    4. After using, type true
    5. After with check, type true.
    6. Click Save Policy.
stakeholder access in supabase

You now need to add authenticated users to your database. This could be your entire team, but for now, just add yourself as a user so you can run and test the app.

  1. On the left side of the screen, under Authentication, click on Users.
  2. Click Add user.
  3. Type your email address, a password that you will remember (or save somewhere), leave Auto Confirm checked, and click Create user.

Currently, our Founder’s Toolkit stores everything in local storage. We could start fresh with our Supabase database, but since we already have significant stakeholder feedback from previous executions of the Toolkit, let’s move the data we already have into our Stakeholders table on Supabase. We could do this manually, by copying and pasting, and we could even ask a LLM to do the work for us.

But, since our data is in JSON, we can use the SQL editor on Supabase to insert the records to the table, using SQL. SQL, or Structured Query Language, is a domain-specific language used to manage data, especially in a relational database management system.

ACTIVITY 2

Move LocalStorage to Cloud Storage

Estimated Time: 15 minutes

You will extract your stakeholder information from local storage in the browser and then import it into your Supabase table.

  1. Go back to your Codespace and spin up your Founder’s Toolkit. 
  2. Open the Developer Tools in the browser, and click on Application in the developer tools window to view the localStorage. 
  3. Find your stakeholder feedback information in the localStorage, and right click on the first JSON line. You will see a popup menu where you can Copy Value. 
  4. Open a text editor (TextEdit or Notepad) and paste the JSON into a blank document.
  5. View the file and note the names of each key is in the JSON, as it may differ slightly from columns in the Supabase table.

This is our sample JSON below

				
					[
  {
    "name": "Jill Stein",
    "type": "interview",
    "feedback": "She is a teacher and knows many students this is a problem for. She thinks bringing in the parents and family to give them some education on the issue is helpful. Also bringing in the school admin to see how they can support. Also, many students do not have good internet access, especially in rural areas.",
    "timestamp": "2026-01-14T03:47:10.531Z"
  },
  {
    "name": "Phil Green",
    "type": "email",
    "feedback": "He is a student and has this issue. He does not have good internet access and he does not have transportation to get to a library either. He would need a way to get access during the school day or a means to access it otherwise. ",
    "timestamp": "2026-01-14T03:48:13.193Z"
  },
  {
    "name": "Billy Bob",
    "type": "interview",
    "feedback": "I absolutely love this idea. We need it!",
    "timestamp": "2026-01-16T01:43:12.027Z"
  },
  {
    "name": "Anna Banana",
    "type": "email",
    "feedback": "This is really a bad idea. I don't like it.",
    "timestamp": "2026-01-16T01:46:33.361Z"
  },
  {
    "name": "Millicent Penny",
    "type": "interview",
    "feedback": "I Love it! Best idea ever.",
    "timestamp": "2026-01-16T01:50:46.785Z"
  },
  {
    "name": "Fred Flintston",
    "type": "interview",
    "feedback": "This is probably the worst idea I have ever heard. Do not like it.",
    "timestamp": "2026-01-16T01:52:06.319Z"
  },
  {
    "name": "Betty White",
    "type": "email",
    "feedback": "Do not do it. It is a bad idea.",
    "timestamp": "2026-01-16T01:53:19.377Z"
  },
  {
    "name": "Mary Contrary",
    "type": "email",
    "feedback": "This is absolutely the most amazing idea I have ever heard. I absolutely love it.",
    "sentiment": "positive",
    "timestamp": "2026-01-16T02:05:42.541Z"
  }
]

				
			
  1. Open your Supabase project, and in the icon menu on the left, click on SQL Editor. 
  2. Paste the following code into the SQL Editor.
				
					INSERT INTO "Stakeholders" (name, type, feedback, created_at)
SELECT 
  value->>'name',
  value->>'type',
  value->>'feedback',
  (value->>'timestamp')::timestamp
FROM json_array_elements('YOUR JSON HERE'::json) AS value;
				
			
  1. Look at the code to understand  how it works.
    The first INSERT INTO line specifies that you want to insert data into the Stakeholders table, specifically into these 4 columns.
    Edit this line to match the table and column names of your Supabase table
    exactly. 
  2. The SELECT line specifies what fields/keys you want to extract from your JSON.
    Edit to change any of the fields listed to match exactly the keys in your JSON. 
    • value->>’name’ means “get the ‘name’ field from the JSON”
    • ::timestamp means “convert the string to a timestamp format”
  3. The FROM line specifies that the JSON array is a set of rows you want to loop through. Each record or row is called value. Paste your JSON in between the quotes ‘ ‘ in the FROM line. 
  4. Click the Run button to run the SQL command. 
  5. If you get any errors, see if you can debug the problem, or get assistance from a LLM. Otherwise, you should see a Success message. 
  6. Go back to the Table Editor. You should see your records added to the table.
ACTIVITY 3

Update Founder’s Toolkit to Store to the Cloud

Estimated Time: 15 minutes

You’ll now add insert capabilities for stakeholders to add feedback themselves, and read/write/delete access to the Stakeholder database for team members.

Since we will be making many changes in the code, we suggest following the full Git workflow from the previous units. 

  1. Go to GitHub and open your Founder’s Toolkit repository
  2. Create a new branch from main and name it supabase-cloud-storage
  3. Open your previous Codespace and checkout the new branch there.
  4. Wait for the environment to load.

You will need your Supabase Project URL and publishable key, which is essentially your API to your database. 

  1. In Supabase, click on the home gear icon on the left to access the project settings. 
  2. Click on Data API to find the Project URL. 
  3. Click on API Keys on the left, and you will find your publishable key there.
  4. In Codespaces, open  your “.env” file and add these 2 lines:

SUPABASE_URL=YOUR_SUPABASE_PROJECT_URL
SUPABASE_ANON_KEY=YOUR_SUPABASE_PUBLISHABLE_KEY

  1. Copy/paste the text above and replace with your project URL and publishable key from Supabase.

We will do this in a few steps, as there is a lot involved here, so adding a bit at a time helps with debugging and issues that arise.

Start with a prompt like the following:

Update the Stakeholder Tracker tab to do the following.

  • Remove display of table of stakeholders and just leave the form.
  • Instead of saving information to local storage, it will now be saved on Supabase. Table name is Stakeholders. Use anonymous role.
  • .env file already includes SUPABASE_URL and SUPABASE_ANON_KEY. 
  • Make sure to update Content Security Policy to allow Supabase endpoints.
  • Insert for anonymous users should not try to read the data back after the insert, as that will fail because they only have INSERT permissions.
  • Provide a success message when record has been added to Supabase.
  1. Follow any installation instructions Copilot gives you to install packages.

  2. Run the app and try adding a new stakeholder with some feedback. You should receive a confirmation message that you succeeded.
  3. Go to your Table Editor on Supabase and see if the table updated with the new record. You may have to refresh the browser to see the new record.
  4. Troubleshoot with the help of LLMs to ensure the app works correctly.
  1. Ask Copilot to add the ability to login as an administrator, to be able to view all the Stakeholder records.

    This is a sample prompt:

  • Add “Admin Login” button to the Stakeholder Tracker screen.
  • Show email/password form.
  • Use Supabase auth.signIn() to authenticate user.
  • If logged in, display the stakeholder table on the screen, below the form.
  • Also display a logout button for users logged in.
  • If not logged in, just show the form, not the table.
  1. Run your app again and log in as admin, using the email/password you set up in Supabase. Once you log in, you should be able to see the Stakeholder table in the Stakeholder Tracker tab. 
  2. Log out. Table should not appear.
  3. Troubleshoot with the help of LLMs to ensure the app works correctly.
  1. Ask Copilot to add edit and delete capabilities for admin users who are logged in.

    This is a sample prompt:

For admin users only, add edit and delete buttons for each row of the stakeholder table.
Those buttons should work for editing and deleting those rows in the Supabase table.

  1. Run the app again. Try adding, editing, and deleting a record and check that the table in Supabase updates correctly.
  2. Log out and check that you can still add a record, but nothing more.
  3. Troubleshoot with the help of LLMs to ensure the app works correctly.

In addition to the stakeholder data being safe and secure, storing the data in the cloud means that the data is accessible to your app users, wherever they may be. This can open up possibilities, like having stakeholders add their own feedback directly, and multiple team members accessing the data from their phones. 

This is the real power of cloud storage. To test it while your app is still in development in Codespaces, can do the following.

  1. Start your app in Codespaces by typing npm start.
  2. Find the Ports tab in the bottom panel, next to Terminal.
  3. You should see your running port (e.g. 3000).
  4. Right-click on the port, go to Port Visibility, and select Public. The Visibility will change to Public in the window.
changing port visibility
  1. Right-click again on the port, and click Copy Local Address. This is the app URL.
  2. Paste the URL somewhere where you can access it from your phone. You should see your app running there. Test adding a new stakeholder, logging in as admin, etc. 
  3. Once you have properly tested, make sure to set your Port Visibility back to Private, or just stop your app. Otherwise, your app is wide-open and unsecured.

Once you are satisfied that your Stakeholder Tracker works to store, update, and delete records on Supabase, and it works on more than one device, it’s time to commit and push.

But first, open your .gitignore file and make sure it contains the .env file because, as you learned before, this prevents your Supabase credentials from being committed to GitHub and they remain safe and secure.

  1. Once you are satisfied and verified everything works, commit and push your changes to Github, either using the Source Control feature in Codespaces, or typing the git commands in a terminal window.
  2. Go to GIthub and merge the pull request, and delete the branch.

Reflection

You have moved your locally stored stakeholder feedback to the cloud, where it is now available to users of the app. Cloud storage is a common feature of most apps, and knowing how to implement it is important.

Sunset and reflection over lake
01

Migration
What was harder than expected when migrating data? What was easier?
02

Possibilities
How does cloud storage change what's possible for your MVP and for your users?
03

Planning
Looking ahead, who needs what level of access for your product? Who can add data? Who can see everything?

Key Terms

  • Cloud File Storage: Storing files (PDFs, images, documents) on remote servers that can be accessed via the internet from any device.
  • Cloud Database: Storing structured data (rows and columns) on remote servers
  • Supabase: A platform that provides storage, database, and authentication services with a generous free tier, designed for startups and MVPs.
  • Persistence: Data that remains saved even after closing the browser, restarting the device, or switching devices
  • CRUD Operations: The four basic functions of data storage:

    • Create – Add new records (INSERT)
    • Read – Retrieve and display data (SELECT)
    • Update – Modify existing records (UPDATE)
    • Delete – Remove records (DELETE)
  • SQL (Structured Query Language): Programming language used to manage and query relational databases
  • Row Level Security (RLS) – Security feature that controls which users can access which rows in a database table

Additional Resources