Skip to content

React Quick Start

Varity Team Core Contributors Updated March 2026

Set up a React app with Vite and add Varity authentication and database.

  • Node.js 18 or later
  • npm, pnpm, or yarn
  • Python 3.8+ (for the CLI)
  1. Create a Vite project (skip if you have an existing project)

    Terminal window
    npm create vite@latest my-app -- --template react-ts
    cd my-app
    npm install
  2. Install Varity packages

    Terminal window
    npm install @varity-labs/sdk @varity-labs/ui-kit @varity-labs/types
  3. Install the CLI

    Terminal window
    pip install varitykit
  1. Set up your auth provider

    src/main.tsx
    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import { PrivyStack } from '@varity-labs/ui-kit';
    import App from './App';
    import './index.css';
    ReactDOM.createRoot(document.getElementById('root')!).render(
    <React.StrictMode>
    <PrivyStack appId={import.meta.env.VITE_VARITY_APP_ID}>
    <App />
    </PrivyStack>
    </React.StrictMode>
    );
  2. Add a login button

    src/App.tsx
    import { PrivyLoginButton, PrivyProtectedRoute, usePrivy } from '@varity-labs/ui-kit';
    function Dashboard() {
    const { user, logout } = usePrivy();
    return (
    <div>
    <h1>Welcome, {user?.email?.address?.split('@')[0]}!</h1>
    <button onClick={logout}>Log out</button>
    </div>
    );
    }
    export default function App() {
    return (
    <div>
    <h1>My App</h1>
    <PrivyLoginButton />
    <PrivyProtectedRoute>
    <Dashboard />
    </PrivyProtectedRoute>
    </div>
    );
    }
  3. Test it

    Terminal window
    npm run dev

    Click the login button. You can sign in with email, Google, Twitter, Discord, or GitHub.

  1. Define your data types

    src/types.ts
    export interface Todo {
    id?: string;
    title: string;
    completed: boolean;
    createdAt: string;
    }
  2. Create a collection helper

    src/database.ts
    import { db } from '@varity-labs/sdk';
    import type { Todo } from './types';
    export const todos = () => db.collection<Todo>('todos');
  3. Build a hook

    src/hooks.ts
    import { useState, useEffect, useCallback } from 'react';
    import { todos } from './database';
    import type { Todo } from './types';
    export function useTodos() {
    const [data, setData] = useState<Todo[]>([]);
    const [loading, setLoading] = useState(true);
    const refresh = useCallback(async () => {
    setLoading(true);
    const result = await todos().get();
    setData(result as Todo[]);
    setLoading(false);
    }, []);
    useEffect(() => { refresh(); }, [refresh]);
    const create = async (title: string) => {
    const todo: Todo = {
    id: `temp-${Date.now()}`,
    title,
    completed: false,
    createdAt: new Date().toISOString(),
    };
    setData(prev => [todo, ...prev]);
    await todos().add({ title, completed: false, createdAt: todo.createdAt });
    await refresh();
    };
    const toggle = async (id: string) => {
    const todo = data.find(t => t.id === id);
    if (!todo) return;
    setData(prev => prev.map(t => t.id === id ? { ...t, completed: !t.completed } : t));
    await todos().update(id, { completed: !todo.completed });
    };
    const remove = async (id: string) => {
    setData(prev => prev.filter(t => t.id !== id));
    await todos().delete(id);
    };
    return { data, loading, create, toggle, remove, refresh };
    }
  4. Use in a component

    src/TodoList.tsx
    import { useTodos } from './hooks';
    export function TodoList() {
    const { data: todos, loading, create, toggle, remove } = useTodos();
    if (loading) return <p>Loading...</p>;
    return (
    <div>
    <button onClick={() => create('New todo')}>Add Todo</button>
    {todos.map(todo => (
    <div key={todo.id}>
    <input
    type="checkbox"
    checked={todo.completed}
    onChange={() => toggle(todo.id!)}
    />
    <span>{todo.title}</span>
    <button onClick={() => remove(todo.id!)}>Delete</button>
    </div>
    ))}
    </div>
    );
    }
  1. Build

    Terminal window
    npm run build
  2. Deploy

    Terminal window
    varitykit app deploy

    Your app is live. Database credentials are injected automatically.

For Vite projects, use the VITE_ prefix:

.env
VITE_VARITY_APP_ID=your-app-id
VITE_PRIVY_APP_ID=your-privy-id