|
| 1 | +# Project Brief: Fullstack Next.js + Cloudflare CRM |
| 2 | + |
| 3 | +**Created**: 2025-11-08 |
| 4 | +**Status**: Ready for Planning |
| 5 | +**Purpose**: Learning exercise to understand Next.js 15 + Cloudflare Workers integration |
| 6 | + |
| 7 | +--- |
| 8 | + |
| 9 | +## Vision |
| 10 | + |
| 11 | +A lightweight CRM built on the fullstack-next-cloudflare template to learn modern fullstack patterns: Next.js App Router, Cloudflare D1/R2, Server Actions, and module-sliced architecture. |
| 12 | + |
| 13 | +--- |
| 14 | + |
| 15 | +## Problem/Opportunity |
| 16 | + |
| 17 | +**Learning objective**: Understand how to build production-grade features on Cloudflare's edge platform by implementing real-world CRM functionality. |
| 18 | + |
| 19 | +**Why CRM as the learning vehicle**: |
| 20 | +- Multi-entity relationships (contacts ↔ deals) |
| 21 | +- CRUD operations with validation |
| 22 | +- Data modeling with foreign keys |
| 23 | +- UI patterns (lists, forms, boards) |
| 24 | +- Follows existing architecture (todos module) |
| 25 | + |
| 26 | +--- |
| 27 | + |
| 28 | +## Target Audience |
| 29 | + |
| 30 | +- **Primary user**: You (Jez) - exploring the stack |
| 31 | +- **Scale**: Single user for learning (no multi-tenancy needed) |
| 32 | +- **Context**: Educational project, not production SaaS |
| 33 | +- **Data**: Can use synthetic/test data |
| 34 | + |
| 35 | +--- |
| 36 | + |
| 37 | +## Core Functionality (MVP) |
| 38 | + |
| 39 | +### 1. Contacts Module |
| 40 | +**Essential**: |
| 41 | +- ✅ Create, read, update, delete contacts |
| 42 | +- ✅ Fields: firstName, lastName, email, phone, company, jobTitle, notes |
| 43 | +- ✅ Search/filter by name, email, company |
| 44 | +- ✅ Tag system (many-to-many: contacts ↔ tags) |
| 45 | +- ✅ User-specific tags with colors |
| 46 | + |
| 47 | +**Deferred to Phase 2** (keep MVP lean): |
| 48 | +- ❌ Activity timeline (calls, meetings, notes) |
| 49 | +- ❌ Avatar uploads to R2 |
| 50 | +- ❌ Email integration |
| 51 | +- ❌ Import/export |
| 52 | + |
| 53 | +### 2. Deals/Pipeline Module |
| 54 | +**Essential**: |
| 55 | +- ✅ Create, read, update, delete deals |
| 56 | +- ✅ Fields: title, value, currency, stage, expectedCloseDate, description |
| 57 | +- ✅ Link deal to contact (simple 1:1 relationship) |
| 58 | +- ✅ Pipeline board view (simple columns by stage) |
| 59 | +- ✅ Fixed stages: Prospecting → Qualification → Proposal → Negotiation → Closed Won/Lost |
| 60 | + |
| 61 | +**Deferred to Phase 2**: |
| 62 | +- ❌ Custom user-defined stages |
| 63 | +- ❌ Drag-and-drop stage changes |
| 64 | +- ❌ Deal probability/forecasting |
| 65 | +- ❌ Multiple contacts per deal |
| 66 | + |
| 67 | +### 3. Dashboard Integration |
| 68 | +**Essential**: |
| 69 | +- ✅ Add navigation to /dashboard/contacts and /dashboard/deals |
| 70 | +- ✅ Simple metrics cards (total contacts, active deals, pipeline value) |
| 71 | + |
| 72 | +**Deferred**: |
| 73 | +- ❌ Charts/graphs |
| 74 | +- ❌ Activity feed |
| 75 | +- ❌ Advanced analytics |
| 76 | + |
| 77 | +--- |
| 78 | + |
| 79 | +## Tech Stack (Validated) |
| 80 | + |
| 81 | +Uses existing template stack - no changes needed: |
| 82 | + |
| 83 | +- **Frontend**: Next.js 15.4.6 (App Router) + React 19 + TypeScript |
| 84 | +- **UI**: Tailwind v4 + shadcn/ui + Lucide icons |
| 85 | +- **Backend**: Cloudflare Workers with Static Assets (@opennextjs/cloudflare) |
| 86 | +- **Database**: Cloudflare D1 (SQLite) with Drizzle ORM |
| 87 | +- **Storage**: Cloudflare R2 (not using for MVP - deferred avatars) |
| 88 | +- **Auth**: Better Auth (already configured) |
| 89 | +- **Forms**: React Hook Form + Zod validation |
| 90 | +- **Deployment**: Cloudflare Workers (via GitHub Actions) |
| 91 | + |
| 92 | +**Why this stack works for learning**: |
| 93 | +- ✅ Modern patterns (Server Actions, RSC) |
| 94 | +- ✅ Edge-first architecture |
| 95 | +- ✅ Type-safe end-to-end (TypeScript + Drizzle + Zod) |
| 96 | +- ✅ Template already has auth, DB, migrations configured |
| 97 | +- ✅ Follows module-sliced pattern (easy to extend) |
| 98 | + |
| 99 | +--- |
| 100 | + |
| 101 | +## Research Findings |
| 102 | + |
| 103 | +### Existing Template Analysis |
| 104 | + |
| 105 | +**What's already built** (from /home/jez/Documents/fullstack-next-cloudflare-demo): |
| 106 | +- ✅ **Auth module**: Better Auth with email/password + Google OAuth |
| 107 | +- ✅ **Todos module**: Complete CRUD example with categories, priorities, status |
| 108 | +- ✅ **Database setup**: D1 + Drizzle + migrations working |
| 109 | +- ✅ **R2 integration**: Image upload pattern (in todos for cover images) |
| 110 | +- ✅ **Module architecture**: `src/modules/[feature]/` with actions/, components/, schemas/ |
| 111 | +- ✅ **UI components**: 13 shadcn/ui components configured |
| 112 | +- ✅ **Deployment**: GitHub Actions workflow ready |
| 113 | + |
| 114 | +**Pattern to follow**: |
| 115 | +The `src/modules/todos/` structure is the perfect blueprint: |
| 116 | +``` |
| 117 | +todos/ |
| 118 | +├── actions/ # Server actions (create, get, update, delete) |
| 119 | +├── components/ # UI components (form, card, list) |
| 120 | +├── models/ # Enums and types |
| 121 | +└── schemas/ # Drizzle + Zod schemas |
| 122 | +``` |
| 123 | + |
| 124 | +We'll replicate this for `contacts/` and `deals/` modules. |
| 125 | + |
| 126 | +### Technical Validation |
| 127 | + |
| 128 | +**✅ D1 Relational Data**: |
| 129 | +- Drizzle ORM supports foreign keys and joins |
| 130 | +- Template already has `todos → categories` relationship |
| 131 | +- Contacts ↔ Deals will work the same way |
| 132 | + |
| 133 | +**✅ Many-to-Many Tags**: |
| 134 | +- Need junction table: `contacts_to_tags` |
| 135 | +- Drizzle example in their docs: https://orm.drizzle.team/docs/rqb#many-to-many |
| 136 | + |
| 137 | +**✅ Server Actions Performance**: |
| 138 | +- Template uses server actions for all mutations |
| 139 | +- Edge runtime = fast globally |
| 140 | +- No API route boilerplate needed |
| 141 | + |
| 142 | +**Known Challenges**: |
| 143 | +1. **Junction table queries** - Drizzle syntax for many-to-many can be verbose |
| 144 | + - Mitigation: Study existing `todos.categoryId` pattern, extend to junction table |
| 145 | +2. **Pipeline board UI** - Kanban layout without drag-drop library |
| 146 | + - Mitigation: Simple CSS Grid columns, manual stage update dropdown (defer drag-drop to Phase 2) |
| 147 | +3. **Search implementation** - D1 doesn't have full-text search |
| 148 | + - Mitigation: Use SQL `LIKE` queries for MVP (good enough for learning) |
| 149 | + |
| 150 | +--- |
| 151 | + |
| 152 | +## Scope Validation |
| 153 | + |
| 154 | +### Why Build This? |
| 155 | +**Learning objectives met**: |
| 156 | +- ✅ Practice module-sliced architecture |
| 157 | +- ✅ Understand Drizzle ORM relationships (1:1, many-to-many) |
| 158 | +- ✅ Learn Server Actions data mutation patterns |
| 159 | +- ✅ Explore D1 migrations workflow |
| 160 | +- ✅ Build complex forms with validation |
| 161 | +- ✅ Create dashboard visualizations |
| 162 | +- ✅ Deploy to Cloudflare edge |
| 163 | + |
| 164 | +**Why NOT use existing CRM**: |
| 165 | +- This is about learning the stack, not production use |
| 166 | +- Building from scratch teaches architectural patterns |
| 167 | +- Template provides 80% foundation (auth, DB, UI), we add 20% (domain logic) |
| 168 | + |
| 169 | +### Why This Scope? |
| 170 | +**MVP is deliberately minimal** to focus on learning core patterns: |
| 171 | +- 2 main entities (contacts, deals) = practice relationships |
| 172 | +- Tags system = practice many-to-many |
| 173 | +- Pipeline board = practice UI state management |
| 174 | +- Dashboard metrics = practice aggregations |
| 175 | + |
| 176 | +**Deferred features** prevent scope creep: |
| 177 | +- Activity logging (complex timeline UI) |
| 178 | +- Avatars (R2 already demonstrated in todos) |
| 179 | +- Custom stages (adds complexity) |
| 180 | +- Advanced analytics (not core learning) |
| 181 | + |
| 182 | +**Time investment** = ~6-8 hours (~6-8 minutes with Claude Code) |
| 183 | +- Realistic for learning project |
| 184 | +- Can complete in 1-2 sessions |
| 185 | +- Leaves room for experimentation |
| 186 | + |
| 187 | +### What Could Go Wrong? |
| 188 | + |
| 189 | +**Risk 1: Overcomplicating relationships** |
| 190 | +- *What*: Trying to add too many foreign keys (deals → contacts → companies → industries...) |
| 191 | +- *Mitigation*: Stick to MVP scope (contacts ↔ tags, deals → contacts). No nested hierarchies. |
| 192 | + |
| 193 | +**Risk 2: UI perfectionism** |
| 194 | +- *What*: Spending hours on drag-and-drop Kanban, animations, etc. |
| 195 | +- *Mitigation*: Use simple table/grid layouts. Focus on functionality, not polish. |
| 196 | + |
| 197 | +**Risk 3: Scope creep during build** |
| 198 | +- *What*: "While I'm here, let me add email integration..." |
| 199 | +- *Mitigation*: Strict adherence to MVP checklist. Document ideas for Phase 2. |
| 200 | + |
| 201 | +--- |
| 202 | + |
| 203 | +## Estimated Effort |
| 204 | + |
| 205 | +**Total MVP**: ~6-8 hours (~6-8 minutes human time with Claude Code) |
| 206 | + |
| 207 | +**Breakdown**: |
| 208 | +- Setup (clone, configure D1, run migrations): 30 min |
| 209 | +- Contacts module (schema, actions, UI, tags): 2.5 hours |
| 210 | +- Deals module (schema, actions, UI, board): 2 hours |
| 211 | +- Dashboard integration (nav, metrics): 1 hour |
| 212 | +- Testing & seed data: 1 hour |
| 213 | +- Documentation: 30 min |
| 214 | + |
| 215 | +**Phase 2** (optional extensions): |
| 216 | +- Activity timeline: +2 hours |
| 217 | +- Avatar uploads: +1 hour |
| 218 | +- Drag-drop Kanban: +2 hours |
| 219 | +- Custom stages: +1.5 hours |
| 220 | +- Advanced search: +2 hours |
| 221 | + |
| 222 | +--- |
| 223 | + |
| 224 | +## Success Criteria (MVP) |
| 225 | + |
| 226 | +**Functional Requirements**: |
| 227 | +- [ ] Can create, edit, delete, search contacts |
| 228 | +- [ ] Can assign multiple tags to contacts |
| 229 | +- [ ] Can create tags with colors |
| 230 | +- [ ] Can create, edit, delete deals |
| 231 | +- [ ] Deals link to contacts (dropdown selector) |
| 232 | +- [ ] Pipeline board shows deals in columns by stage |
| 233 | +- [ ] Dashboard shows: total contacts, active deals, pipeline value |
| 234 | +- [ ] All data isolated to logged-in user |
| 235 | +- [ ] Forms have proper validation (Zod schemas) |
| 236 | +- [ ] UI responsive on mobile/desktop |
| 237 | + |
| 238 | +**Technical Requirements**: |
| 239 | +- [ ] Follows module-sliced architecture (`src/modules/contacts/`, `src/modules/deals/`) |
| 240 | +- [ ] Uses Server Actions (not API routes) |
| 241 | +- [ ] Database migrations run successfully (local + production) |
| 242 | +- [ ] Type-safe end-to-end (TypeScript + Drizzle + Zod) |
| 243 | +- [ ] shadcn/ui components used consistently |
| 244 | +- [ ] Deploys to Cloudflare Workers without errors |
| 245 | + |
| 246 | +**Learning Objectives**: |
| 247 | +- [ ] Understand how to structure multi-entity features |
| 248 | +- [ ] Practice Drizzle ORM relationships (foreign keys, joins, many-to-many) |
| 249 | +- [ ] Learn Server Actions patterns for CRUD |
| 250 | +- [ ] Experience D1 migrations workflow |
| 251 | +- [ ] Build complex forms with React Hook Form + Zod |
| 252 | + |
| 253 | +--- |
| 254 | + |
| 255 | +## Next Steps |
| 256 | + |
| 257 | +### If Proceeding (Recommended) |
| 258 | + |
| 259 | +1. **Exit plan mode** and start implementation |
| 260 | +2. **Clone project** to `/home/jez/Documents/fullstack-next-cloudflare-crm` |
| 261 | +3. **Configure local Cloudflare**: |
| 262 | + - Create new D1 database: `npx wrangler d1 create fullstack-crm` |
| 263 | + - Update `wrangler.jsonc` with new database ID |
| 264 | + - Set up `.dev.vars` with Better Auth secrets |
| 265 | +4. **Implement in phases**: |
| 266 | + - Phase 1: Project setup + database schema |
| 267 | + - Phase 2: Contacts module |
| 268 | + - Phase 3: Deals module |
| 269 | + - Phase 4: Dashboard integration |
| 270 | + - Phase 5: Testing & documentation |
| 271 | +5. **Deploy when ready** (Cloudflare account setup) |
| 272 | + |
| 273 | +### If Refining Scope |
| 274 | + |
| 275 | +**Want simpler?** |
| 276 | +- Skip tags (just contacts + deals) |
| 277 | +- Skip pipeline board (simple table view) |
| 278 | +- Reduces to ~4 hours |
| 279 | + |
| 280 | +**Want more ambitious?** |
| 281 | +- Add activity timeline |
| 282 | +- Add R2 avatar uploads |
| 283 | +- Add custom stages |
| 284 | +- Increases to ~10-12 hours |
| 285 | + |
| 286 | +--- |
| 287 | + |
| 288 | +## Research References |
| 289 | + |
| 290 | +- **Template repo**: https://github.com/jezweb/fullstack-next-cloudflare (forked from ifindev) |
| 291 | +- **Local codebase**: /home/jez/Documents/fullstack-next-cloudflare-demo |
| 292 | +- **Drizzle ORM relationships**: https://orm.drizzle.team/docs/rqb |
| 293 | +- **shadcn/ui components**: https://ui.shadcn.com/docs |
| 294 | +- **Cloudflare D1 docs**: via `mcp__cloudflare-docs__search_cloudflare_documentation` |
| 295 | +- **Relevant skills**: `~/.claude/skills/cloudflare-d1`, `~/.claude/skills/drizzle-orm-d1` |
| 296 | + |
| 297 | +--- |
| 298 | + |
| 299 | +## Recommendation |
| 300 | + |
| 301 | +✅ **Proceed with MVP implementation** |
| 302 | + |
| 303 | +**Rationale**: |
| 304 | +1. Scope is well-defined and realistic (6-8 hours) |
| 305 | +2. Template provides solid foundation (80% already built) |
| 306 | +3. Learning objectives are clear and achievable |
| 307 | +4. No technical blockers (all patterns exist in template) |
| 308 | +5. Can defer advanced features to Phase 2 without compromising learning |
| 309 | + |
| 310 | +**This is an excellent learning project** - complex enough to teach real patterns, simple enough to complete without frustration. |
0 commit comments