compassmock/CLAUDE.md
Nicholai a0dd50f59b
feat(auth): add user profiles and improve auth security (#33)
- Wire up real user data to sidebar, header, and account modal
- Add functional profile editing (first name, last name) via WorkOS API
- Add password change functionality via WorkOS API
- Add logout functionality to sidebar and header dropdowns
- Migrate from manual WorkOS SDK to @workos-inc/authkit-nextjs
- Add server-side input validation with Zod schemas for all auth routes
- Add shared validation schemas for auth, users, teams, schedule, financial
- Fix 30-second auto-logout by properly handling refresh tokens
- Add SidebarUser type and toSidebarUser helper for UI components
- Add getInitials utility for avatar fallbacks
- Document rate limiting configuration for Cloudflare WAF
- Fix login page Suspense boundary for Next.js 15 compatibility
- Remove obsolete workos-client.ts in favor of authkit helpers

Co-authored-by: Nicholai <nicholaivogelfilms@gmail.com>
2026-02-05 08:20:51 -07:00

107 lines
3.5 KiB
Markdown
Executable File

dashboard-app-template
===
a Next.js 15 dashboard template deployed to Cloudflare Workers via OpenNext.
tech stack
---
- Next.js 15.5 with Turbopack
- React 19
- Tailwind CSS v4
- shadcn/ui (new-york style)
- Recharts for data visualization
- Cloudflare Workers (via @opennextjs/cloudflare)
commands
---
- `bun dev` - start dev server (turbopack)
- `bun build` - production build
- `bun preview` - build and preview on cloudflare runtime
- `bun deploy` - build and deploy to cloudflare
- `bun lint` - run eslint
project structure
---
```
src/
├── app/ # Next.js app router
│ ├── dashboard/ # dashboard routes
│ ├── globals.css # tailwind + theme variables
│ ├── layout.tsx # root layout
│ └── page.tsx # home page
├── components/
│ ├── ui/ # shadcn/ui primitives
│ └── *.tsx # app-specific components (sidebar, charts, tables)
├── hooks/ # custom react hooks
└── lib/
└── utils.ts # cn() helper for class merging
```
shadcn/ui
---
uses shadcn/ui with new-york style. add components via:
```bash
bunx shadcn@latest add <component-name>
```
config in `components.json`. aliases:
- `@/components` -> src/components
- `@/components/ui` -> src/components/ui
- `@/lib` -> src/lib
- `@/hooks` -> src/hooks
cloudflare deployment
---
configured in `wrangler.jsonc`. uses OpenNext for Next.js compatibility.
env vars go in `.dev.vars` (local) or cloudflare dashboard (prod).
key bindings:
- `ASSETS` - static asset serving
- `IMAGES` - cloudflare image optimization
- `WORKER_SELF_REFERENCE` - self-reference for caching
known issues (WIP)
---
- gantt chart pan/zoom: zoom controls (+/-) and ctrl+scroll work. pan mode
toggle (pointer/grab) exists but vertical panning does not work correctly
yet - the scroll-based approach conflicts with how frappe-gantt sizes its
container. horizontal panning works. needs a different approach for
vertical navigation (possibly a custom viewport with transform-based
rendering for the body while keeping the header fixed separately).
coding style
---
strict typescript discipline:
- `readonly` everywhere mutation isn't intended. `ReadonlyArray<T>`,
`Readonly<Record<K, V>>`, deep readonly wrappers. write `DeepReadonly<T>`
utilities when needed
- discriminated unions over optional properties. `{ status: 'ok'; data: T } |
{ status: 'error'; error: Error }` instead of `{ status: string; error?:
Error; data?: T }`. makes impossible states unrepresentable
- no `enum`. use `as const` objects or union types instead. enums have quirks,
especially numeric ones with reverse mappings
- branded/opaque types for primitive identifiers. `type UserId = string &
{ readonly __brand: unique symbol }` prevents mixing up `PostId` and `UserId`
- no `any`, no `as`, no `!` - genuinely zero. use `unknown` with proper
narrowing. write type guards instead of assertions
- explicit return types on all exported functions. don't rely on inference for
public APIs. catches accidental changes, improves compile speed
- effect-free module scope. no side effects at top level (no `console.log`,
`fetch`, mutations during import). everything meaningful happens in
explicitly called functions
- result types over thrown exceptions. return `Result<T, E>` or `Either`
instead of throwing. makes error handling visible in type signatures
these trade short-term convenience for long-term correctness. the strict
version is always better even when the permissive version works right now.