L26 · Publish · 6 min

Security basics for app builders

In one sentence

Every Server Action and Route Handler in your app is a public door on the internet, so your server must verify who is signed in, validate every input with a schema, use parameterized database queries, apply rate limits, and never expose secret keys with the NEXT_PUBLIC_ prefix.

Think of it like this

Hiding a staff-only button on a website is like putting a “Staff Only” sign on an unlocked back door. Real security means locking the door itself and checking the badge of everyone who turns the handle, even if they walked around from the alley.

How it works

In Next.js, any Server Action or Route Handler on your DefinitionbackendThe part of an app that runs on a server: it keeps data, checks logins and talks to other services.Open in the glossary → can be called directly over the internet—not just by clicking your DefinitionfrontendThe part of an app that runs in the visitor's browser: what people see and click.Open in the glossary → form. That's why every server endpoint follows the same three-step order before touching your DefinitiondatabaseWhere your app remembers things between visits, like accounts or saved recipes.Open in the glossary →: (1) check the Better Auth session and confirm the user has permission for that record, (2) validate the incoming data against a strict schema (such as Zod: right type, length and format), and (3) run a parameterized query so user text is always treated as data, never as SQL commands.

Keep every DefinitionsecretAnything that opens your accounts: API keys, passwords, tokens. Kept only in Vercel and `.env.local`.Open in the glossary → on the server. Any Definitionenvironment variableA named slot, like `TOKENTIDE_API_KEY`, that holds a setting or secret outside your code.Open in the glossary → whose name starts with NEXT_PUBLIC_ is bundled into the code sent to every visitor's browser—so an DefinitionAPI keyA password your app uses with another service. Whoever has it can spend your money.Open in the glossary →, database address or auth secret must never use NEXT_PUBLIC_. Local development also uses its own Neon development branch, never the DefinitionProductionThe live version of your app, the one everyone sees. It comes from `main`.Open in the glossary → database.

Protect expensive or sensitive doors with a Definitionrate limitA cap on how often something can be done, like sign-in attempts per minute, to stop abuse.Open in the glossary →: cap how many times per minute someone can attempt to sign in, submit a form, or call an AI DefinitionmodelThe AI system that produces answers, like the one behind your coding agent.Open in the glossary →. When your app sends text to an AI provider, leave out or redact personal data unless the feature genuinely requires it, and always validate and escape the model's reply before displaying it.

Finally, your agent adds strict security headers (including a Content Security Policy, or CSP, and tight CORS rules) so browsers block injected scripts and unauthorized sites from impersonating your app. You can check the full checklist on the Quality & security page.

1 · Who & how oftenSession + rate limitChecks the Better Auth session, user permissions, and rate limit before running.
2 · What came inSchema validationVerifies types, lengths and allowed values; rejects malformed input cleanly.
3 · Safe storageParameterized queryTouches the database with parameterized queries and server-only secrets.
FIG. 1 · Every Server Action and Route Handler checks who is calling, validates the input, and only then touches the database.

What it looks like in your project

Whenever your agent writes code touching logins, forms, the database or secrets, it follows the security-and-hardening skill. Before you merge a pull request, you can ask your agent to run a security review across every endpoint and environment variable.

Copy for your agent

Run a security review of my project using the security-and-hardening skill: check that every Server Action and Route Handler verifies the session and validates input with a schema, that all queries are parameterized, that rate limits are in place, and that nothing secret uses NEXT_PUBLIC_.

Quick check · 1 question

What happens if you name an environment variable `NEXT_PUBLIC_TOKENTIDE_API_KEY`?

Go deeper

Next lessonResponsive and accessible from the start

Last reviewed Nov 8, 2026