Skip to main content

Project structure

See where pages, Convex functions, auth files, and settings live after the quick start.

After Protect data, the app has these files:

my-convex-app/
├── app/
│   ├── app.vue                   # header with sign-out, <NuxtPage />
│   └── pages/
│       ├── auth/
│       │   └── signin.vue        # sign-in and sign-up form
│       └── index.vue             # protected todo page
├── convex/
│   ├── _generated/               # generated by Convex; do not edit
│   ├── betterAuth/               # auth component; schema files are generated
│   ├── auth.config.ts            # lets Convex accept session tokens
│   ├── auth.ts                   # createBetterConvexAuth
│   ├── convex.config.ts          # registers the betterAuth component
│   ├── http.ts                   # /api/auth/* routes
│   ├── schema.ts                 # your tables
│   └── todos.ts                  # your queries and mutations
├── .env.example                  # committed; names only, secrets empty
├── .env.local                    # not committed; deployment, URLs, secrets
├── nuxt.config.ts
└── package.json

Keep local settings in .env.local only. Convex commands read it. Run Nuxt with --dotenv .env.local so Nuxt reads the same file. Set production values in your hosting platform, not in a file.

Where code goes

  • app/: pages and components. They call the composables and show state. Hiding a button here does not protect data.
  • convex/: functions that validate arguments, check the user, and read or write data. Put every permission check here.
  • server/: Nuxt server routes. Add one only when you need a server-side secret, a webhook, or your own HTTP API. Pages do not need a server route to call Convex. See server routes.
  • shared/: optional. Put validation schemas and types that both app/ and convex/ use here.

Add Better Auth client plugins

The browser auth client works without extra setup. Some Better Auth plugins add client methods. To type and register them, create app/convex-auth.ts:

app/convex-auth.ts
import { defineConvexAuthClient } from '@lupinum/better-convex-nuxt/better-auth/client'

export default defineConvexAuthClient({
  plugins: [],
})

The module looks for this file in the Nuxt srcDir, which is app/ in Nuxt 4. To use another path, set convex.auth.client in nuxt.config.ts. See Better Auth plugins.

Where tests go

  • Convex tests for permission checks and data rules
  • Nuxt tests for pages and route behavior
  • Browser tests for the full sign-in flow

A browser test alone does not prove that Convex rejects other users. Test the permission check in Convex too.