better-convex-nuxt
v0.2.10
Published
Full-featured Convex integration for Nuxt with SSR, real-time subscriptions, authentication, and permissions
Maintainers
Readme
Better Convex Nuxt
Full-featured Convex integration for Nuxt with SSR, real-time subscriptions, authentication, and permissions.
[!NOTE] Work In Progress This module is rapidly evolving. While we are using it in our own apps, features and APIs are subject to change as we refine the best patterns for Nuxt + Convex.
Contributions and PRs to help improve the library, playground or docs are highly appreciated! 🙏
Features
- Real-time Queries - Fetch data with SSR, then upgrade to WebSocket subscriptions
- Optimistic Updates - Instant UI feedback with automatic rollback on failure
- Authentication - Better Auth integration with email/password, OAuth, and magic links
- Permissions - Role-based access control with ownership rules
- SSR Support - Server-side rendering with hydration
- Type Safety - Full TypeScript inference from your Convex schema
Quick Setup
Install the module:
pnpm add better-convex-nuxtUsage
Queries
<script setup lang="ts">
import { api } from '~/convex/_generated/api'
// Real-time subscription with SSR support
const { data: tasks, status } = await useConvexQuery(
api.tasks.list,
{ status: 'active' }
)
</script>
<template>
<ul v-if="status === 'success'">
<li v-for="task in tasks" :key="task._id">
{{ task.text }}
</li>
</ul>
</template>Mutations
<script setup lang="ts">
import { api } from '~/convex/_generated/api'
const { mutate, pending } = useConvexMutation(api.tasks.create, {
optimisticUpdate: (localStore, args) => {
updateQuery({
query: api.tasks.list,
args: {},
localQueryStore: localStore,
updater: (current) => current
? [{ _id: 'temp', text: args.text, completed: false }, ...current]
: []
})
}
})
await mutate({ text: 'Ship my app' })
</script>Authentication
<script setup lang="ts">
const { isAuthenticated, user } = useConvexAuth()
const authClient = useAuthClient()
async function handleLogin() {
await authClient.signIn.social({ provider: 'github' })
}
</script>
<template>
<div v-if="isAuthenticated">
Welcome, {{ user?.name }}!
</div>
<button v-else @click="handleLogin">
Sign in with GitHub
</button>
</template>Composables
| Composable | Description |
| -------------------------- | ---------------------------------------------------- |
| useConvexQuery | Execute queries with SSR and real-time subscriptions |
| useLazyConvexQuery | Non-blocking queries that load in background |
| useConvexMutation | Execute mutations with optimistic updates |
| useConvexAction | Execute Convex actions |
| useConvexPaginatedQuery | Paginated queries with loadMore() |
| useConvexFileUpload | Upload files to Convex storage with progress |
| useConvexStorageUrl | Get reactive URLs for stored files |
| useConvexAuth | Authentication state (user, token, isAuthenticated) |
| useConvexConnectionState | WebSocket connection status |
| useConvexCached | Read cached query data |
| useConvex | Access raw ConvexClient instance |
Components
| Component | Description |
| ------------------------- | ------------------------------------------- |
| <ConvexAuthenticated> | Renders content only when authenticated |
| <ConvexUnauthenticated> | Renders content only when not authenticated |
| <ConvexAuthLoading> | Renders content during auth state loading |
Documentation
Visit better-convex-nuxt.vercel.app for full documentation including:
Contributing
# Install dependencies
pnpm install
# Generate type stubs
pnpm dev:prepare
# Develop with the playground
pnpm dev
# Run tests
pnpm test
# Lint
pnpm lintAcknowledgements
- File upload composables inspired by nuxt-convex by @onmax
