- 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>
3.5 KiB
Executable File
3.5 KiB
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 buildbun preview- build and preview on cloudflare runtimebun deploy- build and deploy to cloudflarebun 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:
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 servingIMAGES- cloudflare image optimizationWORKER_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:
readonlyeverywhere mutation isn't intended.ReadonlyArray<T>,Readonly<Record<K, V>>, deep readonly wrappers. writeDeepReadonly<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. useas constobjects 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 upPostIdandUserId - no
any, noas, no!- genuinely zero. useunknownwith 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>orEitherinstead 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.