v0 and Next.js app security checklist (before you ship)

Updated · 2 min read

the short answer

How do I secure a Next.js app built with v0?

Every server action and route handler must check the user itself, because they are public endpoints. Keep secrets out of NEXT_PUBLIC_ variables, do not rely on middleware alone for auth, protect Supabase tables with RLS policies, and verify payment webhooks.

Server actions are public endpoints

v0 builds Next.js apps, and Next.js server actions look like ordinary functions in your components. They are not private: each one becomes an endpoint anyone can call with the right request, even if the button that uses it only shows up for admins. Every action that reads or changes data needs its own check of the session and of ownership.

'use server';
export async function deleteProject(id: string) {
  const user = await getUser();               // your auth helper
  if (!user) throw new Error('Not signed in');
  const project = await db.project.findUnique({ where: { id } });
  if (project?.ownerId !== user.id) throw new Error('Not yours');
  await db.project.delete({ where: { id } });
}

Checklist

  • Server actions and route handlers (app/api/...): session and ownership check in each one
  • Middleware: useful for redirects, not as the only auth check; check again where the data is read
  • Environment variables: anything named NEXT_PUBLIC_ ends up in the browser, so no secrets there
  • Supabase or Neon: RLS policies on every table if the browser talks to the database; service role key only on the server
  • Payments: Stripe webhook signature verified on the raw request body
  • AI routes: login, per-user rate limit, max tokens and a spending cap
  • Headers: set a Content-Security-Policy and frame protection in next.config or at Vercel

Questions

Does Vercel make my app secure?

Vercel secures the hosting. Who can call your server actions and read your data is decided by your code.

Is middleware enough to protect pages?

No. Middleware can be bypassed by bugs and does not cover every way data is fetched. Check the session where the data is read or changed as well.

Read next