feat: unify personal and organization starter presets - #10
Conversation
- Add centralized organization configuration (config/organization.ts) - Configure AuthUIProvider with organization plugin in web and tanstack - Create organization pages: settings, members, accept-invite - Add OrganizationSwitcher to AppLayout in both apps - Create tanstack organization routes - Built-in roles: owner, admin, member (no custom roles) - Organization logo upload/delete support Configuration is now easily configurable via @/config/organization
…ation, auth hooks, and add `react-grab` dependency.
…d organization creation, including database schema updates and UI integration.
- Replace dedicated organizationName column with flexible metadata JSONB - Add migration 0002_user_metadata.sql - Update journal for new migration
- Add user-metadata.ts with USER_METADATA_FIELDS configuration - Add organization.ts with ORGANIZATION_LOGO and ORGANIZATION_ROLES - Add helper functions: getAuthUserFields(), getUIUserFields() - Add package exports for new configs - Add README.md documenting shared package
- Remove unused configs: navigation, routes, inviteSignup, signUpFields - Import ORGANIZATION_LOGO from @repo/shared - Remove customRoles (using default admin/member only) - Reduce file size from ~170 lines to ~100 lines - Both web and tanstack apps now use centralized config
- Add createdAt field required by better-auth organization plugin - Create migration 0003_invitation_created_at.sql - Fixes invitation error when inviting members to organization
…nd remove organizationName from user table.
- Better-auth additionalFields requires separate database columns, not JSON - Organization name is handled via frontend and user.create.after hook - Removed unused getAuthUserFields import
- Add hooks.before to capture signup fields and inject into metadata - Update user.create.after to read org name from user.metadata - Works without additionalFields (which requires real columns)
- Create signup-metadata-store.ts with Map for passing signup data - hooks.before stores organizationName by email in Map - databaseHooks.user.create.before injects metadata before DB insert - Auto-cleanup of Map entries after 5 minutes
…neon-http` client for enhanced database performance.
- Add @better-auth-extended/onboarding package - Configure onboarding plugin with createOrganization step - Remove hooks.before and databaseHooks.user.create.before - Delete signup-metadata-store.ts - Organization now created during onboarding flow instead of signup - Add type assertions for better-auth-extended compatibility
- Install @better-auth-extended/onboarding in web app - Add onboarding client plugin to auth-client - Create Onboarding.tsx page with org creation form - Add /onboarding route - Update shared config: remove organizationName from metadata - Export auth type for client type inference Note: Has type errors - needs UI component fixes
- Simplified Onboarding.tsx to use direct API call - Removed onboarding client plugin (type incompatibility) - Use HTML inputs with Tailwind instead of missing shadcn components - All type checks passing Working flow: Signup → /onboarding → Create org → Dashboard
- Fixed runtime error: auth is a type, not a value
- Export type { auth } instead of value export
- Upgraded better-auth from 1.4.12 to 1.4.15
- Re-added onboarding client plugin with 'as any' workaround
- Type checks passing
- Create onboarding.ts config (enable/disable, bypass routes) - Add RequireOnboarding guard component with loading state - Simplify ProtectedRoute (auth only, no onboarding) - Update Dashboard to use both guards - SaaS-style: forces onboarding before accessing app Configuration: - Set ONBOARDING_CONFIG.enabled = false to disable - Customize bypass routes - Easy to apply to any protected route
- Create rest-api/onboarding folder with API functions - check-status.ts: checkOnboardingStatus() - complete-step.ts: completeOnboardingStep() - Update config/redirects.ts: add onboarding path - Update onboarding.ts config: use AUTH_REDIRECTS - Update RequireOnboarding: use rest-api function - Update Onboarding.tsx: use rest-api and AUTH_REDIRECTS - Update auth-client.ts: use APP_URLS.api config No more hardcoded URLs or API calls in components
- check-status.ts: use authClient.onboarding.shouldOnboard()
- complete-step.ts: use authClient.onboarding.step.{stepName}()
- Fixes 403 error from direct REST API calls
- Uses 'as any' for type safety with dynamic methods
- Add should_onboard (boolean, default true) - Add completed_onboarding_steps (text) These fields are required by @better-auth-extended/onboarding plugin to track user onboarding status and completed steps.
RequireOnboarding component handles redirect via React Router instead. This prevents infinite reload loop caused by window.location.href.
Workaround for @daveyplate/better-auth-ui OrganizationRefetcher crash when user has no organization (during onboarding).
- Update backend invitation link to use ?invitationId={id} format
- Change frontend route from /invitation/:id to /accept-invitation
- Ensures compatibility with AcceptInvitationCard component
- Rewrite AcceptInvite page with SignedIn/SignedOut logic - Show signup/signin prompt for unauthenticated users - Add redirectTo query param support in AuthPage - Preserve invitation context through auth flow
- Create ORGANIZATION_CONFIG with requireOrganization flag - Add backend config in packages/auth/src/config/organization.ts - Add frontend config in apps/web/src/config/organization.ts - Enables flexible control over organization enforcement
- Add organization membership check to RequireOnboarding - Redirect to onboarding if user has no active org - Use ORGANIZATION_CONFIG.requireOrganization flag for control - Handle edge case where user is removed from all organizations
- Create @repo/onboarding package with multi-step wizard - Add configurable steps with required/optional flags - Support step completion, skipping, and validation - Add step order and current step tracking - Include roles configuration for organization creators
- Add shouldOnboard, currentOnboardingStep, completedOnboardingSteps fields - Create migration 0005 for schema changes - Update user metadata configuration
- Create reusable image upload/delete handlers - Add ORGANIZATION_LOGO configuration constants - Support both web and tanstack apps
- Added for centralized auth mode config - Added comprehensive documentation in - Updated docs README to include new auth mode guide - Allows developers to easily switch between 'simple' and 'organization' auth modes via config
- Updated auth package to respect auth mode settings - Updated web and tanstack apps to use centralized config - Conditionally render routes in web app based on mode
- Ensure authentication routes are accessible without prior authentication. - Consolidate onboarding and organization routes under a unified structure. - Pass `authClient` to `RequireOnboarding` for proper authentication checks. - Remove aggressive auto-clearing of `shouldOnboard` to allow for multi-step onboarding processes. - Update Zod dependency to v4.3.5. - Adjust `apps/tanstack` scripts to differentiate build/dev commands. - Add `.vercel` to `apps/server/.gitignore`.
- Updated Zod version in multiple packages to v4.3.5. - Renamed build and dev scripts in apps/tanstack for consistency. - Added Zod dependency to the auth package.
…ache Re-enable session.cookieCache (maxAge: 60s) and fix the root cause: when onboarding step handlers wrote directly to DB (sessionTable.activeOrganizationId, userTable.shouldOnboard), the signed cookie cache was never refreshed, so RequireOnboarding guards read stale values and looped back to /onboarding. Fix: - hooks.after now intercepts /onboarding/step/* and /onboarding/skip-step/* paths. After the plugin has run adapter.updateOnboardingState (which sets shouldOnboard=false on the completion step), refreshSessionCookie() re-reads the fresh session from DB via internalAdapter.findSession and re-issues the signed cookie — so the very next guard check sees the updated values. - The createOrganization step handler also calls refreshSessionCookie() inline after writing activeOrganizationId to the session row, giving the client an updated cookie mid-flow (before the completion step). - Added packages/auth/src/utils/refresh-session-cookie.ts helper that wraps internalAdapter.findSession + setSessionCookie with error isolation.
…console noise - Add `debug` level to @repo/logs logger - Demote four verbose logger.info calls inside hooks.after /get-session middleware to logger.debug — fires on every session check and was spamming production logs - Merge duplicate @repo/db imports in packages/auth/src/auth.ts into one - Remove redundant console.error calls from axios response interceptors in web and tanstack apps (error already re-thrown to callers) - Remove console.error from onboarding catch blocks in web and tanstack (user-facing toast already surfaces the error message) - Remove unused sharedUtility export from packages/config/src/index.ts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Sorry @jacksonkasi1, your pull request is larger than the review limit of 150,000 diff characters
|
Important Review skippedToo many files! This PR contains 190 files, which is 90 over the limit of 100. To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch. Upgrade to a paid plan to raise the limit. This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Team Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (190)
You can disable this status message by setting the Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
What changes
FlowStack's personal and organization templates now share one maintained source.
bun run setupasks only for the account model and frontend, installs the selected workspaces, and preserves existing environment files.--output ../my-appcreates an independent starter copy without Git history or environment files. Both React Router and TanStack Start use the Hono API on Node.js.Personal mode disables organization/onboarding backend plugins and UI while retaining the shared database schema. Organization mode includes onboarding and invitations. The change incorporates and extends the cache fix from #7 and the logging cleanup from #9, preserves Better Auth response payloads, refreshes cookies after onboarding/invitation mutations, and fixes fresh-database migrations and username columns.
Dependencies and the transitive lockfile are refreshed. Hono's Zod validator is exercised with Zod 4. TypeScript stays on 6.0.3 because the current ESLint integration rejects TypeScript 7; Node types follow Node 24. The only transitive security override is esbuild. Storage API access is now scoped to the authenticated user or a verified current organization membership.
Validation
bun audit(no known vulnerabilities).Live OAuth, ZeptoMail, R2 operations, and Docker deployment were not exercised against external services. Auth integration tests use embedded PostgreSQL and stub outbound email.
Upgrade considerations
See
docs/getting-started/template-setup.md,docs/advanced/unified-template-upgrade.md, anddocs/advanced/template-verification.md. Existing storage objects need an explicit ownership/key migration; they are not automatically moved or deleted. Existing customized clones do not automatically receive template updates.mainandorganization-v2are unchanged. Their original tips are permanently preserved inbackup/main-2026-09-06andbackup/organization-v2-2026-09-06. All implementation work is ondev. This PR is for review; do not merge or delete the backups automatically.