ui-syncup 0.3.13 → 0.4.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/ai-spec-workflow/SKILL.md +58 -0
- package/.agents/skills/ai-spec-workflow/references/AI_SPECIFICATION_WORKFLOW.md +1434 -0
- package/.agents/skills/ai-spec-workflow/references/templates/design-template.md +729 -0
- package/.agents/skills/ai-spec-workflow/references/templates/requirements-template.md +179 -0
- package/.agents/skills/ai-spec-workflow/references/templates/tasks-template.md +501 -0
- package/.agents/skills/animation-designer/SKILL.md +688 -0
- package/.agents/skills/animation-designer/manifest.yaml +44 -0
- package/.agents/skills/brainstorming/SKILL.md +54 -0
- package/.agents/skills/contract-driven-ui/SKILL.md +270 -0
- package/.agents/skills/dispatching-parallel-agents/SKILL.md +180 -0
- package/.agents/skills/executing-plans/SKILL.md +76 -0
- package/.agents/skills/executing-specs/SKILL.md +53 -0
- package/.agents/skills/finishing-a-development-branch/SKILL.md +200 -0
- package/.agents/skills/github-workflow-automation/SKILL.md +846 -0
- package/.agents/skills/react-best-practices/AGENTS.md +2249 -0
- package/.agents/skills/react-best-practices/README.md +123 -0
- package/.agents/skills/react-best-practices/SKILL.md +121 -0
- package/.agents/skills/react-best-practices/metadata.json +15 -0
- package/.agents/skills/react-best-practices/rules/_sections.md +46 -0
- package/.agents/skills/react-best-practices/rules/_template.md +28 -0
- package/.agents/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/.agents/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
- package/.agents/skills/react-best-practices/rules/async-api-routes.md +38 -0
- package/.agents/skills/react-best-practices/rules/async-defer-await.md +80 -0
- package/.agents/skills/react-best-practices/rules/async-dependencies.md +36 -0
- package/.agents/skills/react-best-practices/rules/async-parallel.md +28 -0
- package/.agents/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/.agents/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/.agents/skills/react-best-practices/rules/bundle-conditional.md +31 -0
- package/.agents/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/.agents/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/.agents/skills/react-best-practices/rules/bundle-preload.md +50 -0
- package/.agents/skills/react-best-practices/rules/client-event-listeners.md +74 -0
- package/.agents/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/.agents/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
- package/.agents/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/.agents/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/.agents/skills/react-best-practices/rules/js-cache-storage.md +70 -0
- package/.agents/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/.agents/skills/react-best-practices/rules/js-early-exit.md +50 -0
- package/.agents/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/.agents/skills/react-best-practices/rules/js-index-maps.md +37 -0
- package/.agents/skills/react-best-practices/rules/js-length-check-first.md +49 -0
- package/.agents/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/.agents/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/.agents/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/.agents/skills/react-best-practices/rules/rendering-activity.md +26 -0
- package/.agents/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/.agents/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/.agents/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/.agents/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/.agents/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/.agents/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/.agents/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/.agents/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/.agents/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/.agents/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/.agents/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/.agents/skills/react-best-practices/rules/rerender-memo.md +44 -0
- package/.agents/skills/react-best-practices/rules/rerender-transitions.md +40 -0
- package/.agents/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/.agents/skills/react-best-practices/rules/server-cache-lru.md +41 -0
- package/.agents/skills/react-best-practices/rules/server-cache-react.md +26 -0
- package/.agents/skills/react-best-practices/rules/server-parallel-fetching.md +79 -0
- package/.agents/skills/react-best-practices/rules/server-serialization.md +38 -0
- package/.agents/skills/react-ui-patterns/SKILL.md +289 -0
- package/.agents/skills/receiving-code-review/SKILL.md +213 -0
- package/.agents/skills/requesting-code-review/SKILL.md +105 -0
- package/.agents/skills/requesting-code-review/code-reviewer.md +146 -0
- package/.agents/skills/reviewing-code/SKILL.md +28 -0
- package/.agents/skills/shadcn/SKILL.md +240 -0
- package/.agents/skills/shadcn/agents/openai.yml +5 -0
- package/.agents/skills/shadcn/assets/shadcn-small.png +0 -0
- package/.agents/skills/shadcn/assets/shadcn.png +0 -0
- package/.agents/skills/shadcn/cli.md +255 -0
- package/.agents/skills/shadcn/customization.md +202 -0
- package/.agents/skills/shadcn/evals/evals.json +47 -0
- package/.agents/skills/shadcn/mcp.md +94 -0
- package/.agents/skills/shadcn/rules/base-vs-radix.md +306 -0
- package/.agents/skills/shadcn/rules/composition.md +195 -0
- package/.agents/skills/shadcn/rules/forms.md +192 -0
- package/.agents/skills/shadcn/rules/icons.md +101 -0
- package/.agents/skills/shadcn/rules/styling.md +162 -0
- package/.agents/skills/steering-creation/SKILL.md +221 -0
- package/.agents/skills/steering-creation/references/STEERING_CREATION_INSTRUCTION.md +850 -0
- package/.agents/skills/subagent-driven-development/SKILL.md +240 -0
- package/.agents/skills/subagent-driven-development/code-quality-reviewer-prompt.md +20 -0
- package/.agents/skills/subagent-driven-development/implementer-prompt.md +78 -0
- package/.agents/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
- package/.agents/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/.agents/skills/systematic-debugging/SKILL.md +296 -0
- package/.agents/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/.agents/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/.agents/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/.agents/skills/systematic-debugging/find-polluter.sh +63 -0
- package/.agents/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/.agents/skills/systematic-debugging/test-academic.md +14 -0
- package/.agents/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/.agents/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/.agents/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/.agents/skills/test-driven-development/SKILL.md +371 -0
- package/.agents/skills/test-driven-development/testing-anti-patterns.md +299 -0
- package/.agents/skills/using-git-worktrees/SKILL.md +217 -0
- package/.agents/skills/using-superpowers/SKILL.md +87 -0
- package/.agents/skills/verification-before-completion/SKILL.md +139 -0
- package/.agents/skills/web-design-guidelines/SKILL.md +36 -0
- package/.agents/skills/writing-plans/SKILL.md +116 -0
- package/.agents/skills/writing-skills/SKILL.md +655 -0
- package/.agents/skills/writing-skills/anthropic-best-practices.md +1150 -0
- package/.agents/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
- package/.agents/skills/writing-skills/graphviz-conventions.dot +172 -0
- package/.agents/skills/writing-skills/persuasion-principles.md +187 -0
- package/.agents/skills/writing-skills/render-graphs.js +168 -0
- package/.agents/skills/writing-skills/testing-skills-with-subagents.md +384 -0
- package/.ai/steering/product.md +51 -0
- package/.ai/steering/structure.md +275 -0
- package/.ai/steering/tech.md +188 -0
- package/.claude/agents/database-architect.md +96 -0
- package/.claude/agents/deployment-pipeline-architect.md +122 -0
- package/.claude/agents/nextjs-expert.md +69 -0
- package/.claude/agents/ui-design-expert.md +106 -0
- package/.claudeignore +69 -0
- package/.dockerignore +8 -0
- package/.env.development +86 -0
- package/.env.example +171 -0
- package/.env.production +139 -0
- package/.env.test +58 -0
- package/.gitattributes +2 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +33 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +20 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +23 -0
- package/.github/workflows/ci.yml +64 -0
- package/.github/workflows/release.yml +174 -0
- package/.nvmrc +1 -0
- package/.releaserc.json +18 -0
- package/.vercelignore +73 -0
- package/AGENTS.md +544 -0
- package/CHANGELOG.md +69 -0
- package/CODE_OF_CONDUCT.md +21 -0
- package/CONTRIBUTING.md +32 -0
- package/Dockerfile +84 -0
- package/LICENSE +21 -0
- package/README.md +328 -59
- package/SECURITY.md +16 -0
- package/bun.lock +3853 -0
- package/cli/README.md +94 -0
- package/cli/bun.lock +306 -0
- package/cli/index.ts +96 -0
- package/cli/package-lock.json +2157 -0
- package/cli/package.json +30 -0
- package/cli/src/commands/backup.ts +78 -0
- package/cli/src/commands/doctor.ts +82 -0
- package/cli/src/commands/init.ts +234 -0
- package/cli/src/commands/logs.ts +26 -0
- package/cli/src/commands/open.ts +23 -0
- package/cli/src/commands/remove.ts +44 -0
- package/cli/src/commands/restart.ts +21 -0
- package/cli/src/commands/restore.ts +90 -0
- package/cli/src/commands/start.ts +26 -0
- package/cli/src/commands/status.ts +25 -0
- package/cli/src/commands/stop.ts +20 -0
- package/cli/src/commands/upgrade.ts +28 -0
- package/cli/src/lib/docker.ts +40 -0
- package/cli/src/lib/env.ts +42 -0
- package/cli/src/lib/ui.ts +43 -0
- package/cli/tsconfig.json +13 -0
- package/cli/tsup.config.ts +12 -0
- package/components.json +24 -0
- package/docker/README.md +430 -0
- package/docker/compose.dev-minio.yml +30 -0
- package/docker/compose.dev.yml +39 -0
- package/docker/compose.local.yml +84 -0
- package/docker/compose.yml +153 -0
- package/docs/VERSIONING.md +101 -0
- package/docs/database/DRIZZLE_COMMANDS_EXPLAINED.md +1779 -0
- package/docs/database/DRIZZLE_ZOD_POSTGRESQL_INSTRUCTION.md +646 -0
- package/docs/database/MIGRATION_BEST_PRACTICES.md +601 -0
- package/docs/database/MIGRATION_ROLLBACK.md +1080 -0
- package/docs/database/MIGRATION_SYSTEM.md +165 -0
- package/docs/database/MIGRATION_TROUBLESHOOTING.md +881 -0
- package/docs/development/ENVIRONMENT_CONFIG.md +896 -0
- package/docs/development/LOCAL_DEVELOPMENT.md +456 -0
- package/docs/development/REMOTE_DATABASE_SETUP.md +786 -0
- package/docs/development/STORAGE_SETUP.md +207 -0
- package/docs/development/SUPABASE_LOCAL_SETUP.md +178 -0
- package/docs/development/TESTING.md +714 -0
- package/docs/feature-architectures/LOADING_ARCHITECTURE.md +343 -0
- package/docs/feature-architectures/NOTIFICATION_ARCHITECTURE.md +858 -0
- package/docs/feature-architectures/RATE_LIMIT_RESET.md +147 -0
- package/docs/feature-architectures/RBAC.md +1132 -0
- package/docs/feature-architectures/RESOURCE_LIMITS.md +69 -0
- package/docs/feature-architectures/SECURITY.md +284 -0
- package/docs/feature-architectures/WORKSPACES.md +278 -0
- package/docs/plans/admin-setup-wizard-routing-plan.md +623 -0
- package/drizzle/0000_purple_wilson_fisk.sql +360 -0
- package/drizzle/0001_drop_instance_public_url.sql +1 -0
- package/drizzle/meta/0000_snapshot.json +3118 -0
- package/drizzle/meta/_journal.json +20 -0
- package/drizzle.config.ts +13 -0
- package/eslint.config.mjs +44 -0
- package/install.sh +180 -0
- package/next.config.ts +91 -0
- package/package.json +128 -22
- package/playwright.config.ts +70 -0
- package/postcss.config.mjs +7 -0
- package/public/file.svg +1 -0
- package/public/globe.svg +1 -0
- package/public/logo.svg +11 -0
- package/public/next.svg +1 -0
- package/public/playground/CPM-101/as-is-image.jpg +0 -0
- package/public/playground/CPM-101/to-be-image.jpg +0 -0
- package/public/playground/TEST-1/LinkedIn-skeleton-screen.png +0 -0
- package/public/playground/TEST-1/https___dev-to-uploads.s3.amazonaws.com_uploads_articles_vuahe90ka1mkx9aepmea.webp +0 -0
- package/public/playground/TEST-1/linkedin_skeletonscreen.jpg +0 -0
- package/public/vercel.svg +1 -0
- package/public/window.svg +1 -0
- package/scripts/__tests__/migrate.integration.test.ts +642 -0
- package/scripts/__tests__/migrate.property.test.ts +1714 -0
- package/scripts/__tests__/migrate.test.ts +536 -0
- package/scripts/admin-reset-password.ts +114 -0
- package/scripts/check-email-queue.ts +99 -0
- package/scripts/check-sessions.ts +50 -0
- package/scripts/db-pull-data.sh +73 -0
- package/scripts/force-verify-email.sh +13 -0
- package/scripts/migrate.ts +693 -0
- package/scripts/process-email-queue.ts +26 -0
- package/scripts/reset-db.ts +47 -0
- package/scripts/reset-rate-limit.sh +26 -0
- package/scripts/reset-remote-db.sql +31 -0
- package/scripts/retry-failed-emails.ts +67 -0
- package/scripts/seed.ts +605 -0
- package/scripts/setup-monitoring.sh +440 -0
- package/scripts/sync-migration-tracking.ts +113 -0
- package/scripts/test-ci-error-handling.sh +237 -0
- package/scripts/test-ci-workflow.sh +200 -0
- package/scripts/test-migration.sh +151 -0
- package/scripts/validate-env.ts +25 -0
- package/scripts/validate-migration-system.ts +566 -0
- package/scripts/verify-ci-status-reporting.sh +206 -0
- package/scripts/verify-user-email.sql +22 -0
- package/scripts/verify-vercel-integration.ts +292 -0
- package/seed_data.md +54 -0
- package/src/app/(protected)/(team)/(routes)/[projectSlug]/error.tsx +89 -0
- package/src/app/(protected)/(team)/(routes)/[projectSlug]/loading.tsx +101 -0
- package/src/app/(protected)/(team)/(routes)/[projectSlug]/page.tsx +91 -0
- package/src/app/(protected)/(team)/(routes)/issue/[issueKey]/README.md +192 -0
- package/src/app/(protected)/(team)/(routes)/issue/[issueKey]/error.tsx +58 -0
- package/src/app/(protected)/(team)/(routes)/issue/[issueKey]/loading.tsx +14 -0
- package/src/app/(protected)/(team)/(routes)/issue/[issueKey]/not-found.tsx +47 -0
- package/src/app/(protected)/(team)/(routes)/issue/[issueKey]/page.tsx +91 -0
- package/src/app/(protected)/(team)/projects/page.tsx +16 -0
- package/src/app/(protected)/(team)/team/settings/(section)/instance/page.tsx +52 -0
- package/src/app/(protected)/(team)/team/settings/(section)/integrations/loading.tsx +5 -0
- package/src/app/(protected)/(team)/team/settings/(section)/integrations/page.tsx +23 -0
- package/src/app/(protected)/(team)/team/settings/(section)/members/loading.tsx +5 -0
- package/src/app/(protected)/(team)/team/settings/(section)/members/page.tsx +35 -0
- package/src/app/(protected)/(team)/team/settings/layout.tsx +72 -0
- package/src/app/(protected)/(team)/team/settings/loading.tsx +5 -0
- package/src/app/(protected)/(team)/team/settings/page.tsx +71 -0
- package/src/app/(protected)/dev/auth/README.md +151 -0
- package/src/app/(protected)/dev/auth/page.tsx +590 -0
- package/src/app/(protected)/layout.test.tsx +209 -0
- package/src/app/(protected)/layout.tsx +28 -0
- package/src/app/(protected)/onboarding/page.tsx +27 -0
- package/src/app/(protected)/settings/integrations/page.tsx +23 -0
- package/src/app/(protected)/settings/layout.tsx +26 -0
- package/src/app/(protected)/settings/notifications/page.tsx +26 -0
- package/src/app/(protected)/settings/other/page.tsx +23 -0
- package/src/app/(protected)/settings/page.tsx +23 -0
- package/src/app/(protected)/settings/preferences/page.tsx +23 -0
- package/src/app/(protected)/settings/security/page.tsx +37 -0
- package/src/app/(public)/forgot-password/page.tsx +20 -0
- package/src/app/(public)/invite/project/[token]/error.tsx +50 -0
- package/src/app/(public)/invite/project/[token]/loading.tsx +39 -0
- package/src/app/(public)/invite/project/[token]/page.tsx +156 -0
- package/src/app/(public)/layout.tsx +9 -0
- package/src/app/(public)/privacy-policy/page.tsx +12 -0
- package/src/app/(public)/reset-password/page.tsx +37 -0
- package/src/app/(public)/setup/__tests__/page.test.tsx +30 -0
- package/src/app/(public)/setup/page.tsx +17 -0
- package/src/app/(public)/share/issue/[token]/page.tsx +51 -0
- package/src/app/(public)/sign-in/page.tsx +55 -0
- package/src/app/(public)/sign-up/page.tsx +23 -0
- package/src/app/(public)/verify-email/page.tsx +22 -0
- package/src/app/(public)/verify-email-confirm/page.tsx +40 -0
- package/src/app/api/auth/[...all]/route.ts +6 -0
- package/src/app/api/auth/delete-account/route.ts +134 -0
- package/src/app/api/auth/dev/force-verify/route.ts +180 -0
- package/src/app/api/auth/dev/reset-rate-limit/route.ts +144 -0
- package/src/app/api/auth/dev/sessions/route.ts +172 -0
- package/src/app/api/auth/forgot-password/__tests__/forgot-password.property.test.ts +397 -0
- package/src/app/api/auth/forgot-password/route.ts +277 -0
- package/src/app/api/auth/logout/route.ts +115 -0
- package/src/app/api/auth/me/route.ts +123 -0
- package/src/app/api/auth/providers/__tests__/route.test.ts +236 -0
- package/src/app/api/auth/providers/route.ts +119 -0
- package/src/app/api/auth/resend-verification/route.ts +262 -0
- package/src/app/api/auth/reset-password/__tests__/reset-password.property.test.ts +493 -0
- package/src/app/api/auth/reset-password/__tests__/route.test.ts +284 -0
- package/src/app/api/auth/reset-password/route.ts +251 -0
- package/src/app/api/auth/verify-email/route.ts +232 -0
- package/src/app/api/example-cors/route.ts +61 -0
- package/src/app/api/health/route.ts +14 -0
- package/src/app/api/invite/project/[token]/__tests__/accept-invitation.integration.test.ts +348 -0
- package/src/app/api/invite/project/[token]/decline/route.ts +99 -0
- package/src/app/api/invite/project/[token]/route.ts +269 -0
- package/src/app/api/issues/[issueId]/activities/route.ts +213 -0
- package/src/app/api/issues/[issueId]/attachments/[attachmentId]/annotations/[annotationId]/comments/[commentId]/route.ts +486 -0
- package/src/app/api/issues/[issueId]/attachments/[attachmentId]/annotations/[annotationId]/comments/route.ts +283 -0
- package/src/app/api/issues/[issueId]/attachments/[attachmentId]/annotations/[annotationId]/read/route.ts +242 -0
- package/src/app/api/issues/[issueId]/attachments/[attachmentId]/annotations/[annotationId]/route.ts +534 -0
- package/src/app/api/issues/[issueId]/attachments/[attachmentId]/annotations/route.ts +514 -0
- package/src/app/api/issues/[issueId]/attachments/[attachmentId]/route.ts +161 -0
- package/src/app/api/issues/[issueId]/attachments/route.ts +376 -0
- package/src/app/api/issues/[issueId]/route.ts +516 -0
- package/src/app/api/notifications/[id]/read/route.ts +131 -0
- package/src/app/api/notifications/__tests__/notifications.integration.test.ts +350 -0
- package/src/app/api/notifications/read-all/route.ts +72 -0
- package/src/app/api/notifications/route.ts +148 -0
- package/src/app/api/notifications/unread-count/route.ts +77 -0
- package/src/app/api/projects/[id]/activities/route.ts +174 -0
- package/src/app/api/projects/[id]/invitations/[invitationId]/resend/route.ts +99 -0
- package/src/app/api/projects/[id]/invitations/[invitationId]/route.ts +96 -0
- package/src/app/api/projects/[id]/invitations/route.ts +254 -0
- package/src/app/api/projects/[id]/issues/route.ts +452 -0
- package/src/app/api/projects/[id]/join/route.ts +207 -0
- package/src/app/api/projects/[id]/members/[memberId]/route.ts +364 -0
- package/src/app/api/projects/[id]/members/me/route.ts +121 -0
- package/src/app/api/projects/[id]/members/route.ts +129 -0
- package/src/app/api/projects/[id]/route.ts +476 -0
- package/src/app/api/projects/route.ts +394 -0
- package/src/app/api/setup/admin/route.ts +255 -0
- package/src/app/api/setup/complete/__tests__/route.test.ts +60 -0
- package/src/app/api/setup/complete/route.ts +244 -0
- package/src/app/api/setup/config/route.ts +195 -0
- package/src/app/api/setup/export/route.ts +111 -0
- package/src/app/api/setup/health/route.ts +74 -0
- package/src/app/api/setup/import/route.ts +154 -0
- package/src/app/api/setup/status/route.ts +82 -0
- package/src/app/api/setup/workspace/route.ts +252 -0
- package/src/app/api/teams/[teamId]/export/route.ts +115 -0
- package/src/app/api/teams/[teamId]/invitations/[invitationId]/resend/route.ts +132 -0
- package/src/app/api/teams/[teamId]/invitations/[invitationId]/route.ts +117 -0
- package/src/app/api/teams/[teamId]/invitations/route.ts +363 -0
- package/src/app/api/teams/[teamId]/members/[userId]/route.ts +335 -0
- package/src/app/api/teams/[teamId]/members/route.ts +184 -0
- package/src/app/api/teams/[teamId]/members/search/route.ts +202 -0
- package/src/app/api/teams/[teamId]/route.ts +423 -0
- package/src/app/api/teams/[teamId]/switch/route.ts +140 -0
- package/src/app/api/teams/[teamId]/transfer-ownership/route.ts +212 -0
- package/src/app/api/teams/invitations/[token]/accept/route.ts +140 -0
- package/src/app/api/teams/invitations/by-id/[id]/accept/route.ts +98 -0
- package/src/app/api/teams/invitations/by-id/[id]/decline/route.ts +90 -0
- package/src/app/api/teams/route.ts +278 -0
- package/src/app/api/uploads/media/route.ts +118 -0
- package/src/app/api/uploads/presigned/route.ts +49 -0
- package/src/app/api/user/linked-accounts/route.ts +35 -0
- package/src/app/email-preview/page.tsx +11 -0
- package/src/app/favicon.ico +0 -0
- package/src/app/global-error.tsx +21 -0
- package/src/app/layout.tsx +50 -0
- package/src/app/page.tsx +5 -0
- package/src/components/icons/atlassian-icon.tsx +22 -0
- package/src/components/icons/index.ts +1 -0
- package/src/components/layout/SIDEBAR_LAYOUT_BEST_PRACTICES.md +240 -0
- package/src/components/layout/app-shell-header-store.tsx +20 -0
- package/src/components/layout/app-shell-skeleton.tsx +89 -0
- package/src/components/layout/app-shell-wrapper.tsx +32 -0
- package/src/components/layout/app-shell.test.tsx +155 -0
- package/src/components/layout/app-shell.tsx +100 -0
- package/src/components/shared/headers/app-header-configurator.tsx +42 -0
- package/src/components/shared/headers/app-header.tsx +103 -0
- package/src/components/shared/headers/header-user-menu.tsx +247 -0
- package/src/components/shared/headers/index.ts +44 -0
- package/src/components/shared/headers/page-header.tsx +25 -0
- package/src/components/shared/notifications/__tests__/notification-bell.test.tsx +159 -0
- package/src/components/shared/notifications/__tests__/notification-dropdown.test.tsx +296 -0
- package/src/components/shared/notifications/__tests__/notification-item.test.tsx +328 -0
- package/src/components/shared/notifications/index.ts +45 -0
- package/src/components/shared/notifications/notification-actions.tsx +295 -0
- package/src/components/shared/notifications/notification-bell-button.tsx +77 -0
- package/src/components/shared/notifications/notification-dropdown.tsx +160 -0
- package/src/components/shared/notifications/notification-group-item.tsx +268 -0
- package/src/components/shared/notifications/notification-item.tsx +193 -0
- package/src/components/shared/notifications/notification-load-more.tsx +50 -0
- package/src/components/shared/notifications/notification-panel.tsx +49 -0
- package/src/components/shared/notifications/utils.tsx +127 -0
- package/src/components/shared/permission-guard/index.ts +1 -0
- package/src/components/shared/permission-guard/permission-tooltip.tsx +45 -0
- package/src/components/shared/relative-time.tsx +53 -0
- package/src/components/shared/section-container.tsx +32 -0
- package/src/components/shared/service-status-banner.tsx +121 -0
- package/src/components/shared/settings-sidebar/index.ts +2 -0
- package/src/components/shared/settings-sidebar/team-setting-aside.tsx +97 -0
- package/src/components/shared/settings-sidebar/user-settings-aside.tsx +66 -0
- package/src/components/shared/sidebar/app-sidebar.tsx +146 -0
- package/src/components/shared/sidebar/index.ts +36 -0
- package/src/components/shared/sidebar/sidebar-main.tsx +81 -0
- package/src/components/shared/sidebar/sidebar-project.tsx +61 -0
- package/src/components/shared/sidebar/sidebar-team-avatar.tsx +126 -0
- package/src/components/shared/sidebar/sidebar-team-switcher.tsx +185 -0
- package/src/components/shared/sidebar/type.ts +97 -0
- package/src/components/ui/alert-dialog.tsx +157 -0
- package/src/components/ui/alert.tsx +66 -0
- package/src/components/ui/avatar-upload.tsx +147 -0
- package/src/components/ui/avatar.tsx +53 -0
- package/src/components/ui/badge.tsx +46 -0
- package/src/components/ui/breadcrumb.tsx +109 -0
- package/src/components/ui/button.tsx +60 -0
- package/src/components/ui/card.tsx +92 -0
- package/src/components/ui/checkbox.tsx +32 -0
- package/src/components/ui/collapsible.tsx +33 -0
- package/src/components/ui/command.tsx +184 -0
- package/src/components/ui/dialog.tsx +143 -0
- package/src/components/ui/dropdown-menu.tsx +257 -0
- package/src/components/ui/empty.tsx +104 -0
- package/src/components/ui/field.tsx +244 -0
- package/src/components/ui/image-cropper-dialog.tsx +167 -0
- package/src/components/ui/input.tsx +21 -0
- package/src/components/ui/label.tsx +24 -0
- package/src/components/ui/optimized-image.tsx +220 -0
- package/src/components/ui/pagination.tsx +127 -0
- package/src/components/ui/popover.tsx +48 -0
- package/src/components/ui/progress.tsx +31 -0
- package/src/components/ui/radio-group.tsx +45 -0
- package/src/components/ui/scroll-area.tsx +58 -0
- package/src/components/ui/select.tsx +187 -0
- package/src/components/ui/separator.tsx +28 -0
- package/src/components/ui/sheet.tsx +139 -0
- package/src/components/ui/sidebar.tsx +733 -0
- package/src/components/ui/skeleton.tsx +13 -0
- package/src/components/ui/sonner.tsx +40 -0
- package/src/components/ui/spinner.tsx +16 -0
- package/src/components/ui/switch.tsx +31 -0
- package/src/components/ui/table.tsx +116 -0
- package/src/components/ui/tabs.tsx +66 -0
- package/src/components/ui/textarea.tsx +23 -0
- package/src/components/ui/tooltip.tsx +61 -0
- package/src/config/__tests__/workspace.property.test.ts +40 -0
- package/src/config/auth.ts +62 -0
- package/src/config/integrations.ts +126 -0
- package/src/config/quotas.ts +20 -0
- package/src/config/roles.ts +463 -0
- package/src/config/settings-nav.ts +39 -0
- package/src/config/team-settings-nav.ts +37 -0
- package/src/config/user-settings-nav.ts +42 -0
- package/src/config/version.ts +1 -0
- package/src/config/workspace.ts +64 -0
- package/src/features/annotations/README.md +283 -0
- package/src/features/annotations/api/annotations-api.ts +194 -0
- package/src/features/annotations/api/comments-api.ts +147 -0
- package/src/features/annotations/api/index.ts +71 -0
- package/src/features/annotations/api/save-annotation.ts +150 -0
- package/src/features/annotations/api/schemas.ts +142 -0
- package/src/features/annotations/components/annotated-attachment-view.tsx +576 -0
- package/src/features/annotations/components/annotation-action-sheet.tsx +140 -0
- package/src/features/annotations/components/annotation-annotations-panel.tsx +213 -0
- package/src/features/annotations/components/annotation-box.tsx +539 -0
- package/src/features/annotations/components/annotation-canvas.tsx +534 -0
- package/src/features/annotations/components/annotation-comment-input.tsx +145 -0
- package/src/features/annotations/components/annotation-context-menu.tsx +164 -0
- package/src/features/annotations/components/annotation-drawer.tsx +231 -0
- package/src/features/annotations/components/annotation-layer.tsx +271 -0
- package/src/features/annotations/components/annotation-pin.tsx +318 -0
- package/src/features/annotations/components/annotation-popover.tsx +562 -0
- package/src/features/annotations/components/annotation-thread-panel.tsx +485 -0
- package/src/features/annotations/components/annotation-thread-preview.tsx +195 -0
- package/src/features/annotations/components/annotation-toolbar.tsx +244 -0
- package/src/features/annotations/components/keyboard-shortcuts-modal.tsx +79 -0
- package/src/features/annotations/docs/ANNOTATIONS_ARCHITECTURE.md +67 -0
- package/src/features/annotations/docs/ANNOTATION_SAVE_ARCHITECTURE.md +422 -0
- package/src/features/annotations/docs/ANNOTATION_SAVE_FEATURE.md +408 -0
- package/src/features/annotations/docs/BOX_ANNOTATION_GUIDE.md +542 -0
- package/src/features/annotations/docs/NEXTSTEP.md +28 -0
- package/src/features/annotations/docs/STALE_CLOSURE_FIX.md +344 -0
- package/src/features/annotations/docs/UNDO_REDO_QUICK_START.md +545 -0
- package/src/features/annotations/docs/local_first_canvas_autosave_architecture.md +674 -0
- package/src/features/annotations/examples/complete-example.tsx +266 -0
- package/src/features/annotations/examples/save-annotation-example.tsx +309 -0
- package/src/features/annotations/hooks/__tests__/use-annotation-permissions.property.test.tsx +493 -0
- package/src/features/annotations/hooks/index.ts +36 -0
- package/src/features/annotations/hooks/use-annotation-batch-save.ts +109 -0
- package/src/features/annotations/hooks/use-annotation-comments.ts +353 -0
- package/src/features/annotations/hooks/use-annotation-drafts.ts +137 -0
- package/src/features/annotations/hooks/use-annotation-edit-state.ts +99 -0
- package/src/features/annotations/hooks/use-annotation-history-tracker.ts +159 -0
- package/src/features/annotations/hooks/use-annotation-integration.ts +916 -0
- package/src/features/annotations/hooks/use-annotation-permissions.ts +210 -0
- package/src/features/annotations/hooks/use-annotation-popover.ts +175 -0
- package/src/features/annotations/hooks/use-annotation-save.ts +208 -0
- package/src/features/annotations/hooks/use-annotation-tools.ts +237 -0
- package/src/features/annotations/hooks/use-annotations-with-history.ts +332 -0
- package/src/features/annotations/hooks/use-auto-save.ts +94 -0
- package/src/features/annotations/index.ts +111 -0
- package/src/features/annotations/types/annotation.ts +201 -0
- package/src/features/annotations/types/index.ts +28 -0
- package/src/features/annotations/utils/history-manager.ts +73 -0
- package/src/features/annotations/utils/index.ts +2 -0
- package/src/features/annotations/utils/map-attachments-to-threads.ts +28 -0
- package/src/features/annotations/utils/position-comment-input.ts +136 -0
- package/src/features/annotations/utils/re-sequence-labels.ts +92 -0
- package/src/features/annotations/utils/validate-annotation-label.ts +120 -0
- package/src/features/auth/api/types.ts +101 -0
- package/src/features/auth/components/__tests__/role-gate.test.tsx +448 -0
- package/src/features/auth/components/__tests__/social-login-buttons.test.tsx +313 -0
- package/src/features/auth/components/auth-card.tsx +36 -0
- package/src/features/auth/components/forgot-password-form.tsx +115 -0
- package/src/features/auth/components/index.ts +14 -0
- package/src/features/auth/components/invite-code-input.tsx +155 -0
- package/src/features/auth/components/invited-user-form.tsx +309 -0
- package/src/features/auth/components/onboarding-form.tsx +195 -0
- package/src/features/auth/components/password-strength-indicator.tsx +113 -0
- package/src/features/auth/components/reset-password-form.tsx +138 -0
- package/src/features/auth/components/role-gate.tsx +124 -0
- package/src/features/auth/components/self-registration-choice.tsx +153 -0
- package/src/features/auth/components/sign-in-form.tsx +159 -0
- package/src/features/auth/components/sign-up-form.tsx +158 -0
- package/src/features/auth/components/social-login-buttons.tsx +219 -0
- package/src/features/auth/hooks/__tests__/use-onboarding.test.tsx +109 -0
- package/src/features/auth/hooks/__tests__/use-session.test.tsx +160 -0
- package/src/features/auth/hooks/index.ts +15 -0
- package/src/features/auth/hooks/use-accept-invitation.ts +194 -0
- package/src/features/auth/hooks/use-delete-account.ts +86 -0
- package/src/features/auth/hooks/use-force-verify.ts +89 -0
- package/src/features/auth/hooks/use-forgot-password.ts +144 -0
- package/src/features/auth/hooks/use-link-account.ts +78 -0
- package/src/features/auth/hooks/use-linked-accounts.ts +88 -0
- package/src/features/auth/hooks/use-onboarding.ts +159 -0
- package/src/features/auth/hooks/use-resend-verification.ts +139 -0
- package/src/features/auth/hooks/use-reset-password.ts +151 -0
- package/src/features/auth/hooks/use-reset-rate-limit.ts +56 -0
- package/src/features/auth/hooks/use-self-registration.ts +202 -0
- package/src/features/auth/hooks/use-session.ts +81 -0
- package/src/features/auth/hooks/use-sessions.ts +59 -0
- package/src/features/auth/hooks/use-sign-in.ts +234 -0
- package/src/features/auth/hooks/use-sign-out.ts +88 -0
- package/src/features/auth/hooks/use-sign-up.ts +194 -0
- package/src/features/auth/hooks/use-unlink-account.ts +100 -0
- package/src/features/auth/hooks/use-verify-email-token.ts +125 -0
- package/src/features/auth/index.ts +75 -0
- package/src/features/auth/screens/forgot-password-screen.tsx +33 -0
- package/src/features/auth/screens/index.ts +7 -0
- package/src/features/auth/screens/onboarding-screen.tsx +49 -0
- package/src/features/auth/screens/reset-password-screen.tsx +33 -0
- package/src/features/auth/screens/sign-in-screen.tsx +61 -0
- package/src/features/auth/screens/sign-up-screen.tsx +37 -0
- package/src/features/auth/screens/verify-email-confirm-screen.tsx +286 -0
- package/src/features/auth/screens/verify-email-screen.tsx +146 -0
- package/src/features/auth/types/index.ts +14 -0
- package/src/features/auth/utils/__tests__/validators.test.ts +331 -0
- package/src/features/auth/utils/password-strength.ts +129 -0
- package/src/features/auth/utils/validators.ts +124 -0
- package/src/features/email-preview/actions/render-email.ts +21 -0
- package/src/features/email-preview/screens/email-preview-screen.tsx +81 -0
- package/src/features/folder-scaffold-template/index.ts +0 -0
- package/src/features/instance-settings/components/index.ts +6 -0
- package/src/features/instance-settings/components/instance-settings-form.tsx +180 -0
- package/src/features/instance-settings/components/instance-status-display.tsx +158 -0
- package/src/features/instance-settings/index.ts +7 -0
- package/src/features/instance-settings/screens/index.ts +5 -0
- package/src/features/instance-settings/screens/instance-settings-screen.tsx +59 -0
- package/src/features/issues/README.md +330 -0
- package/src/features/issues/api/create-issue.ts +19 -0
- package/src/features/issues/api/delete-issue.ts +27 -0
- package/src/features/issues/api/get-issue-activities.ts +58 -0
- package/src/features/issues/api/get-issue-details.ts +25 -0
- package/src/features/issues/api/get-project-issues-server.ts +44 -0
- package/src/features/issues/api/get-project-issues.ts +21 -0
- package/src/features/issues/api/index.ts +44 -0
- package/src/features/issues/api/update-issue.ts +31 -0
- package/src/features/issues/api/upload-attachment.ts +81 -0
- package/src/features/issues/components/activity-timeline.tsx +440 -0
- package/src/features/issues/components/canvas-state-indicator.tsx +90 -0
- package/src/features/issues/components/centered-canvas-view.tsx +739 -0
- package/src/features/issues/components/image-selector.tsx +123 -0
- package/src/features/issues/components/image-upload-zone.tsx +262 -0
- package/src/features/issues/components/infinite-canvas-background.tsx +163 -0
- package/src/features/issues/components/inline-editable-select.tsx +173 -0
- package/src/features/issues/components/inline-editable-text.tsx +225 -0
- package/src/features/issues/components/inline-editable-textarea.tsx +219 -0
- package/src/features/issues/components/inline-editable-user-select.tsx +202 -0
- package/src/features/issues/components/issue-deletion-dialog.tsx +142 -0
- package/src/features/issues/components/issue-details-panel.tsx +101 -0
- package/src/features/issues/components/issues-create-dialog.tsx +578 -0
- package/src/features/issues/components/issues-list-filter.tsx +312 -0
- package/src/features/issues/components/issues-list.tsx +151 -0
- package/src/features/issues/components/issues-priority-badge.tsx +77 -0
- package/src/features/issues/components/issues-status-badge.tsx +100 -0
- package/src/features/issues/components/metadata-section.tsx +389 -0
- package/src/features/issues/components/optimized-attachment-view.tsx +528 -0
- package/src/features/issues/components/optimized-image.tsx +257 -0
- package/src/features/issues/components/panel-header.tsx +186 -0
- package/src/features/issues/components/preload.ts +31 -0
- package/src/features/issues/components/priority-selector.tsx +101 -0
- package/src/features/issues/components/responsive-issue-layout-skeleton.tsx +139 -0
- package/src/features/issues/components/responsive-issue-layout.tsx +617 -0
- package/src/features/issues/components/status-selector.tsx +320 -0
- package/src/features/issues/components/type-selector.tsx +102 -0
- package/src/features/issues/components/upload-progress-overlay.tsx +35 -0
- package/src/features/issues/components/uploaded-image-preview.tsx +173 -0
- package/src/features/issues/components/workflow-control.tsx +318 -0
- package/src/features/issues/components/zoom-controls.tsx +150 -0
- package/src/features/issues/config/index.ts +47 -0
- package/src/features/issues/config/options.ts +323 -0
- package/src/features/issues/config/workflow.ts +102 -0
- package/src/features/issues/docs/ARCHITECTURE_DIAGRAM.md +321 -0
- package/src/features/issues/docs/BACKEND_ARCHITECTURE.md +194 -0
- package/src/features/issues/docs/IMAGE_COMPONENTS_ARCHITECTURE.md +363 -0
- package/src/features/issues/docs/IMAGE_COMPONENTS_IMPORTS.md +412 -0
- package/src/features/issues/docs/IMPLEMENTATION_CHECKLIST.md +210 -0
- package/src/features/issues/docs/ROUTE_SETUP_COMPLETE.md +242 -0
- package/src/features/issues/hooks/index.ts +78 -0
- package/src/features/issues/hooks/use-canvas-transform.ts +255 -0
- package/src/features/issues/hooks/use-create-issue.ts +28 -0
- package/src/features/issues/hooks/use-elastic-scroll.ts +296 -0
- package/src/features/issues/hooks/use-issue-activities.ts +71 -0
- package/src/features/issues/hooks/use-issue-delete.ts +84 -0
- package/src/features/issues/hooks/use-issue-details.ts +70 -0
- package/src/features/issues/hooks/use-issue-filters.ts +50 -0
- package/src/features/issues/hooks/use-issue-update.ts +93 -0
- package/src/features/issues/hooks/use-keyboard-shortcuts.ts +104 -0
- package/src/features/issues/hooks/use-optimized-image.ts +228 -0
- package/src/features/issues/hooks/use-project-issues.ts +14 -0
- package/src/features/issues/index.ts +65 -0
- package/src/features/issues/screens/issue-details-screen.tsx +207 -0
- package/src/features/issues/screens/issue-details-skeletons.tsx +295 -0
- package/src/features/issues/screens/issue-share-screen.tsx +56 -0
- package/src/features/issues/types/index.ts +48 -0
- package/src/features/issues/types/issue.ts +291 -0
- package/src/features/issues/utils/filter-issues.ts +141 -0
- package/src/features/issues/utils/index.ts +14 -0
- package/src/features/legal/index.ts +1 -0
- package/src/features/legal/screens/privacy-policy-screen.tsx +307 -0
- package/src/features/notifications/api/get-notifications.ts +58 -0
- package/src/features/notifications/api/get-unread-count.ts +37 -0
- package/src/features/notifications/api/index.ts +35 -0
- package/src/features/notifications/api/mark-all-as-read.ts +37 -0
- package/src/features/notifications/api/mark-as-read.ts +41 -0
- package/src/features/notifications/api/types.ts +109 -0
- package/src/features/notifications/hooks/__tests__/use-notification-subscription.test.ts +206 -0
- package/src/features/notifications/hooks/index.ts +28 -0
- package/src/features/notifications/hooks/use-mark-all-as-read.ts +106 -0
- package/src/features/notifications/hooks/use-mark-as-read.ts +106 -0
- package/src/features/notifications/hooks/use-notification-subscription.ts +244 -0
- package/src/features/notifications/hooks/use-notification-toast.ts +161 -0
- package/src/features/notifications/hooks/use-notifications.ts +80 -0
- package/src/features/notifications/hooks/use-unread-count.ts +60 -0
- package/src/features/notifications/index.ts +48 -0
- package/src/features/notifications/utils/group-notifications.ts +152 -0
- package/src/features/notifications/utils/index.ts +9 -0
- package/src/features/projects/api/create-invitation.ts +45 -0
- package/src/features/projects/api/create-project.ts +64 -0
- package/src/features/projects/api/delete-project.ts +50 -0
- package/src/features/projects/api/get-project-activities.ts +43 -0
- package/src/features/projects/api/get-project-members.ts +53 -0
- package/src/features/projects/api/get-project.ts +49 -0
- package/src/features/projects/api/get-projects.ts +61 -0
- package/src/features/projects/api/index.ts +27 -0
- package/src/features/projects/api/join-project.ts +52 -0
- package/src/features/projects/api/leave-project.ts +51 -0
- package/src/features/projects/api/list-invitations.ts +36 -0
- package/src/features/projects/api/remove-member.ts +60 -0
- package/src/features/projects/api/resend-invitation.ts +36 -0
- package/src/features/projects/api/revoke-invitation.ts +36 -0
- package/src/features/projects/api/types.ts +286 -0
- package/src/features/projects/api/update-member-role.ts +70 -0
- package/src/features/projects/api/update-project.ts +69 -0
- package/src/features/projects/components/__tests__/project-detail-activity-feed.test.tsx +106 -0
- package/src/features/projects/components/__tests__/project-invitation-dialog.test.tsx +211 -0
- package/src/features/projects/components/__tests__/project-member-manager-dialog.test.tsx +254 -0
- package/src/features/projects/components/index.ts +21 -0
- package/src/features/projects/components/project-actions.tsx +248 -0
- package/src/features/projects/components/project-create-dialog.tsx +410 -0
- package/src/features/projects/components/project-detail-activity-feed.tsx +206 -0
- package/src/features/projects/components/project-detail-header.tsx +103 -0
- package/src/features/projects/components/project-detail-overview.tsx +128 -0
- package/src/features/projects/components/project-icon-selector.test.tsx +49 -0
- package/src/features/projects/components/project-icon-selector.tsx +76 -0
- package/src/features/projects/components/project-invitation-dialog.tsx +368 -0
- package/src/features/projects/components/project-issues.tsx +128 -0
- package/src/features/projects/components/project-leave-button.tsx +69 -0
- package/src/features/projects/components/project-list-card.tsx +246 -0
- package/src/features/projects/components/project-list-filters.tsx +320 -0
- package/src/features/projects/components/project-member-manager-dialog.tsx +419 -0
- package/src/features/projects/components/project-settings-dialog.tsx +204 -0
- package/src/features/projects/components/project-stats.tsx +46 -0
- package/src/features/projects/components/project-title-section.tsx +78 -0
- package/src/features/projects/config/icons.ts +91 -0
- package/src/features/projects/hooks/index.ts +28 -0
- package/src/features/projects/hooks/use-create-invitation.ts +83 -0
- package/src/features/projects/hooks/use-create-project.ts +77 -0
- package/src/features/projects/hooks/use-delete-project.ts +84 -0
- package/src/features/projects/hooks/use-join-project.ts +43 -0
- package/src/features/projects/hooks/use-leave-project.ts +84 -0
- package/src/features/projects/hooks/use-project-activities.ts +39 -0
- package/src/features/projects/hooks/use-project-filters.ts +86 -0
- package/src/features/projects/hooks/use-project-invitations.ts +66 -0
- package/src/features/projects/hooks/use-project-members.ts +57 -0
- package/src/features/projects/hooks/use-project.ts +67 -0
- package/src/features/projects/hooks/use-projects.ts +49 -0
- package/src/features/projects/hooks/use-recent-projects.ts +58 -0
- package/src/features/projects/hooks/use-remove-member.ts +89 -0
- package/src/features/projects/hooks/use-resend-invitation.ts +68 -0
- package/src/features/projects/hooks/use-revoke-invitation.ts +71 -0
- package/src/features/projects/hooks/use-team-member-suggestions.ts +133 -0
- package/src/features/projects/hooks/use-update-member-role.ts +92 -0
- package/src/features/projects/hooks/use-update-project.ts +88 -0
- package/src/features/projects/index.ts +91 -0
- package/src/features/projects/screens/index.ts +3 -0
- package/src/features/projects/screens/invitation-acceptance-screen.tsx +320 -0
- package/src/features/projects/screens/project-detail-screen-wrapper.tsx +47 -0
- package/src/features/projects/screens/project-detail-screen.tsx +661 -0
- package/src/features/projects/screens/projects-list-screen.tsx +161 -0
- package/src/features/projects/types/index.ts +59 -0
- package/src/features/projects/utils/format-helpers.ts +16 -0
- package/src/features/projects/utils/index.ts +2 -0
- package/src/features/projects/utils/role-helpers.ts +25 -0
- package/src/features/setup/api/complete-setup.ts +21 -0
- package/src/features/setup/api/create-admin.ts +21 -0
- package/src/features/setup/api/create-first-workspace.ts +21 -0
- package/src/features/setup/api/get-instance-status.ts +12 -0
- package/src/features/setup/api/get-service-health.ts +12 -0
- package/src/features/setup/api/index.ts +44 -0
- package/src/features/setup/api/save-instance-config.ts +21 -0
- package/src/features/setup/api/types.ts +122 -0
- package/src/features/setup/components/__tests__/setup-wizard-ui.test.tsx +362 -0
- package/src/features/setup/components/admin-account-step.tsx +205 -0
- package/src/features/setup/components/first-workspace-step.tsx +120 -0
- package/src/features/setup/components/index.ts +9 -0
- package/src/features/setup/components/instance-config-step.tsx +107 -0
- package/src/features/setup/components/mail-config-step.tsx +205 -0
- package/src/features/setup/components/sample-data-step.tsx +131 -0
- package/src/features/setup/components/service-health-step.tsx +180 -0
- package/src/features/setup/components/service-status-badge.tsx +50 -0
- package/src/features/setup/components/setup-progress.tsx +103 -0
- package/src/features/setup/components/setup-wizard.tsx +169 -0
- package/src/features/setup/hooks/index.ts +12 -0
- package/src/features/setup/hooks/use-complete-setup.ts +23 -0
- package/src/features/setup/hooks/use-create-admin.ts +25 -0
- package/src/features/setup/hooks/use-create-first-workspace.ts +24 -0
- package/src/features/setup/hooks/use-instance-status.ts +21 -0
- package/src/features/setup/hooks/use-save-instance-config.ts +23 -0
- package/src/features/setup/hooks/use-service-health.ts +21 -0
- package/src/features/setup/hooks/use-setup-wizard.ts +152 -0
- package/src/features/setup/hooks/use-workspace-mode.ts +19 -0
- package/src/features/setup/index.ts +30 -0
- package/src/features/setup/screens/index.ts +1 -0
- package/src/features/setup/screens/setup-screen.tsx +40 -0
- package/src/features/setup/types/index.ts +69 -0
- package/src/features/setup/utils/index.ts +78 -0
- package/src/features/team-settings/components/index.ts +39 -0
- package/src/features/team-settings/components/loading-states.tsx +296 -0
- package/src/features/team-settings/components/permission-guard.tsx +23 -0
- package/src/features/team-settings/components/settings-card.tsx +22 -0
- package/src/features/team-settings/components/settings-context-provider.tsx +51 -0
- package/src/features/team-settings/components/settings-error-boundary.tsx +366 -0
- package/src/features/team-settings/components/settings-navigation.tsx +87 -0
- package/src/features/team-settings/components/settings-section.tsx +23 -0
- package/src/features/team-settings/components/team-danger-zone.tsx +275 -0
- package/src/features/team-settings/components/team-information-form.tsx +116 -0
- package/src/features/team-settings/components/team-invitations-list.tsx +463 -0
- package/src/features/team-settings/components/team-members-list.tsx +342 -0
- package/src/features/team-settings/components/team-permission-guard.tsx +56 -0
- package/src/features/team-settings/components/team-setting-integrations.tsx +27 -0
- package/src/features/team-settings/components/team-setting-member.tsx +28 -0
- package/src/features/team-settings/components/team-settings-general.tsx +131 -0
- package/src/features/team-settings/components/transfer-ownership-modal.tsx +164 -0
- package/src/features/team-settings/components/unauthorized-access.tsx +52 -0
- package/src/features/team-settings/hooks/__tests__/use-team-settings.test.tsx +139 -0
- package/src/features/team-settings/hooks/index.ts +1 -0
- package/src/features/team-settings/hooks/use-team-settings.ts +148 -0
- package/src/features/team-settings/hooks/use-transfer-ownership.ts +45 -0
- package/src/features/team-settings/index.ts +25 -0
- package/src/features/team-settings/screens/index.ts +1 -0
- package/src/features/team-settings/screens/team-settings-screen.tsx +33 -0
- package/src/features/team-settings/types/index.ts +78 -0
- package/src/features/team-settings/utils/index.ts +6 -0
- package/src/features/team-settings/utils/mock-data.ts +40 -0
- package/src/features/teams/api/cancel-invitation.ts +25 -0
- package/src/features/teams/api/create-invitation.ts +28 -0
- package/src/features/teams/api/create-team.ts +14 -0
- package/src/features/teams/api/delete-team.ts +19 -0
- package/src/features/teams/api/get-invitations.ts +25 -0
- package/src/features/teams/api/get-team-members.ts +25 -0
- package/src/features/teams/api/get-team.ts +13 -0
- package/src/features/teams/api/get-teams.ts +19 -0
- package/src/features/teams/api/index.ts +49 -0
- package/src/features/teams/api/leave-team.ts +22 -0
- package/src/features/teams/api/remove-member.ts +25 -0
- package/src/features/teams/api/resend-invitation.ts +26 -0
- package/src/features/teams/api/switch-team.ts +13 -0
- package/src/features/teams/api/types.ts +122 -0
- package/src/features/teams/api/update-member-roles.ts +28 -0
- package/src/features/teams/api/update-team.ts +17 -0
- package/src/features/teams/components/create-team-dialog.tsx +105 -0
- package/src/features/teams/hooks/__tests__/cache-invalidation.property.test.tsx +268 -0
- package/src/features/teams/hooks/index.ts +35 -0
- package/src/features/teams/hooks/use-can-manage-members.ts +21 -0
- package/src/features/teams/hooks/use-can-manage-team.ts +21 -0
- package/src/features/teams/hooks/use-cancel-invitation.ts +52 -0
- package/src/features/teams/hooks/use-create-invitation.ts +59 -0
- package/src/features/teams/hooks/use-create-team.ts +38 -0
- package/src/features/teams/hooks/use-delete-team.ts +43 -0
- package/src/features/teams/hooks/use-invitations.ts +31 -0
- package/src/features/teams/hooks/use-leave-team.ts +43 -0
- package/src/features/teams/hooks/use-remove-member.ts +58 -0
- package/src/features/teams/hooks/use-resend-invitation.ts +52 -0
- package/src/features/teams/hooks/use-switch-team.ts +41 -0
- package/src/features/teams/hooks/use-team-members.ts +31 -0
- package/src/features/teams/hooks/use-team-permissions.ts +102 -0
- package/src/features/teams/hooks/use-team.ts +30 -0
- package/src/features/teams/hooks/use-teams.ts +26 -0
- package/src/features/teams/hooks/use-update-member-roles.ts +64 -0
- package/src/features/teams/hooks/use-update-team.ts +47 -0
- package/src/features/teams/index.ts +111 -0
- package/src/features/user-settings/actions/set-password.ts +63 -0
- package/src/features/user-settings/api/index.ts +16 -0
- package/src/features/user-settings/components/__tests__/security-settings.test.tsx +125 -0
- package/src/features/user-settings/components/delete-account-dialog.tsx +185 -0
- package/src/features/user-settings/components/index.ts +13 -0
- package/src/features/user-settings/components/integrations-list.tsx +152 -0
- package/src/features/user-settings/components/notification-preferences.tsx +112 -0
- package/src/features/user-settings/components/other-settings.tsx +126 -0
- package/src/features/user-settings/components/password-section.tsx +297 -0
- package/src/features/user-settings/components/security-settings.tsx +184 -0
- package/src/features/user-settings/components/user-preferences.tsx +146 -0
- package/src/features/user-settings/hooks/index.ts +8 -0
- package/src/features/user-settings/hooks/use-notification-preferences.ts +65 -0
- package/src/features/user-settings/hooks/use-user-preferences.ts +52 -0
- package/src/features/user-settings/index.ts +22 -0
- package/src/features/user-settings/screens/index.ts +11 -0
- package/src/features/user-settings/screens/integrations-screen.tsx +24 -0
- package/src/features/user-settings/screens/notifications-screen.tsx +29 -0
- package/src/features/user-settings/screens/other-settings-screen.tsx +24 -0
- package/src/features/user-settings/screens/setting-preferences-screen.tsx +24 -0
- package/src/features/user-settings/screens/user-settings-screen.tsx +23 -0
- package/src/features/user-settings/types/index.ts +42 -0
- package/src/features/user-settings/utils/index.ts +8 -0
- package/src/hooks/use-long-press.ts +196 -0
- package/src/hooks/use-media-upload.ts +95 -0
- package/src/hooks/use-mobile.ts +19 -0
- package/src/hooks/use-team.ts +32 -0
- package/src/instrumentation.ts +14 -0
- package/src/lib/__tests__/auth-config.test.ts +166 -0
- package/src/lib/__tests__/config.test.ts +42 -0
- package/src/lib/__tests__/db.test.ts +101 -0
- package/src/lib/__tests__/env.property.test.ts +197 -0
- package/src/lib/__tests__/env.test.ts +177 -0
- package/src/lib/__tests__/health-check.test.ts +87 -0
- package/src/lib/__tests__/oauth-errors.test.ts +184 -0
- package/src/lib/__tests__/oauth-redirect.test.ts +224 -0
- package/src/lib/__tests__/oauth-scopes.test.ts +268 -0
- package/src/lib/__tests__/storage.test.ts +58 -0
- package/src/lib/__tests__/url-validator.test.ts +232 -0
- package/src/lib/api-client.ts +93 -0
- package/src/lib/auth-client.ts +5 -0
- package/src/lib/auth-config.ts +146 -0
- package/src/lib/auth.ts +209 -0
- package/src/lib/config.ts +228 -0
- package/src/lib/cors.ts +96 -0
- package/src/lib/date.ts +16 -0
- package/src/lib/db.ts +88 -0
- package/src/lib/env.ts +489 -0
- package/src/lib/feedback.ts +29 -0
- package/src/lib/health-check.ts +229 -0
- package/src/lib/logger.ts +204 -0
- package/src/lib/oauth-errors.ts +138 -0
- package/src/lib/performance.ts +367 -0
- package/src/lib/query-server.ts +35 -0
- package/src/lib/query.tsx +43 -0
- package/src/lib/resend.ts +36 -0
- package/src/lib/security-headers.ts +165 -0
- package/src/lib/setup-status.ts +34 -0
- package/src/lib/storage.ts +150 -0
- package/src/lib/supabase-client.ts +58 -0
- package/src/lib/testing/test-db.ts +75 -0
- package/src/lib/url-validator.ts +168 -0
- package/src/lib/utils.ts +6 -0
- package/src/mocks/README.md +42 -0
- package/src/mocks/activity.fixtures.ts +281 -0
- package/src/mocks/annotation.fixtures.ts +325 -0
- package/src/mocks/attachment.fixtures.ts +80 -0
- package/src/mocks/email.fixtures.ts +61 -0
- package/src/mocks/index.ts +33 -0
- package/src/mocks/issue.fixtures.ts +364 -0
- package/src/mocks/landing.fixtures.ts +118 -0
- package/src/mocks/notification.fixtures.ts +111 -0
- package/src/mocks/project-activity.fixtures.ts +69 -0
- package/src/mocks/project-invitation.fixtures.ts +95 -0
- package/src/mocks/project-member.fixtures.ts +93 -0
- package/src/mocks/project.fixtures.ts +249 -0
- package/src/mocks/settings.fixtures.ts +56 -0
- package/src/mocks/share.fixtures.ts +48 -0
- package/src/mocks/team-member.fixtures.ts +147 -0
- package/src/mocks/team.fixtures.ts +35 -0
- package/src/mocks/user-settings.fixtures.ts +77 -0
- package/src/mocks/user.fixtures.ts +21 -0
- package/src/providers/theme-provider.tsx +11 -0
- package/src/proxy/__tests__/proxy-setup-gate.test.ts +43 -0
- package/src/proxy.ts +169 -0
- package/src/server/annotations/__tests__/annotation-limit.property.test.ts +291 -0
- package/src/server/annotations/__tests__/attachment-deletion-cascade.property.test.ts +385 -0
- package/src/server/annotations/__tests__/comment-delete-authorization.property.test.ts +419 -0
- package/src/server/annotations/__tests__/sanitize.property.test.ts +302 -0
- package/src/server/annotations/annotation-service.ts +305 -0
- package/src/server/annotations/comment-service.ts +288 -0
- package/src/server/annotations/index.ts +61 -0
- package/src/server/annotations/permission-utils.ts +125 -0
- package/src/server/annotations/sanitize.ts +134 -0
- package/src/server/annotations/types.ts +161 -0
- package/src/server/audit/audit-service.ts +85 -0
- package/src/server/audit/index.ts +11 -0
- package/src/server/audit/types.ts +75 -0
- package/src/server/auth/__tests__/README.md +368 -0
- package/src/server/auth/__tests__/account-linking.integration.test.ts +410 -0
- package/src/server/auth/__tests__/auth-integration.test.ts +811 -0
- package/src/server/auth/__tests__/cookies.test.ts +337 -0
- package/src/server/auth/__tests__/login.property.test.ts +428 -0
- package/src/server/auth/__tests__/oauth-integration.test.ts +555 -0
- package/src/server/auth/__tests__/password.test.ts +194 -0
- package/src/server/auth/__tests__/rate-limiter.test.ts +450 -0
- package/src/server/auth/__tests__/rbac.test.ts +474 -0
- package/src/server/auth/__tests__/session.test.ts +599 -0
- package/src/server/auth/__tests__/signup.property.test.ts +224 -0
- package/src/server/auth/__tests__/token-encryption.test.ts +171 -0
- package/src/server/auth/__tests__/tokens.test.ts +476 -0
- package/src/server/auth/__tests__/verify-email.property.test.ts +372 -0
- package/src/server/auth/cookies.ts +184 -0
- package/src/server/auth/password.ts +94 -0
- package/src/server/auth/rate-limiter.ts +257 -0
- package/src/server/auth/rbac.ts +1168 -0
- package/src/server/auth/session.ts +392 -0
- package/src/server/auth/token-encryption.ts +201 -0
- package/src/server/auth/tokens.ts +397 -0
- package/src/server/db/schema/account.ts +21 -0
- package/src/server/db/schema/annotation-read-status.ts +57 -0
- package/src/server/db/schema/better-auth-verifications.ts +27 -0
- package/src/server/db/schema/email-jobs.ts +24 -0
- package/src/server/db/schema/index.ts +20 -0
- package/src/server/db/schema/instance-settings.ts +42 -0
- package/src/server/db/schema/issue-activities.ts +97 -0
- package/src/server/db/schema/issue-attachments.ts +101 -0
- package/src/server/db/schema/issues.ts +139 -0
- package/src/server/db/schema/notifications.ts +119 -0
- package/src/server/db/schema/project-activities.ts +116 -0
- package/src/server/db/schema/project-invitations.ts +34 -0
- package/src/server/db/schema/project-members.ts +29 -0
- package/src/server/db/schema/projects.ts +46 -0
- package/src/server/db/schema/sessions.ts +17 -0
- package/src/server/db/schema/team-invitations.ts +22 -0
- package/src/server/db/schema/team-members.ts +18 -0
- package/src/server/db/schema/teams.ts +15 -0
- package/src/server/db/schema/user-roles.ts +14 -0
- package/src/server/db/schema/users.ts +17 -0
- package/src/server/db/schema/verification-tokens.ts +15 -0
- package/src/server/email/README.md +258 -0
- package/src/server/email/__tests__/client.property.test.ts +218 -0
- package/src/server/email/__tests__/payload.property.test.ts +205 -0
- package/src/server/email/__tests__/queue.test.ts +407 -0
- package/src/server/email/__tests__/render-template.test.tsx +172 -0
- package/src/server/email/client.ts +70 -0
- package/src/server/email/index.ts +20 -0
- package/src/server/email/providers/console-provider.ts +43 -0
- package/src/server/email/providers/index.ts +5 -0
- package/src/server/email/providers/resend-provider.ts +59 -0
- package/src/server/email/providers/smtp-provider.ts +65 -0
- package/src/server/email/queue.ts +365 -0
- package/src/server/email/render-template.tsx +117 -0
- package/src/server/email/templates/layout.tsx +66 -0
- package/src/server/email/templates/ownership-transfer-email.tsx +75 -0
- package/src/server/email/templates/password-reset-email.tsx +72 -0
- package/src/server/email/templates/project-invitation-email.tsx +70 -0
- package/src/server/email/templates/security-alert-email.tsx +161 -0
- package/src/server/email/templates/team-invitation-email.tsx +68 -0
- package/src/server/email/templates/verification-email.tsx +61 -0
- package/src/server/email/templates/welcome-email.tsx +60 -0
- package/src/server/email/worker.ts +182 -0
- package/src/server/issues/activity-service.ts +422 -0
- package/src/server/issues/attachment-service.ts +379 -0
- package/src/server/issues/index.ts +68 -0
- package/src/server/issues/issue-service.ts +569 -0
- package/src/server/issues/types.ts +233 -0
- package/src/server/notifications/__tests__/notification-service.integration.test.ts +405 -0
- package/src/server/notifications/index.ts +13 -0
- package/src/server/notifications/notification-service.ts +526 -0
- package/src/server/notifications/types.ts +234 -0
- package/src/server/projects/__tests__/activity-logging.integration.test.ts +319 -0
- package/src/server/projects/__tests__/invitation-email.integration.test.ts +258 -0
- package/src/server/projects/__tests__/invitation-service.integration.test.ts +651 -0
- package/src/server/projects/__tests__/member-service.property.test.ts +397 -0
- package/src/server/projects/__tests__/project-service.property.test.ts +116 -0
- package/src/server/projects/activity-service.ts +548 -0
- package/src/server/projects/index.ts +11 -0
- package/src/server/projects/invitation-service.ts +773 -0
- package/src/server/projects/member-service.ts +458 -0
- package/src/server/projects/project-service.ts +491 -0
- package/src/server/projects/schemas.ts +310 -0
- package/src/server/projects/types.ts +166 -0
- package/src/server/projects/utils.ts +128 -0
- package/src/server/setup/__tests__/health-check.property.test.ts +70 -0
- package/src/server/setup/__tests__/sample-data.property.test.ts +82 -0
- package/src/server/setup/__tests__/setup.property.test.ts +95 -0
- package/src/server/setup/health-check-service.ts +294 -0
- package/src/server/setup/index.ts +35 -0
- package/src/server/setup/sample-data-service.ts +233 -0
- package/src/server/setup/setup-service.ts +229 -0
- package/src/server/setup/types.ts +96 -0
- package/src/server/teams/__tests__/export.property.test.ts +542 -0
- package/src/server/teams/__tests__/get-members.integration.test.ts +105 -0
- package/src/server/teams/__tests__/invitation-flow.integration.test.ts +402 -0
- package/src/server/teams/__tests__/invitations.property.test.ts +235 -0
- package/src/server/teams/__tests__/member-management-flow.integration.test.ts +306 -0
- package/src/server/teams/__tests__/members.property.test.ts +180 -0
- package/src/server/teams/__tests__/ownership-transfer.property.test.ts +173 -0
- package/src/server/teams/__tests__/resource-limits.property.test.ts +382 -0
- package/src/server/teams/__tests__/team-context-management.integration.test.ts +396 -0
- package/src/server/teams/__tests__/team-context.property.test.ts +854 -0
- package/src/server/teams/__tests__/team-creation-flow.integration.test.ts +310 -0
- package/src/server/teams/__tests__/team-creation.property.test.ts +280 -0
- package/src/server/teams/errors.ts +396 -0
- package/src/server/teams/export-service.ts +383 -0
- package/src/server/teams/index.ts +10 -0
- package/src/server/teams/invitation-service.ts +708 -0
- package/src/server/teams/member-service.ts +334 -0
- package/src/server/teams/resource-limits.ts +211 -0
- package/src/server/teams/slug.ts +58 -0
- package/src/server/teams/team-context.ts +648 -0
- package/src/server/teams/team-service.ts +660 -0
- package/src/server/teams/types.ts +81 -0
- package/src/server/teams/validation.ts +209 -0
- package/src/styles/globals.css +160 -0
- package/src/types/deployment.ts +39 -0
- package/supabase/config.toml +357 -0
- package/supabase/seed.sql +480 -0
- package/tests/e2e/.gitkeep +0 -0
- package/tests/e2e/QUICK_START.md +98 -0
- package/tests/e2e/README.md +301 -0
- package/tests/e2e/auth.spec.ts +583 -0
- package/tests/e2e/global-setup.ts +23 -0
- package/tests/e2e/global-teardown.ts +23 -0
- package/tests/e2e/helpers/auth-helpers.ts +310 -0
- package/tests/e2e/helpers/test-fixtures.ts +286 -0
- package/tests/e2e/smoke-test.spec.ts +330 -0
- package/tsconfig.json +48 -0
- package/vitest.config.ts +50 -0
- package/vitest.setup.ts +56 -0
- package/dist/index.js +0 -778
|
@@ -0,0 +1,896 @@
|
|
|
1
|
+
# Environment Configuration Guide
|
|
2
|
+
|
|
3
|
+
This guide explains how to use the environment-specific configuration utilities in UI SyncUp.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The application provides a centralized configuration system through `src/lib/config.ts` that handles:
|
|
8
|
+
|
|
9
|
+
- Environment detection (production, development, test, preview)
|
|
10
|
+
- Feature flags management
|
|
11
|
+
- Environment-specific configuration values
|
|
12
|
+
- Deployment metadata access
|
|
13
|
+
|
|
14
|
+
## Environment Detection
|
|
15
|
+
|
|
16
|
+
### Basic Environment Checks
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { isProduction, isDevelopment, isTest } from '@/lib/config'
|
|
20
|
+
|
|
21
|
+
// Check current environment
|
|
22
|
+
if (isProduction()) {
|
|
23
|
+
// Production-only code (e.g., enable monitoring)
|
|
24
|
+
initializeErrorTracking()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (isDevelopment()) {
|
|
28
|
+
// Development-only code (e.g., debug logging)
|
|
29
|
+
console.log('Debug mode enabled')
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (isTest()) {
|
|
33
|
+
// Test-only code
|
|
34
|
+
mockExternalServices()
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Vercel-Specific Checks
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { isPreview, isVercelProduction, isVercel } from '@/lib/config'
|
|
42
|
+
|
|
43
|
+
// Check if running on Vercel preview environment
|
|
44
|
+
if (isPreview()) {
|
|
45
|
+
// Preview deployment code
|
|
46
|
+
showPreviewBanner()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Check if running on Vercel production
|
|
50
|
+
if (isVercelProduction()) {
|
|
51
|
+
// Vercel production-specific code
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Check if running on Vercel platform at all
|
|
55
|
+
if (isVercel()) {
|
|
56
|
+
// Any Vercel deployment (production or preview)
|
|
57
|
+
enableVercelAnalytics()
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Get Environment Name
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { getEnvironment } from '@/lib/config'
|
|
65
|
+
|
|
66
|
+
const env = getEnvironment()
|
|
67
|
+
// Returns: 'production' | 'preview' | 'development' | 'test'
|
|
68
|
+
|
|
69
|
+
console.log(`Running in ${env} environment`)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Feature Flags
|
|
73
|
+
|
|
74
|
+
### Built-in Feature Flags
|
|
75
|
+
|
|
76
|
+
The application supports two built-in feature flags:
|
|
77
|
+
|
|
78
|
+
1. **Analytics** - `NEXT_PUBLIC_ENABLE_ANALYTICS`
|
|
79
|
+
2. **Debug Mode** - `NEXT_PUBLIC_ENABLE_DEBUG`
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import { isAnalyticsEnabled, isDebugEnabled } from '@/lib/config'
|
|
83
|
+
|
|
84
|
+
// Check if analytics is enabled
|
|
85
|
+
if (isAnalyticsEnabled()) {
|
|
86
|
+
initializeAnalytics()
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Check if debug mode is enabled
|
|
90
|
+
if (isDebugEnabled()) {
|
|
91
|
+
enableVerboseLogging()
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Type-Safe Feature Flag Check
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { isFeatureEnabled } from '@/lib/config'
|
|
99
|
+
|
|
100
|
+
// Type-safe feature flag check
|
|
101
|
+
if (isFeatureEnabled('analytics')) {
|
|
102
|
+
// Analytics code
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (isFeatureEnabled('debug')) {
|
|
106
|
+
// Debug code
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Custom Feature Flags
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
import { getFeatureFlag } from '@/lib/config'
|
|
114
|
+
|
|
115
|
+
// Get custom feature flag with default value
|
|
116
|
+
const enableNewUI = getFeatureFlag('NEXT_PUBLIC_ENABLE_NEW_UI', false)
|
|
117
|
+
const enableBetaFeatures = getFeatureFlag('NEXT_PUBLIC_BETA_FEATURES', true)
|
|
118
|
+
|
|
119
|
+
if (enableNewUI) {
|
|
120
|
+
renderNewUI()
|
|
121
|
+
} else {
|
|
122
|
+
renderLegacyUI()
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Feature Flag Format
|
|
127
|
+
|
|
128
|
+
Feature flags accept the following truthy values (case-insensitive):
|
|
129
|
+
- `"true"`
|
|
130
|
+
- `"1"`
|
|
131
|
+
- `"yes"`
|
|
132
|
+
- `"on"`
|
|
133
|
+
|
|
134
|
+
All other values (including empty string) are considered false.
|
|
135
|
+
|
|
136
|
+
**Example `.env.local`:**
|
|
137
|
+
```bash
|
|
138
|
+
NEXT_PUBLIC_ENABLE_ANALYTICS=true
|
|
139
|
+
NEXT_PUBLIC_ENABLE_DEBUG=1
|
|
140
|
+
NEXT_PUBLIC_ENABLE_NEW_UI=yes
|
|
141
|
+
NEXT_PUBLIC_BETA_FEATURES=on
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Configuration Object
|
|
145
|
+
|
|
146
|
+
### Using the Config Object
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
import { config } from '@/lib/config'
|
|
150
|
+
|
|
151
|
+
// Environment information
|
|
152
|
+
console.log(config.env.isProduction) // boolean
|
|
153
|
+
console.log(config.env.isDevelopment) // boolean
|
|
154
|
+
console.log(config.env.isTest) // boolean
|
|
155
|
+
console.log(config.env.isPreview) // boolean
|
|
156
|
+
console.log(config.env.isVercelProduction) // boolean
|
|
157
|
+
console.log(config.env.isVercel) // boolean
|
|
158
|
+
console.log(config.env.name) // 'production' | 'preview' | 'development' | 'test'
|
|
159
|
+
|
|
160
|
+
// Feature flags
|
|
161
|
+
console.log(config.features.analytics) // boolean
|
|
162
|
+
console.log(config.features.debug) // boolean
|
|
163
|
+
|
|
164
|
+
// Application URLs
|
|
165
|
+
console.log(config.app.url) // string (e.g., 'https://ui-syncup.com')
|
|
166
|
+
console.log(config.app.apiUrl) // string (e.g., 'https://ui-syncup.com/api')
|
|
167
|
+
|
|
168
|
+
// Deployment information (Vercel)
|
|
169
|
+
console.log(config.deployment.branch) // string (e.g., 'main', 'develop')
|
|
170
|
+
console.log(config.deployment.commitSha) // string (e.g., 'abc123...')
|
|
171
|
+
console.log(config.deployment.commitMessage) // string
|
|
172
|
+
console.log(config.deployment.url) // string (Vercel deployment URL)
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Example: Conditional Rendering
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
import { config } from '@/lib/config'
|
|
179
|
+
|
|
180
|
+
export function AppHeader() {
|
|
181
|
+
return (
|
|
182
|
+
<header>
|
|
183
|
+
<Logo />
|
|
184
|
+
{config.env.isPreview && (
|
|
185
|
+
<Badge variant="warning">Preview Environment</Badge>
|
|
186
|
+
)}
|
|
187
|
+
{config.features.debug && (
|
|
188
|
+
<DebugPanel deployment={config.deployment} />
|
|
189
|
+
)}
|
|
190
|
+
</header>
|
|
191
|
+
)
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Environment-Specific Values
|
|
196
|
+
|
|
197
|
+
### Get Values Based on Environment
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
import { getEnvValue } from '@/lib/config'
|
|
201
|
+
|
|
202
|
+
// API timeout based on environment
|
|
203
|
+
const apiTimeout = getEnvValue({
|
|
204
|
+
production: 5000, // 5 seconds in production
|
|
205
|
+
preview: 10000, // 10 seconds in preview
|
|
206
|
+
development: 30000, // 30 seconds in development
|
|
207
|
+
default: 10000, // Default fallback
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
// Cache duration
|
|
211
|
+
const cacheDuration = getEnvValue({
|
|
212
|
+
production: 3600, // 1 hour in production
|
|
213
|
+
development: 60, // 1 minute in development
|
|
214
|
+
default: 300, // 5 minutes default
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
// Log level
|
|
218
|
+
const logLevel = getEnvValue({
|
|
219
|
+
production: 'error',
|
|
220
|
+
preview: 'warn',
|
|
221
|
+
development: 'debug',
|
|
222
|
+
test: 'silent',
|
|
223
|
+
default: 'info',
|
|
224
|
+
})
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Example: API Client Configuration
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
import { getEnvValue, isProduction } from '@/lib/config'
|
|
231
|
+
|
|
232
|
+
const apiConfig = {
|
|
233
|
+
timeout: getEnvValue({
|
|
234
|
+
production: 5000,
|
|
235
|
+
development: 30000,
|
|
236
|
+
default: 10000,
|
|
237
|
+
}),
|
|
238
|
+
retries: getEnvValue({
|
|
239
|
+
production: 3,
|
|
240
|
+
development: 1,
|
|
241
|
+
default: 2,
|
|
242
|
+
}),
|
|
243
|
+
enableLogging: !isProduction(),
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export const apiClient = createApiClient(apiConfig)
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## Runtime Environment Detection
|
|
250
|
+
|
|
251
|
+
### Browser vs Server
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
import { isBrowser, isServer } from '@/lib/config'
|
|
255
|
+
|
|
256
|
+
// Check if running in browser
|
|
257
|
+
if (isBrowser()) {
|
|
258
|
+
// Browser-only code
|
|
259
|
+
window.addEventListener('resize', handleResize)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Check if running on server
|
|
263
|
+
if (isServer()) {
|
|
264
|
+
// Server-only code
|
|
265
|
+
const data = await fetchServerData()
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Example: Conditional Imports
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
import { isBrowser } from '@/lib/config'
|
|
273
|
+
|
|
274
|
+
export async function initializeApp() {
|
|
275
|
+
if (isBrowser()) {
|
|
276
|
+
// Dynamically import browser-only modules
|
|
277
|
+
const { initAnalytics } = await import('./analytics')
|
|
278
|
+
initAnalytics()
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## Common Use Cases
|
|
284
|
+
|
|
285
|
+
### 1. Initialize Analytics
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
import { isProduction, isAnalyticsEnabled } from '@/lib/config'
|
|
289
|
+
|
|
290
|
+
export function initializeAnalytics() {
|
|
291
|
+
if (isProduction() && isAnalyticsEnabled()) {
|
|
292
|
+
// Initialize analytics only in production with flag enabled
|
|
293
|
+
analytics.init({
|
|
294
|
+
trackingId: process.env.NEXT_PUBLIC_GA_ID,
|
|
295
|
+
})
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### 2. Debug Logging
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
import { isDebugEnabled, isDevelopment } from '@/lib/config'
|
|
304
|
+
|
|
305
|
+
export function debugLog(message: string, data?: unknown) {
|
|
306
|
+
if (isDebugEnabled() || isDevelopment()) {
|
|
307
|
+
console.log(`[DEBUG] ${message}`, data)
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### 3. Feature Rollout
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
import { getFeatureFlag, isPreview } from '@/lib/config'
|
|
316
|
+
|
|
317
|
+
export function shouldShowNewFeature(): boolean {
|
|
318
|
+
// Show new feature in preview environments or if flag is enabled
|
|
319
|
+
return isPreview() || getFeatureFlag('NEXT_PUBLIC_ENABLE_NEW_FEATURE', false)
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### 4. Error Reporting
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
import { isProduction, config } from '@/lib/config'
|
|
327
|
+
|
|
328
|
+
export function reportError(error: Error) {
|
|
329
|
+
if (isProduction()) {
|
|
330
|
+
// Send to error tracking service
|
|
331
|
+
errorTracker.captureException(error, {
|
|
332
|
+
environment: config.env.name,
|
|
333
|
+
deployment: config.deployment,
|
|
334
|
+
})
|
|
335
|
+
} else {
|
|
336
|
+
// Log to console in development
|
|
337
|
+
console.error(error)
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### 5. API Base URL
|
|
343
|
+
|
|
344
|
+
```typescript
|
|
345
|
+
import { config } from '@/lib/config'
|
|
346
|
+
|
|
347
|
+
export const API_BASE_URL = config.app.apiUrl
|
|
348
|
+
|
|
349
|
+
export async function fetchData(endpoint: string) {
|
|
350
|
+
const response = await fetch(`${API_BASE_URL}${endpoint}`)
|
|
351
|
+
return response.json()
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### 6. Deployment Information Display
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
import { config, isPreview } from '@/lib/config'
|
|
359
|
+
|
|
360
|
+
export function DeploymentInfo() {
|
|
361
|
+
if (!isPreview()) return null
|
|
362
|
+
|
|
363
|
+
return (
|
|
364
|
+
<div className="deployment-info">
|
|
365
|
+
<p>Branch: {config.deployment.branch}</p>
|
|
366
|
+
<p>Commit: {config.deployment.commitSha.slice(0, 7)}</p>
|
|
367
|
+
<p>Message: {config.deployment.commitMessage}</p>
|
|
368
|
+
</div>
|
|
369
|
+
)
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## Best Practices
|
|
374
|
+
|
|
375
|
+
### 1. Use Type-Safe Helpers
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
// ✅ Good - Type-safe
|
|
379
|
+
import { isProduction } from '@/lib/config'
|
|
380
|
+
if (isProduction()) { }
|
|
381
|
+
|
|
382
|
+
// ❌ Avoid - Direct env access
|
|
383
|
+
if (process.env.NODE_ENV === 'production') { }
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### 2. Centralize Feature Flags
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
// ✅ Good - Use config utilities
|
|
390
|
+
import { isFeatureEnabled } from '@/lib/config'
|
|
391
|
+
const showNewUI = isFeatureEnabled('analytics')
|
|
392
|
+
|
|
393
|
+
// ❌ Avoid - Manual parsing
|
|
394
|
+
const showNewUI = process.env.NEXT_PUBLIC_ENABLE_ANALYTICS === 'true'
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### 3. Use Config Object for Multiple Checks
|
|
398
|
+
|
|
399
|
+
```typescript
|
|
400
|
+
// ✅ Good - Single import
|
|
401
|
+
import { config } from '@/lib/config'
|
|
402
|
+
if (config.env.isProduction && config.features.analytics) { }
|
|
403
|
+
|
|
404
|
+
// ❌ Avoid - Multiple imports
|
|
405
|
+
import { isProduction, isAnalyticsEnabled } from '@/lib/config'
|
|
406
|
+
if (isProduction() && isAnalyticsEnabled()) { }
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### 4. Document Custom Feature Flags
|
|
410
|
+
|
|
411
|
+
When adding new feature flags, document them:
|
|
412
|
+
|
|
413
|
+
```typescript
|
|
414
|
+
/**
|
|
415
|
+
* Feature flag for new dashboard UI
|
|
416
|
+
* Environment variable: NEXT_PUBLIC_ENABLE_NEW_DASHBOARD
|
|
417
|
+
* Default: false
|
|
418
|
+
*/
|
|
419
|
+
export const useNewDashboard = () => {
|
|
420
|
+
return getFeatureFlag('NEXT_PUBLIC_ENABLE_NEW_DASHBOARD', false)
|
|
421
|
+
}
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
## Environment Variables Reference
|
|
425
|
+
|
|
426
|
+
### Required Variables
|
|
427
|
+
|
|
428
|
+
See `.env.example` for all required environment variables.
|
|
429
|
+
|
|
430
|
+
### Authentication Variables
|
|
431
|
+
|
|
432
|
+
#### better-auth Configuration
|
|
433
|
+
|
|
434
|
+
| Variable | Type | Required | Description |
|
|
435
|
+
|----------|------|----------|-------------|
|
|
436
|
+
| `BETTER_AUTH_SECRET` | string | ✅ Yes | Secret key for signing tokens and session cookies. Must be at least 32 characters. Keep this secure and never commit to version control. |
|
|
437
|
+
| `BETTER_AUTH_URL` | string (URL) | ✅ Yes | Base URL for authentication callbacks. Must match your deployment URL (e.g., `http://localhost:3000` for local, `https://your-domain.com` for production). |
|
|
438
|
+
|
|
439
|
+
#### Google OAuth
|
|
440
|
+
|
|
441
|
+
| Variable | Type | Required | Description |
|
|
442
|
+
|----------|------|----------|-------------|
|
|
443
|
+
| `GOOGLE_CLIENT_ID` | string | ✅ Yes | Google OAuth client ID from Google Cloud Console. |
|
|
444
|
+
| `GOOGLE_CLIENT_SECRET` | string | ✅ Yes | Google OAuth client secret. |
|
|
445
|
+
| `GOOGLE_REDIRECT_URI` | string (URL) | ✅ Yes | Google OAuth redirect URI (e.g., `http://localhost:3000/api/auth/callback/google`). |
|
|
446
|
+
|
|
447
|
+
#### Microsoft OAuth (Optional)
|
|
448
|
+
|
|
449
|
+
| Variable | Type | Required | Description |
|
|
450
|
+
|----------|------|----------|-------------|
|
|
451
|
+
| `MICROSOFT_CLIENT_ID` | string | ⚠️ Optional | Microsoft OAuth client ID from Azure AD. When not set, Microsoft sign-in is disabled. |
|
|
452
|
+
| `MICROSOFT_CLIENT_SECRET` | string | ⚠️ Optional | Microsoft OAuth client secret. |
|
|
453
|
+
| `MICROSOFT_TENANT_ID` | string | ⚠️ Optional | Microsoft tenant ID. Defaults to `common` for multi-tenant support. Use a specific tenant ID for single-tenant apps. |
|
|
454
|
+
|
|
455
|
+
#### Atlassian OAuth (Optional)
|
|
456
|
+
|
|
457
|
+
| Variable | Type | Required | Description |
|
|
458
|
+
|----------|------|----------|-------------|
|
|
459
|
+
| `ATLASSIAN_CLIENT_ID` | string | ⚠️ Optional | Atlassian OAuth client ID from Atlassian Developer Console. When not set, Atlassian sign-in is disabled. |
|
|
460
|
+
| `ATLASSIAN_CLIENT_SECRET` | string | ⚠️ Optional | Atlassian OAuth client secret. |
|
|
461
|
+
|
|
462
|
+
**Generating BETTER_AUTH_SECRET:**
|
|
463
|
+
|
|
464
|
+
```bash
|
|
465
|
+
# Using OpenSSL (recommended)
|
|
466
|
+
openssl rand -base64 32
|
|
467
|
+
|
|
468
|
+
# Using Node.js
|
|
469
|
+
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
|
|
470
|
+
|
|
471
|
+
# Using Python
|
|
472
|
+
python -c "import secrets; print(secrets.token_urlsafe(32))"
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
**Security Best Practices:**
|
|
476
|
+
- Generate a unique secret for each environment (development, staging, production)
|
|
477
|
+
- Never reuse secrets across environments
|
|
478
|
+
- Rotate secrets periodically (every 90 days recommended)
|
|
479
|
+
- Store secrets in secure secret management systems (Vercel Environment Variables, AWS Secrets Manager, etc.)
|
|
480
|
+
- Never commit secrets to version control
|
|
481
|
+
|
|
482
|
+
#### Email Service (Resend)
|
|
483
|
+
|
|
484
|
+
| Variable | Type | Required | Description |
|
|
485
|
+
|----------|------|----------|-------------|
|
|
486
|
+
| `RESEND_API_KEY` | string | ✅ Yes | API key from Resend for sending transactional emails (verification, password reset). Get from [resend.com/api-keys](https://resend.com/api-keys). |
|
|
487
|
+
| `RESEND_FROM_EMAIL` | string (email) | ✅ Yes | Default sender email address. Must be verified in Resend. Format: `noreply@your-domain.com` |
|
|
488
|
+
|
|
489
|
+
**Setting up Resend:**
|
|
490
|
+
|
|
491
|
+
1. **Create Account**: Sign up at [resend.com](https://resend.com)
|
|
492
|
+
|
|
493
|
+
2. **Verify Domain** (Production):
|
|
494
|
+
- Go to Domains → Add Domain
|
|
495
|
+
- Add your domain (e.g., `your-domain.com`)
|
|
496
|
+
- Add DNS records (SPF, DKIM, DMARC) to your DNS provider
|
|
497
|
+
- Wait for verification (usually 5-10 minutes)
|
|
498
|
+
|
|
499
|
+
3. **Get API Key**:
|
|
500
|
+
- Go to API Keys → Create API Key
|
|
501
|
+
- Name it (e.g., "UI SyncUp Production")
|
|
502
|
+
- Copy the key (starts with `re_`)
|
|
503
|
+
- Store securely in environment variables
|
|
504
|
+
|
|
505
|
+
4. **Development Setup**:
|
|
506
|
+
- For local development, you can use Resend's test mode
|
|
507
|
+
- Emails sent in test mode are not actually delivered but appear in your Resend dashboard
|
|
508
|
+
- Or verify a test domain for actual email delivery
|
|
509
|
+
|
|
510
|
+
**Email Templates Used:**
|
|
511
|
+
- `verification-email.tsx` - Email verification link
|
|
512
|
+
- `password-reset-email.tsx` - Password reset link
|
|
513
|
+
- `welcome-email.tsx` - Welcome message after verification
|
|
514
|
+
- `security-alert-email.tsx` - Security notifications (password changed, etc.)
|
|
515
|
+
|
|
516
|
+
#### Database Connection
|
|
517
|
+
|
|
518
|
+
| Variable | Type | Required | Description |
|
|
519
|
+
|----------|------|----------|-------------|
|
|
520
|
+
| `DATABASE_URL` | string | ✅ Yes | PostgreSQL connection string (pooled connection). Format: `postgresql://user:password@host:5432/database` |
|
|
521
|
+
| `DIRECT_URL` | string | ⚠️ Optional | Direct PostgreSQL connection string (non-pooled, for migrations). Required for Drizzle migrations. |
|
|
522
|
+
|
|
523
|
+
**Connection String Format:**
|
|
524
|
+
```
|
|
525
|
+
postgresql://[user]:[password]@[host]:[port]/[database]?[options]
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
**Example:**
|
|
529
|
+
```bash
|
|
530
|
+
# Local development
|
|
531
|
+
DATABASE_URL=postgresql://postgres:password@localhost:5432/ui_syncup
|
|
532
|
+
|
|
533
|
+
# Supabase (pooled)
|
|
534
|
+
DATABASE_URL=postgresql://postgres.xxxxx:password@aws-0-us-east-1.pooler.supabase.com:5432/postgres
|
|
535
|
+
|
|
536
|
+
# Supabase (direct - for migrations)
|
|
537
|
+
DIRECT_URL=postgresql://postgres.xxxxx:password@aws-0-us-east-1.pooler.supabase.com:5432/postgres
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
**Connection Pooling:**
|
|
541
|
+
- Use `DATABASE_URL` for application queries (pooled connection)
|
|
542
|
+
- Use `DIRECT_URL` for migrations (direct connection)
|
|
543
|
+
- Supabase provides both pooled and direct connection strings
|
|
544
|
+
- Pooled connections are recommended for production to handle concurrent requests
|
|
545
|
+
|
|
546
|
+
### Feature Flag Variables
|
|
547
|
+
|
|
548
|
+
| Variable | Type | Default | Description |
|
|
549
|
+
|----------|------|---------|-------------|
|
|
550
|
+
| `NEXT_PUBLIC_ENABLE_ANALYTICS` | boolean | `false` | Enable analytics tracking |
|
|
551
|
+
| `NEXT_PUBLIC_ENABLE_DEBUG` | boolean | `false` | Enable debug mode |
|
|
552
|
+
|
|
553
|
+
### Vercel System Variables
|
|
554
|
+
|
|
555
|
+
These are automatically set by Vercel:
|
|
556
|
+
|
|
557
|
+
| Variable | Description |
|
|
558
|
+
|----------|-------------|
|
|
559
|
+
| `VERCEL_ENV` | Environment type: `production`, `preview`, or `development` |
|
|
560
|
+
| `VERCEL_URL` | Deployment URL |
|
|
561
|
+
| `VERCEL_GIT_COMMIT_REF` | Git branch name |
|
|
562
|
+
| `VERCEL_GIT_COMMIT_SHA` | Git commit SHA |
|
|
563
|
+
| `VERCEL_GIT_COMMIT_MESSAGE` | Git commit message |
|
|
564
|
+
|
|
565
|
+
## Testing
|
|
566
|
+
|
|
567
|
+
### Mocking Environment in Tests
|
|
568
|
+
|
|
569
|
+
```typescript
|
|
570
|
+
import { describe, it, expect, vi } from 'vitest'
|
|
571
|
+
|
|
572
|
+
describe('Feature with environment check', () => {
|
|
573
|
+
it('should behave differently in production', async () => {
|
|
574
|
+
// Mock environment
|
|
575
|
+
vi.stubEnv('NODE_ENV', 'production')
|
|
576
|
+
|
|
577
|
+
const { isProduction } = await import('@/lib/config')
|
|
578
|
+
expect(isProduction()).toBe(true)
|
|
579
|
+
|
|
580
|
+
vi.unstubAllEnvs()
|
|
581
|
+
})
|
|
582
|
+
})
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
## Related Documentation
|
|
586
|
+
|
|
587
|
+
- [Deployment Guide](./DEPLOYMENT.md) - Deployment procedures and environment setup
|
|
588
|
+
- [Local Development](./LOCAL_DEVELOPMENT.md) - Local development environment setup
|
|
589
|
+
- [Environment Variables](../src/lib/env.ts) - Environment variable validation
|
|
590
|
+
|
|
591
|
+
## Authentication Setup Guide
|
|
592
|
+
|
|
593
|
+
### Local Development Setup
|
|
594
|
+
|
|
595
|
+
1. **Copy Environment Template**
|
|
596
|
+
```bash
|
|
597
|
+
cp .env.example .env.local
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
2. **Generate better-auth Secret**
|
|
601
|
+
```bash
|
|
602
|
+
openssl rand -base64 32
|
|
603
|
+
```
|
|
604
|
+
Copy the output and set it as `BETTER_AUTH_SECRET` in `.env.local`
|
|
605
|
+
|
|
606
|
+
3. **Set Base URL**
|
|
607
|
+
```bash
|
|
608
|
+
BETTER_AUTH_URL=http://localhost:3000
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
4. **Configure Database**
|
|
612
|
+
- Start local PostgreSQL (see `docs/LOCAL_DEVELOPMENT.md`)
|
|
613
|
+
- Set `DATABASE_URL` to your local connection string
|
|
614
|
+
```bash
|
|
615
|
+
DATABASE_URL=postgresql://postgres:password@localhost:5432/ui_syncup
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
5. **Setup Resend (Optional for local dev)**
|
|
619
|
+
- Sign up at [resend.com](https://resend.com)
|
|
620
|
+
- Get API key from dashboard
|
|
621
|
+
- Set `RESEND_API_KEY` and `RESEND_FROM_EMAIL`
|
|
622
|
+
- For testing, you can use Resend's test mode
|
|
623
|
+
|
|
624
|
+
6. **Run Migrations**
|
|
625
|
+
```bash
|
|
626
|
+
bun run db:migrate
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
7. **Start Development Server**
|
|
630
|
+
```bash
|
|
631
|
+
bun dev
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
### Production Deployment (Vercel)
|
|
635
|
+
|
|
636
|
+
1. **Set Environment Variables in Vercel**
|
|
637
|
+
- Go to Project Settings → Environment Variables
|
|
638
|
+
- Add all required variables from `.env.example`
|
|
639
|
+
|
|
640
|
+
2. **Generate Production Secret**
|
|
641
|
+
```bash
|
|
642
|
+
openssl rand -base64 32
|
|
643
|
+
```
|
|
644
|
+
- Add as `BETTER_AUTH_SECRET` in Vercel
|
|
645
|
+
- Use different secrets for Preview and Production environments
|
|
646
|
+
|
|
647
|
+
3. **Set Production URLs**
|
|
648
|
+
```bash
|
|
649
|
+
BETTER_AUTH_URL=https://your-domain.com
|
|
650
|
+
NEXT_PUBLIC_APP_URL=https://your-domain.com
|
|
651
|
+
NEXT_PUBLIC_API_URL=https://your-domain.com/api
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
4. **Configure Database**
|
|
655
|
+
- Use Supabase or your PostgreSQL provider
|
|
656
|
+
- Set `DATABASE_URL` (pooled connection)
|
|
657
|
+
- Set `DIRECT_URL` (direct connection for migrations)
|
|
658
|
+
|
|
659
|
+
5. **Setup Resend**
|
|
660
|
+
- Verify your domain in Resend
|
|
661
|
+
- Add DNS records (SPF, DKIM, DMARC)
|
|
662
|
+
- Create production API key
|
|
663
|
+
- Set `RESEND_API_KEY` and `RESEND_FROM_EMAIL`
|
|
664
|
+
|
|
665
|
+
6. **Deploy**
|
|
666
|
+
```bash
|
|
667
|
+
git push origin main
|
|
668
|
+
```
|
|
669
|
+
Vercel will automatically deploy with the configured environment variables
|
|
670
|
+
|
|
671
|
+
### Environment-Specific Configuration
|
|
672
|
+
|
|
673
|
+
#### Development
|
|
674
|
+
```bash
|
|
675
|
+
NODE_ENV=development
|
|
676
|
+
BETTER_AUTH_URL=http://localhost:3000
|
|
677
|
+
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
|
678
|
+
DATABASE_URL=postgresql://postgres:password@localhost:5432/ui_syncup
|
|
679
|
+
RESEND_FROM_EMAIL=dev@localhost # Test mode
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
#### Preview (Vercel)
|
|
683
|
+
```bash
|
|
684
|
+
NODE_ENV=production
|
|
685
|
+
VERCEL_ENV=preview
|
|
686
|
+
BETTER_AUTH_URL=https://your-app-git-branch.vercel.app
|
|
687
|
+
NEXT_PUBLIC_APP_URL=https://your-app-git-branch.vercel.app
|
|
688
|
+
DATABASE_URL=postgresql://... # Preview database
|
|
689
|
+
RESEND_FROM_EMAIL=preview@your-domain.com
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
#### Production (Vercel)
|
|
693
|
+
```bash
|
|
694
|
+
NODE_ENV=production
|
|
695
|
+
VERCEL_ENV=production
|
|
696
|
+
BETTER_AUTH_URL=https://your-domain.com
|
|
697
|
+
NEXT_PUBLIC_APP_URL=https://your-domain.com
|
|
698
|
+
DATABASE_URL=postgresql://... # Production database
|
|
699
|
+
RESEND_FROM_EMAIL=noreply@your-domain.com
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
### Security Checklist
|
|
703
|
+
|
|
704
|
+
- [ ] `BETTER_AUTH_SECRET` is at least 32 characters
|
|
705
|
+
- [ ] Different secrets for each environment
|
|
706
|
+
- [ ] Secrets stored in secure secret management (not in code)
|
|
707
|
+
- [ ] `BETTER_AUTH_URL` matches deployment URL
|
|
708
|
+
- [ ] Database connection uses SSL in production
|
|
709
|
+
- [ ] Resend domain is verified
|
|
710
|
+
- [ ] Email sender domain matches verified domain
|
|
711
|
+
- [ ] All secrets are marked as "Sensitive" in Vercel
|
|
712
|
+
- [ ] Environment variables are not exposed to client (no `NEXT_PUBLIC_` prefix for secrets)
|
|
713
|
+
|
|
714
|
+
### Testing Authentication
|
|
715
|
+
|
|
716
|
+
1. **Test Registration**
|
|
717
|
+
```bash
|
|
718
|
+
curl -X POST http://localhost:3000/api/auth/signup \
|
|
719
|
+
-H "Content-Type: application/json" \
|
|
720
|
+
-d '{"email":"test@example.com","password":"Test123!@#","name":"Test User"}'
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
2. **Check Email Logs**
|
|
724
|
+
- Development: Check Resend dashboard for test emails
|
|
725
|
+
- Production: Check email delivery in Resend logs
|
|
726
|
+
|
|
727
|
+
3. **Test Sign-In**
|
|
728
|
+
```bash
|
|
729
|
+
curl -X POST http://localhost:3000/api/auth/login \
|
|
730
|
+
-H "Content-Type: application/json" \
|
|
731
|
+
-d '{"email":"test@example.com","password":"Test123!@#"}'
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
4. **Verify Session**
|
|
735
|
+
```bash
|
|
736
|
+
curl http://localhost:3000/api/auth/me \
|
|
737
|
+
-H "Cookie: session=your-session-cookie"
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
## Troubleshooting
|
|
741
|
+
|
|
742
|
+
### Authentication Issues
|
|
743
|
+
|
|
744
|
+
#### "BETTER_AUTH_SECRET must be at least 32 characters"
|
|
745
|
+
- Generate a new secret: `openssl rand -base64 32`
|
|
746
|
+
- Ensure the secret is properly set in environment variables
|
|
747
|
+
- Restart the development server after changing `.env.local`
|
|
748
|
+
|
|
749
|
+
#### "Email delivery failed"
|
|
750
|
+
- Verify `RESEND_API_KEY` is correct
|
|
751
|
+
- Check sender email is verified in Resend
|
|
752
|
+
- Ensure sender domain has proper DNS records (SPF, DKIM)
|
|
753
|
+
- Check Resend dashboard for delivery logs and errors
|
|
754
|
+
|
|
755
|
+
#### "Database connection failed"
|
|
756
|
+
- Verify `DATABASE_URL` format is correct
|
|
757
|
+
- Check database is running and accessible
|
|
758
|
+
- Ensure database user has proper permissions
|
|
759
|
+
- For Supabase, verify connection pooling is enabled
|
|
760
|
+
|
|
761
|
+
#### "Session cookie not set"
|
|
762
|
+
- Verify `BETTER_AUTH_URL` matches your deployment URL
|
|
763
|
+
- Check cookies are enabled in browser
|
|
764
|
+
- Ensure HTTPS is used in production (required for Secure cookies)
|
|
765
|
+
- Verify no CORS issues blocking cookie setting
|
|
766
|
+
|
|
767
|
+
#### "Email verification link expired"
|
|
768
|
+
- Tokens expire after 24 hours by default
|
|
769
|
+
- User can request a new verification email
|
|
770
|
+
- Check system time is synchronized (token expiration uses server time)
|
|
771
|
+
|
|
772
|
+
#### "Password reset not working"
|
|
773
|
+
- Reset tokens expire after 1 hour
|
|
774
|
+
- Ensure email delivery is working
|
|
775
|
+
- Check user exists in database
|
|
776
|
+
- Verify token hasn't been used already
|
|
777
|
+
|
|
778
|
+
### Feature Flag Not Working
|
|
779
|
+
|
|
780
|
+
1. Ensure the environment variable is prefixed with `NEXT_PUBLIC_` for client-side access
|
|
781
|
+
2. Restart the development server after changing `.env.local`
|
|
782
|
+
3. Check the value is one of the truthy values: `true`, `1`, `yes`, `on`
|
|
783
|
+
|
|
784
|
+
### Environment Detection Issues
|
|
785
|
+
|
|
786
|
+
1. Verify `NODE_ENV` is set correctly
|
|
787
|
+
2. For Vercel-specific checks, ensure you're deployed on Vercel
|
|
788
|
+
3. Check `VERCEL_ENV` is set in Vercel deployment settings
|
|
789
|
+
|
|
790
|
+
### Config Object Shows Stale Values
|
|
791
|
+
|
|
792
|
+
The config object is evaluated at module load time. If you need dynamic values, use the function-based helpers:
|
|
793
|
+
|
|
794
|
+
```typescript
|
|
795
|
+
// ✅ Dynamic - Re-evaluated each time
|
|
796
|
+
if (isProduction()) { }
|
|
797
|
+
|
|
798
|
+
// ⚠️ Static - Evaluated once at module load
|
|
799
|
+
if (config.env.isProduction) { }
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
### Common Error Messages
|
|
803
|
+
|
|
804
|
+
| Error | Cause | Solution |
|
|
805
|
+
|-------|-------|----------|
|
|
806
|
+
| "Environment validation failed" | Missing or invalid environment variables | Check `.env.local` against `.env.example` |
|
|
807
|
+
| "Invalid token signature" | Token signed with different secret | Ensure `BETTER_AUTH_SECRET` is consistent |
|
|
808
|
+
| "Session expired" | Session older than 7 days | User needs to sign in again |
|
|
809
|
+
| "Rate limit exceeded" | Too many requests | Wait for rate limit window to reset |
|
|
810
|
+
| "Email already registered" | Duplicate registration attempt | User should sign in or reset password |
|
|
811
|
+
| "Email not verified" | Attempting to sign in before verification | Check email for verification link |
|
|
812
|
+
|
|
813
|
+
|
|
814
|
+
## Quick Reference
|
|
815
|
+
|
|
816
|
+
### Essential Commands
|
|
817
|
+
|
|
818
|
+
```bash
|
|
819
|
+
# Generate better-auth secret
|
|
820
|
+
openssl rand -base64 32
|
|
821
|
+
|
|
822
|
+
# Copy environment template
|
|
823
|
+
cp .env.example .env.local
|
|
824
|
+
|
|
825
|
+
# Validate environment variables
|
|
826
|
+
bun run validate-env
|
|
827
|
+
|
|
828
|
+
# Run database migrations
|
|
829
|
+
bun run db:migrate
|
|
830
|
+
|
|
831
|
+
# Start development server
|
|
832
|
+
bun dev
|
|
833
|
+
|
|
834
|
+
# Build for production
|
|
835
|
+
bun build
|
|
836
|
+
```
|
|
837
|
+
|
|
838
|
+
### Environment Variable Checklist
|
|
839
|
+
|
|
840
|
+
#### Minimum Required for Local Development
|
|
841
|
+
- [ ] `NODE_ENV=development`
|
|
842
|
+
- [ ] `NEXT_PUBLIC_APP_URL=http://localhost:3000`
|
|
843
|
+
- [ ] `NEXT_PUBLIC_API_URL=http://localhost:3000/api`
|
|
844
|
+
- [ ] `DATABASE_URL` (PostgreSQL connection)
|
|
845
|
+
- [ ] `BETTER_AUTH_SECRET` (32+ characters)
|
|
846
|
+
- [ ] `BETTER_AUTH_URL=http://localhost:3000`
|
|
847
|
+
- [ ] `RESEND_API_KEY` (for email features)
|
|
848
|
+
- [ ] `RESEND_FROM_EMAIL` (verified email)
|
|
849
|
+
|
|
850
|
+
#### Additional for Production
|
|
851
|
+
- [ ] All development variables
|
|
852
|
+
- [ ] `DIRECT_URL` (for migrations)
|
|
853
|
+
- [ ] `SUPABASE_URL`
|
|
854
|
+
- [ ] `SUPABASE_ANON_KEY`
|
|
855
|
+
- [ ] `SUPABASE_SERVICE_ROLE_KEY`
|
|
856
|
+
- [ ] `R2_*` variables (for file storage)
|
|
857
|
+
- [ ] `GOOGLE_*` variables (for OAuth)
|
|
858
|
+
- [ ] Production URLs (HTTPS)
|
|
859
|
+
- [ ] Verified email domain in Resend
|
|
860
|
+
|
|
861
|
+
### File Locations
|
|
862
|
+
|
|
863
|
+
| File | Purpose |
|
|
864
|
+
|------|---------|
|
|
865
|
+
| `.env.example` | Template with all variables and documentation |
|
|
866
|
+
| `.env.local` | Local development variables (gitignored) |
|
|
867
|
+
| `.env.development` | Development defaults (optional) |
|
|
868
|
+
| `.env.production` | Production defaults (optional) |
|
|
869
|
+
| `.env.test` | Test environment variables |
|
|
870
|
+
| `src/lib/env.ts` | Environment validation schema |
|
|
871
|
+
| `docs/ENVIRONMENT_CONFIG.md` | This documentation |
|
|
872
|
+
| `docs/DEPLOYMENT.md` | Deployment procedures |
|
|
873
|
+
| `docs/LOCAL_DEVELOPMENT.md` | Local setup guide |
|
|
874
|
+
|
|
875
|
+
### Related Documentation
|
|
876
|
+
|
|
877
|
+
- [Authentication System Design](./.ai/specs/authentication-system/design.md) - Auth architecture and implementation
|
|
878
|
+
- [Authentication Requirements](./.ai/specs/authentication-system/requirements.md) - Auth requirements and acceptance criteria
|
|
879
|
+
- [Deployment Guide](./DEPLOYMENT.md) - Production deployment procedures
|
|
880
|
+
- [Local Development](./LOCAL_DEVELOPMENT.md) - Local environment setup
|
|
881
|
+
- [Database Setup](./DRIZZLE_ZOD_POSTGRESQL_INSTRUCTION.md) - Database configuration
|
|
882
|
+
- [Security Best Practices](./SECURITY.md) - Security guidelines
|
|
883
|
+
|
|
884
|
+
### Support Resources
|
|
885
|
+
|
|
886
|
+
- **Resend Documentation**: [resend.com/docs](https://resend.com/docs)
|
|
887
|
+
- **better-auth Documentation**: [better-auth.com/docs](https://better-auth.com/docs)
|
|
888
|
+
- **Drizzle ORM**: [orm.drizzle.team](https://orm.drizzle.team)
|
|
889
|
+
- **Next.js Environment Variables**: [nextjs.org/docs/app/building-your-application/configuring/environment-variables](https://nextjs.org/docs/app/building-your-application/configuring/environment-variables)
|
|
890
|
+
- **Vercel Environment Variables**: [vercel.com/docs/projects/environment-variables](https://vercel.com/docs/projects/environment-variables)
|
|
891
|
+
|
|
892
|
+
---
|
|
893
|
+
|
|
894
|
+
**Last Updated**: November 2025
|
|
895
|
+
**Version**: 1.0.0
|
|
896
|
+
**Maintained By**: UI SyncUp Team
|