Files
Reactive-Resume/docs/contributing/architecture.mdx
T
Amruth Pillai 192880e416 use vite+
2026-03-18 22:03:24 +01:00

323 lines
10 KiB
Plaintext

---
title: "Project Architecture"
description: "Understand the architecture and codebase structure of Reactive Resume"
---
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.
---
## Tech Stack Overview
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>
---
## Application Architecture
```mermaid
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 Structure
### Root Level
| 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 |
### Source Code (`src/`)
<AccordionGroup>
<Accordion title="components/" icon="cube">
Reusable React components organized by category: - **`ui/`** — Base UI components (Button, Card, Dialog, etc.) -
**`resume/`** — Resume-specific components (sections, templates) - **`input/`** — Form input components
(ColorPicker, RichInput) - **`layout/`** — Layout components (Sidebar, LoadingScreen) - **`animation/`** — Animation
components (Spotlight, TextMask) - **`theme/`** — Theme management components - **`typography/`** — Font management
components
</Accordion>
<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>
</AccordionGroup>
---
## Key Concepts
### File-Based Routing
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>
### API Layer (ORPC)
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:**
```tsx
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());
```
### State Management
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 |
### Database Schema
The database schema is defined using Drizzle ORM in `src/integrations/drizzle/schema.ts`:
```tsx
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
});
```
---
## Common Development Patterns
### Adding a New Component
1. Create the component in the appropriate `src/components/` subdirectory
2. Export it from the directory's index file (if applicable)
3. Use TypeScript props interfaces for type safety
4. Follow existing patterns for consistency
```tsx
// 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>;
};
```
### Adding a New Route
1. Create a new file in `src/routes/` following TanStack Router conventions
2. The route tree auto-generates when you save
3. Use `createFileRoute` for type-safe routes
```tsx
// 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>;
}
```
### Adding an API Endpoint
1. Add the route handler in `src/integrations/orpc/router/`
2. Create service functions in `src/integrations/orpc/services/` if needed
3. The endpoint is automatically typed on the client
```tsx
// 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}!` };
}),
});
```
### Adding Translations
1. Wrap text with `t` macro or `<Trans>` component
2. Run `pnpm run lingui:extract` to update locale files
3. Edit the `.po` files in `locales/` to add translations
```tsx
import { t } from "@lingui/core/macro";
import { Trans } from "@lingui/react/macro";
// In component
const title = t`Welcome`;
<Trans>Click here to continue</Trans>;
```
---
## Configuration Files
| 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 |
---
## Contributing Guidelines
<Steps>
<Step title="Fork & Clone">Fork the repository on GitHub and clone your fork locally.</Step>
<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>
</Steps>
<Note>Make sure to read any `CONTRIBUTING.md` file in the repository for additional guidelines.</Note>
---
## Need Help?
<CardGroup cols={2}>
<Card title="GitHub Discussions" icon="comments" href="https://github.com/amruthpillai/reactive-resume/discussions">
Ask questions and discuss ideas with the community.
</Card>
<Card title="GitHub Issues" icon="bug" href="https://github.com/amruthpillai/reactive-resume/issues">
Report bugs or request features.
</Card>
</CardGroup>