Skip to content

Commit 78d06a6

Browse files
committed
feat(stack-migration): migrate to better-auth + drizzle + cloudflare workers; convert to pnpm/turbo monorepo; standardize TypeScript, shared options/lookups, and visual maps across app; update docs and root scripts
1 parent d70fc32 commit 78d06a6

File tree

323 files changed

+60023
-33497
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

323 files changed

+60023
-33497
lines changed

.gitignore

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,14 @@
1+
dist
12
node_modules
2-
3-
# Output
4-
.output
5-
.vercel
6-
.netlify
3+
CLAUDE.md
4+
.cursor
5+
.vscode
6+
.idea
77
.wrangler
8-
/.svelte-kit
9-
/build
10-
11-
# OS
12-
.DS_Store
13-
Thumbs.db
14-
15-
# Env
8+
.svelte-kit
9+
build
10+
.dev.vars
1611
.env
17-
.env.*
18-
!.env.example
19-
!.env.test
20-
21-
# Vite
22-
vite.config.js.timestamp-*
23-
vite.config.ts.timestamp-*
24-
25-
generated/*
26-
src/generated/*
27-
.github/prompts/*
12+
.claude
13+
local-state
14+
.turbo/

CLAUDE.md

Lines changed: 127 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -4,132 +4,175 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
44

55
## Project Overview
66

7-
BottleCRM is a SaaS CRM platform built with SvelteKit, designed for startups and enterprises with role-based access control (RBAC). The application features multi-tenancy through organizations, with strict data isolation enforced at the database level.
7+
BottleCRM is a multi-tenant SaaS CRM platform built as a monorepo with SvelteKit, designed for startups and enterprises with role-based access control (RBAC). The application features organization-based multi-tenancy with strict data isolation enforced at the database level.
88

99
## Technology Stack
1010

11-
- **Frontend**: SvelteKit 2.x with Svelte 5.x
11+
- **Frontend**: SvelteKit 2.x with Svelte 5.x (TypeScript)
1212
- **Styling**: TailwindCSS 4.x
13-
- **Database**: PostgreSQL with Prisma ORM
13+
- **Database**: PostgreSQL with Drizzle ORM
14+
- **Authentication**: Better Auth with organization plugin
1415
- **Icons**: Lucide Svelte
1516
- **Validation**: Zod
16-
- **Package Manager**: pnpm
17-
- **Type Checking**: JSDoc style type annotations (no TypeScript)
17+
- **Package Manager**: pnpm (v10.0.0)
18+
- **Build Tool**: Turbo (monorepo management)
19+
- **Deployment**: Cloudflare Workers/Pages
20+
21+
## Monorepo Structure
22+
23+
```
24+
├── apps/
25+
│ ├── web/ # SvelteKit frontend application
26+
│ └── api/ # Node.js API service (optional)
27+
├── shared/
28+
│ ├── database/ # Drizzle ORM schema and migrations
29+
│ └── constants/ # Shared constants across apps
30+
└── supabase/ # Supabase configuration (if used)
31+
```
1832

1933
## Development Commands
2034

35+
### Monorepo Root Commands
2136
```bash
22-
# Development server
37+
# Install dependencies
38+
pnpm install
39+
40+
# Development (all apps)
2341
pnpm run dev
2442

25-
# Build for production
43+
# Build (all apps)
2644
pnpm run build
2745

28-
# Preview production build
29-
pnpm run preview
46+
# Web app specific
47+
pnpm run web:dev
48+
pnpm run web:build
49+
pnpm run web:preview
50+
51+
# API app specific
52+
pnpm run api:dev
53+
pnpm run api:build
54+
```
3055

56+
### Database Commands
57+
```bash
58+
# Generate SQL and types
59+
pnpm run db:generate
60+
61+
# Run migrations (local)
62+
pnpm run db:migrate:local
63+
64+
# Run migrations (production)
65+
pnpm run db:migrate:prod
66+
67+
# Generate, migrate, build in one command (local)
68+
pnpm run db:gmb:local
69+
70+
# Database studio UI
71+
pnpm run db:studio
72+
```
73+
74+
### Web App Commands (from apps/web/)
75+
```bash
3176
# Type checking
3277
pnpm run check
33-
34-
# Type checking with watch mode
3578
pnpm run check:watch
3679

37-
# Linting and formatting (both required to pass)
80+
# Linting and formatting
3881
pnpm run lint
39-
40-
# Format code
4182
pnpm run format
42-
43-
# Database operations
44-
npx prisma migrate dev
45-
npx prisma generate
46-
npx prisma studio
4783
```
4884

4985
## Architecture Overview
5086

5187
### Multi-Tenant Structure
52-
- **Organizations**: Top-level tenant containers with strict data isolation
53-
- **Users**: Can belong to multiple organizations with different roles (ADMIN/USER)
54-
- **Super Admin**: Users with @micropyramid.com email domain have platform-wide access
88+
- **Organizations**: Top-level tenant containers with complete data isolation
89+
- **Members**: Users belong to organizations with specific roles (member/admin)
90+
- **Sessions**: Track active organization via `activeOrganizationId`
91+
- **Super Admin**: Platform-wide access (determined by business logic, not email domain)
5592

5693
### Core CRM Entities
5794
- **Leads**: Initial prospects that can be converted to Accounts/Contacts/Opportunities
58-
- **Accounts**: Company/organization records
95+
- **Accounts** (`crm_account`): Company/organization records
5996
- **Contacts**: Individual people associated with accounts
60-
- **Opportunities**: Sales deals with pipeline stages
61-
- **Tasks/Events**: Activity management
62-
- **Cases**: Customer support tickets
63-
- **Products/Quotes**: Sales catalog and quotation system
97+
- **Opportunities**: Sales deals with pipeline stages and forecast categories
98+
- **Tasks/Events**: Activity management linked to various entities
99+
- **Cases**: Customer support tickets with priority and status tracking
100+
- **Products/Quotes**: Product catalog and professional quotation system
64101

65102
### Authentication & Authorization
66-
- Session-based authentication using cookies (`session`, `org`, `org_name`)
67-
- Organization selection required after login via `/org` route
68-
- Route protection in `src/hooks.server.js`:
103+
- **Better Auth**: Session-based authentication with JWT plugin support
104+
- **Organization Context**: Active organization stored in session (`activeOrganizationId`)
105+
- **Route Protection** in `apps/web/src/hooks.server.ts`:
69106
- `/app/*` routes require authentication and organization membership
70-
- `/admin/*` routes restricted to @micropyramid.com domain users
71-
- `/org` route for organization selection
107+
- `/admin/*` routes require authentication (additional checks in route logic)
108+
- `/org` route for organization selection post-login
109+
- **Database Integration**: Drizzle adapter for Better Auth tables
72110

73111
### Data Access Control
74-
- All database queries must include organization filtering
75-
- User can only access data from organizations they belong to
76-
- Prisma schema enforces relationships with `organizationId` foreign keys
112+
- All CRM queries must filter by `organizationId`
113+
- Organization membership verified through `member` table
114+
- Strict foreign key constraints enforce data integrity
115+
- Audit logging tracks all data modifications
77116

78117
### Route Structure
79118
- `(site)`: Public marketing pages
80-
- `(no-layout)`: Auth pages (login, org selection)
81-
- `(app)`: Main CRM application (requires auth + org membership)
82-
- `(admin)`: Platform administration (requires @micropyramid.com email)
119+
- `(no-layout)`: Authentication pages (login, org selection)
120+
- `(app)`: Main CRM application (requires auth + active org)
121+
- `(admin)`: Platform administration
83122

84123
### Key Files
85-
- `src/hooks.server.js`: Authentication, org membership validation, route protection
86-
- `src/lib/prisma.js`: Database client configuration
87-
- `src/lib/stores/auth.js`: Authentication state management
88-
- `prisma/schema.prisma`: Complete database schema with RBAC models
124+
- `apps/web/src/hooks.server.ts`: Authentication setup and route guards
125+
- `apps/web/src/lib/auth.ts`: Better Auth configuration
126+
- `shared/database/src/schema/`: Database schema definitions
127+
- `base.ts`: Authentication tables (user, session, organization, member)
128+
- `app.ts`: CRM-specific tables
129+
- `enums.ts`: PostgreSQL enums for type safety
130+
131+
## Environment Configuration
132+
133+
### Local Development (.dev.vars)
134+
Create `apps/web/.dev.vars` for local development:
135+
```env
136+
DATABASE_URL="postgresql://postgres:password@localhost:5432/bottlecrm?schema=public"
137+
BASE_URL="http://localhost:5173"
138+
GOOGLE_CLIENT_ID=""
139+
GOOGLE_CLIENT_SECRET=""
140+
```
141+
142+
### Production (wrangler.jsonc)
143+
Configure in `apps/web/wrangler.jsonc` under `vars` section or use Cloudflare Secrets.
144+
145+
## Database Schema Patterns
146+
147+
### Entity Conventions
148+
- Primary keys: `id` (UUID via `randomUUID()`)
149+
- Timestamps: `createdAt`, `updatedAt` with defaults
150+
- Soft deletes: `isDeleted`, `deletedAt`, `deletedById`
151+
- Organization scoping: `organizationId` foreign key
152+
- Owner tracking: `ownerId` references user
153+
154+
### Enum Usage
155+
All enums defined in `shared/database/src/schema/enums.ts`:
156+
- `leadStatus`, `leadSource`
157+
- `opportunityStage`, `opportunityType`
158+
- `taskStatus`, `taskPriority`
159+
- `caseStatus`, `quoteStatus`
160+
- Industry, rating, and other business enums
89161

90162
## Form Development
91-
- All form labels must be properly associated with form controls for accessibility
92-
- Use Zod for form validation
93-
- Follow existing patterns in `/contacts`, `/leads`, `/accounts` for consistency
94-
95-
## Coding Standards
96-
97-
### Type Safety
98-
- **NO TypeScript**: This project uses JavaScript with JSDoc style type annotations only
99-
- **JSDoc Comments**: Use JSDoc syntax for type information and documentation
100-
- **Type Checking**: Use `pnpm run check` to validate types via JSDoc annotations
101-
- **Function Parameters**: Document parameter types using JSDoc `@param` tags
102-
- **Return Types**: Document return types using JSDoc `@returns` tags
103-
104-
### JSDoc Examples
105-
```javascript
106-
/**
107-
* Updates a contact in the database
108-
* @param {string} contactId - The contact identifier
109-
* @param {Object} updateData - The data to update
110-
* @param {string} updateData.name - Contact name
111-
* @param {string} updateData.email - Contact email
112-
* @param {string} organizationId - Organization ID for data isolation
113-
* @returns {Promise<Object>} The updated contact object
114-
*/
115-
async function updateContact(contactId, updateData, organizationId) {
116-
// Implementation
117-
}
118-
119-
/**
120-
* @typedef {Object} User
121-
* @property {string} id - User ID
122-
* @property {string} email - User email
123-
* @property {string} name - User name
124-
* @property {string[]} organizationIds - Array of organization IDs
125-
*/
126-
127-
/** @type {User|null} */
128-
let currentUser = null;
129-
```
163+
- Use proper TypeScript types for form data
164+
- Implement Zod schemas for validation
165+
- Ensure all form controls have associated labels
166+
- Follow existing patterns in the codebase
167+
168+
## Testing Strategy
169+
- Run `pnpm run check` before committing
170+
- Ensure `pnpm run lint` passes
171+
- Build verification with `pnpm run build`
130172

131173
## Security Requirements
132174
- Never expose cross-organization data
133-
- Always filter queries by user's organization membership
134-
- Validate user permissions before any data operations
135-
- Use parameterized queries via Prisma to prevent SQL injection
175+
- Always include `organizationId` in queries
176+
- Validate organization membership before data access
177+
- Use Drizzle's parameterized queries
178+
- Audit sensitive operations

DEV.md

Lines changed: 63 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,68 @@
1-
# BottleCRM
1+
## BottleCRM Dev Guide
22

3-
never use $app from sveltekit. ref: https://kit.svelte.dev/docs/packaging#best-practices
3+
- Never use `$app` from SvelteKit. See: https://kit.svelte.dev/docs/packaging#best-practices
44

5-
# dev
6-
nvm use 22.13.0
7-
npx prisma generate
8-
npx prisma migrate dev
5+
### Monorepo
96

10-
for development, run both sveltkeit and wss
11-
npm run dev
12-
npm run wss
7+
- Package manager: pnpm
8+
- Workspaces:
9+
- `apps/web` (SvelteKit)
10+
- `apps/api` (Express/Node)
11+
- `shared/database` (Drizzle ORM + Drizzle Kit migrations)
1312

14-
# before comitting for deployment
15-
run `npx eslint src --ext .svelte`
16-
run `pnpm run build` to check for errors, warnings and fix.
17-
run `npx svelte-check` to check for errors and warnings to fix
13+
### Node/Tooling
1814

19-
# prod
20-
nvm use 22.13.0
21-
npx prisma generate
22-
npx prisma migrate deploy
15+
- Node: `nvm use 22.13.0`
16+
- Install: `pnpm install`
17+
18+
### Database (Drizzle)
19+
20+
- Generate SQL and types: `pnpm --filter @opensource-startup-crm/database db:generate`
21+
- Dev migrations: `pnpm --filter @opensource-startup-crm/database db:migrate:local`
22+
- Prod migrations: `pnpm --filter @opensource-startup-crm/database db:migrate:prod`
23+
- Studio: `pnpm --filter @opensource-startup-crm/database db:studio`
24+
25+
#### Drizzle workflow
26+
27+
- Edit schema in `shared/database/src/schema/*`.
28+
- Generate migration + types:
29+
- From repo root: `pnpm db:generate`
30+
- Or inside package: `pnpm --filter @opensource-startup-crm/database db:generate`
31+
- Apply migrations locally:
32+
- From root: `pnpm db:migrate:local`
33+
- Apply migrations in prod:
34+
- From root: `pnpm db:migrate:prod`
35+
- One-shot (generate + migrate + build):
36+
- Local: `pnpm --filter @opensource-startup-crm/database db:gmb:local`
37+
- Prod: `pnpm --filter @opensource-startup-crm/database db:gmb:prod`
38+
39+
Notes
40+
41+
- Drizzle config: `shared/database/drizzle.config.ts`
42+
- Migrations output: `shared/database/migrations/`
43+
- Ensure database env vars are set before running commands (wrangler `.dev.vars` or system env).
44+
45+
### Development
46+
47+
- Run Web (SvelteKit): `pnpm --filter @opensource-startup-crm/web dev`
48+
- Run API: `pnpm --filter @opensource-startup-crm/api dev`
49+
50+
Or use root scripts:
51+
52+
- Web dev: `pnpm web:dev`
53+
- Web build: `pnpm web:build`
54+
- Web preview: `pnpm web:preview`
55+
- API dev: `pnpm api:dev`
56+
- API build: `pnpm api:build`
57+
58+
### Lint/Type/Build
59+
60+
- Type check: `pnpm --filter @opensource-startup-crm/web check`
61+
- Lint: `pnpm --filter @opensource-startup-crm/web lint`
62+
- Build: `pnpm --filter @opensource-startup-crm/web build`
63+
64+
### Pre-commit checklist
65+
66+
- `pnpm -r run lint`
67+
- `pnpm -r run build`
68+
- `pnpm --filter @opensource-startup-crm/web check`

0 commit comments

Comments
 (0)