mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-07-25 01:15:26 +10:00
Squashed commit of the following:
commit b2b0470a1d9267d042ec0ac66523c6635bf5b199
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Tue May 19 13:13:38 2026 +0200
chore: update .gitignore to include .vite-hooks and modify pnpm-lock.yaml for dependencies
commit d28fadb5cd8706c874e616102878b4a394ec84c1
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Tue May 19 13:08:04 2026 +0200
fix: remove timestamp conflict guard
commit c6998d9dbab19d09d3c8054feef1d2e4117555eb
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Tue May 19 12:11:51 2026 +0200
chore(release): v5.1.5
commit f33d168711804880e1f12e88d24290aae16cc258
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Tue May 19 11:58:35 2026 +0200
revert: compose.yml
commit d961e6535811a10c335525fb33a08d03e737278d
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Tue May 19 11:58:08 2026 +0200
refactor(agent): replace 'revert' terminology with 'restore' for clarity, resolves #3086
commit 17f351171be218e33f01c469d95e4164d4c8dc57
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Tue May 19 11:10:41 2026 +0200
refactor(pdf): simplify sidebar section filtering and update summary feature logic
commit d55179b9d76879e3204de185e8b53fadd0a107ed
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Tue May 19 09:53:37 2026 +0200
chore: update pnpm-lock.yaml and turbo.json
commit 7cade6980e1a04352536bd44ef773f338c4ef599
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Tue May 19 09:38:30 2026 +0200
fix(polyfill): add tested polyfill for Map Upsert methods
commit 26d175bb9c53d93225d1e907678445252c13d660
Merge: 1cf33dc6c 5b1297fa2
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Tue May 19 09:23:29 2026 +0200
Merge remote-tracking branch 'origin/main' into feat/explore-hono-orpc-migration
# Conflicts:
# packages/api/src/services/agent-url.ts
# packages/runtime-externals/package.json
commit 1cf33dc6c9d81735730ad656e16dab6501c6d6a1
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Tue May 19 09:22:12 2026 +0200
chore: preserve branch changes before main sync
commit b380a4b00fdbcdd81ff4f8ef72b330fd027ccda5
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Mon May 18 07:50:28 2026 +0200
chore: lot of fixes for monorepo migration
commit 8fcf0ec64e1c29572ebaff494338368bfcf75760
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Fri May 15 13:57:17 2026 +0200
chore: update knip version and refine web app routing with new SEO endpoints
commit 234e68086ff15610a93877354c98e2c020364533
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Fri May 15 12:10:06 2026 +0200
refactor(auth): update OAuth routes to include API prefix and remove unused schema endpoint
commit 91c84b9a8496b0ce21d71cae9f8b2a027638c9ac
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Fri May 15 11:54:29 2026 +0200
chore: update dependencies and enhance PWA metadata in web app
commit 150117d4a5a9dd6cd92c64891aad8cae90f6a7af
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Fri May 15 11:12:35 2026 +0200
docs: revise manifest-only pwa testing scope
commit 6b939a55661aec9dd8122b184e4b60a5c7325fb5
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Fri May 15 11:11:33 2026 +0200
docs: add manifest-only pwa design
commit 1422e1fc96c400948b273210a1067251087d15d4
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Fri May 15 11:05:04 2026 +0200
chore(dev): simplify server proxy config
commit bc2ff5a9f6fda41e6c40333c8f163aa23a6c5e48
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Fri May 15 11:04:50 2026 +0200
docs: add unsafe oauth redirect plan
commit 445359ebe9b96c1515bf1c4c3f73ba8a8448ec12
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Fri May 15 11:04:34 2026 +0200
feat(auth): add unsafe oauth redirect flag
commit 73fffdd24598e56b2793f7657919bc794835892e
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Fri May 15 10:55:02 2026 +0200
docs: design unsafe oauth redirect flag
commit c0066aa19c15fc8a4c8e5179ed49889c117519f4
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Fri May 15 10:22:04 2026 +0200
chore: update translation source paths
commit 9033da082418d252aafd6c2eed72f71f014be3d9
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Fri May 15 10:09:25 2026 +0200
refactor(arch): react spa + hono migration
commit 6f27936c11bda895977dc63ee550c3346d4ce24b
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Fri May 15 01:10:47 2026 +0200
docs: add docker nightly tagging design
commit ecc1fd9a88a0ee1dca2f1977dfc17f74527fe1da
Author: Amruth Pillai <im.amruth@gmail.com>
Date: Thu May 14 20:05:44 2026 +0200
feat: migrate to hono spa server
This commit is contained in:
+100
-278
@@ -1,321 +1,143 @@
|
||||
---
|
||||
title: "Project Architecture"
|
||||
description: "Understand the architecture and codebase structure of Reactive Resume"
|
||||
description: "Understand the Reactive Resume monorepo, runtime boundaries, and package ownership model"
|
||||
---
|
||||
|
||||
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 a pnpm/Turborepo monorepo. The product runs as one deployed Node.js process, while the source is split into a full-stack web app, a server adapter, and focused internal packages.
|
||||
|
||||
Internal packages are source-consumed through their `package.json` export maps. Import package subpaths, not another workspace's private `src` files.
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
## Runtime Shape
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
%% Client Side
|
||||
subgraph Client ["Client"]
|
||||
Router["TanStack Router"]
|
||||
Query["TanStack Query"]
|
||||
ORPCClient["oRPC Client"]
|
||||
PDF["@react-pdf/renderer (client-side PDF export)"]
|
||||
Browser["Browser"] --> WebRoutes["apps/web routes"]
|
||||
WebRoutes --> ORPCClient["oRPC client"]
|
||||
ORPCClient --> RPC["/api/rpc"]
|
||||
|
||||
subgraph NodeProcess["Node process"]
|
||||
Server["apps/server Hono adapter"]
|
||||
API["packages/api feature routers"]
|
||||
Auth["packages/auth"]
|
||||
MCP["packages/mcp"]
|
||||
PDFServer["@reactive-resume/pdf/server"]
|
||||
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"]
|
||||
|
||||
Router --> ORPCClient
|
||||
Query --> ORPCClient
|
||||
ORPCClient -- calls --> ORPCRouter
|
||||
ORPCRouter --> Services
|
||||
Auth --> Services
|
||||
Services --> Drizzle
|
||||
Drizzle --> Database
|
||||
Services --> Storage
|
||||
Router --> PDF
|
||||
Server --> RPC
|
||||
RPC --> API
|
||||
Server --> Auth
|
||||
Server --> MCP
|
||||
API --> PDFServer
|
||||
API --> DB["packages/db"]
|
||||
API --> Storage["File system or S3-compatible storage"]
|
||||
DB --> Postgres["PostgreSQL"]
|
||||
```
|
||||
|
||||
**Diagram:** This flow shows data and control flow between the main architectural layers of Reactive Resume.
|
||||
`apps/web` owns the TanStack Start experience. `apps/server` owns the production Hono process and mounts RPC, auth, OpenAPI, MCP, static uploads, schema JSON, and the built web app.
|
||||
|
||||
---
|
||||
|
||||
## Directory Structure
|
||||
## Workspace Map
|
||||
|
||||
### 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) - **`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>
|
||||
| Workspace | Ownership |
|
||||
| --- | --- |
|
||||
| `apps/web` | TanStack Start routes, web features, browser PDF.js preview/viewer code, PWA setup, oRPC browser client |
|
||||
| `apps/server` | Hono route composition, production HTTP adapters, MCP transport, OpenAPI/well-known handlers, static file serving, startup checks |
|
||||
| `packages/api` | oRPC procedures and feature-owned business behavior under `src/features/*` |
|
||||
| `packages/auth` | Better Auth config, auth helpers, and exported auth types |
|
||||
| `packages/db` | Drizzle client and schema; root `migrations/` stores generated migrations |
|
||||
| `packages/env` | Server environment validation and root `.env` loading |
|
||||
| `packages/schema` | Zod schemas and typed resume/page/template models |
|
||||
| `packages/resume` | Pure resume-domain helpers, including JSON Patch behavior and network icon mapping |
|
||||
| `packages/pdf` | React PDF document, template primitives, templates, font registration, and browser/server generation adapters |
|
||||
| `packages/docx` | DOCX export generation |
|
||||
| `packages/mcp` | MCP tools, prompts, resources, server card, and tool metadata |
|
||||
| `packages/ui` | Shared Base UI/shadcn-style primitives and hooks |
|
||||
| `packages/ai` | AI provider types, prompts, resume parsing/sanitization helpers, and model-facing tool contracts |
|
||||
| `packages/import` | Resume importers |
|
||||
| `packages/fonts` | Font metadata |
|
||||
| `packages/email` | Email transport and templates |
|
||||
| `packages/utils` | Narrow cross-cutting utilities with explicit export subpaths |
|
||||
| `packages/config` | Shared development configuration |
|
||||
| `tooling` | Development-only scripts and repo tooling |
|
||||
|
||||
---
|
||||
|
||||
## Key Concepts
|
||||
## Boundary Rules
|
||||
|
||||
### File-Based Routing
|
||||
- Use `@reactive-resume/*` package exports for cross-workspace imports.
|
||||
- Do not import another workspace through `apps/**`, `packages/**`, `@reactive-resume/*/src/**`, or a TypeScript path alias to another workspace's `src`.
|
||||
- Keep browser-only code in web features or explicit browser subpaths.
|
||||
- Keep server-only code in server packages or explicit server subpaths.
|
||||
- Keep environment-neutral domain packages free of DB, HTTP, DOM, and app imports.
|
||||
- Add public package exports deliberately. Wildcard exports are reserved for leaf-style public surfaces such as UI components/hooks and schema resume files.
|
||||
|
||||
Routes are automatically generated from the file structure in `src/routes/`. TanStack Router conventions:
|
||||
The checks are executable:
|
||||
|
||||
| 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: text("id").primaryKey().defaultRandom(),
|
||||
title: text("title").notNull(),
|
||||
slug: text("slug").notNull(),
|
||||
// ... more fields
|
||||
});
|
||||
```bash
|
||||
pnpm exec turbo boundaries
|
||||
pnpm exec biome check biome.json turbo.json tooling/grit/no-cross-workspace-src-imports.grit apps/web/tsconfig.json apps/*/turbo.json packages/*/turbo.json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Development Patterns
|
||||
## Feature Placement
|
||||
|
||||
### Adding a New Component
|
||||
When adding code, choose the owner by behavior:
|
||||
|
||||
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>;
|
||||
```
|
||||
| Change | Put it here |
|
||||
| --- | --- |
|
||||
| Route, loader, route-level server handler, or web workflow | `apps/web/src/routes` plus `apps/web/src/features/<domain>` |
|
||||
| API procedure or authenticated business behavior | `packages/api/src/features/<domain>` |
|
||||
| Pure resume data logic | `packages/resume` |
|
||||
| Resume schema or template list shape | `packages/schema` |
|
||||
| React PDF template/rendering behavior | `packages/pdf` |
|
||||
| PDF.js canvas/viewer UI | `apps/web/src/features/resume` |
|
||||
| DOCX export behavior | `packages/docx` |
|
||||
| MCP tool/prompt/resource behavior | `packages/mcp` |
|
||||
| Shared UI primitive/hook | `packages/ui` |
|
||||
| Cross-cutting helper | Prefer a domain package first; otherwise add an explicit `packages/utils` export |
|
||||
|
||||
---
|
||||
|
||||
## Configuration Files
|
||||
## Web Layout
|
||||
|
||||
| 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 |
|
||||
`apps/web/src/routes` stays route-owned. Route files handle URL shape, loaders, redirects, metadata, and SSR flags.
|
||||
|
||||
Domain UI and browser-heavy implementation code lives under `apps/web/src/features`. Current feature areas include resume preview/export/public pages, command palette, auth, settings, theme, locale, and user menu behavior.
|
||||
|
||||
Generic app-local components remain in `apps/web/src/components`; shared reusable primitives live in `packages/ui`.
|
||||
|
||||
Dialog runtime state is centralized in `apps/web/src/dialogs/store.ts`, while dialog schemas and renderers are registered by domain under `apps/web/src/dialogs/{auth,api-key,resume}`.
|
||||
|
||||
---
|
||||
|
||||
## Contributing Guidelines
|
||||
## API Layout
|
||||
|
||||
<Steps>
|
||||
<Step title="Fork & Clone">Fork the repository on GitHub and clone your fork locally.</Step>
|
||||
`packages/api/src/routers/index.ts` exports the top-level oRPC contract. Feature modules under `packages/api/src/features/*` own their procedure modules, services, helpers, tests, and public package exports.
|
||||
|
||||
<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>
|
||||
Avoid reintroducing technical-layer folders such as `services/` or `helpers/` at the package root. If a helper is used by one feature, keep it in that feature. If it becomes shared, name the shared capability explicitly and export it intentionally.
|
||||
|
||||
---
|
||||
|
||||
## Need Help?
|
||||
## PDF And Export Boundaries
|
||||
|
||||
<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>
|
||||
`packages/pdf` owns React PDF generation:
|
||||
|
||||
- `@reactive-resume/pdf/browser` creates browser PDF blobs.
|
||||
- `@reactive-resume/pdf/server` creates server PDF files.
|
||||
- Template code stays under `packages/pdf/src/templates`.
|
||||
|
||||
Localized section-title resolution stays in the caller because it depends on web/server locale context. PDF.js preview and viewer code stays in `apps/web/src/features/resume`, not in `packages/pdf`.
|
||||
|
||||
DOCX export generation lives in `packages/docx`.
|
||||
|
||||
---
|
||||
|
||||
## MCP Boundary
|
||||
|
||||
MCP implementation lives in `packages/mcp`. It exposes canonical unprefixed tool names such as `list_resumes`, `read_resume`, and `apply_resume_patch`.
|
||||
|
||||
The server process imports MCP from `@reactive-resume/mcp` and injects the in-process oRPC router client. It must not import MCP code from `apps/web/src`.
|
||||
|
||||
@@ -4,8 +4,8 @@ description: "Set up a local development environment for Reactive Resume"
|
||||
---
|
||||
|
||||
<Info>
|
||||
**Prerequisites**: - [Node.js](https://nodejs.org/) v20 or higher - [pnpm](https://pnpm.io/) v10.28.0 or higher
|
||||
(package manager) - [Docker](https://docs.docker.com/get-docker/) and Docker Compose - [Git](https://git-scm.com/)
|
||||
**Prerequisites**: - [Node.js](https://nodejs.org/) v24 - [pnpm](https://pnpm.io/) v11.1.2 through Corepack -
|
||||
[Docker](https://docs.docker.com/get-docker/) and Docker Compose - [Git](https://git-scm.com/)
|
||||
</Info>
|
||||
|
||||
This guide walks you through setting up Reactive Resume for local development. Whether you're contributing to the project or customizing it for your needs, these steps will get you up and running.
|
||||
@@ -18,16 +18,16 @@ This guide walks you through setting up Reactive Resume for local development. W
|
||||
<Step title="Clone the Repository">
|
||||
```bash
|
||||
git clone https://github.com/amruthpillai/reactive-resume.git
|
||||
cd Reactive-Resume
|
||||
cd reactive-resume
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Install Dependencies">
|
||||
This project uses [pnpm](https://pnpm.io/) as its package manager for its speed and efficiency.
|
||||
This project uses [pnpm](https://pnpm.io/) through Corepack.
|
||||
|
||||
```bash
|
||||
# Install pnpm if you haven't already
|
||||
npm install -g pnpm
|
||||
# Enable the package manager version from package.json
|
||||
corepack enable
|
||||
|
||||
# Install project dependencies
|
||||
pnpm install
|
||||
@@ -35,23 +35,24 @@ This guide walks you through setting up Reactive Resume for local development. W
|
||||
</Step>
|
||||
|
||||
<Step title="Start Infrastructure Services">
|
||||
Start the required services using the development-specific Docker Compose file:
|
||||
If you want to run the app directly on your machine with `pnpm dev`, start only the infrastructure services:
|
||||
|
||||
```bash
|
||||
docker compose -f compose.dev.yml up -d
|
||||
docker compose -f compose.dev.yml up -d postgres redis seaweedfs seaweedfs_create_bucket
|
||||
```
|
||||
|
||||
This starts the following infrastructure services:
|
||||
- **PostgreSQL** — Database (port 5432)
|
||||
- **Redis** — AI Agent workspace streams/state (port 6379)
|
||||
- **SeaweedFS** — S3-compatible storage (port 8333)
|
||||
- **Mailpit** — Email testing server (SMTP on port 1025, UI on port 8025)
|
||||
|
||||
<Info>
|
||||
**From v5.1.0 onwards** — PDF generation now runs entirely in the browser via `@react-pdf/renderer`, so no Browserless or Chromium container is required for development.
|
||||
</Info>
|
||||
|
||||
<Tip>
|
||||
Use `compose.dev.yml` instead of `compose.yml` for local development. The development file only includes infrastructure services with ports exposed to your host machine, while the main `compose.yml` includes the full application stack intended for production deployments.
|
||||
`compose.dev.yml` can also run the app in a development container with `docker compose -f compose.dev.yml up -d`.
|
||||
Use the service-filtered command above when you want local editor tooling and `pnpm dev` on the host.
|
||||
</Tip>
|
||||
|
||||
<Tip>
|
||||
@@ -63,7 +64,9 @@ This guide walks you through setting up Reactive Resume for local development. W
|
||||
Create a `.env` file in the project root:
|
||||
|
||||
```bash
|
||||
# Server
|
||||
# Application
|
||||
PORT=3000
|
||||
SERVER_PORT=3001
|
||||
APP_URL=http://localhost:3000
|
||||
|
||||
# Database
|
||||
@@ -82,6 +85,11 @@ This guide walks you through setting up Reactive Resume for local development. W
|
||||
# Email (Mailpit for local development)
|
||||
SMTP_HOST=localhost
|
||||
SMTP_PORT=1025
|
||||
SMTP_FROM="Reactive Resume <noreply@rxresu.me>"
|
||||
|
||||
# AI Agent workspace and saved AI providers
|
||||
REDIS_URL=redis://localhost:6379
|
||||
ENCRYPTION_SECRET=change-me-to-a-secure-agent-secret-in-production
|
||||
```
|
||||
|
||||
<Tip>
|
||||
@@ -90,11 +98,12 @@ This guide walks you through setting up Reactive Resume for local development. W
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Run Database Migrations">
|
||||
Apply the database schema:
|
||||
<Step title="Run Database Migrations If Needed">
|
||||
The server startup path runs migrations before serving traffic. To apply migrations manually without starting the app,
|
||||
export `DATABASE_URL` because Drizzle Kit reads directly from `process.env`:
|
||||
|
||||
```bash
|
||||
pnpm run db:migrate
|
||||
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/postgres" pnpm run db:migrate
|
||||
```
|
||||
</Step>
|
||||
|
||||
@@ -115,14 +124,16 @@ Here are the most commonly used scripts during development:
|
||||
|
||||
### Development
|
||||
|
||||
| Command | Description |
|
||||
| -------------------- | -------------------------------------------- |
|
||||
| `pnpm run dev` | Start the development server with hot reload |
|
||||
| `pnpm run build` | Build the application for production |
|
||||
| `pnpm run start` | Start the production server |
|
||||
| `pnpm run lint` | Run Oxlint linter and formatter |
|
||||
| `pnpm run format` | Run Oxfmt formatter |
|
||||
| `pnpm run typecheck` | Run TypeScript type checking |
|
||||
| Command | Description |
|
||||
| ------------------------------ | ----------------------------------------------------------- |
|
||||
| `pnpm dev` | Start the web and server development processes |
|
||||
| `pnpm build` | Build the production web bundle and server bundle |
|
||||
| `pnpm start` | Start the built production server |
|
||||
| `pnpm typecheck` | Run TypeScript type checking |
|
||||
| `pnpm test` | Run Vitest across workspaces |
|
||||
| `pnpm exec biome check .` | Run a non-mutating Biome check |
|
||||
| `pnpm check` | Run Biome with write/fix behavior (`--write --unsafe`) |
|
||||
| `pnpm exec turbo boundaries` | Check workspace/package boundary rules |
|
||||
|
||||
### Database
|
||||
|
||||
@@ -138,44 +149,30 @@ Here are the most commonly used scripts during development:
|
||||
| ------------------------- | -------------------------------------- |
|
||||
| `pnpm run lingui:extract` | Extract translatable strings from code |
|
||||
|
||||
### Documentation
|
||||
|
||||
| Command | Description |
|
||||
| ------------------- | ------------------------------------------ |
|
||||
| `pnpm run docs:dev` | Start the Mintlify docs development server |
|
||||
|
||||
---
|
||||
|
||||
## Understanding the Project Structure
|
||||
|
||||
Understanding the project structure will help you navigate the codebase:
|
||||
|
||||
```
|
||||
reactive-resume/
|
||||
├── src/
|
||||
│ ├── components/ # Reusable React components
|
||||
│ │ ├── ui/ # Base UI components (Button, Card, etc.)
|
||||
│ │ ├── resume/ # Resume-specific components
|
||||
│ │ └── ...
|
||||
│ ├── dialogs/ # Modal dialogs
|
||||
│ ├── hooks/ # Custom React hooks
|
||||
│ ├── integrations/ # Third-party integrations
|
||||
│ │ ├── auth/ # Better Auth integration
|
||||
│ │ ├── drizzle/ # Database schema & utilities
|
||||
│ │ └── orpc/ # API routes & services
|
||||
│ ├── routes/ # File-based routing (TanStack Router)
|
||||
│ │ ├── builder/ # Resume builder pages
|
||||
│ │ ├── dashboard/ # User dashboard
|
||||
│ │ ├── auth/ # Authentication pages
|
||||
│ │ └── ...
|
||||
│ ├── schema/ # Zod schemas for validation
|
||||
│ ├── utils/ # Utility functions
|
||||
│ └── styles/ # Global CSS styles
|
||||
├── public/ # Static assets
|
||||
├── locales/ # Translation files (.po format)
|
||||
├── migrations/ # Database migrations
|
||||
├── docs/ # Mintlify documentation
|
||||
└── data/ # Local data (fonts, uploads)
|
||||
├── apps/
|
||||
│ ├── web/ # TanStack Start routes, web features, and browser UI
|
||||
│ └── server/ # Hono production server, HTTP adapters, static serving
|
||||
├── packages/
|
||||
│ ├── api/ # oRPC features and business behavior
|
||||
│ ├── auth/ # Better Auth configuration and helpers
|
||||
│ ├── db/ # Drizzle client and schema
|
||||
│ ├── docx/ # DOCX export generation
|
||||
│ ├── mcp/ # MCP tools, prompts, resources, and metadata
|
||||
│ ├── pdf/ # React PDF rendering and PDF generation adapters
|
||||
│ ├── resume/ # Pure resume-domain helpers
|
||||
│ ├── schema/ # Zod schemas and typed models
|
||||
│ ├── ui/ # Shared Base UI/shadcn-style primitives
|
||||
│ └── ...
|
||||
├── tooling/ # Development-only scripts and repository tooling
|
||||
├── migrations/ # Generated database migrations
|
||||
├── docs/ # Documentation
|
||||
└── data/ # Local development data and uploads
|
||||
```
|
||||
|
||||
---
|
||||
@@ -194,7 +191,7 @@ This opens a web-based GUI at [https://local.drizzle.studio](https://local.drizz
|
||||
|
||||
### Making Schema Changes
|
||||
|
||||
1. Edit the schema in `src/integrations/drizzle/schema.ts`
|
||||
1. Edit the schema in `packages/db/src/schema/*`
|
||||
2. Generate a migration:
|
||||
```bash
|
||||
pnpm run db:generate
|
||||
@@ -235,7 +232,7 @@ After adding new translatable text, extract them to the locale files:
|
||||
pnpm run lingui:extract
|
||||
```
|
||||
|
||||
Translation files are located in the `locales/` directory in `.po` format.
|
||||
Translation files are located in `apps/web/locales` in `.po` format.
|
||||
|
||||
---
|
||||
|
||||
@@ -243,12 +240,14 @@ Translation files are located in the `locales/` directory in `.po` format.
|
||||
|
||||
### Linting & Formatting
|
||||
|
||||
Uses [Oxlint](https://oxlint.dev/) for linting and [Oxfmt](https://oxfmt.dev/) for formatting:
|
||||
Uses [Biome](https://biomejs.dev/) for linting, formatting, import organization, and Tailwind class sorting:
|
||||
|
||||
```bash
|
||||
# Check and auto-fix issues
|
||||
pnpm run lint:fix
|
||||
pnpm run format:fix
|
||||
# Non-mutating check
|
||||
pnpm exec biome check .
|
||||
|
||||
# Project script with write/fix behavior
|
||||
pnpm check
|
||||
```
|
||||
|
||||
### Type Checking
|
||||
@@ -260,9 +259,8 @@ pnpm run typecheck
|
||||
```
|
||||
|
||||
<Tip>
|
||||
Configure your IDE to use Oxlint for automatic linting and Oxfmt for automatic formatting on save. For VS Code,
|
||||
install the [Oxlint extension](https://marketplace.visualstudio.com/items?itemName=oxc.oxc-vscode) and configure the
|
||||
settings in `.vscode/settings.json`.
|
||||
Configure your IDE to use Biome for formatting and lint diagnostics. The repo uses tabs, double quotes, 120-column
|
||||
lines, and organized import groups.
|
||||
</Tip>
|
||||
|
||||
---
|
||||
@@ -270,9 +268,9 @@ pnpm run typecheck
|
||||
## Troubleshooting
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Port 3000 is already in use">
|
||||
Another process is using port 3000. Either stop that process or start the dev server on a different port: ```bash
|
||||
PORT=3001 pnpm run dev ```
|
||||
<Accordion title="Port 3000 or 3001 is already in use">
|
||||
The Vite web server uses `PORT` (default `3000`), and the Hono server uses `SERVER_PORT` (default `3001`).
|
||||
Either stop the conflicting process or choose alternate ports: ```bash PORT=3002 SERVER_PORT=3003 pnpm dev ```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Database connection refused">
|
||||
|
||||
Reference in New Issue
Block a user