-
Notifications
You must be signed in to change notification settings - Fork 5
Getting Started
Dev with Bobby edited this page Nov 27, 2025
·
1 revision
Install via your preferred package manager:
# Bun (recommended)
bun add convex-panel --dev
# npm
npm install convex-panel --save-dev
# Yarn
yarn add convex-panel --dev
# pnpm
pnpm add convex-panel --save-devDuring installation, the package will automatically:
- Check if you're logged in to Convex
- Prompt you to run
npx convex loginif not logged in - Detect your Convex access token from
~/.convex/config.json - Add it to your project's
.envfile asCONVEX_ACCESS_TOKEN
Create a .env.local file in your project root:
NEXT_PUBLIC_CONVEX_URL="your_convex_url"
NEXT_PUBLIC_ACCESS_TOKEN="your_access_token"
NEXT_PUBLIC_DEPLOY_KEY="your_deploy_key"REACT_APP_CONVEX_URL="your_convex_url"
REACT_APP_ACCESS_TOKEN="your_access_token"
REACT_APP_DEPLOY_KEY="your_deploy_key"# Unix/macOS
cat ~/.convex/config.json
# Windows
more %USERPROFILE%\.convex\config.jsonConvex Panel supports two authentication methods:
OAuth provides a secure, user-friendly authentication flow. Requires a server endpoint for token exchange.
1. Create token exchange endpoint (app/api/convex/exchange/route.ts):
import { NextRequest, NextResponse } from 'next/server';
export async function POST(request: NextRequest) {
const { code, codeVerifier, redirectUri } = await request.json();
const body = new URLSearchParams({
client_id: process.env.CONVEX_CLIENT_ID!,
client_secret: process.env.CONVEX_CLIENT_SECRET!,
grant_type: 'authorization_code',
redirect_uri: redirectUri,
code,
...(codeVerifier && { code_verifier: codeVerifier }),
});
const tokenResponse = await fetch('https://api.convex.dev/oauth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: body.toString(),
});
const token = await tokenResponse.json();
return NextResponse.json(token);
}2. Use the component with OAuth:
<ConvexPanel
oauthConfig={{
clientId: process.env.NEXT_PUBLIC_CONVEX_CLIENT_ID!,
redirectUri: window.location.origin,
scope: 'project',
tokenExchangeUrl: '/api/convex/exchange',
}}
convex={convex}
/>For simpler setups without OAuth:
<ConvexPanel
accessToken={process.env.NEXT_PUBLIC_ACCESS_TOKEN!}
deployKey={process.env.NEXT_PUBLIC_DEPLOY_KEY!}
convex={convex}
/>"use client";
import { ConvexReactClient, ConvexProvider } from "convex/react";
import dynamic from 'next/dynamic';
const ConvexPanel = dynamic(() => import("convex-panel"), { ssr: false });
const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
export function ConvexClientProvider({ children }) {
return (
<ConvexProvider client={convex}>
{children}
<ConvexPanel
accessToken={process.env.NEXT_PUBLIC_ACCESS_TOKEN!}
convex={convex}
/>
</ConvexProvider>
);
}import { ConvexPanel } from 'convex-panel';
import { ConvexReactClient, ConvexProvider } from "convex/react";
const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL);
function App() {
return (
<ConvexProvider client={convex}>
<YourApp />
<ConvexPanel
accessToken={import.meta.env.VITE_ACCESS_TOKEN}
convex={convex}
/>
</ConvexProvider>
);
}