Skip to main content

Architecture

Uxie uses tRPC to provide end-to-end typesafe APIs. The API is built on top of Next.js API routes and uses Prisma as the ORM layer to interact with a PostgreSQL database.

What is tRPC?

tRPC allows you to easily build & consume fully typesafe APIs without schemas or code generation. It leverages TypeScript’s inference to provide autocompletion and type safety across your entire stack.

API Routers

The Uxie API is organized into the following routers:
  • document - Document management, collaboration, and vectorization
  • user - User profile and document listing
  • highlight - Text and image highlighting within documents
  • message - Chat messages for AI conversations about documents
  • flashcard - Flashcard generation and retrieval for studying

Making API Calls

Client Setup

The tRPC client is configured in /src/lib/api.ts and uses React Query hooks for data fetching:
import { api } from "@/lib/api";

// Use the api object in your React components
function MyComponent() {
  const { data, isLoading } = api.user.getUsersDocs.useQuery();
  
  return (
    <div>
      {data?.map(doc => (
        <div key={doc.id}>{doc.title}</div>
      ))}
    </div>
  );
}

Queries vs Mutations

Queries are for reading data:
const { data } = api.document.getDocData.useQuery({ 
  docId: "123" 
});
Mutations are for creating, updating, or deleting data:
const mutation = api.document.updateTitle.useMutation();

mutation.mutate({
  docId: "123",
  title: "New Title"
});

Request Context

Every tRPC procedure has access to a context object that includes:
ctx.session
Session | null
The authenticated user’s session (null if not authenticated)
ctx.prisma
PrismaClient
The Prisma client for database operations

Session Object

When authenticated, the session includes:
{
  user: {
    id: string;
    name: string;
    email: string;
    image: string;
    plan: "FREE" | "FREE_PLUS" | "PRO";
  }
}

Error Handling

All API procedures can throw TRPCError with appropriate error codes:
const mutation = api.document.getDocData.useQuery(
  { docId: "123" },
  {
    onError: (error) => {
      if (error.data?.code === "UNAUTHORIZED") {
        console.error("Not authorized to access this document");
      }
    }
  }
);

Data Transformers

Uxie uses SuperJSON to serialize/deserialize data, which allows you to send Date objects, Sets, Maps, and more over the wire:
// Dates are automatically serialized and deserialized
const { data } = api.user.getUsersDocs.useQuery();
console.log(data[0].updatedAt instanceof Date); // true

Type Safety

Import types from your router for full type safety:
import type { RouterInputs } from "@/lib/api";

type DocumentInput = RouterInputs["document"]["getDocData"];
// { docId: string }

Next Steps

Authentication

Learn about authentication and protected procedures

Document API

Manage documents, collaborators, and vectorization

Highlight API

Add and manage highlights in documents

Flashcard API

Generate and retrieve flashcards for studying

Build docs developers (and LLMs) love