86  86. Step 12: Run the Application

As of Oct 22, 2026 · Official docs: Next.js

Now that the back end is set up, you can run the Next.js app on your own computer and try every feature. In Classes 10–12, this is (I) Try the app.

86.1 Start the Development Server

Claude starts the app by running this command in the terminal. To start it yourself, type it in VS Code’s terminal, in the task-app folder, and press Enter:

npm run dev

npm run runs a script listed in package.json, and dev is the script that starts Next.js’s development server: a web server on your own computer, at the address localhost:3000 (localhost means “this computer”, and 3000 is the port, a numbered door on your computer that the server listens at). It keeps running, and updates the page when the code changes, until you stop it: click in the terminal and press Ctrl+C (Ctrl, not Cmd, also on a Mac).

The packages must already be installed with npm install (Step 2). Then open http://localhost:3000.

86.2 Test Core Functionality

Walk through the main user flow to confirm everything is wired up correctly.

1. Sign up or sign in

  • Sign up with an email and a password, or click Login with Google.
  • Ensure you’re taken to the dashboard.
  • In the Supabase dashboard, Authentication > Users, verify your user was created.

2. Create a task

  • From the dashboard, create a new task (title and description).
  • Confirm:
    • The task appears in your list.
    • After a moment, an AI label appears.
  • Check the tasks table in the Supabase Table Editor to see the new row.

3. Attach an image

  • Open the task and attach an image.
  • Confirm:
    • The file appears in the task-attachments bucket (Supabase dashboard, Storage).
    • The image is displayed in the app.
  • Try uploading a file that isn’t an image, or one larger than 1 MB, to see the error handling.

4. Upgrade to Premium

  • Open your profile page. It shows your current plan and how many tasks you created out of your limit.
  • Click Manage Subscription. For a free user, this opens a Stripe-hosted checkout page. Check that the product and price are right.
  • Pay with the Stripe test card 4242 4242 4242 4242, any future expiration date (such as 12/34), and any three-digit CVC. No real money moves.
  • Complete checkout and return to the app.
  • Verify that your plan changed to Premium: on the profile page, and in the Supabase Table Editor, where your row in the profiles table has subscription_plan set to premium.

5. Manage the subscription

  • Click Manage Subscription again. For a premium user, it opens Stripe’s customer portal, where a subscriber can manage or cancel the subscription. Look around, then return to the app.

6. Sign out

  • On the profile page, click Sign Out.
  • Confirm:
    • You’re back on the login page.
    • Protected pages, such as the dashboard, are no longer accessible without signing in again.

86.3 If Something Fails

Tell Claude exactly what you clicked and what you saw. Claude can read the server output in the terminal, and each Edge Function’s logs are in the Supabase dashboard under Edge Functions.

If the AI label or the upgrade fails

If creating a task or upgrading fails, open the function’s logs in the Supabase dashboard (Edge Functions) and show Claude what they say. One known fix, which Claude can make with you: for an “Invalid JWT” (401) error, turn off Verify JWT with legacy secret for that function (Edge Functions > the function > Details). This is safe here: the functions check the user’s login themselves. See Step 11.

Practice Questions

Easy

Question 1 · Short answer

What does each of these two commands do?

npm install
npm run dev
  • npm install downloads all the packages the project needs (they are listed in package.json) into the node_modules folder.
  • npm run dev runs the dev script listed in package.json, which starts the Next.js development server: it runs the app on your own computer so you can use it in your browser, until you stop it with Ctrl+C.

You install the packages once, in an earlier step; after that, npm run dev is enough to start the app.

Question 2 · Short answer

Once the development server is running, which address do you usually open in your browser? What does localhost in that address mean?

http://localhost:3000. localhost means “this computer”: the app is served from your own machine, not from the internet, so only you can open it. The 3000 is the port - the numbered “door” on your computer that the app is listening at.

Question 3 · Multiple choice

You reach the Stripe checkout page while testing. What should you enter?

  1. Your own credit card - the amount is small
  2. The card number 4242 4242 4242 4242, any future expiry date and any 3-digit CVC
  3. The card number 1234 5678 9012 3456 and any past expiry date
  4. Nothing - checkout can’t be tested on localhost

b. 4242 4242 4242 4242 is a Stripe test card: with any future expiry date, any 3-digit CVC and any billing info, it simulates a successful payment, and no real money moves. Don’t use a real card for testing (a). Option c is not a test card, and the expiry date must be in the future. Option d is wrong: this page has you test checkout while the app runs locally.

Question 4 · True or false

Once you have signed in with Google and landed on the dashboard, there is nothing else to check for sign-in.

False. The page also asks you to look in the Supabase dashboard under Authentication > Users to verify that your user was created. Checking both sides - the app and the back end - confirms that the data was really saved, not just that the page looked right.

Question 5 · Short answer

The development server is running in VS Code’s terminal, and you want to stop it. What do you press? Does Maria, on a Mac, press something different?

Click in the terminal and press Ctrl+C. Maria presses Ctrl+C too: in the terminal it is Ctrl, not Cmd, also on a Mac. The server then stops, and http://localhost:3000 no longer answers until you run npm run dev again.

Medium

Question 6 · Matching

After each test action, where can you confirm in Supabase that it worked? One place on the right is not used.

Test action Where to check
1. Sign in with Google A. The tasks table
2. Create a task B. The storage bucket that holds task images
3. Upload an image to a task C. The Users list under Authentication
D. The Google Cloud Console

1 → C, 2 → A, 3 → B.

D is not part of Supabase: the Google Cloud Console is where you set up “Sign in with Google”, not where your app’s users are recorded.

Question 7 · Ordering

Put the steps for testing a subscription in the right order:

  • A. Enter the test card 4242 4242 4242 4242, a future expiry date and any 3-digit CVC
  • B. Click “Manage Subscription”
  • C. Check that your plan changed to Premium
  • D. Confirm you are on a Stripe-hosted checkout page that shows the right product and price
  • E. Complete checkout and return to the app

B → D → A → E → C.

Question 8 · Short answer

What is a protected route, and how would you check that signing out really protects it?

A protected route is a page of the app that only signed-in users may see - for example, the dashboard with your tasks. To check it: sign out, then try to open the dashboard directly by typing its address (for example http://localhost:3000/dashboard) into the browser. You should be sent back to the login page instead of seeing any tasks.

Question 9 · Short answer

Why does the page ask you to try uploading an invalid file type or a very large file on purpose?

To test the app’s error handling - what happens when things go wrong. The app should refuse the file and show a clear message, not crash or save the file anyway. Real users will sometimes pick the wrong file, so the “unhappy path” needs testing just as much as the normal one.

Question 10 · Multiple choice

Sam has just upgraded to Premium. He clicks Manage Subscription on his profile page again. What happens?

  1. He gets a second Stripe checkout page and pays again
  2. Stripe’s customer portal opens, where he can manage or cancel his subscription
  3. Nothing: the button works only for free users
  4. The app signs him out

b. The same button does two jobs: for a free user it opens Stripe’s checkout page (a), and for a premium user it opens the customer portal. It doesn’t stop working (c), and signing out (d) is the separate Sign Out button.

Hard

Question 11 · Scenario

You create a task. It shows up in your list and as a new row in the tasks table, but even after you refresh the page, no AI label ever appears. Which part of the system is the most likely problem, and what would you check?

The task was saved, so sign-in and the database work. What’s missing is the AI labeling, which the AI task-creation edge function does by calling OpenAI with OPENAI_API_KEY. Check:

  • the function’s Logs in the Supabase dashboard (Edge Functions) for an error message;
  • that the OPENAI_API_KEY secret is set in your Supabase project (npx supabase secrets list shows the names of the secrets that are set);
  • that the OpenAI key is valid and your OpenAI account has API credit.

If the logs show an “Invalid JWT” (401) error, one known fix is to turn off Verify JWT with legacy secret for that function (Edge Functions > the function > Details). That is safe here, because the function checks the user’s login itself.

Question 12 · Scenario

Checkout on Stripe’s page succeeds and you are sent back to the app, but your plan stays free. Which part of the system is responsible for recording the payment in your database? Name three things you would check.

The stripe-webhook edge function. After checkout, Stripe sends an event to that function, and the function updates the user’s subscription status in the database. If your plan doesn’t change to Premium, that event probably never arrived or was rejected. Any three of:

  • the webhook’s endpoint URL in Stripe is https://[your-project-ref].supabase.co/functions/v1/stripe-webhook (not the temporary URL from the Stripe setup step);
  • Verify JWT with legacy secret is off for stripe-webhook;
  • the Stripe event destination uses the Snapshot payload style and sends checkout.session.completed;
  • the STRIPE_WEBHOOK_SECRET stored in Supabase matches the signing secret that Stripe shows for that endpoint;
  • the function’s Logs in Supabase, and the delivery attempts listed for the endpoint in the Stripe Dashboard.

Question 13 · Long answer

You are “running the app locally”, yet signing in, saving tasks and paying all work. Explain which parts of the system run on your computer and which run somewhere else while you test at http://localhost:3000.

Only the Next.js app runs on your computer (started with npm run dev). Everything else is in the cloud:

  • Supabase - the database, the sign-in system, the storage bucket and the edge functions - runs on Supabase’s servers, in the project you created on the Supabase website;
  • Google handles the “Sign in with Google” step;
  • OpenAI suggests the task labels (called by an edge function);
  • Stripe hosts the checkout page and sends webhook events to your edge function.

So “running locally” means your computer serves the app’s pages, and those pages talk over the internet to all of these services. That’s why the app needs an internet connection and the right keys in .env.local even when it runs locally.

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