Documentation
Documentation
Introduction

Getting Started

Getting started
Getting StartedInstallationQuick StartProject Structure

Configuration

Configuration
ConfigurationEnvironment ConfigurationEdge ConfigDatabaseAuth SecretStripeFirebaseStorageGoogle Maps And Cloud Service AccountOAuth ProvidersEmail DeliverySentryFeature Flags

Architecture

Architecture
Architecture OverviewTech StackoRPC MiddlewareDesign Principles

Patterns

Patterns
Code Patterns & ConventionsFeature ModulesError HandlingType Safety

Database

Database
DatabaseSetupSchema DefinitionDatabase OperationsMigrationsCaching
Data Tables

API

oRPCProceduresRoutersoRPC Proxy Setup
APIsOpenAPIREST Endpoints

Auth & Access

AuthenticationConfigurationOAuth ProvidersRolesSession Management
AuthorizationUser RolesPermissions

Routing & i18n

RoutingDeclarative RoutingNavigation
InternationalizationTranslationsLocale Routing

Components & UI

ComponentsButtonsFormsNavigationDialogs
StylesTailwind CSSThemingTypography

Storage

Storage
StorageConfigurationUsageBuckets
Stripe Billing

Extra

Caching

Templates

Templates
Template GuidesCreate New FeatureCreate New PageCreate Database TableCreate oRPC RouterAdd Translations

Development

Development
DevelopmentCommandsAI AgentsBest Practices
Pulling Updates

oRPC

Type-safe API with oRPC

Overview

The project uses oRPC for end-to-end type safety between server procedures and client consumers.

Architecture

src/rpc/
├── procedures/
│   ├── routers/        # Feature routers
│   ├── root.ts         # Root router
│   └── rpc.ts          # Runtime, context, middleware, procedures
├── react.tsx           # Client provider + query utils
├── server.tsx          # Server-side query utils + hydration
├── openapi.ts          # OpenAPI document generation
└── tags.ts             # OpenAPI tags

Client Usage

Use useRpcUtils() with TanStack Query:

"use client";

import { useRpcUtils } from "@/rpc/react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";

export function TodoList({ organizationId }: { organizationId: string }) {
  const rpc = useRpcUtils();
  const queryClient = useQueryClient();

  const listQuery = useQuery(
    rpc.todos.list.queryOptions({
      input: { organizationId },
    }),
  );

  const toggleMutation = useMutation(
    rpc.todos.toggle.mutationOptions({
      onSuccess: () => {
        queryClient.invalidateQueries({ queryKey: rpc.todos.key() });
      },
    }),
  );

  return null;
}

Server Usage

Use server query utils to prefetch in Server Components:

import { getServerQueryClient, rpc } from "@/rpc/server";

export default async function Page({ organizationId }: { organizationId: string }) {
  await getServerQueryClient().prefetchQuery(
    rpc.todos.list.queryOptions({
      input: { organizationId },
    }),
  );

  return null;
}

Do not use revalidatePath for RPC cache flow. Invalidate query keys from client mutations.

Next Steps

Procedures

Routers

Middleware Architecture

On this page

Overview
Architecture
Client Usage
Server Usage
Next Steps