docs/contributing/architecture.mdx
This guide provides a comprehensive overview of Reactive Resume's architecture and codebase structure, helping you understand how different parts of the application work together.
Reactive Resume is built with a modern, type-safe stack:
<CardGroup cols={2}> <Card title="Frontend" icon="browser"> - **React 19** with TanStack Start - **TypeScript** for type safety - **Tailwind CSS** for styling - **Radix UI** for accessible components </Card> <Card title="Backend" icon="server"> - **ORPC** for type-safe RPC - **Drizzle ORM** with PostgreSQL - **Better Auth** for authentication - **Sharp** for image processing </Card> </CardGroup>flowchart TD
%% Client Side
subgraph Client ["Client"]
Router["TanStack Router"]
Query["TanStack Query"]
ORPCClient["oRPC Client"]
end
%% Server Side
subgraph Server ["Server"]
ORPCRouter["oRPC Router"]
Auth["Better Auth"]
Services["Services Layer"]
Drizzle["Drizzle ORM"]
end
Database["PostgreSQL"]
Storage["File System OR S3-Compatible Storage"]
Printer["Printer (Browserless/Chromium)"]
Router --> ORPCClient
Query --> ORPCClient
ORPCClient -- calls --> ORPCRouter
ORPCRouter --> Services
Auth --> Services
Services --> Drizzle
Drizzle --> Database
Services --> Storage
Services --> Printer
Diagram: This flow shows data and control flow between the main architectural layers of Reactive Resume.
| Directory | Purpose |
|---|---|
src/ | Main application source code |
public/ | Static assets served directly |
locales/ | Translation files (.po format) |
migrations/ | Database migration files |
docs/ | Mintlify documentation |
data/ | Local data storage (fonts, uploads) |
scripts/ | Utility scripts |
src/)<Accordion title="routes/" icon="route">
File-based routing using TanStack Router: - **`__root.tsx`** — Root layout with providers - **`_home/`** — Public
home page routes - **`auth/`** — Authentication routes (login, register, etc.) - **`dashboard/`** — User dashboard
routes - **`builder/`** — Resume builder routes (the main editor) - **`printer/`** — PDF printing route - **`api/`**
— API routes
</Accordion>
<Accordion title="integrations/" icon="plug">
Third-party service integrations: - **`auth/`** — Better Auth client configuration - **`drizzle/`** — Database
schema and utilities - **`orpc/`** — API router, client, and services - **`ai/`** — AI service integrations -
**`import/`** — Resume import utilities
</Accordion>
<Accordion title="dialogs/" icon="window-maximize">
Modal dialog components: - **`auth/`** — Authentication dialogs - **`resume/`** — Resume management dialogs -
**`api-key/`** — API key management dialogs - **`manager.tsx`** — Dialog manager component - **`store.ts`** — Dialog
state management (Zustand)
</Accordion>
<Accordion title="schema/" icon="file-code">
Zod schemas for validation: - **`resume/`** — Resume data schemas - **`icons.ts`** — Icon definitions -
**`templates.ts`** — Template definitions
</Accordion>
<Accordion title="hooks/" icon="hook">
Custom React hooks: - `use-confirm.tsx` — Confirmation dialog hook - `use-prompt.tsx` — Prompt dialog hook -
`use-mobile.tsx` — Mobile detection hook - `use-safe-context.tsx` — Safe context consumption
</Accordion>
<Accordion title="utils/" icon="wrench">
Utility functions: - `env.ts` — Environment variable validation - `locale.ts` — Locale utilities - `theme.ts` —
Theme utilities - `string.ts` — String manipulation - `file.ts` — File handling utilities
</Accordion>
Routes are automatically generated from the file structure in src/routes/. TanStack Router conventions:
| Pattern | Description | Example |
|---|---|---|
index.tsx | Index route | /dashboard |
$param.tsx | Dynamic parameter | /builder/$resumeId |
_layout/ | Layout group (prefix) | _home/ |
__root.tsx | Root layout | Wraps all routes |
<Warning>Never edit src/routeTree.gen.ts manually — it's auto-generated when you run the dev server.</Warning>
ORPC provides end-to-end type safety for API calls:
src/integrations/orpc/
├── client.ts # Client-side ORPC setup
├── router/ # API route definitions
│ ├── auth.ts # Authentication endpoints
│ ├── resume.ts # Resume CRUD operations
│ └── storage.ts # File storage operations
├── services/ # Business logic layer
└── helpers/ # Utility functions
Using the API client:
import { useQuery } from "@tanstack/react-query";
import { orpc } from "@/integrations/orpc/client";
// Type-safe API calls with TanStack Query
const { data } = useQuery(orpc.resume.findMany.queryOptions());
Reactive Resume uses a hybrid approach:
| Type | Tool | Use Case |
|---|---|---|
| Server State | TanStack Query | API data, caching, sync |
| Client State | Zustand | UI state, dialogs, preferences |
| Form State | React Hook Form | Form inputs and validation |
The database schema is defined using Drizzle ORM in src/integrations/drizzle/schema.ts:
import { pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
export const resume = pgTable("resume", {
id: uuid("id").primaryKey().defaultRandom(),
title: text("title").notNull(),
slug: text("slug").notNull(),
// ... more fields
});
src/components/ subdirectory// src/components/ui/my-component.tsx
import { cn } from "@/utils/style";
interface MyComponentProps {
title: string;
className?: string;
}
export const MyComponent = ({ title, className }: MyComponentProps) => {
return <div className={cn("p-4", className)}>{title}</div>;
};
src/routes/ following TanStack Router conventionscreateFileRoute for type-safe routes// src/routes/my-page.tsx
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/my-page")({
component: MyPage,
});
function MyPage() {
return <div>My Page Content</div>;
}
src/integrations/orpc/router/src/integrations/orpc/services/ if needed// In router file
import { z } from "zod";
import { publicProcedure, router } from "../server";
export const myRouter = router({
hello: publicProcedure.input(z.object({ name: z.string() })).handler(async ({ input }) => {
return { message: `Hello, ${input.name}!` };
}),
});
t macro or <Trans> componentpnpm run lingui:extract to update locale files.po files in locales/ to add translationsimport { t } from "@lingui/core/macro";
import { Trans } from "@lingui/react/macro";
// In component
const title = t`Welcome`;
<Trans>Click here to continue</Trans>;
| File | Purpose |
|---|---|
vite.config.ts | Vite bundler configuration |
tsconfig.json | TypeScript configuration |
.oxfmtrc.json | Formatter settings |
.oxlintrc.json | Linter settings |
drizzle.config.ts | Drizzle ORM configuration |
lingui.config.ts | Lingui i18n configuration |
components.json | shadcn/ui component configuration |
<Step title="Create a Branch">
Create a feature branch from `main`: ```bash git checkout -b feature/my-feature ```
</Step>
<Step title="Make Changes">Implement your changes following the patterns described above.</Step>
<Step title="Test Locally">
Ensure the app works correctly with your changes: ```bash pnpm run dev pnpm run lint pnpm run typecheck ```
</Step>
<Step title="Commit & Push">Write clear commit messages and push to your fork.</Step>
<Step title="Open a Pull Request">
Open a PR against the main repository with a clear description of your changes.
</Step>
<Note>Make sure to read any CONTRIBUTING.md file in the repository for additional guidelines.</Note>