From 8538ab969af9994212b3e57c7d6d5818e822ad8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A0=D0=98=D0=BB=D1=8C=D1=8F=20=D0=A8=D0=B0=D0=BB=D0=BE?= =?UTF-8?q?=D0=BD=D0=B8=D0=BD?= Date: Wed, 29 Oct 2025 13:43:43 +0500 Subject: [PATCH] first --- .cursor/rules/key-principles.mdc | 17 + .cursor/rules/naming-coventions.mdc | 11 + .cursor/rules/performance.mdc | 11 + .cursor/rules/project-structure.mdc | 20 + .cursor/rules/syntax-and-formatting.mdc | 10 + .cursor/rules/typescript-usage.mdc | 10 + .cursor/rules/ui-and-styling.mdc | 11 + .editorconfig | 9 + .env.local.example | 76 + .github/dependabot.yml | 15 + .github/workflows/validate-prs.yml | 39 + .gitignore | 44 + .idea/.gitignore | 8 + .idea/dataSources.xml | 12 + .idea/data_source_mapping.xml | 6 + .idea/main-test.iml | 12 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + .npmrc | 1 + .vscode/extensions.json | 7 + .vscode/settings.json | 32 + .windsurfrules | 60 + README.md | 8 + apps/web/.gitignore | 39 + .../app/(marketing)/[locale]/(home)/page.tsx | 25 + .../(marketing)/[locale]/[...rest]/page.tsx | 5 + .../[locale]/blog/[...path]/page.tsx | 128 + .../app/(marketing)/[locale]/blog/page.tsx | 39 + .../(marketing)/[locale]/changelog/page.tsx | 35 + .../app/(marketing)/[locale]/contact/page.tsx | 33 + .../[locale]/docs/[[...path]]/layout.tsx | 33 + .../[locale]/docs/[[...path]]/page.tsx | 93 + apps/web/app/(marketing)/[locale]/layout.tsx | 55 + .../[locale]/legal/[...path]/page.tsx | 68 + .../app/(marketing)/[locale]/not-found.tsx | 5 + .../app/(saas)/app/(account)/admin/layout.tsx | 73 + .../admin/organizations/[id]/page.tsx | 52 + .../(account)/admin/organizations/page.tsx | 5 + .../(saas)/app/(account)/admin/users/page.tsx | 9 + .../app/(saas)/app/(account)/chatbot/page.tsx | 54 + apps/web/app/(saas)/app/(account)/layout.tsx | 6 + apps/web/app/(saas)/app/(account)/page.tsx | 26 + .../app/(account)/settings/billing/page.tsx | 40 + .../(account)/settings/danger-zone/page.tsx | 27 + .../app/(account)/settings/general/page.tsx | 34 + .../(saas)/app/(account)/settings/layout.tsx | 77 + .../app/(account)/settings/security/page.tsx | 68 + .../(without-organization-slug)/layout.tsx | 8 + .../new-organization/page.tsx | 21 + .../[invitationId]/page.tsx | 35 + .../[organizationSlug]/chatbot/page.tsx | 72 + .../[organizationSlug]/layout.tsx | 42 + .../[organizationSlug]/page.tsx | 47 + .../settings/billing/page.tsx | 51 + .../settings/danger-zone/page.tsx | 19 + .../settings/general/page.tsx | 21 + .../[organizationSlug]/settings/layout.tsx | 99 + .../settings/members/page.tsx | 37 + apps/web/app/(saas)/app/[...rest]/page.tsx | 5 + apps/web/app/(saas)/app/choose-plan/page.tsx | 71 + apps/web/app/(saas)/app/layout.tsx | 52 + apps/web/app/(saas)/app/not-found.tsx | 5 + apps/web/app/(saas)/app/onboarding/page.tsx | 35 + .../app/(saas)/auth/forgot-password/page.tsx | 17 + apps/web/app/(saas)/auth/layout.tsx | 14 + apps/web/app/(saas)/auth/login/page.tsx | 17 + .../app/(saas)/auth/reset-password/page.tsx | 17 + apps/web/app/(saas)/auth/signup/page.tsx | 48 + apps/web/app/(saas)/auth/verify/page.tsx | 17 + apps/web/app/(saas)/layout.tsx | 17 + apps/web/app/api/[[...rest]]/route.ts | 11 + apps/web/app/api/docs-search/route.ts | 20 + apps/web/app/docs-source.ts | 28 + apps/web/app/favicon.ico | Bin 0 -> 6434 bytes apps/web/app/globals.css | 42 + apps/web/app/icon.png | Bin 0 -> 6434 bytes apps/web/app/image-proxy/[...path]/route.ts | 31 + apps/web/app/layout.tsx | 17 + apps/web/app/robots.ts | 10 + apps/web/app/sitemap.ts | 43 + apps/web/biome.json | 3 + apps/web/components.json | 17 + apps/web/content-collections.ts | 112 + .../content/docs/getting-started/meta.de.json | 4 + .../content/docs/getting-started/meta.json | 4 + .../docs/getting-started/overview.de.mdx | 6 + .../content/docs/getting-started/overview.mdx | 6 + apps/web/content/docs/index.de.mdx | 6 + apps/web/content/docs/index.mdx | 43 + apps/web/content/docs/meta.json | 3 + apps/web/content/legal/privacy-policy.de.md | 5 + apps/web/content/legal/privacy-policy.md | 5 + apps/web/content/legal/terms.de.md | 5 + apps/web/content/legal/terms.md | 5 + apps/web/content/posts/first-post.de.mdx | 14 + apps/web/content/posts/first-post.mdx | 14 + apps/web/content/posts/second-post.mdx | 29 + apps/web/global.d.ts | 16 + apps/web/middleware.ts | 144 + apps/web/modules/analytics/index.tsx | 1 + .../analytics/provider/custom/index.tsx | 17 + .../analytics/provider/google/index.tsx | 17 + .../analytics/provider/mixpanel/index.tsx | 29 + .../analytics/provider/pirsch/index.tsx | 33 + .../analytics/provider/plausible/index.tsx | 32 + .../analytics/provider/posthog/index.tsx | 35 + .../analytics/provider/umami/index.tsx | 32 + .../analytics/provider/vercel/index.tsx | 20 + apps/web/modules/i18n/lib/locale-cookie.ts | 14 + apps/web/modules/i18n/lib/update-locale.ts | 10 + apps/web/modules/i18n/request.ts | 22 + apps/web/modules/i18n/routing.ts | 20 + .../marketing/blog/components/PostContent.tsx | 17 + .../blog/components/PostListItem.tsx | 80 + apps/web/modules/marketing/blog/types.ts | 3 + .../modules/marketing/blog/utils/lib/posts.ts | 25 + .../marketing/blog/utils/mdx-components.tsx | 103 + .../changelog/components/ChangelogSection.tsx | 31 + apps/web/modules/marketing/changelog/types.ts | 6 + .../marketing/home/components/ContactForm.tsx | 132 + .../marketing/home/components/FaqSection.tsx | 58 + .../marketing/home/components/Features.tsx | 281 + .../marketing/home/components/Hero.tsx | 180 + .../marketing/home/components/Newsletter.tsx | 90 + .../home/components/PricingSection.tsx | 24 + apps/web/modules/marketing/home/lib/api.ts | 41 + apps/web/modules/marketing/home/types.ts | 6 + .../shared/components/ContentMenu.tsx | 60 + .../marketing/shared/components/Footer.tsx | 46 + .../marketing/shared/components/NavBar.tsx | 218 + .../marketing/shared/components/NotFound.tsx | 20 + .../shared/components/TableOfContents.tsx | 53 + .../saas/admin/component/EmailVerified.tsx | 37 + .../organizations/OrganizationForm.tsx | 154 + .../organizations/OrganizationList.tsx | 294 + .../saas/admin/component/users/UserList.tsx | 373 + apps/web/modules/saas/admin/lib/api.ts | 82 + apps/web/modules/saas/admin/lib/links.ts | 5 + .../web/modules/saas/ai/components/AiChat.tsx | 199 + apps/web/modules/saas/ai/lib/api.ts | 103 + .../auth/components/ForgotPasswordForm.tsx | 135 + .../saas/auth/components/LoginForm.tsx | 357 + .../saas/auth/components/LoginModeSwitch.tsx | 28 + .../modules/saas/auth/components/OtpForm.tsx | 169 + .../auth/components/ResetPasswordForm.tsx | 139 + .../saas/auth/components/SessionProvider.tsx | 51 + .../saas/auth/components/SignupForm.tsx | 282 + .../auth/components/SocialSigninButton.tsx | 47 + .../saas/auth/constants/oauth-providers.tsx | 37 + .../saas/auth/hooks/errors-messages.ts | 50 + .../modules/saas/auth/hooks/use-session.ts | 12 + apps/web/modules/saas/auth/lib/api.ts | 60 + apps/web/modules/saas/auth/lib/server.ts | 75 + .../modules/saas/auth/lib/session-context.ts | 12 + .../onboarding/components/OnboardingForm.tsx | 72 + .../onboarding/components/OnboardingStep1.tsx | 115 + .../components/ActiveOrganizationProvider.tsx | 130 + .../components/ChangeOrganizationNameForm.tsx | 93 + .../components/CreateOrganizationForm.tsx | 110 + .../components/DeleteOrganizationForm.tsx | 75 + .../components/InviteMemberForm.tsx | 148 + .../OrganizationInvitationAlert.tsx | 18 + .../OrganizationInvitationModal.tsx | 115 + .../OrganizationInvitationsList.tsx | 237 + .../components/OrganizationLogo.tsx | 61 + .../components/OrganizationLogoForm.tsx | 122 + .../components/OrganizationMembersBlock.tsx | 42 + .../components/OrganizationMembersList.tsx | 273 + .../components/OrganizationRoleSelect.tsx | 43 + .../components/OrganizationSelect.tsx | 160 + .../components/OrganizationStart.tsx | 39 + .../components/OrganizationsGrid.tsx | 59 + .../saas/organizations/hooks/member-roles.ts | 12 + .../hooks/use-active-organization.ts | 23 + .../lib/active-organization-context.ts | 18 + .../web/modules/saas/organizations/lib/api.ts | 159 + .../saas/payments/components/ActivePlan.tsx | 110 + .../payments/components/ActivePlanBadge.tsx | 32 + .../saas/payments/components/ChangePlan.tsx | 29 + .../saas/payments/components/PricingTable.tsx | 300 + .../modules/saas/payments/hooks/plan-data.tsx | 53 + .../modules/saas/payments/hooks/purchases.tsx | 20 + apps/web/modules/saas/payments/lib/api.ts | 80 + .../saas/payments/lib/purchases-context.ts | 16 + apps/web/modules/saas/payments/lib/server.ts | 17 + apps/web/modules/saas/payments/types.ts | 3 + .../components/ActiveSessionsBlock.tsx | 109 + .../settings/components/ChangeEmailForm.tsx | 76 + .../settings/components/ChangeNameForm.tsx | 72 + .../settings/components/ChangePassword.tsx | 130 + .../components/ConnectedAccountsBlock.tsx | 82 + .../settings/components/CropImageDialog.tsx | 79 + .../components/CustomerPortalButton.tsx | 42 + .../settings/components/DeleteAccountForm.tsx | 64 + .../settings/components/PasskeysBlock.tsx | 114 + .../saas/settings/components/SetPassword.tsx | 61 + .../saas/settings/components/SettingsMenu.tsx | 61 + .../components/SubscriptionStatusBadge.tsx | 38 + .../settings/components/TwoFactorBlock.tsx | 290 + .../settings/components/UserAvatarForm.tsx | 29 + .../settings/components/UserAvatarUpload.tsx | 111 + .../settings/components/UserLanguageForm.tsx | 81 + .../saas/shared/components/AppWrapper.tsx | 33 + .../saas/shared/components/AuthWrapper.tsx | 49 + .../components/ConfirmationAlertProvider.tsx | 101 + .../modules/saas/shared/components/Footer.tsx | 20 + .../modules/saas/shared/components/NavBar.tsx | 189 + .../saas/shared/components/PageHeader.tsx | 16 + .../saas/shared/components/Pagination.tsx | 53 + .../saas/shared/components/SettingsItem.tsx | 37 + .../saas/shared/components/SettingsList.tsx | 13 + .../components/SidebarContentLayout.tsx | 18 + .../saas/shared/components/TabGroup.tsx | 36 + .../saas/shared/components/UserMenu.tsx | 176 + apps/web/modules/saas/shared/lib/api.ts | 27 + apps/web/modules/saas/shared/lib/state.ts | 3 + apps/web/modules/saas/start/UserStart.tsx | 23 + .../saas/start/components/StatsTile.tsx | 77 + .../shared/components/ApiClientProvider.tsx | 28 + .../shared/components/ColorModeToggle.tsx | 82 + .../shared/components/ConsentBanner.tsx | 52 + .../shared/components/ConsentProvider.tsx | 42 + .../modules/shared/components/Document.tsx | 58 + .../shared/components/LocaleSwitch.tsx | 72 + apps/web/modules/shared/components/Logo.tsx | 41 + .../web/modules/shared/components/Spinner.tsx | 10 + .../modules/shared/components/UserAvatar.tsx | 43 + .../modules/shared/hooks/cookie-consent.ts | 8 + apps/web/modules/shared/hooks/form-errors.ts | 214 + .../modules/shared/hooks/locale-currency.tsx | 11 + apps/web/modules/shared/hooks/router.ts | 32 + apps/web/modules/shared/lib/api-client.ts | 9 + apps/web/modules/shared/lib/cache.ts | 15 + apps/web/modules/shared/lib/content.ts | 148 + .../modules/shared/lib/middleware-helpers.ts | 74 + apps/web/modules/shared/lib/query-client.ts | 35 + apps/web/modules/shared/lib/server.ts | 21 + apps/web/modules/ui/components/accordion.tsx | 60 + .../modules/ui/components/alert-dialog.tsx | 141 + apps/web/modules/ui/components/alert.tsx | 65 + apps/web/modules/ui/components/avatar.tsx | 49 + apps/web/modules/ui/components/badge.tsx | 46 + apps/web/modules/ui/components/button.tsx | 75 + apps/web/modules/ui/components/card.tsx | 82 + apps/web/modules/ui/components/dialog.tsx | 120 + .../modules/ui/components/dropdown-menu.tsx | 204 + apps/web/modules/ui/components/form.tsx | 181 + apps/web/modules/ui/components/input-otp.tsx | 80 + apps/web/modules/ui/components/input.tsx | 23 + apps/web/modules/ui/components/label.tsx | 26 + .../modules/ui/components/password-input.tsx | 42 + apps/web/modules/ui/components/progress.tsx | 28 + apps/web/modules/ui/components/select.tsx | 123 + apps/web/modules/ui/components/sheet.tsx | 140 + apps/web/modules/ui/components/skeleton.tsx | 15 + apps/web/modules/ui/components/table.tsx | 119 + apps/web/modules/ui/components/tabs.tsx | 54 + apps/web/modules/ui/components/textarea.tsx | 21 + apps/web/modules/ui/components/toast.tsx | 33 + apps/web/modules/ui/components/tooltip.tsx | 30 + apps/web/modules/ui/lib/index.ts | 7 + apps/web/next.config.ts | 56 + apps/web/package.json | 114 + apps/web/playwright.config.ts | 41 + apps/web/postcss.config.cjs | 5 + apps/web/public/images/blog/author.jpg | Bin 0 -> 3279 bytes apps/web/public/images/blog/author2.jpg | Bin 0 -> 4490 bytes apps/web/public/images/blog/cover.png | Bin 0 -> 153746 bytes apps/web/public/images/docs/login.png | Bin 0 -> 183595 bytes apps/web/public/images/hero-dark.svg | 17 + apps/web/public/images/hero-image-dark.png | Bin 0 -> 613580 bytes apps/web/public/images/hero-image.png | Bin 0 -> 883430 bytes apps/web/public/images/hero.svg | 17 + .../public/images/supastarter-logo-dark.svg | 20 + .../public/images/supastarter-logo-light.svg | 20 + apps/web/tests/home.spec.ts | 22 + apps/web/tsconfig.json | 24 + biome.json | 56 + config/index.ts | 167 + config/package.json | 11 + config/tsconfig.json | 3 + config/types.ts | 86 + package.json | 30 + packages/ai/biome.json | 3 + packages/ai/client.ts | 1 + packages/ai/index.ts | 8 + packages/ai/lib/index.ts | 1 + packages/ai/lib/prompts.ts | 9 + packages/ai/package.json | 22 + packages/ai/tsconfig.json | 5 + packages/api/biome.json | 3 + packages/api/index.ts | 1 + packages/api/package.json | 37 + packages/api/src/app.ts | 80 + packages/api/src/lib/openapi-schema.ts | 45 + packages/api/src/middleware/admin.ts | 26 + packages/api/src/middleware/auth.ts | 22 + packages/api/src/middleware/cors.ts | 11 + packages/api/src/middleware/locale.ts | 18 + packages/api/src/middleware/logger.ts | 6 + .../api/src/routes/admin/organizations.ts | 54 + packages/api/src/routes/admin/router.ts | 8 + packages/api/src/routes/admin/users.ts | 38 + packages/api/src/routes/ai.ts | 303 + packages/api/src/routes/auth.ts | 10 + packages/api/src/routes/contact/router.ts | 51 + packages/api/src/routes/contact/types.ts | 9 + packages/api/src/routes/health.ts | 13 + packages/api/src/routes/newsletter.ts | 54 + .../routes/organizations/lib/membership.ts | 20 + .../api/src/routes/organizations/router.ts | 55 + .../api/src/routes/payments/lib/purchases.ts | 21 + packages/api/src/routes/payments/router.ts | 217 + packages/api/src/routes/payments/types.ts | 22 + packages/api/src/routes/uploads.ts | 50 + packages/api/src/routes/webhooks.ts | 14 + packages/api/tsconfig.json | 5 + packages/auth/auth.ts | 272 + packages/auth/biome.json | 3 + packages/auth/client.ts | 25 + packages/auth/index.ts | 1 + packages/auth/lib/helper.ts | 18 + packages/auth/lib/organization.ts | 34 + packages/auth/package.json | 27 + .../auth/plugins/invitation-only/index.ts | 39 + packages/auth/tsconfig.json | 5 + packages/database/biome.json | 3 + packages/database/drizzle/client.ts | 15 + packages/database/drizzle/drizzle.config.ts | 9 + packages/database/drizzle/index.ts | 4 + packages/database/drizzle/queries/ai-chats.ts | 88 + packages/database/drizzle/queries/index.ts | 4 + .../database/drizzle/queries/organizations.ts | 105 + .../database/drizzle/queries/purchases.ts | 59 + packages/database/drizzle/queries/users.ts | 112 + packages/database/drizzle/schema/index.ts | 1 + packages/database/drizzle/schema/mysql.ts | 226 + packages/database/drizzle/schema/postgres.ts | 235 + packages/database/drizzle/schema/sqlite.ts | 235 + packages/database/drizzle/zod.ts | 40 + packages/database/index.ts | 1 + packages/database/package.json | 32 + packages/database/prisma/client.ts | 18 + packages/database/prisma/index.ts | 7 + packages/database/prisma/queries/ai-chats.ts | 92 + packages/database/prisma/queries/index.ts | 4 + .../database/prisma/queries/organizations.ts | 128 + packages/database/prisma/queries/purchases.ts | 69 + packages/database/prisma/queries/users.ts | 113 + packages/database/prisma/schema.prisma | 212 + packages/database/prisma/zod/index.ts | 7633 ++++++++++ packages/database/tsconfig.json | 5 + packages/i18n/biome.json | 3 + packages/i18n/index.ts | 2 + packages/i18n/lib/messages.ts | 18 + packages/i18n/package.json | 16 + packages/i18n/translations/de.json | 826 + packages/i18n/translations/en.json | 826 + packages/i18n/tsconfig.json | 5 + packages/i18n/types.ts | 6 + packages/logs/biome.json | 3 + packages/logs/index.ts | 1 + packages/logs/lib/logger.ts | 7 + packages/logs/package.json | 18 + packages/logs/tsconfig.json | 5 + packages/mail/.gitignore | 3 + packages/mail/biome.json | 3 + packages/mail/emails/EmailVerification.tsx | 48 + packages/mail/emails/ForgotPassword.tsx | 46 + packages/mail/emails/MagicLink.tsx | 46 + packages/mail/emails/NewUser.tsx | 58 + packages/mail/emails/NewsletterSignup.tsx | 30 + .../mail/emails/OrganizationInvitation.tsx | 55 + packages/mail/emails/index.ts | 15 + packages/mail/global.d.ts | 5 + packages/mail/index.ts | 1 + packages/mail/package.json | 32 + packages/mail/src/components/Logo.tsx | 32 + .../mail/src/components/PrimaryButton.tsx | 18 + packages/mail/src/components/Wrapper.tsx | 57 + packages/mail/src/provider/console.ts | 10 + packages/mail/src/provider/custom.ts | 9 + packages/mail/src/provider/index.ts | 1 + packages/mail/src/provider/mailgun.ts | 42 + packages/mail/src/provider/nodemailer.ts | 24 + packages/mail/src/provider/plunk.ts | 24 + packages/mail/src/provider/postmark.ts | 29 + packages/mail/src/provider/resend.ts | 26 + packages/mail/src/util/send.ts | 61 + packages/mail/src/util/templates.ts | 37 + packages/mail/src/util/translations.ts | 6 + packages/mail/tsconfig.json | 5 + packages/mail/types.ts | 19 + packages/payments/biome.json | 3 + packages/payments/index.ts | 2 + packages/payments/package.json | 32 + packages/payments/provider/creem/index.ts | 220 + packages/payments/provider/index.ts | 1 + .../payments/provider/lemonsqueezy/index.ts | 246 + packages/payments/provider/polar/index.ts | 181 + packages/payments/provider/stripe/index.ts | 254 + packages/payments/src/lib/customer.ts | 36 + packages/payments/src/lib/helper.ts | 85 + packages/payments/tsconfig.json | 5 + packages/payments/types.ts | 33 + packages/storage/biome.json | 3 + packages/storage/index.ts | 1 + packages/storage/package.json | 20 + packages/storage/provider/index.ts | 1 + packages/storage/provider/s3/index.ts | 89 + packages/storage/tsconfig.json | 5 + packages/storage/types.ts | 21 + packages/utils/biome.json | 3 + packages/utils/index.ts | 1 + packages/utils/lib/base-url.ts | 9 + packages/utils/package.json | 14 + packages/utils/tsconfig.json | 5 + pnpm-lock.yaml | 12693 ++++++++++++++++ pnpm-workspace.yaml | 5 + tooling/scripts/biome.json | 3 + tooling/scripts/package.json | 22 + tooling/scripts/src/create-user.ts | 63 + tooling/scripts/tsconfig.json | 5 + tooling/tailwind/biome.json | 3 + tooling/tailwind/package.json | 13 + tooling/tailwind/tailwind-animate.css | 275 + tooling/tailwind/theme.css | 131 + tooling/typescript/base.json | 24 + tooling/typescript/biome.json | 3 + tooling/typescript/nextjs.json | 19 + tooling/typescript/package.json | 11 + tooling/typescript/react-library.json | 11 + tsconfig.json | 3 + turbo.json | 32 + 434 files changed, 44051 insertions(+) create mode 100644 .cursor/rules/key-principles.mdc create mode 100644 .cursor/rules/naming-coventions.mdc create mode 100644 .cursor/rules/performance.mdc create mode 100644 .cursor/rules/project-structure.mdc create mode 100644 .cursor/rules/syntax-and-formatting.mdc create mode 100644 .cursor/rules/typescript-usage.mdc create mode 100644 .cursor/rules/ui-and-styling.mdc create mode 100644 .editorconfig create mode 100644 .env.local.example create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/validate-prs.yml create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/dataSources.xml create mode 100644 .idea/data_source_mapping.xml create mode 100644 .idea/main-test.iml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .npmrc create mode 100644 .vscode/extensions.json create mode 100644 .vscode/settings.json create mode 100644 .windsurfrules create mode 100644 README.md create mode 100644 apps/web/.gitignore create mode 100644 apps/web/app/(marketing)/[locale]/(home)/page.tsx create mode 100644 apps/web/app/(marketing)/[locale]/[...rest]/page.tsx create mode 100644 apps/web/app/(marketing)/[locale]/blog/[...path]/page.tsx create mode 100644 apps/web/app/(marketing)/[locale]/blog/page.tsx create mode 100644 apps/web/app/(marketing)/[locale]/changelog/page.tsx create mode 100644 apps/web/app/(marketing)/[locale]/contact/page.tsx create mode 100644 apps/web/app/(marketing)/[locale]/docs/[[...path]]/layout.tsx create mode 100644 apps/web/app/(marketing)/[locale]/docs/[[...path]]/page.tsx create mode 100644 apps/web/app/(marketing)/[locale]/layout.tsx create mode 100644 apps/web/app/(marketing)/[locale]/legal/[...path]/page.tsx create mode 100644 apps/web/app/(marketing)/[locale]/not-found.tsx create mode 100644 apps/web/app/(saas)/app/(account)/admin/layout.tsx create mode 100644 apps/web/app/(saas)/app/(account)/admin/organizations/[id]/page.tsx create mode 100644 apps/web/app/(saas)/app/(account)/admin/organizations/page.tsx create mode 100644 apps/web/app/(saas)/app/(account)/admin/users/page.tsx create mode 100644 apps/web/app/(saas)/app/(account)/chatbot/page.tsx create mode 100644 apps/web/app/(saas)/app/(account)/layout.tsx create mode 100644 apps/web/app/(saas)/app/(account)/page.tsx create mode 100644 apps/web/app/(saas)/app/(account)/settings/billing/page.tsx create mode 100644 apps/web/app/(saas)/app/(account)/settings/danger-zone/page.tsx create mode 100644 apps/web/app/(saas)/app/(account)/settings/general/page.tsx create mode 100644 apps/web/app/(saas)/app/(account)/settings/layout.tsx create mode 100644 apps/web/app/(saas)/app/(account)/settings/security/page.tsx create mode 100644 apps/web/app/(saas)/app/(organizations)/(without-organization-slug)/layout.tsx create mode 100644 apps/web/app/(saas)/app/(organizations)/(without-organization-slug)/new-organization/page.tsx create mode 100644 apps/web/app/(saas)/app/(organizations)/(without-organization-slug)/organization-invitation/[invitationId]/page.tsx create mode 100644 apps/web/app/(saas)/app/(organizations)/[organizationSlug]/chatbot/page.tsx create mode 100644 apps/web/app/(saas)/app/(organizations)/[organizationSlug]/layout.tsx create mode 100644 apps/web/app/(saas)/app/(organizations)/[organizationSlug]/page.tsx create mode 100644 apps/web/app/(saas)/app/(organizations)/[organizationSlug]/settings/billing/page.tsx create mode 100644 apps/web/app/(saas)/app/(organizations)/[organizationSlug]/settings/danger-zone/page.tsx create mode 100644 apps/web/app/(saas)/app/(organizations)/[organizationSlug]/settings/general/page.tsx create mode 100644 apps/web/app/(saas)/app/(organizations)/[organizationSlug]/settings/layout.tsx create mode 100644 apps/web/app/(saas)/app/(organizations)/[organizationSlug]/settings/members/page.tsx create mode 100644 apps/web/app/(saas)/app/[...rest]/page.tsx create mode 100644 apps/web/app/(saas)/app/choose-plan/page.tsx create mode 100644 apps/web/app/(saas)/app/layout.tsx create mode 100644 apps/web/app/(saas)/app/not-found.tsx create mode 100644 apps/web/app/(saas)/app/onboarding/page.tsx create mode 100644 apps/web/app/(saas)/auth/forgot-password/page.tsx create mode 100644 apps/web/app/(saas)/auth/layout.tsx create mode 100644 apps/web/app/(saas)/auth/login/page.tsx create mode 100644 apps/web/app/(saas)/auth/reset-password/page.tsx create mode 100644 apps/web/app/(saas)/auth/signup/page.tsx create mode 100644 apps/web/app/(saas)/auth/verify/page.tsx create mode 100644 apps/web/app/(saas)/layout.tsx create mode 100644 apps/web/app/api/[[...rest]]/route.ts create mode 100644 apps/web/app/api/docs-search/route.ts create mode 100644 apps/web/app/docs-source.ts create mode 100644 apps/web/app/favicon.ico create mode 100644 apps/web/app/globals.css create mode 100644 apps/web/app/icon.png create mode 100644 apps/web/app/image-proxy/[...path]/route.ts create mode 100644 apps/web/app/layout.tsx create mode 100644 apps/web/app/robots.ts create mode 100644 apps/web/app/sitemap.ts create mode 100644 apps/web/biome.json create mode 100644 apps/web/components.json create mode 100644 apps/web/content-collections.ts create mode 100644 apps/web/content/docs/getting-started/meta.de.json create mode 100644 apps/web/content/docs/getting-started/meta.json create mode 100644 apps/web/content/docs/getting-started/overview.de.mdx create mode 100644 apps/web/content/docs/getting-started/overview.mdx create mode 100644 apps/web/content/docs/index.de.mdx create mode 100644 apps/web/content/docs/index.mdx create mode 100644 apps/web/content/docs/meta.json create mode 100644 apps/web/content/legal/privacy-policy.de.md create mode 100644 apps/web/content/legal/privacy-policy.md create mode 100644 apps/web/content/legal/terms.de.md create mode 100644 apps/web/content/legal/terms.md create mode 100644 apps/web/content/posts/first-post.de.mdx create mode 100644 apps/web/content/posts/first-post.mdx create mode 100644 apps/web/content/posts/second-post.mdx create mode 100644 apps/web/global.d.ts create mode 100644 apps/web/middleware.ts create mode 100644 apps/web/modules/analytics/index.tsx create mode 100644 apps/web/modules/analytics/provider/custom/index.tsx create mode 100644 apps/web/modules/analytics/provider/google/index.tsx create mode 100644 apps/web/modules/analytics/provider/mixpanel/index.tsx create mode 100644 apps/web/modules/analytics/provider/pirsch/index.tsx create mode 100644 apps/web/modules/analytics/provider/plausible/index.tsx create mode 100644 apps/web/modules/analytics/provider/posthog/index.tsx create mode 100644 apps/web/modules/analytics/provider/umami/index.tsx create mode 100644 apps/web/modules/analytics/provider/vercel/index.tsx create mode 100644 apps/web/modules/i18n/lib/locale-cookie.ts create mode 100644 apps/web/modules/i18n/lib/update-locale.ts create mode 100644 apps/web/modules/i18n/request.ts create mode 100644 apps/web/modules/i18n/routing.ts create mode 100644 apps/web/modules/marketing/blog/components/PostContent.tsx create mode 100644 apps/web/modules/marketing/blog/components/PostListItem.tsx create mode 100644 apps/web/modules/marketing/blog/types.ts create mode 100644 apps/web/modules/marketing/blog/utils/lib/posts.ts create mode 100644 apps/web/modules/marketing/blog/utils/mdx-components.tsx create mode 100644 apps/web/modules/marketing/changelog/components/ChangelogSection.tsx create mode 100644 apps/web/modules/marketing/changelog/types.ts create mode 100644 apps/web/modules/marketing/home/components/ContactForm.tsx create mode 100644 apps/web/modules/marketing/home/components/FaqSection.tsx create mode 100644 apps/web/modules/marketing/home/components/Features.tsx create mode 100644 apps/web/modules/marketing/home/components/Hero.tsx create mode 100644 apps/web/modules/marketing/home/components/Newsletter.tsx create mode 100644 apps/web/modules/marketing/home/components/PricingSection.tsx create mode 100644 apps/web/modules/marketing/home/lib/api.ts create mode 100644 apps/web/modules/marketing/home/types.ts create mode 100644 apps/web/modules/marketing/shared/components/ContentMenu.tsx create mode 100644 apps/web/modules/marketing/shared/components/Footer.tsx create mode 100644 apps/web/modules/marketing/shared/components/NavBar.tsx create mode 100644 apps/web/modules/marketing/shared/components/NotFound.tsx create mode 100644 apps/web/modules/marketing/shared/components/TableOfContents.tsx create mode 100644 apps/web/modules/saas/admin/component/EmailVerified.tsx create mode 100644 apps/web/modules/saas/admin/component/organizations/OrganizationForm.tsx create mode 100644 apps/web/modules/saas/admin/component/organizations/OrganizationList.tsx create mode 100644 apps/web/modules/saas/admin/component/users/UserList.tsx create mode 100644 apps/web/modules/saas/admin/lib/api.ts create mode 100644 apps/web/modules/saas/admin/lib/links.ts create mode 100644 apps/web/modules/saas/ai/components/AiChat.tsx create mode 100644 apps/web/modules/saas/ai/lib/api.ts create mode 100644 apps/web/modules/saas/auth/components/ForgotPasswordForm.tsx create mode 100644 apps/web/modules/saas/auth/components/LoginForm.tsx create mode 100644 apps/web/modules/saas/auth/components/LoginModeSwitch.tsx create mode 100644 apps/web/modules/saas/auth/components/OtpForm.tsx create mode 100644 apps/web/modules/saas/auth/components/ResetPasswordForm.tsx create mode 100644 apps/web/modules/saas/auth/components/SessionProvider.tsx create mode 100644 apps/web/modules/saas/auth/components/SignupForm.tsx create mode 100644 apps/web/modules/saas/auth/components/SocialSigninButton.tsx create mode 100644 apps/web/modules/saas/auth/constants/oauth-providers.tsx create mode 100644 apps/web/modules/saas/auth/hooks/errors-messages.ts create mode 100644 apps/web/modules/saas/auth/hooks/use-session.ts create mode 100644 apps/web/modules/saas/auth/lib/api.ts create mode 100644 apps/web/modules/saas/auth/lib/server.ts create mode 100644 apps/web/modules/saas/auth/lib/session-context.ts create mode 100644 apps/web/modules/saas/onboarding/components/OnboardingForm.tsx create mode 100644 apps/web/modules/saas/onboarding/components/OnboardingStep1.tsx create mode 100644 apps/web/modules/saas/organizations/components/ActiveOrganizationProvider.tsx create mode 100644 apps/web/modules/saas/organizations/components/ChangeOrganizationNameForm.tsx create mode 100644 apps/web/modules/saas/organizations/components/CreateOrganizationForm.tsx create mode 100644 apps/web/modules/saas/organizations/components/DeleteOrganizationForm.tsx create mode 100644 apps/web/modules/saas/organizations/components/InviteMemberForm.tsx create mode 100644 apps/web/modules/saas/organizations/components/OrganizationInvitationAlert.tsx create mode 100644 apps/web/modules/saas/organizations/components/OrganizationInvitationModal.tsx create mode 100644 apps/web/modules/saas/organizations/components/OrganizationInvitationsList.tsx create mode 100644 apps/web/modules/saas/organizations/components/OrganizationLogo.tsx create mode 100644 apps/web/modules/saas/organizations/components/OrganizationLogoForm.tsx create mode 100644 apps/web/modules/saas/organizations/components/OrganizationMembersBlock.tsx create mode 100644 apps/web/modules/saas/organizations/components/OrganizationMembersList.tsx create mode 100644 apps/web/modules/saas/organizations/components/OrganizationRoleSelect.tsx create mode 100644 apps/web/modules/saas/organizations/components/OrganizationSelect.tsx create mode 100644 apps/web/modules/saas/organizations/components/OrganizationStart.tsx create mode 100644 apps/web/modules/saas/organizations/components/OrganizationsGrid.tsx create mode 100644 apps/web/modules/saas/organizations/hooks/member-roles.ts create mode 100644 apps/web/modules/saas/organizations/hooks/use-active-organization.ts create mode 100644 apps/web/modules/saas/organizations/lib/active-organization-context.ts create mode 100644 apps/web/modules/saas/organizations/lib/api.ts create mode 100644 apps/web/modules/saas/payments/components/ActivePlan.tsx create mode 100644 apps/web/modules/saas/payments/components/ActivePlanBadge.tsx create mode 100644 apps/web/modules/saas/payments/components/ChangePlan.tsx create mode 100644 apps/web/modules/saas/payments/components/PricingTable.tsx create mode 100644 apps/web/modules/saas/payments/hooks/plan-data.tsx create mode 100644 apps/web/modules/saas/payments/hooks/purchases.tsx create mode 100644 apps/web/modules/saas/payments/lib/api.ts create mode 100644 apps/web/modules/saas/payments/lib/purchases-context.ts create mode 100644 apps/web/modules/saas/payments/lib/server.ts create mode 100644 apps/web/modules/saas/payments/types.ts create mode 100644 apps/web/modules/saas/settings/components/ActiveSessionsBlock.tsx create mode 100644 apps/web/modules/saas/settings/components/ChangeEmailForm.tsx create mode 100644 apps/web/modules/saas/settings/components/ChangeNameForm.tsx create mode 100644 apps/web/modules/saas/settings/components/ChangePassword.tsx create mode 100644 apps/web/modules/saas/settings/components/ConnectedAccountsBlock.tsx create mode 100644 apps/web/modules/saas/settings/components/CropImageDialog.tsx create mode 100644 apps/web/modules/saas/settings/components/CustomerPortalButton.tsx create mode 100644 apps/web/modules/saas/settings/components/DeleteAccountForm.tsx create mode 100644 apps/web/modules/saas/settings/components/PasskeysBlock.tsx create mode 100644 apps/web/modules/saas/settings/components/SetPassword.tsx create mode 100644 apps/web/modules/saas/settings/components/SettingsMenu.tsx create mode 100644 apps/web/modules/saas/settings/components/SubscriptionStatusBadge.tsx create mode 100644 apps/web/modules/saas/settings/components/TwoFactorBlock.tsx create mode 100644 apps/web/modules/saas/settings/components/UserAvatarForm.tsx create mode 100644 apps/web/modules/saas/settings/components/UserAvatarUpload.tsx create mode 100644 apps/web/modules/saas/settings/components/UserLanguageForm.tsx create mode 100644 apps/web/modules/saas/shared/components/AppWrapper.tsx create mode 100644 apps/web/modules/saas/shared/components/AuthWrapper.tsx create mode 100644 apps/web/modules/saas/shared/components/ConfirmationAlertProvider.tsx create mode 100644 apps/web/modules/saas/shared/components/Footer.tsx create mode 100644 apps/web/modules/saas/shared/components/NavBar.tsx create mode 100644 apps/web/modules/saas/shared/components/PageHeader.tsx create mode 100644 apps/web/modules/saas/shared/components/Pagination.tsx create mode 100644 apps/web/modules/saas/shared/components/SettingsItem.tsx create mode 100644 apps/web/modules/saas/shared/components/SettingsList.tsx create mode 100644 apps/web/modules/saas/shared/components/SidebarContentLayout.tsx create mode 100644 apps/web/modules/saas/shared/components/TabGroup.tsx create mode 100644 apps/web/modules/saas/shared/components/UserMenu.tsx create mode 100644 apps/web/modules/saas/shared/lib/api.ts create mode 100644 apps/web/modules/saas/shared/lib/state.ts create mode 100644 apps/web/modules/saas/start/UserStart.tsx create mode 100644 apps/web/modules/saas/start/components/StatsTile.tsx create mode 100644 apps/web/modules/shared/components/ApiClientProvider.tsx create mode 100644 apps/web/modules/shared/components/ColorModeToggle.tsx create mode 100644 apps/web/modules/shared/components/ConsentBanner.tsx create mode 100644 apps/web/modules/shared/components/ConsentProvider.tsx create mode 100644 apps/web/modules/shared/components/Document.tsx create mode 100644 apps/web/modules/shared/components/LocaleSwitch.tsx create mode 100644 apps/web/modules/shared/components/Logo.tsx create mode 100644 apps/web/modules/shared/components/Spinner.tsx create mode 100644 apps/web/modules/shared/components/UserAvatar.tsx create mode 100644 apps/web/modules/shared/hooks/cookie-consent.ts create mode 100644 apps/web/modules/shared/hooks/form-errors.ts create mode 100644 apps/web/modules/shared/hooks/locale-currency.tsx create mode 100644 apps/web/modules/shared/hooks/router.ts create mode 100644 apps/web/modules/shared/lib/api-client.ts create mode 100644 apps/web/modules/shared/lib/cache.ts create mode 100644 apps/web/modules/shared/lib/content.ts create mode 100644 apps/web/modules/shared/lib/middleware-helpers.ts create mode 100644 apps/web/modules/shared/lib/query-client.ts create mode 100644 apps/web/modules/shared/lib/server.ts create mode 100644 apps/web/modules/ui/components/accordion.tsx create mode 100644 apps/web/modules/ui/components/alert-dialog.tsx create mode 100644 apps/web/modules/ui/components/alert.tsx create mode 100644 apps/web/modules/ui/components/avatar.tsx create mode 100644 apps/web/modules/ui/components/badge.tsx create mode 100644 apps/web/modules/ui/components/button.tsx create mode 100644 apps/web/modules/ui/components/card.tsx create mode 100644 apps/web/modules/ui/components/dialog.tsx create mode 100644 apps/web/modules/ui/components/dropdown-menu.tsx create mode 100644 apps/web/modules/ui/components/form.tsx create mode 100644 apps/web/modules/ui/components/input-otp.tsx create mode 100644 apps/web/modules/ui/components/input.tsx create mode 100644 apps/web/modules/ui/components/label.tsx create mode 100644 apps/web/modules/ui/components/password-input.tsx create mode 100644 apps/web/modules/ui/components/progress.tsx create mode 100644 apps/web/modules/ui/components/select.tsx create mode 100644 apps/web/modules/ui/components/sheet.tsx create mode 100644 apps/web/modules/ui/components/skeleton.tsx create mode 100644 apps/web/modules/ui/components/table.tsx create mode 100644 apps/web/modules/ui/components/tabs.tsx create mode 100644 apps/web/modules/ui/components/textarea.tsx create mode 100644 apps/web/modules/ui/components/toast.tsx create mode 100644 apps/web/modules/ui/components/tooltip.tsx create mode 100644 apps/web/modules/ui/lib/index.ts create mode 100644 apps/web/next.config.ts create mode 100644 apps/web/package.json create mode 100644 apps/web/playwright.config.ts create mode 100644 apps/web/postcss.config.cjs create mode 100644 apps/web/public/images/blog/author.jpg create mode 100644 apps/web/public/images/blog/author2.jpg create mode 100644 apps/web/public/images/blog/cover.png create mode 100644 apps/web/public/images/docs/login.png create mode 100644 apps/web/public/images/hero-dark.svg create mode 100644 apps/web/public/images/hero-image-dark.png create mode 100644 apps/web/public/images/hero-image.png create mode 100644 apps/web/public/images/hero.svg create mode 100644 apps/web/public/images/supastarter-logo-dark.svg create mode 100644 apps/web/public/images/supastarter-logo-light.svg create mode 100644 apps/web/tests/home.spec.ts create mode 100644 apps/web/tsconfig.json create mode 100644 biome.json create mode 100644 config/index.ts create mode 100644 config/package.json create mode 100644 config/tsconfig.json create mode 100644 config/types.ts create mode 100644 package.json create mode 100644 packages/ai/biome.json create mode 100644 packages/ai/client.ts create mode 100644 packages/ai/index.ts create mode 100644 packages/ai/lib/index.ts create mode 100644 packages/ai/lib/prompts.ts create mode 100644 packages/ai/package.json create mode 100644 packages/ai/tsconfig.json create mode 100644 packages/api/biome.json create mode 100644 packages/api/index.ts create mode 100644 packages/api/package.json create mode 100644 packages/api/src/app.ts create mode 100644 packages/api/src/lib/openapi-schema.ts create mode 100644 packages/api/src/middleware/admin.ts create mode 100644 packages/api/src/middleware/auth.ts create mode 100644 packages/api/src/middleware/cors.ts create mode 100644 packages/api/src/middleware/locale.ts create mode 100644 packages/api/src/middleware/logger.ts create mode 100644 packages/api/src/routes/admin/organizations.ts create mode 100644 packages/api/src/routes/admin/router.ts create mode 100644 packages/api/src/routes/admin/users.ts create mode 100644 packages/api/src/routes/ai.ts create mode 100644 packages/api/src/routes/auth.ts create mode 100644 packages/api/src/routes/contact/router.ts create mode 100644 packages/api/src/routes/contact/types.ts create mode 100644 packages/api/src/routes/health.ts create mode 100644 packages/api/src/routes/newsletter.ts create mode 100644 packages/api/src/routes/organizations/lib/membership.ts create mode 100644 packages/api/src/routes/organizations/router.ts create mode 100644 packages/api/src/routes/payments/lib/purchases.ts create mode 100644 packages/api/src/routes/payments/router.ts create mode 100644 packages/api/src/routes/payments/types.ts create mode 100644 packages/api/src/routes/uploads.ts create mode 100644 packages/api/src/routes/webhooks.ts create mode 100644 packages/api/tsconfig.json create mode 100644 packages/auth/auth.ts create mode 100644 packages/auth/biome.json create mode 100644 packages/auth/client.ts create mode 100644 packages/auth/index.ts create mode 100644 packages/auth/lib/helper.ts create mode 100644 packages/auth/lib/organization.ts create mode 100644 packages/auth/package.json create mode 100644 packages/auth/plugins/invitation-only/index.ts create mode 100644 packages/auth/tsconfig.json create mode 100644 packages/database/biome.json create mode 100644 packages/database/drizzle/client.ts create mode 100644 packages/database/drizzle/drizzle.config.ts create mode 100644 packages/database/drizzle/index.ts create mode 100644 packages/database/drizzle/queries/ai-chats.ts create mode 100644 packages/database/drizzle/queries/index.ts create mode 100644 packages/database/drizzle/queries/organizations.ts create mode 100644 packages/database/drizzle/queries/purchases.ts create mode 100644 packages/database/drizzle/queries/users.ts create mode 100644 packages/database/drizzle/schema/index.ts create mode 100644 packages/database/drizzle/schema/mysql.ts create mode 100644 packages/database/drizzle/schema/postgres.ts create mode 100644 packages/database/drizzle/schema/sqlite.ts create mode 100644 packages/database/drizzle/zod.ts create mode 100644 packages/database/index.ts create mode 100644 packages/database/package.json create mode 100644 packages/database/prisma/client.ts create mode 100644 packages/database/prisma/index.ts create mode 100644 packages/database/prisma/queries/ai-chats.ts create mode 100644 packages/database/prisma/queries/index.ts create mode 100644 packages/database/prisma/queries/organizations.ts create mode 100644 packages/database/prisma/queries/purchases.ts create mode 100644 packages/database/prisma/queries/users.ts create mode 100644 packages/database/prisma/schema.prisma create mode 100644 packages/database/prisma/zod/index.ts create mode 100644 packages/database/tsconfig.json create mode 100644 packages/i18n/biome.json create mode 100644 packages/i18n/index.ts create mode 100644 packages/i18n/lib/messages.ts create mode 100644 packages/i18n/package.json create mode 100644 packages/i18n/translations/de.json create mode 100644 packages/i18n/translations/en.json create mode 100644 packages/i18n/tsconfig.json create mode 100644 packages/i18n/types.ts create mode 100644 packages/logs/biome.json create mode 100644 packages/logs/index.ts create mode 100644 packages/logs/lib/logger.ts create mode 100644 packages/logs/package.json create mode 100644 packages/logs/tsconfig.json create mode 100644 packages/mail/.gitignore create mode 100644 packages/mail/biome.json create mode 100644 packages/mail/emails/EmailVerification.tsx create mode 100644 packages/mail/emails/ForgotPassword.tsx create mode 100644 packages/mail/emails/MagicLink.tsx create mode 100644 packages/mail/emails/NewUser.tsx create mode 100644 packages/mail/emails/NewsletterSignup.tsx create mode 100644 packages/mail/emails/OrganizationInvitation.tsx create mode 100644 packages/mail/emails/index.ts create mode 100644 packages/mail/global.d.ts create mode 100644 packages/mail/index.ts create mode 100644 packages/mail/package.json create mode 100644 packages/mail/src/components/Logo.tsx create mode 100644 packages/mail/src/components/PrimaryButton.tsx create mode 100644 packages/mail/src/components/Wrapper.tsx create mode 100644 packages/mail/src/provider/console.ts create mode 100644 packages/mail/src/provider/custom.ts create mode 100644 packages/mail/src/provider/index.ts create mode 100644 packages/mail/src/provider/mailgun.ts create mode 100644 packages/mail/src/provider/nodemailer.ts create mode 100644 packages/mail/src/provider/plunk.ts create mode 100644 packages/mail/src/provider/postmark.ts create mode 100644 packages/mail/src/provider/resend.ts create mode 100644 packages/mail/src/util/send.ts create mode 100644 packages/mail/src/util/templates.ts create mode 100644 packages/mail/src/util/translations.ts create mode 100644 packages/mail/tsconfig.json create mode 100644 packages/mail/types.ts create mode 100644 packages/payments/biome.json create mode 100644 packages/payments/index.ts create mode 100644 packages/payments/package.json create mode 100644 packages/payments/provider/creem/index.ts create mode 100644 packages/payments/provider/index.ts create mode 100644 packages/payments/provider/lemonsqueezy/index.ts create mode 100644 packages/payments/provider/polar/index.ts create mode 100644 packages/payments/provider/stripe/index.ts create mode 100644 packages/payments/src/lib/customer.ts create mode 100644 packages/payments/src/lib/helper.ts create mode 100644 packages/payments/tsconfig.json create mode 100644 packages/payments/types.ts create mode 100644 packages/storage/biome.json create mode 100644 packages/storage/index.ts create mode 100644 packages/storage/package.json create mode 100644 packages/storage/provider/index.ts create mode 100644 packages/storage/provider/s3/index.ts create mode 100644 packages/storage/tsconfig.json create mode 100644 packages/storage/types.ts create mode 100644 packages/utils/biome.json create mode 100644 packages/utils/index.ts create mode 100644 packages/utils/lib/base-url.ts create mode 100644 packages/utils/package.json create mode 100644 packages/utils/tsconfig.json create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml create mode 100644 tooling/scripts/biome.json create mode 100644 tooling/scripts/package.json create mode 100644 tooling/scripts/src/create-user.ts create mode 100644 tooling/scripts/tsconfig.json create mode 100644 tooling/tailwind/biome.json create mode 100644 tooling/tailwind/package.json create mode 100644 tooling/tailwind/tailwind-animate.css create mode 100644 tooling/tailwind/theme.css create mode 100644 tooling/typescript/base.json create mode 100644 tooling/typescript/biome.json create mode 100644 tooling/typescript/nextjs.json create mode 100644 tooling/typescript/package.json create mode 100644 tooling/typescript/react-library.json create mode 100644 tsconfig.json create mode 100644 turbo.json diff --git a/.cursor/rules/key-principles.mdc b/.cursor/rules/key-principles.mdc new file mode 100644 index 0000000..85b8b0f --- /dev/null +++ b/.cursor/rules/key-principles.mdc @@ -0,0 +1,17 @@ +--- +description: +globs: +alwaysApply: true +--- +This rule describes the key principles of how to generate code for this project. + +Whenever code is generated assume you are an expert in TypeScript, Node.js, Next.js App Router, React, Shadcn UI, Radix UI and Tailwind. + +- Write concise, technical TypeScript code with accurate examples. +- Use functional and declarative programming patterns; avoid classes. +- Prefer iteration and modularization over code duplication. +- Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError). +- Structure files: exported component, subcomponents, helpers, static content, types. + +Follow Next.js docs for Data Fetching, Rendering, and Routing. +Follow the documentation at supastarter.dev/docs/nextjs for supastarter specifc patterns. diff --git a/.cursor/rules/naming-coventions.mdc b/.cursor/rules/naming-coventions.mdc new file mode 100644 index 0000000..68bbd95 --- /dev/null +++ b/.cursor/rules/naming-coventions.mdc @@ -0,0 +1,11 @@ +--- +description: +globs: +alwaysApply: true +--- +This rule describes what naming conventions to use for files, folders, components and methods. + +- Use lowercase with dashes for directories (e.g., components/auth-wizard). +- Use PascalCase for component names +- Use camelCase for variables and method names +- Favor named exports for components. \ No newline at end of file diff --git a/.cursor/rules/performance.mdc b/.cursor/rules/performance.mdc new file mode 100644 index 0000000..c7cca19 --- /dev/null +++ b/.cursor/rules/performance.mdc @@ -0,0 +1,11 @@ +--- +description: +globs: +alwaysApply: true +--- +This rule describes how to optimize the code for performance. + +- Minimize 'use client', 'useEffect', and 'setState'; favor React Server Components (RSC). +- Wrap client components in Suspense with fallback. +- Use dynamic loading for non-critical components. +- Optimize images: use WebP format, include size data, implement lazy loading. diff --git a/.cursor/rules/project-structure.mdc b/.cursor/rules/project-structure.mdc new file mode 100644 index 0000000..0e1a089 --- /dev/null +++ b/.cursor/rules/project-structure.mdc @@ -0,0 +1,20 @@ +--- +description: +globs: +alwaysApply: true +--- +This rule describes the basic project structure of the repository and where to find or add certain parts of the application: + +- The main application is in the `packages/app` directory which is a Next.js App Router. Put all frontend-only code in this directory. +- Put all backend logic into one of the `packages` directories: + - `packages/ai` contains all AI-related code + - `packages/api` contains all API routes + - `packages/auth` contains the config for better-auth and helper functions + - `packages/database` contains the database schema and auto-generated types + - `packages/i18n` contains translations and internationalization helper functions + - `packages/logs` contains the logging config and helper functions + - `packages/mail` contains providers for sending mails and email templates + - `packages/payments` contains code for payment providers and payment processing + - `packages/storage` contains providers for storing files and images + - `packages/utils` contains utility functions + - `config` contains the application configuration \ No newline at end of file diff --git a/.cursor/rules/syntax-and-formatting.mdc b/.cursor/rules/syntax-and-formatting.mdc new file mode 100644 index 0000000..c5afa91 --- /dev/null +++ b/.cursor/rules/syntax-and-formatting.mdc @@ -0,0 +1,10 @@ +--- +description: +globs: +alwaysApply: true +--- +This rule describes syntax and formatting rules used across the codebase. + +- Use the "function" keyword for pure functions. +- Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements. +- Use declarative JSX. \ No newline at end of file diff --git a/.cursor/rules/typescript-usage.mdc b/.cursor/rules/typescript-usage.mdc new file mode 100644 index 0000000..25884f0 --- /dev/null +++ b/.cursor/rules/typescript-usage.mdc @@ -0,0 +1,10 @@ +--- +description: +globs: +alwaysApply: true +--- +This rule describes how to use typescript across the project. + +- Use TypeScript for all code; prefer interfaces over types. +- Avoid enums; use maps instead. +- Use functional components with TypeScript interfaces. diff --git a/.cursor/rules/ui-and-styling.mdc b/.cursor/rules/ui-and-styling.mdc new file mode 100644 index 0000000..bfcd309 --- /dev/null +++ b/.cursor/rules/ui-and-styling.mdc @@ -0,0 +1,11 @@ +--- +description: +globs: +alwaysApply: true +--- +This rule describes guidelines for creating UI and styling components: + +- Use Shadcn UI, Radix, and Tailwind for components and styling. +- Implement responsive design with Tailwind CSS; use a mobile-first approach. +- Use the `cn` function for class name concatenation. +- The global theme variables and tailwind config are defined in `tooling/tailwind/theme.css`. diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..92ab8bf --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = false +insert_final_newline = true diff --git a/.env.local.example b/.env.local.example new file mode 100644 index 0000000..6480166 --- /dev/null +++ b/.env.local.example @@ -0,0 +1,76 @@ +# Database +DATABASE_URL="YOUR_DATABASE_CONNECTION_STRING" +# ... if you use Supabase +DIRECT_URL="" + +# Site url +NEXT_PUBLIC_SITE_URL="http://localhost:3000" + +# Authentication +BETTER_AUTH_SECRET="A_RANDOM_SECRET_STRING" +# ... for Github +GITHUB_CLIENT_ID="YOUR_GITHUB_CLIENT_ID" +GITHUB_CLIENT_SECRET="YOUR_GITHUB_CLIENT_SECRET" +# ... for Google +GOOGLE_CLIENT_ID="YOUR_GOOGLE_CLIENT_ID" +GOOGLE_CLIENT_SECRET="YOUR_GOOGLE_CLIENT_SECRET" + +# Mails +# ... with nodemailer +MAIL_HOST="" +MAIL_PORT="" +MAIL_USER="" +MAIL_PASS="" +# ... with Plunk +PLUNK_API_KEY="" +# ... with Resend +RESEND_API_KEY="" +# ... with Postmark +POSTMARK_SERVER_TOKEN="" +# ... with Mailgun +MAILGUN_API_KEY="" +MAILGUN_DOMAIN="" + +# Payments +# ... with Lemonsqueezy +LEMONSQUEEZY_API_KEY="" +LEMONSQUEEZY_WEBHOOK_SECRET="" +LEMONSQUEEZY_STORE_ID="" +# ... with Stripe +STRIPE_SECRET_KEY="" +STRIPE_WEBHOOK_SECRET="" +# ... with Chargebee +CHARGEBEE_SITE="" +CHARGEBEE_API_KEY="" +# ... with Creem +CREEM_API_KEY="" +CREEM_WEBHOOK_SECRET="" +# ... with Polar +POLAR_ACCESS_TOKEN="" +POLAR_WEBHOOK_SECRET="" + +# Product price ids +NEXT_PUBLIC_PRICE_ID_PRO_MONTHLY="asdf" +NEXT_PUBLIC_PRICE_ID_PRO_YEARLY="asdf" +NEXT_PUBLIC_PRICE_ID_LIFETIME="asdf" + +# Analytics +# ... for Pirsch +NEXT_PUBLIC_PIRSCH_CODE="" +# ... for Plausible +NEXT_PUBLIC_PLAUSIBLE_URL="" +# ... for Mixpanel +NEXT_PUBLIC_MIXPANEL_TOKEN="" +# ... for Google Analytics +NEXT_PUBLIC_GOOGLE_ANALYTICS_ID="" + +# Storage +S3_ACCESS_KEY_ID="" +S3_SECRET_ACCESS_KEY="" +S3_ENDPOINT="" +S3_REGION="" +NEXT_PUBLIC_AVATARS_BUCKET_NAME="avatars" + +# AI +# ... with OpenAI +OPENAI_API_KEY="" diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..4babf98 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,15 @@ +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/" + open-pull-requests-limit: 2 + schedule: + interval: "daily" + ignore: + - dependency-name: "cropperjs" + versions: [">1.6.2"] + groups: + production-dependencies: + dependency-type: "production" + development-dependencies: + dependency-type: "development" diff --git a/.github/workflows/validate-prs.yml b/.github/workflows/validate-prs.yml new file mode 100644 index 0000000..dc92c74 --- /dev/null +++ b/.github/workflows/validate-prs.yml @@ -0,0 +1,39 @@ +name: Validate PRs + +on: + pull_request: + branches: [main] + +env: + DATABASE_URL: ${{ secrets.DATABASE_URL }} + +jobs: + lint: + name: Lint code + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Setup Biome + uses: biomejs/setup-biome@v2 + - name: Run Biome + run: biome ci . + e2e: + name: Run e2e tests + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: lts/* + - uses: pnpm/action-setup@v4 + - name: Install dependencies + run: pnpm install && pnpm --filter database generate + - name: Run Playwright tests + run: pnpm --filter web e2e:ci + - uses: actions/upload-artifact@v4 + if: ${{ !cancelled() }} + with: + name: playwright-report + path: apps/web/playwright-report/ + retention-days: 30 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b0efb65 --- /dev/null +++ b/.gitignore @@ -0,0 +1,44 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +node_modules +.pnp +.pnp.js + +# testing +coverage + +# next.js +.next/ +out/ +build +.swc/ + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# turbo +.turbo + +# ui +dist/ + +# typescript +*.tsbuildinfo + +# other +.react-email/ +.content-collections/ diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 0000000..56b7bb4 --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,12 @@ + + + + + postgresql + true + org.postgresql.Driver + jdbc:postgresql://localhost:5432/betterauth + $ProjectFileDir$ + + + \ No newline at end of file diff --git a/.idea/data_source_mapping.xml b/.idea/data_source_mapping.xml new file mode 100644 index 0000000..2d2d036 --- /dev/null +++ b/.idea/data_source_mapping.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/main-test.iml b/.idea/main-test.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/.idea/main-test.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..bd8b072 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..f0c0c3d --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +public-hoist-pattern[]=*prisma* diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..2f18a36 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + "recommendations": [ + "lokalise.i18n-ally", + "bradlc.vscode-tailwindcss", + "biomejs.biome" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..7c222d7 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,32 @@ +{ + "editor.defaultFormatter": "biomejs.biome", + "editor.formatOnSave": true, + "editor.formatOnPaste": true, + "emmet.showExpandedAbbreviation": "never", + "tailwindCSS.experimental.classRegex": [ + ["cn\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"] + ], + "editor.codeActionsOnSave": { + "quickfix.biome": "explicit", + "source.organizeImports.biome": "explicit" + }, + "typescript.preferences.importModuleSpecifier": "non-relative", + "typescript.tsdk": "node_modules/typescript/lib", + "i18n-ally.localesPaths": ["packages/i18n/translations"], + "i18n-ally.keystyle": "nested", + "i18n-ally.enabledFrameworks": ["next-intl"], + "i18n-ally.keysInUse": ["mail.organizationInvitation.headline"], + "i18n-ally.tabStyle": "tab", + "[typescript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[typescriptreact]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[json]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[prisma]": { + "editor.defaultFormatter": "Prisma.prisma" + } +} diff --git a/.windsurfrules b/.windsurfrules new file mode 100644 index 0000000..6415834 --- /dev/null +++ b/.windsurfrules @@ -0,0 +1,60 @@ +You are an expert in TypeScript, Node.js, Next.js App Router, React, Shadcn UI, Radix UI and Tailwind. + +Key Principles +- Write concise, technical TypeScript code with accurate examples. +- Use functional and declarative programming patterns; avoid classes. +- Prefer iteration and modularization over code duplication. +- Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError). +- Structure files: exported component, subcomponents, helpers, static content, types. + +Project Structure +- The main application is in the `packages/app` directory which is a Next.js App Router. Put all frontend-only code in this directory. +- Put all backend logic into one of the `packages` directories: + - `packages/ai` contains all AI-related code + - `packages/api` contains all API routes + - `packages/auth` contains the config for better-auth and helper functions + - `packages/database` contains the database schema and auto-generated types + - `packages/i18n` contains translations and internationalization helper functions + - `packages/logs` contains the logging config and helper functions + - `packages/mail` contains providers for sending mails and email templates + - `packages/payments` contains code for payment providers and payment processing + - `packages/storage` contains providers for storing files and images + - `packages/utils` contains utility functions + - `config` contains the application configuration + +Naming Conventions +- Use lowercase with dashes for directories (e.g., components/auth-wizard). +- Favor named exports for components. + +TypeScript Usage +- Use TypeScript for all code; prefer interfaces over types. +- Avoid enums; use maps instead. +- Use functional components with TypeScript interfaces. + +Syntax and Formatting +- Use the "function" keyword for pure functions. +- Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements. +- Use declarative JSX. + +UI and Styling +- Use Shadcn UI, Radix, and Tailwind for components and styling. +- Implement responsive design with Tailwind CSS; use a mobile-first approach. +- Use the `cn` function for class name concatenation. +- The global theme variables and tailwind config are defined in `tooling/tailwind/theme.css`. + +Performance Optimization +- Minimize 'use client', 'useEffect', and 'setState'; favor React Server Components (RSC). +- Wrap client components in Suspense with fallback. +- Use dynamic loading for non-critical components. +- Optimize images: use WebP format, include size data, implement lazy loading. + +Key Conventions +- Use 'nuqs' for URL search parameter state management. +- Optimize Web Vitals (LCP, CLS, FID). +- Limit 'use client': +- Favor server components and Next.js SSR. +- Use only for Web API access in small components. +- Avoid for data fetching or state management. + +Follow Next.js docs for Data Fetching, Rendering, and Routing. +Follow the documentation at supastarter.dev/docs/nextjs for supastarter specifc patterns. diff --git a/README.md b/README.md new file mode 100644 index 0000000..d4fed72 --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# supastarter for Next.js + +supastarter is the ultimate starter kit for production-ready, scalable SaaS applications. + +## Helpful links + +- [📘 Documentation](https://supastarter.dev/docs/nextjs) +- [🚀 Demo](https://demo.supastarter.dev) \ No newline at end of file diff --git a/apps/web/.gitignore b/apps/web/.gitignore new file mode 100644 index 0000000..ebaca49 --- /dev/null +++ b/apps/web/.gitignore @@ -0,0 +1,39 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage +/playwright-report +/test-results + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + +.content-collections diff --git a/apps/web/app/(marketing)/[locale]/(home)/page.tsx b/apps/web/app/(marketing)/[locale]/(home)/page.tsx new file mode 100644 index 0000000..2cd572c --- /dev/null +++ b/apps/web/app/(marketing)/[locale]/(home)/page.tsx @@ -0,0 +1,25 @@ +import { FaqSection } from "@marketing/home/components/FaqSection"; +import { Features } from "@marketing/home/components/Features"; +import { Hero } from "@marketing/home/components/Hero"; +import { Newsletter } from "@marketing/home/components/Newsletter"; +import { PricingSection } from "@marketing/home/components/PricingSection"; +import { setRequestLocale } from "next-intl/server"; + +export default async function Home({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + setRequestLocale(locale); + + return ( + <> + + + + + + + ); +} diff --git a/apps/web/app/(marketing)/[locale]/[...rest]/page.tsx b/apps/web/app/(marketing)/[locale]/[...rest]/page.tsx new file mode 100644 index 0000000..4583936 --- /dev/null +++ b/apps/web/app/(marketing)/[locale]/[...rest]/page.tsx @@ -0,0 +1,5 @@ +import { notFound } from "next/navigation"; + +export default function CatchAll() { + notFound(); +} diff --git a/apps/web/app/(marketing)/[locale]/blog/[...path]/page.tsx b/apps/web/app/(marketing)/[locale]/blog/[...path]/page.tsx new file mode 100644 index 0000000..d00f4bb --- /dev/null +++ b/apps/web/app/(marketing)/[locale]/blog/[...path]/page.tsx @@ -0,0 +1,128 @@ +import { LocaleLink, localeRedirect } from "@i18n/routing"; +import { PostContent } from "@marketing/blog/components/PostContent"; +import { getPostBySlug } from "@marketing/blog/utils/lib/posts"; +import { getBaseUrl } from "@repo/utils"; +import { getActivePathFromUrlParam } from "@shared/lib/content"; +import { getLocale, getTranslations, setRequestLocale } from "next-intl/server"; +import Image from "next/image"; + +type Params = { + path: string; + locale: string; +}; + +export async function generateMetadata(props: { params: Promise }) { + const params = await props.params; + + const { path } = params; + + const locale = await getLocale(); + const slug = getActivePathFromUrlParam(path); + const post = await getPostBySlug(slug, { locale }); + + return { + title: post?.title, + description: post?.excerpt, + openGraph: { + title: post?.title, + description: post?.excerpt, + images: post?.image + ? [ + post.image.startsWith("http") + ? post.image + : new URL(post.image, getBaseUrl()).toString(), + ] + : [], + }, + }; +} + +export default async function BlogPostPage(props: { params: Promise }) { + const { path, locale } = await props.params; + setRequestLocale(locale); + + const t = await getTranslations(); + + const slug = getActivePathFromUrlParam(path); + const post = await getPostBySlug(slug, { locale }); + + if (!post) { + return localeRedirect({ href: "/blog", locale }); + } + + const { title, date, authorName, authorImage, tags, image, body } = post; + + return ( +
+
+
+ + ← {t("blog.back")} + +
+ +

{title}

+ +
+ {authorName && ( +
+ {authorImage && ( +
+ {authorName} +
+ )} +
+

+ {authorName} +

+
+
+ )} + +
+

+ {Intl.DateTimeFormat("en-US").format( + new Date(date), + )} +

+
+ + {tags && ( +
+ {tags.map((tag) => ( + + #{tag} + + ))} +
+ )} +
+
+ + {image && ( +
+ {title} +
+ )} + +
+ +
+
+ ); +} diff --git a/apps/web/app/(marketing)/[locale]/blog/page.tsx b/apps/web/app/(marketing)/[locale]/blog/page.tsx new file mode 100644 index 0000000..fdc4fac --- /dev/null +++ b/apps/web/app/(marketing)/[locale]/blog/page.tsx @@ -0,0 +1,39 @@ +import { PostListItem } from "@marketing/blog/components/PostListItem"; +import { getAllPosts } from "@marketing/blog/utils/lib/posts"; +import { getLocale, getTranslations } from "next-intl/server"; + +export async function generateMetadata() { + const t = await getTranslations(); + return { + title: t("blog.title"), + }; +} + +export default async function BlogListPage() { + const locale = await getLocale(); + const t = await getTranslations(); + + const posts = await getAllPosts(); + + return ( +
+
+

{t("blog.title")}

+

{t("blog.description")}

+
+ +
+ {posts + .filter((post) => post.published && locale === post.locale) + .sort( + (a, b) => + new Date(b.date).getTime() - + new Date(a.date).getTime(), + ) + .map((post) => ( + + ))} +
+
+ ); +} diff --git a/apps/web/app/(marketing)/[locale]/changelog/page.tsx b/apps/web/app/(marketing)/[locale]/changelog/page.tsx new file mode 100644 index 0000000..71bf0fe --- /dev/null +++ b/apps/web/app/(marketing)/[locale]/changelog/page.tsx @@ -0,0 +1,35 @@ +import { ChangelogSection } from "@marketing/changelog/components/ChangelogSection"; +import { getTranslations } from "next-intl/server"; + +export default async function PricingPage() { + const t = await getTranslations(); + + return ( +
+
+

+ {t("changelog.title")} +

+

+ {t("changelog.description")} +

+
+ +
+ ); +} diff --git a/apps/web/app/(marketing)/[locale]/contact/page.tsx b/apps/web/app/(marketing)/[locale]/contact/page.tsx new file mode 100644 index 0000000..ff01c5f --- /dev/null +++ b/apps/web/app/(marketing)/[locale]/contact/page.tsx @@ -0,0 +1,33 @@ +import { ContactForm } from "@marketing/home/components/ContactForm"; +import { config } from "@repo/config"; +import { getTranslations } from "next-intl/server"; +import { redirect } from "next/navigation"; + +export async function generateMetadata() { + const t = await getTranslations(); + return { + title: t("contact.title"), + }; +} + +export default async function ContactPage() { + if (!config.contactForm.enabled) { + redirect("/"); + } + + const t = await getTranslations(); + return ( +
+
+

+ {t("contact.title")} +

+

+ {t("contact.description")} +

+
+ + +
+ ); +} diff --git a/apps/web/app/(marketing)/[locale]/docs/[[...path]]/layout.tsx b/apps/web/app/(marketing)/[locale]/docs/[[...path]]/layout.tsx new file mode 100644 index 0000000..40e9752 --- /dev/null +++ b/apps/web/app/(marketing)/[locale]/docs/[[...path]]/layout.tsx @@ -0,0 +1,33 @@ +import { DocsLayout } from "fumadocs-ui/layouts/docs"; +import { getTranslations } from "next-intl/server"; +import type { PropsWithChildren } from "react"; +import { docsSource } from "../../../../docs-source"; + +export default async function DocumentationLayout({ + children, + params, +}: PropsWithChildren<{ + params: Promise<{ locale: string }>; +}>) { + const t = await getTranslations(); + const { locale } = await params; + + return ( +
+ {t("documentation.title")}, + url: "/docs", + }} + sidebar={{ + defaultOpenLevel: 1, + }} + > + {children} + +
+ ); +} diff --git a/apps/web/app/(marketing)/[locale]/docs/[[...path]]/page.tsx b/apps/web/app/(marketing)/[locale]/docs/[[...path]]/page.tsx new file mode 100644 index 0000000..a2b452a --- /dev/null +++ b/apps/web/app/(marketing)/[locale]/docs/[[...path]]/page.tsx @@ -0,0 +1,93 @@ +import { MDXContent } from "@content-collections/mdx/react"; +import { config } from "@repo/config"; +import { File, Files, Folder } from "fumadocs-ui/components/files"; +import { ImageZoom } from "fumadocs-ui/components/image-zoom"; +import { Step, Steps } from "fumadocs-ui/components/steps"; +import { Tab, Tabs } from "fumadocs-ui/components/tabs"; +import defaultMdxComponents from "fumadocs-ui/mdx"; +import { DocsBody, DocsPage } from "fumadocs-ui/page"; +import { getTranslations, setRequestLocale } from "next-intl/server"; +import { notFound } from "next/navigation"; +import { docsSource } from "../../../../docs-source"; + +export default async function DocumentationPage(props: { + params: Promise<{ path?: string[]; locale: string }>; +}) { + const params = await props.params; + setRequestLocale(params.locale); + const page = docsSource.getPage(params.path, params.locale); + + if (!page) { + notFound(); + } + + return ( + + +

{page.data.title}

+ {page.data.description && ( +

+ {page.data.description} +

+ )} +
+ ( + + ), + }} + /> +
+
+
+ ); +} + +export async function generateStaticParams() { + return docsSource.getPages().flatMap((page) => ({ + path: page.slugs, + locale: page.locale ?? config.i18n.defaultLocale, + })); +} + +export async function generateMetadata(props: { + params: Promise<{ path?: string[]; locale: string }>; +}) { + const t = await getTranslations(); + const params = await props.params; + const page = docsSource.getPage(params.path, params.locale); + + if (!page) { + notFound(); + } + + return { + title: `${page.data.title} | ${t("documentation.title")}`, + description: page.data.description, + }; +} diff --git a/apps/web/app/(marketing)/[locale]/layout.tsx b/apps/web/app/(marketing)/[locale]/layout.tsx new file mode 100644 index 0000000..0c6750a --- /dev/null +++ b/apps/web/app/(marketing)/[locale]/layout.tsx @@ -0,0 +1,55 @@ +import { Footer } from "@marketing/shared/components/Footer"; +import { NavBar } from "@marketing/shared/components/NavBar"; +import { config } from "@repo/config"; +import { SessionProvider } from "@saas/auth/components/SessionProvider"; +import { Document } from "@shared/components/Document"; +import { I18nProvider as FumadocsI18nProvider } from "fumadocs-ui/i18n"; +import { RootProvider as FumadocsRootProvider } from "fumadocs-ui/provider"; +import { NextIntlClientProvider } from "next-intl"; +import { getMessages, setRequestLocale } from "next-intl/server"; +import { notFound } from "next/navigation"; +import type { PropsWithChildren } from "react"; + +const locales = Object.keys(config.i18n.locales); + +export function generateStaticParams() { + return locales.map((locale) => ({ locale })); +} + +export default async function MarketingLayout({ + children, + params, +}: PropsWithChildren<{ params: Promise<{ locale: string }> }>) { + const { locale } = await params; + + setRequestLocale(locale); + + if (!locales.includes(locale as any)) { + notFound(); + } + + const messages = await getMessages(); + + return ( + + + + + + +
{children}
+