NonDev Apps

Day 06 of 07

Build the results history and shareable grade links

Goal: Today you save every grade to Supabase, build a history page for users to revisit past results, and add a public share URL for each grade — the viral loop that brings new users to your product.

What to do

01

Create the grades table in Supabase

Add a database table to permanently store every grade result.

  • In Supabase → Table Editor, click Create a new table.
  • Name the table: grades
  • Turn off "Enable Row Level Security" for now.
  • Add these columns:
  • — id: uuid, default gen_random_uuid(), primary key
  • — user_id: text, NOT NULL
  • — headline: text, NOT NULL
  • — subheadline: text, NOT NULL
  • — cta: text, NOT NULL
  • — bullets: text, NOT NULL
  • — result: text, NOT NULL (stores the full Claude response)
  • — overall_score: int4, nullable (you will parse this from the result)
  • — share_slug: text, nullable, UNIQUE constraint (check "Is Unique" checkbox)
  • — created_at: timestamptz, default now(), NOT NULL
  • Click Save.
  • The share_slug column is how you will create a public URL for each grade — e.g. /grade/abc123.
  • The UNIQUE constraint on share_slug prevents two grades from getting the same share URL.
02

Save each grade to the database

Update the API route to insert a new row into the grades table after every successful grade.

  • Open Claude Code and paste: "Update the /api/grade route to: (1) After a successful Claude API response, extract the overall score by searching the result text for 'OVERALL SCORE: ' followed by a number — use: const scoreMatch = result.match(/OVERALL SCORE: (\d+)\/10/); const overallScore = scoreMatch ? parseInt(scoreMatch[1]) : null. (2) Generate a 6-character share slug: const shareSlug = Math.random().toString(36).substring(2, 8). (3) Insert a new row into the Supabase 'grades' table using the service_role client with: user_id (from the authenticated user), headline, subheadline, cta, bullets (all from the request body), result (the full Claude response text), overall_score, share_slug, created_at: new Date().toISOString(). (4) Return the existing grade result plus shareSlug in the response JSON: { result, gradesUsed, isPro, shareSlug }."
  • After Claude Code updates the route, test a grade on localhost:3000.
  • Go to Supabase → Table Editor → grades → Browse.
  • You should see a new row with all the fields filled in.
  • Check the share_slug column has a 6-character random string like "k4x8mq".
  • Check overall_score has a number (or null if the regex did not match).
  • If the row appears but overall_score is null, the regex is not matching. Paste an example result text into Claude Code and ask it to fix the regex.
03

Build the grade history page

Create a page where users can see all their past grades.

  • Open Claude Code and paste: "Create a server component page at app/history/page.tsx that: (1) Gets the authenticated user using the Supabase server client. (2) If no user, redirects to /sign-in. (3) Queries the grades table for all rows where user_id = user.id, ordered by created_at descending. (4) Renders each grade as a card showing: the headline field (truncated to 60 characters with ... if longer), the overall_score as a coloured badge (green bg for 7+, amber bg for 5–6, red bg for below 5, grey if null), and the created_at date formatted as 'Jun 26, 2026'. (5) Each card is a link to /grade/[share_slug]. (6) If no grades yet, shows: 'No grades yet. Use the grader to see your history here.' with a link back to /. (7) Add a page title 'Your grade history' and a subtitle 'Every landing page you have graded.'"
  • After Claude Code creates the page, add a link to it in your app.
  • In page.tsx (the main grading page), add a "History" link in the top nav next to the Sign Out button.
  • Test by visiting localhost:3000/history — you should see the grades you have already run.
  • Click one of the grade cards — it should try to navigate to /grade/[share_slug] (which does not exist yet — you will build that next).
04

Build the public share page

Create a publicly accessible page that shows a grade result without requiring sign-in.

  • Open Claude Code and paste: "Create a dynamic page at app/grade/[slug]/page.tsx that: (1) Gets the slug from params. (2) Queries the Supabase grades table using the anon key client (not service_role — this page is public) for a row where share_slug = slug. (3) If no row found, calls notFound(). (4) Displays the full result in the same five-card format as the main grader page. (5) At the top, shows a header: 'Grade result for:' followed by the headline in bold, and the overall_score badge. (6) At the bottom, shows a CTA box with: 'Grade your own landing page — free for your first 3 grades.' and a green button linking to /. (7) Exports generateMetadata that sets title to '[overall_score]/10 — Copy Grade for: [headline truncated]' and description to the Top priority fix from the result text. (8) This page must NOT require authentication."
  • Test by copying a share_slug from your Supabase grades table and visiting: localhost:3000/grade/[that slug].
  • Open the URL in a private browser window (not signed in) to confirm it works publicly.
  • The CTA at the bottom is the most important part — every person who sees a shared grade and clicks through is a potential subscriber.
  • The public share page is indexed by Google — good SEO content comes from your users sharing real grade results.
05

Add the share button to grade results

After every grade, show a share section with a copy link button and a pre-written tweet.

  • Open Claude Code and paste: "After the grade result cards are displayed in page.tsx, add a share section with: (1) A subtitle 'Share your result' in small grey text. (2) A 'Copy link' button that copies https://[YOUR DOMAIN]/grade/[shareSlug] to the clipboard and shows 'Copied!' for 2 seconds. Use navigator.clipboard.writeText(url). (3) A 'Post on X' button that opens in a new tab: https://twitter.com/intent/tweet?text= followed by URL-encoded text: 'I graded my landing page with Copy Grader — scored [SCORE]/10. Top fix: [TOP PRIORITY FIX]. Try it free: [URL]'. Parse the top priority fix from the result text by finding 'Top priority fix:' and taking everything after it until the end of the line. (4) Style the share section with a light grey background, rounded corners, and a subtle border."
  • Replace [YOUR DOMAIN] with your actual Vercel domain.
  • Test the copy button — note that clipboard access requires HTTPS, so test on the live Vercel URL rather than localhost.
  • Test the tweet button — it should open a Twitter compose window with the text pre-filled including the real score and real top fix.
  • The pre-written tweet with a specific score and insight is far more shareable than a generic "check this out" message.
06

Deploy and test the full sharing flow

Get history and sharing live and verify the viral loop works end-to-end.

  • Commit all changes: "Day 6: history and sharing complete". Push to GitHub.
  • Wait for Vercel to deploy, then test the full sharing flow on your live URL:
  • — Grade a page.
  • — Click "Copy link" — paste in a new browser tab to confirm the URL works.
  • — Open that URL in a private browser window (not signed in) — the result should be visible publicly.
  • — Confirm the CTA at the bottom links to your home page.
  • — Click "Post on X" — check the pre-filled tweet text includes the real score and insight.
  • Visit /history — confirm past grades appear with score badges and dates.
  • Share the updated product link with the same person from Day 2 and Day 3, or post a Day 6 update in your community.

Expected result

Every grade is saved. Users can browse their full grade history with coloured score badges. Each result has a public shareable URL. The Tweet button pre-fills with a real score and specific insight. You have a built-in growth loop.

Key takeaway

  • Every shared grade is free advertising for your product. The CTA at the bottom of every share page converts viewers into users. The tweet with a specific score ("I scored 4/10 on my headline") is shareable because it is honest and specific — not just "check this tool out".
Day 6 — Build results history and shareable grade links | 7-Day SaaS Build Challenge | NonDev Apps