{"repo":"LubomirGeorgiev/cloudflare-workers-nextjs-saas-template","free":true,"listed":false,"github":"https://github.com/LubomirGeorgiev/cloudflare-workers-nextjs-saas-template","clone":"git clone https://github.com/LubomirGeorgiev/cloudflare-workers-nextjs-saas-template.git","description":"Cloudflare Workers/Next.js SaaS Template","language":"TypeScript","stars":778,"topics":["cloudflare","cloudflare-workers","nextjs","saas-boilerplate"],"license":"MIT","category":"saas_boilerplate","readme_excerpt":"# Cloudflare Workers SaaS Template\n\n[![.github/workflows/deploy.yml](https://github.com/LubomirGeorgiev/cloudflare-workers-nextjs-saas-template/actions/workflows/deploy.yml/badge.svg)](https://github.com/LubomirGeorgiev/cloudflare-workers-nextjs-saas-template/actions/workflows/deploy.yml)\n\n# [Live Demo](https://nextjs-saas-template.lubomirgeorgiev.com/sign-up)\n# [Github Repo](https://github.com/LubomirGeorgiev/cloudflare-workers-nextjs-saas-template)\n\nThis is a SaaS template for Cloudflare Workers. It uses Vinext on Vite to run a Next.js App Router application directly on Cloudflare Workers.\n\n## What is Vinext?\n\n[Vinext](https://vinext.io/) is Cloudflare's experimental implementation of the public Next.js API surface on top of Vite. The goal is to let a Next.js app keep familiar App Router patterns, React Server Components, route handlers, and `next/*` imports while using Vite as the build and dev toolchain instead of the standard Next.js compiler pipeline.\n\nFor this template, Vinext is the runtime and deployment path for Cloudflare Workers. `pnpm dev` starts the Vinext development server, `pnpm build` produces the Vinext/Vite production output, and `pnpm deploy` uses `vinext-cloudflare deploy` to build and deploy the Worker. Vinext has first-class Cloudflare Workers support, including access to bindings such as D1, KV, R2, Images, Durable Objects, and AI through `cloudflare:workers`.\n\nVinext is not a fork of Next.js and is not affiliated with Vercel. It is still experimental, so framework-sensitive changes should be verified with `pnpm run check:vinext`, `pnpm run typecheck`, `pnpm run lint`, and `pnpm run build`.\n\n> [!TIP]\n> This template is brought to you by 👉 [Aski.Chat](https://aski.chat?utm_source=saas-template-readme) 👈 - AI customer support agents that answer visitors, capture leads, and surface customer intelligence from every conversation.\n>\n> - Website-trained AI agents for support and sales\n> - Lead capture and qualification from real conversations\n> - Learn what customers keep asking, then improve your docs, FAQs, and product\n>\n> Turn every visitor question into a faster answer and a sharper product signal.\n\n# Supported Features:\n\n- 🔐 Authentication with Lucia Auth\n  - 📧 Email/Password Sign In\n  - 📝 Email/Password Sign Up\n  - 🔑 WebAuthn/Passkey Authentication\n  - 🌐 Google OAuth/SSO Integration\n  - 🔄 Forgot Password Flow\n  - 🔒 Change Password\n  - ✉️ Email Verification\n  - 🗝️ Session Management with Cloudflare KV\n  - 🤖 Turnstile Captcha Integration\n  - ⚡ Rate Limiting for Auth Endpoints\n  - 🛡️ Protected Routes and Layouts\n  - 📋 Session Listing and Management\n  - 🔒 Anti-Disposable Email Protection\n- 💾 Database with Drizzle and Cloudflare D1\n  - 🏗️ Type-safe Database Operations\n  - 🔄 Automatic Migration Generation\n  - 💻 SQLite for Local Development\n  - ⚡ Efficient Data Fetching\n  - 🔍 Type-safe Queries\n- 📨 Email Service with Cloudflare Email Service\n  - 🎨 Beautiful Email Templates\n  - 👀 Email Preview Mode\n  - 🔧 Local Email Development Server\n  - 📬 Transactional Emails\n  - ✉️ Email Verification Flow\n  - 📱 Responsive Email Templates\n- 🚀 Deployment with Github Actions\n  - ⚙️ Automatic Deployments\n  - 🔐 Environment Variables Management\n  - 📦 Database Migrations\n  - 🔄 Comprehensive CI/CD Pipeline\n  - 🧹 Cache Purging\n  - ✅ Type Checking\n  - 🧪 Integration Tests\n  - 🧪 End-to-end Tests\n  - 📏 Deploy Size Tracking\n- 🎨 Modern UI\n  - 🎨 Tailwind CSS\n  - 🧩 Shadcn UI Components\n  - 🌓 Dark/Light Mode\n  - 📱 Responsive Design\n  - ⚡ Loading States and Animations\n  - 🔔 Toast Notifications\n  - ⚙️ Settings Dashboard\n  - 🏠 Landing Page\n  - ✨ Beautiful Email Templates\n  - 👤 Profile Settings Page\n  - 🎯 Form Validation States\n- 💳 Team Subscription Billing\n  - 🧩 Per-team plans (Free / Pro / Enterprise) defined in code\n  - 💳 Embedded Stripe Elements (Payment Element) for checkout — no redirect to hosted pages\n  - 🔔 Webhook-driven subscription lifecycle (Stripe is the source of truth)\n  - 🔁 In-app plan changes and cancellation\n  - 🧾 Stripe Customer Portal for payment methods, invoices, and billing details\n  - 🔒 Plan-based entitlements and feature gating (e.g. seat limits)\n  - 🛠️ One-command Stripe setup (`pnpm stripe:setup`)\n- 🤖 AI-agent platform (public API, OAuth, MCP)\n  - 🌐 Versioned public REST API built with Hono, reusing the app's own service layer\n  - 📘 OpenAPI 3.1 document generated from the same Valibot schemas the server validates with\n  - 📖 Server-rendered API reference with client-side search — no spec-viewer bundle — plus authentication and error-code guides\n  - 🔑 API keys for users and teams, with scopes, optional expiry, and one-time secret display\n  - 🪪 OAuth 2.1 authorization server (PKCE, dynamic client registration, consent screen)\n  - 🔌 Remote MCP server whose tools are derived from the OpenAPI document — no hand-written tool list\n  - 🧭 Connect guides for Claude Code, claude.ai, ChatGPT, Cursor, VS Code, Codex, Antigravity, and Grok CLI\n  - 🧹 Self-service revocation from Settings → API & MCP, plus an admin view of registered OAuth apps\n- 👑 Admin Dashboard\n  - 👥 User Management\n  - 🪪 OAuth app registry with verification and revocation\n- 📝 Content Management System\n  - 🗂️ Config-driven collections for blog and docs content\n  - ✍️ Rich TipTap editor with markdown paste, markdown copy, tables, code highlighting, and alert blocks\n  - 🧭 Docs navigation builder with managed public URLs\n  - 🖼️ Media library with R2-backed image uploads, alt text editing, and featured images\n  - 🏷️ Tags and categories with entry usage tracking\n  - 🕒 Draft, published, archived, and scheduled entry workflows\n  - 🧾 Version history for CMS entries\n  - ⚡ KV-backed CMS entry caching and cache maintenance actions\n  - 🔍 Full-text docs search\n  - 🤖 AI-assisted SEO description generation\n  - 🧱 Blog, docs, sitemap.xml, JSON-LD schema, and llms.txt rendering\n- ✨ Validations with Zod and React Hook Form\n  - 🛡️ Type-safe Form Validations\n  - 🔒 Server-side Validations\n  - 🔍 Client-side Validations\n  - 🧹 Input Sanitization\n  - ⚡ Real-time Validation\n  - 🔄 Form State Management\n- 👨‍💻 Developer Experience\n  - 🧪 Local Development Setup\n  - 📘 TypeScript Support\n  - 🔍 Oxlint Configuration\n  - 🧪 Co-located Vitest Unit Tests\n  - 🧪 Cloudflare Workers Vitest Integration Tests\n  - 🧪 Vitest and Playwright E2E Tests\n  - ⚡ Vinext and Vite Build Pipeline\n  - 🔐 Type-safe Environment Variables\n  - 🏗️ Cloudflare Types Generation\n  - 🤖 AI-powered Development with AI Agents\n  - 📚 Comprehensive Documentation\n  - 📐 Project Structure Best Practices\n- ⚡ Edge Computing\n  - 🌍 Global Deployment with Cloudflare Workers\n  - 🚀 Zero Cold Starts\n  - 💨 Edge Caching\n  - ⚛️ React Server Components\n  - 🖥️ Server-side Rendering\n  - 💾 Edge Database with D1\n  - 🗄️ Session Storage with KV\n  - 🖼️ Cloudflare Images-powered Image Optimization\n  - ⚡ API Rate Limiting\n- 🏢 Multi-tenancy Support\n  - 👥 Organization Management\n  - 👤 User Roles and Permissions\n  - 🔍 Tenant Isolation\n  - 🔄 Resource Sharing Controls\n  - 📊 Per-tenant Analytics\n  - 🔐 Tenant-specific Configurations\n  - 💼 Team Collaboration Features\n- 🌐 Internationalization (i18n) with next-intl\n  - 🍪 Cookie-based locale with Accept-Language negotiation (no URL changes)\n  - 🔀 Locale switcher in the footer\n  - 🗂️ JSON message catalogs (English and Spanish included)\n  - 🧭 Auto-detected by Vinext (no `createNextIntlPlugin` wrapper needed)\n  - 🔒 Type-safe message keys\n\n## Internationalization (i18n)\n\nThe template ships with [next-intl](https://next-intl.dev/) configured in\n\"without i18n routing\" mode: the active locale is resolved from a `NEXT_LOCALE`\ncookie, falling back to the request's `Accept-Language` header and then the\ndefault locale, so URLs stay unchanged across the app.\n\nEverything lives in `src/i18n/`:\n\n- `config.ts` — locale list, default locale, cookie name, and switcher labels.\n- `request.ts` — the Vinext-auto-detected next-intl request config.\n- `locale.ts` / `locale-actions.ts` — server-side locale resolution and the cookie-setting server action.\n- `messages/<locale>.json` — one message catalog per locale.\n\nTo add a locale (e.g. French):\n\n1. Add `\"fr\"` to `LOCALES` and a `fr` entry to `LOCALE_LABELS` in `src/i18n/config.ts`.\n2. Create `src/i18n/messages/fr.json` mirroring the keys in `en.json`.\n\nUse `useTranslations` in client components and `getTranslations` in server\ncomponents. `messages/en.json` is the source of truth for type-safe keys via the\naugmentation in `src/i18n/next-intl.d.ts`.\n\n## Planned features (TODO):\n\n- [ ] Update Meta SEO tags 🔍\n- [ ] Dynamic OpenGraph images 📸\n- [ ] Notifications 🔔\n- [ ] Webhooks 🔗\n\n# Running it locally\n\n1. `pnpm install`\n2. `pnpx wrangler login` - Login to your Cloudflare account to use Cloudflare bindings while testing locally.\n3. Copy `.env.example` to `.env` and fill in the values.\n4. `pnpm db:migrate:dev` - Creates a local SQLite database and applies migrations\n5. `pnpm db:seed` - Seeds the database with test data\n6. `pnpm dev` - Starts the Vinext development server\n7. Go to http://localhost:3000/sign-in and login with the test user credentials: test@test.com / password\n8. Go to http://localhost:3000/admin to manage users and the CMS.\n\n## Billing setup (team subscriptions)\n\nBilling is per-team: each team owns a single Stripe subscription to a plan (Free / Pro / Enterprise). Plans are defined in code in [`src/constants/plans.json`](src/constants/plans.json) and consumed by both the app and the setup script, so Stripe and code never drift. Payment collection uses embedded Stripe Elements (the Payment Element), and plan changes/cancellation are handled by in-app server actions. The hosted [Stripe Customer Portal](https://docs.stripe.com/customer-management) complements this for self-service payment method updates, invoice history, and billing details — the billing page shows a \"Manage billing\" button once the team has a Stripe customer.\n\nThe subscription lifecycle is **webhook-driven**: Stripe is the source of truth and the DB is a cache updated from webhook events. The app never mutates ","default_branch":"main","files":1016,"tree":[".agents/skills/prepare-cloudflare-production-deployment/SKILL.md",".agents/skills/prepare-cloudflare-production-deployment/agents/openai.yaml",".claude/launch.json",".cursor/mcp.json",".editorconfig",".env.example",".eslintrc",".fallowrc.jsonc",".github/workflows/deploy.yml",".gitignore",".oxlintrc.json",".vscode/extensions.json",".vscode/settings.json","AGENTS.md","CLAUDE.md","LICENSE","README.md","cms-plan.md","cms.config.ts","components.json","docs/api-and-mcp-internals.md","docs/cursor-cloud-environment.md","docs/database-and-migrations.md","docs/extending-api-and-mcp.md","docs/page-caching.md","docs/worker-hot-path-and-bundle-size.md","drizzle.config.ts","metrics/cloudflare-workers-nextjs-saas-template-deploy-size-history.jsonl","next.config.ts","opencode.json","package.json","pnpm-lock.yaml","pnpm-workspace.yaml","public/.assetsignore","public/.gitkeep","public/logo.png","public/logo.svg","scripts/generate-logo-assets.mjs","scripts/generate-openapi.mjs","scripts/get-db-id.mjs","scripts/get-db-name.mjs","scripts/get-kv-id.mjs","scripts/package.json","scripts/preview-emails.mjs","scripts/record-metrics.mjs","scripts/render-metrics-report.mjs","scripts/stripe-setup.mjs","scripts/utils/metrics.mjs","scripts/utils/metrics.test.mjs","scripts/utils/noop-module.mjs","scripts/utils/parse-wrangler.mjs","scripts/utils/workers-runtime-stub.mjs","src/actions/api-key-actions.ts","src/actions/list-cms-media.action.ts","src/actions/session.action.ts","src/actions/sign-out.action.ts","src/actions/team-actions.ts","src/actions/team-membership-actions.ts","src/actions/upload-image.action.ts","src/api/generated-document.ts","src/api/index.ts","src/api/middleware/audience.ts","src/api/middleware/auth.ts","src/api/middleware/problem-json.ts","src/api/middleware/rate-limit.test.ts","src/api/middleware/rate-limit.ts","src/api/openapi-document.test.ts","src/api/openapi-document.ts","src/api/openapi.ts","src/api/operation.test.ts","src/api/operation.ts","src/api/routes/api-keys.ts","src/api/routes/billing.ts","src/api/routes/invitations.ts","src/api/routes/me.ts","src/api/routes/members.ts","src/api/routes/teams.ts","src/api/types.ts","src/app/[locale]/(app)/(admin)/admin/_actions/cms-entry-actions.test.ts","src/app/[locale]/(app)/(admin)/admin/_actions/cms-entry-actions.ts","src/app/[locale]/(app)/(admin)/admin/_actions/cms-entry-revalidation.ts","src/app/[locale]/(app)/(admin)/admin/_actions/cms-media-actions.test.ts","src/app/[locale]/(app)/(admin)/admin/_actions/cms-media-actions.ts","src/app/[locale]/(app)/(admin)/admin/_actions/cms-navigation-actions.ts","src/app/[locale]/(app)/(admin)/admin/_actions/cms-system-actions.ts","src/app/[locale]/(app)/(admin)/admin/_actions/cms-tag-actions.test.ts","src/app/[locale]/(app)/(admin)/admin/_actions/cms-tag-actions.ts","src/app/[locale]/(app)/(admin)/admin/_actions/get-user.action.ts","src/app/[locale]/(app)/(admin)/admin/_actions/get-users.action.ts","src/app/[locale]/(app)/(admin)/admin/_actions/oauth-apps-actions.ts","src/app/[locale]/(app)/(admin)/admin/_actions/user-credentials-actions.ts","src/app/[locale]/(app)/(admin)/admin/_components/admin-sidebar.tsx","src/app/[locale]/(app)/(admin)/admin/_components/admin-table-shell.tsx","src/app/[locale]/(app)/(admin)/admin/_components/oauth-apps/columns.tsx","src/app/[locale]/(app)/(admin)/admin/_components/oauth-apps/oauth-apps-table.tsx","src/app/[locale]/(app)/(admin)/admin/_components/relative-date-cell.tsx","src/app/[locale]/(app)/(admin)/admin/_components/use-admin-table-pagination.ts","src/app/[locale]/(app)/(admin)/admin/_components/users/admin-user-section.tsx","src/app/[locale]/(app)/(admin)/admin/_components/users/columns.tsx","src/app/[locale]/(app)/(admin)/admin/_components/users/user-api-keys.tsx","src/app/[locale]/(app)/(admin)/admin/_components/users/user-connected-apps.tsx","src/app/[locale]/(app)/(admin)/admin/_components/users/user-credentials-section.tsx","src/app/[locale]/(app)/(admin)/admin/_components/users/user-teams.tsx","src/app/[locale]/(app)/(admin)/admin/_components/users/users-table.tsx","src/app/[locale]/(app)/(admin)/admin/cms/[collection]/[entryId]/page.tsx","src/app/[locale]/(app)/(admin)/admin/cms/[collection]/_components/cms-dynamic-field.tsx","src/app/[locale]/(app)/(admin)/admin/cms/[collection]/_components/cms-entries-table.tsx","src/app/[locale]/(app)/(admin)/admin/cms/[collection]/_components/cms-entry-form.tsx","src/app/[locale]/(app)/(admin)/admin/cms/[collection]/_components/cms-entry-locale-switcher.tsx","src/app/[locale]/(app)/(admin)/admin/cms/[collection]/_components/cms-translation-stale-banner.tsx","src/app/[locale]/(app)/(admin)/admin/cms/[collection]/_components/featured-image-upload.tsx","src/app/[locale]/(app)/(admin)/admin/cms/[collection]/_components/version-history.tsx","src/app/[locale]/(app)/(admin)/admin/cms/[collection]/new/page.tsx","src/app/[locale]/(app)/(admin)/admin/cms/[collection]/page.tsx","src/app/[locale]/(app)/(admin)/admin/cms/_actions/version-actions.test.ts","src/app/[locale]/(app)/(admin)/admin/cms/_actions/version-actions.ts","src/app/[locale]/(app)/(admin)/admin/cms/_components/cms-entry-status-badge.tsx","src/app/[locale]/(app)/(admin)/admin/cms/_components/cms-system-actions.tsx","src/app/[locale]/(app)/(admin)/admin/cms/_components/cms-translation-switcher.tsx","src/app/[locale]/(app)/(admin)/admin/cms/_components/locale-coverage-badges.test.ts","src/app/[locale]/(app)/(admin)/admin/cms/_components/locale-coverage-badges.tsx","src/app/[locale]/(app)/(admin)/admin/cms/docs/navigation/page.tsx","src/app/[locale]/(app)/(admin)/admin/cms/media/[mediaId]/_components/edit-alt-text.tsx","src/app/[locale]/(app)/(admin)/admin/cms/media/[mediaId]/page.tsx","src/app/[locale]/(app)/(admin)/admin/cms/media/_components/media-list-table.tsx","src/app/[locale]/(app)/(admin)/admin/cms/media/_components/media-table-actions.tsx","src/app/[locale]/(app)/(admin)/admin/cms/media/page.tsx","src/app/[locale]/(app)/(admin)/admin/cms/navigation/[siteKey]/_components/cms-navigation-manager.tsx","src/app/[locale]/(app)/(admin)/admin/cms/navigation/[siteKey]/page.tsx","src/app/[locale]/(app)/(admin)/admin/cms/page.tsx","src/app/[locale]/(app)/(admin)/admin/cms/tags/[id]/page.tsx","src/app/[locale]/(app)/(admin)/admin/cms/tags/_components/tag-form.tsx","src/app/[locale]/(app)/(admin)/admin/cms/tags/_components/tag-locale-switcher.tsx","src/app/[locale]/(app)/(admin)/admin/cms/tags/new/page.tsx","src/app/[locale]/(app)/(admin)/admin/cms/tags/page.tsx","src/app/[locale]/(app)/(admin)/admin/debug/_components/env-dump.tsx","src/app/[locale]/(app)/(admin)/admin/debug/page.tsx","src/app/[locale]/(app)/(admin)/admin/jobs/jobs-tables.tsx","src/app/[locale]/(app)/(admin)/admin/jobs/page.tsx","src/app/[locale]/(app)/(admin)/admin/layout.tsx","src/app/[locale]/(app)/(admin)/admin/oauth-apps/page.tsx","src/app/[locale]/(app)/(admin)/admin/page.tsx","src/app/[locale]/(app)/(admin)/admin/users/[userId]/page.tsx","src/app/[locale]/(app)/(dashboard)/dashboard/billing/page.tsx","src/app/[locale]/(app)/(dashboard)/dashboard/page.tsx","src/app/[locale]/(app)/(dashboard)/dashboard/teams/[teamSlug]/billing/_components/addon-cards.tsx","src/app/[locale]/(app)/(dashboard)/dashboard/teams/[teamSlug]/billing/_components/customer-portal-button.tsx","src/app/[locale]/(app)/(dashboard)/dashboard/teams/[teamSlug]/billing/_components/plan-cards.tsx","src/app/[locale]/(app)/(dashboard)/dashboard/teams/[teamSlug]/billing/_components/stripe-payment-form.tsx","src/app/[locale]/(app)/(dashboard)/dashboard/teams/[teamSlug]/billing/billing.actions.ts","src/app/[locale]/(app)/(dashboard)/dashboard/teams/[teamSlug]/billing/page.tsx","src/app/[locale]/(app)/(dashboard)/dashboard/teams/[teamSlug]/page.tsx","src/app/[locale]/(app)/(dashboard)/dashboard/teams/[teamSlug]/team-page-guard.ts","src/app/[locale]/(app)/(dashboard)/dashboard/teams/create/page.tsx","src/app/[locale]/(app)/(dashboard)/dashboard/teams/page.tsx","src/app/[locale]/(app)/(dashboard)/dashboard/teams/pending-invitations.tsx","src/app/[locale]/(app)/(dashboard)/layout.tsx","src/app/[locale]/(app)/(settings)/settings/[...segment]/page.tsx","src/app/[locale]/(app)/(settings)/settings/api-mcp/api-mcp.actions.ts","src/app/[locale]/(app)/(settings)/settings/api-mcp/connected-apps-list.tsx","src/app/[locale]/(app)/(settings)/settings/api-mcp/page.tsx","src/app/[locale]/(app)/(settings)/settings/error.tsx","src/app/[locale]/(app)/(settings)/settings/language-form.tsx","src/app/[locale]/(app)/(settings)/settings/layout.tsx","src/app/[locale]/(app)/(settings)/settings/page.tsx","src/app/[locale]/(app)/(settings)/settings/security/page.tsx","src/app/[locale]/(app)/(settings)/settings/security/passkey-settings.actions.ts","src/app/[locale]/(app)/(settings)/settings/security/passkey.client.tsx","src/app/[locale]/(app)/(settings)/settings/sessions/page.tsx","src/app/[locale]/(app)/(settings)/settings/sessions/sessions.actions.ts","src/app/[locale]/(app)/(settings)/settings/sessions/sessions.client.tsx","src/app/[locale]/(app)/(settings)/settings/settings-breadcrumbs.tsx","src/app/[locale]/(app)/(settings)/settings/settings-form.tsx","src/app/[locale]/(app)/(settings)/settings/settings-nav.tsx","src/app/[locale]/(app)/(settings)/settings/settings.actions.ts","src/app/[locale]/(app)/oauth/authorize/authorize.actions.ts","src/app/[locale]/(app)/oauth/authorize/consent.client.tsx","src/app/[locale]/(app)/oauth/authorize/page.tsx","src/app/[locale]/(auth)/_components/auth-status-card.tsx","src/app/[locale]/(auth)/_components/sso-buttons.tsx","src/app/[locale]/(auth)/forgot-password/forgot-password.action.ts","src/app/[locale]/(auth)/forgot-password/forgot-password.client.tsx","src/app/[locale]/(auth)/forgot-password/page.tsx","src/app/[locale]/(auth)/layout.tsx","src/app/[locale]/(auth)/reset-password/not-found.tsx","src/app/[locale]/(auth)/reset-password/page.tsx","src/app/[locale]/(auth)/reset-password/reset-password.action.ts","src/app/[locale]/(auth)/reset-password/reset-password.client.tsx","src/app/[locale]/(auth)/send-verification.action.ts","src/app/[locale]/(auth)/sign-in/opengraph-image.tsx","src/app/[locale]/(auth)/sign-in/page.tsx","src/app/[locale]/(auth)/sign-in/sign-in-auth.test.ts","src/app/[locale]/(auth)/sign-in/sign-in-auth.ts","src/app/[locale]/(auth)/sign-in/sign-in.action.ts","src/app/[locale]/(auth)/sign-in/sign-in.client.tsx","src/app/[locale]/(auth)/sign-up/opengraph-image.tsx","src/app/[locale]/(auth)/sign-up/page.tsx","src/app/[locale]/(auth)/sign-up/passkey-sign-up.actions.ts","src/app/[locale]/(auth)/sign-up/sign-up.actions.ts","src/app/[locale]/(auth)/sign-up/sign-up.client.tsx","src/app/[locale]/(auth)/sso/google/callback/google-callback.action.ts","src/app/[locale]/(auth)/sso/google/callback/google-callback.client.tsx","src/app/[locale]/(auth)/sso/google/callback/page.tsx","src/app/[locale]/(auth)/sso/google/route.ts","src/app/[locale]/(auth)/team-invite/not-found.tsx","src/app/[locale]/(auth)/team-invite/page.tsx","src/app/[locale]/(auth)/team-invite/team-invite.action.ts","src/app/[locale]/(auth)/team-invite/team-invite.client.tsx","src/app/[locale]/(auth)/verify-email/not-found.tsx","src/app/[locale]/(auth)/verify-email/page.tsx","src/app/[locale]/(auth)/verify-email/verify-email.action.ts","src/app/[locale]/(auth)/verify-email/verify-email.client.tsx","src/app/[locale]/(legal)/layout.tsx","src/app/[locale]/(legal)/privacy/opengraph-image.tsx","src/app/[locale]/(legal)/privacy/page.tsx","src/app/[locale]/(legal)/terms/opengraph-image.tsx","src/app/[locale]/(legal)/terms/page.tsx","src/app/[locale]/(marketing)/blog/[slug]/not-found.tsx","src/app/[locale]/(marketing)/blog/[slug]/opengraph-image.tsx","src/app/[locale]/(marketing)/blog/[slug]/page.tsx","src/app/[locale]/(marketing)/blog/_components/blog-list-page.tsx","src/app/[locale]/(marketing)/blog/authors/[authorId]/opengraph-image.tsx","src/app/[locale]/(marketing)/blog/authors/[authorId]/page.tsx","src/app/[locale]/(marketing)/blog/authors/opengraph-image.tsx","src/app/[locale]/(marketing)/blog/authors/page.tsx","src/app/[locale]/(marketing)/blog/layout.tsx","src/app/[locale]/(marketing)/blog/opengraph-image.tsx","src/app/[locale]/(marketing)/blog/page.tsx","src/app/[locale]/(marketing)/blog/tags/[slug]/opengraph-image.tsx","src/app/[locale]/(marketing)/blog/tags/[slug]/page.tsx","src/app/[locale]/(marketing)/blog/tags/opengraph-image.tsx","src/app/[locale]/(marketing)/blog/tags/page.tsx","src/app/[locale]/(marketing)/docs/[[...slug]]/opengraph-image.tsx","src/app/[locale]/(marketing)/docs/[[...slug]]/page.tsx","src/app/[locale]/(marketing)/docs/_actions/search-docs.action.ts","src/app/[locale]/(marketing)/docs/_components/copy-docs-markdown-button.tsx","src/app/[locale]/(marketing)/docs/_components/docs-article-body.tsx","src/app/[locale]/(marketing)/docs/_components/docs-cross-links.tsx","src/app/[locale]/(marketing)/docs/_components/docs-guide-links.tsx","src/app/[locale]/(marketing)/docs/_components/docs-nav-indent.ts","src/app/[locale]/(marketing)/docs/_components/docs-navigation-chrome.tsx","src/app/[locale]/(marketing)/docs/_components/docs-on-this-page-nav.tsx","src/app/[locale]/(marketing)/docs/_components/docs-prose-section.tsx","src/app/[locale]/(marketing)/docs/_components/docs-search-highlighting.test.ts","src/app/[locale]/(marketing)/docs/_components/docs-search-highlighting.ts","src/app/[locale]/(marketing)/docs/_components/docs-search.tsx","src/app/[locale]/(marketing)/docs/_components/docs-sidebar.tsx","src/app/[locale]/(marketing)/docs/_components/mobile-docs-nav.tsx","src/app/[locale]/(marketing)/docs/api/_components/api-code-block.tsx","src/app/[locale]/(marketing)/docs/api/_components/api-json-preview.tsx","src/app/[locale]/(marketing)/docs/api/_components/api-operation.tsx","src/app/[locale]/(marketing)/docs/api/_components/api-reference-dom.ts","src/app/[locale]/(marketing)/docs/api/_components/api-reference-filter.tsx","src/app/[locale]/(marketing)/docs/api/_components/api-reference-index.tsx","src/app/[locale]/(marketing)/docs/api/_components/api-schema-fields.tsx","src/app/[locale]/(marketing)/docs/api/errors/opengraph-image.tsx","src/app/[locale]/(marketing)/docs/api/errors/page.tsx","src/app/[locale]/(marketing)/docs/api/opengraph-image.tsx","src/app/[locale]/(marketing)/docs/api/page.tsx","src/app/[locale]/(marketing)/docs/authentication/opengraph-image.tsx","src/app/[locale]/(marketing)/docs/authentication/page.tsx","src/app/[locale]/(marketing)/docs/layout.tsx","src/app/[locale]/(marketing)/docs/mcp/opengraph-image.tsx","src/app/[locale]/(marketing)/docs/mcp/page.tsx","src/app/[locale]/(marketing)/docs/opengraph-image.tsx","src/app/[locale]/(marketing)/layout.tsx","src/app/[locale]/(marketing)/page.tsx","src/app/[locale]/layout.tsx","src/app/[locale]/opengraph-image.tsx","src/app/api/cms-images/[...path]/route.ts","src/app/api/docs/search/route.ts","src/app/api/get-session/route.ts","src/app/api/stripe/webhook/route.ts","src/app/build-sitemap.ts","src/app/docs/llms.txt/route.test.ts","src/app/docs/llms.txt/route.ts","src/app/enums.ts","src/app/favicon.ico","src/app/globals.css","src/app/icon.svg","src/app/markdown/[collection]/[slug]/route.ts","src/app/robots.ts","src/app/sitemap-alternates.test.ts","src/app/sitemap-alternates.ts","src/app/sitemap.ts","src/components/api-keys/api-key-secret-reveal.tsx","src/components/api-keys/api-keys-manager.tsx","src/components/api-keys/create-api-key-dialog.tsx","src/components/api-keys/create-api-key-form.tsx","src/components/api-keys/edit-api-key-scopes-dialog.tsx","src/components/api-keys/rest-api-quickstart.tsx","src/components/api-keys/scope-picker.tsx","src/components/api-scope-grid.tsx","src/components/app-sidebar-data.test.ts","src/components/app-sidebar-data.ts","src/components/app-sidebar.tsx","src/components/aski-chat-logo.tsx","src/components/aski-chat-sticky-banner.tsx","src/components/blog-back-link.tsx","src/components/blog-card.tsx","src/components/blog-empty-state.tsx","src/components/blog-pagination-server.tsx","src/components/captcha.tsx","src/components/cms-content-renderer.tsx","src/components/cms-entry-body.tsx","src/components/cms-entry-tags.tsx","src/components/confirm-destructive-dialog.tsx","src/components/content-table-of-contents-nav.tsx","src/components/copy-to-clipboard-button.tsx","src/components/data-table.tsx","src/components/email-verification-dialog.tsx","src/components/empty-state-card.tsx","src/components/footer.tsx","src/components/github-stars-badge.tsx","src/components/hairline-grid.tsx","src/components/highlighted-code.tsx","src/components/landing/cta.tsx","src/components/landing/deploy-terminal.tsx","src/components/landing/faq.tsx","src/components/landing/features.tsx","src/components/landing/hero.tsx","src/components/landing/stack.tsx","src/components/locale-flag.tsx","src/components/locale-switcher.tsx","src/components/logo.tsx","src/components/mcp/agent-client-logo.tsx","src/components/mcp/connect-agent-guide.tsx","src/components/mcp/mcp-connect-section.tsx","src/components/nav-main.tsx","src/components/nav-projects.tsx","src/components/nav-user.tsx","src/components/navigation-shell.tsx","src/components/navigation-top-loader.tsx","src/components/navigation-with-cms-links-fallback.tsx","src/components/navigation-with-cms-links.tsx","src/components/navigation.tsx","src/components/page-error-state.tsx","src/components/page-header.tsx","src/components/providers.tsx","src/components/public-config-hydrator.tsx","src/components/root-shell.tsx","src/components/separator-with-text.tsx","src/components/session-client-sync.tsx","src/components/session-hydrator.test.ts","src/components/session-hydrator.tsx","src/components/streamed-metadata-hoister.tsx","src/components/team-switcher.tsx","src/components/teams/create-team-form.tsx","src/components/teams/invite-member-modal.tsx","src/components/teams/remove-member-button.tsx","src/components/teams/rename-team-modal.tsx","src/components/teams/revoke-invitation-button.tsx","src/components/teams/team-api-keys.tsx","src/components/theme-switch.tsx","src/components/tiptap-extension/markdown-paste-extension.ts","src/components/tiptap-extension/node-background-extension.ts","src/components/tiptap-icons/alert-circle-icon.tsx","src/components/tiptap-icons/align-center-icon.tsx","src/components/tiptap-icons/align-justify-icon.tsx","src/components/tiptap-icons/align-left-icon.tsx","src/components/tiptap-icons/align-right-icon.tsx","src/components/tiptap-icons/arrow-left-icon.tsx","src/components/tiptap-icons/ban-icon.tsx","src/components/tiptap-icons/blockquote-icon.tsx","src/components/tiptap-icons/bold-icon.tsx","src/components/tiptap-icons/check-icon.tsx","src/components/tiptap-icons/chevron-down-icon.tsx","src/components/tiptap-icons/close-icon.tsx","src/components/tiptap-icons/code-block-icon.tsx","src/components/tiptap-icons/code2-icon.tsx","src/components/tiptap-icons/copy-icon.tsx","src/components/tiptap-icons/corner-down-left-icon.tsx","src/components/tiptap-icons/external-link-icon.tsx","src/components/tiptap-icons/heading-five-icon.tsx","src/components/tiptap-icons/heading-four-icon.tsx","src/components/tiptap-icons/heading-icon.tsx","src/components/tiptap-icons/heading-one-icon.tsx","src/components/tiptap-icons/heading-six-icon.tsx","src/components/tiptap-icons/heading-three-icon.tsx","src/components/tiptap-icons/heading-two-icon.tsx","src/components/tiptap-icons/highlighter-icon.tsx","src/components/tiptap-icons/horizontal-rule-icon.tsx","src/components/tiptap-icons/image-plus-icon.tsx","src/components/tiptap-icons/italic-icon.tsx","src/components/tiptap-icons/link-icon.tsx","src/components/tiptap-icons/list-icon.tsx","src/components/tiptap-icons/list-ordered-icon.tsx","src/components/tiptap-icons/list-todo-icon.tsx","src/components/tiptap-icons/redo2-icon.tsx","src/components/tiptap-icons/strike-icon.tsx","src/components/tiptap-icons/subscript-icon.tsx","src/components/tiptap-icons/superscript-icon.tsx","src/components/tiptap-icons/table-column-plus-icon.tsx","src/components/tiptap-icons/table-icon.tsx","src/components/tiptap-icons/table-row-plus-icon.tsx","src/components/tiptap-icons/trash-icon.tsx","src/components/tiptap-icons/underline-icon.tsx","src/components/tiptap-icons/undo2-icon.tsx","src/components/tiptap-node/alert-block/alert-block-editor-extension.tsx","src/components/tiptap-node/alert-block/alert-block-extension.ts"],"storefront":"/r/LubomirGeorgiev","claimed":false,"request_supported":{"post":"https://gitbuyer.com/r/LubomirGeorgiev/cloudflare-workers-nextjs-saas-template/request-supported","requests":0},"note":"indexed from public GitHub; nothing is for sale on this page. Clone it from GitHub. Paid listings live at /search."}