▲Beginner
Next.js
A Next.js 14 App Router project with tacobase auth and CRUD. Includes a public home page with a drop-in auth form and a protected /dashboard route that redirects unauthenticated users.
Next.js 14App RouterReactTypeScriptCRUDAuth
What's in this example
Zero-config client
createClient() reads NEXT_PUBLIC_ env vars automatically.
Protected dashboard
Redirect to / if user is not authenticated.
useCollection hook
Filtered and sorted list tied to the current user.
CRUD
Create and delete posts directly from the dashboard.
Next.js env prefix
Client-side env vars must be prefixed with NEXT_PUBLIC_. Use .env.local so they are not committed to git.
Setup
cp .env.example .env.local
# NEXT_PUBLIC_TACOBASE_URL=https://your-app.tacobase.dev
# NEXT_PUBLIC_TACOBASE_API_KEY=tbk_...
npm install
npm run devKey files
src/lib/tacobase.ts
// src/lib/tacobase.ts
import { createClient } from '@tacobase/client'
// Zero-config: reads NEXT_PUBLIC_TACOBASE_URL and
// NEXT_PUBLIC_TACOBASE_API_KEY from env automatically
const db = createClient()
export default dbsrc/app/page.tsx
// src/app/page.tsx — public home page
'use client'
import { useAuth, AuthForm } from '@tacobase/react'
import { useRouter } from 'next/navigation'
export default function HomePage() {
const { user, loading } = useAuth()
const router = useRouter()
if (loading) return <p>Loading...</p>
if (user) {
router.push('/dashboard')
return null
}
return (
<AuthForm
providers={['google', 'github']}
onSuccess={() => router.push('/dashboard')}
/>
)
}src/app/dashboard/page.tsx
// src/app/dashboard/page.tsx — protected route
'use client'
import { useAuth, useCollection } from '@tacobase/react'
import db from '@/lib/tacobase'
export default function DashboardPage() {
const { user, loading, signOut } = useAuth()
const { data: posts } = useCollection('posts', {
filter: `author = "${user?.id}"`,
sort: '-created',
})
if (loading) return <p>Loading...</p>
if (!user) { router.push('/'); return null }
async function createPost(title: string) {
await db.collection('posts').create({ title, author: user!.id })
}
// ...
}