create-nextdevtpl 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -0
- package/catalog.json +385 -0
- package/dist/catalog.d.ts +3 -0
- package/dist/catalog.js +112 -0
- package/dist/catalog.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +115 -0
- package/dist/cli.js.map +1 -0
- package/dist/filesystem.d.ts +10 -0
- package/dist/filesystem.js +86 -0
- package/dist/filesystem.js.map +1 -0
- package/dist/generate.d.ts +5 -0
- package/dist/generate.js +758 -0
- package/dist/generate.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/selection.d.ts +2 -0
- package/dist/selection.js +111 -0
- package/dist/selection.js.map +1 -0
- package/dist/service-templates.d.ts +4 -0
- package/dist/service-templates.js +180 -0
- package/dist/service-templates.js.map +1 -0
- package/dist/types.d.ts +65 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +54 -0
- package/template/.dockerignore +14 -0
- package/template/.env.example +282 -0
- package/template/.gitattributes +17 -0
- package/template/.node-version +1 -0
- package/template/Dockerfile +45 -0
- package/template/LICENSE +21 -0
- package/template/README.md +267 -0
- package/template/biome.json +68 -0
- package/template/cloudflare/templates/logger.ts +162 -0
- package/template/cloudflare/templates/mail/server.ts +6 -0
- package/template/cloudflare/templates/mail/templates.ts +87 -0
- package/template/cloudflare/templates/mail/utils.ts +69 -0
- package/template/cloudflare/worker.mjs +25 -0
- package/template/components.json +22 -0
- package/template/compose.yaml +74 -0
- package/template/deploy/check-health.mjs +25 -0
- package/template/deploy/docker/README.md +14 -0
- package/template/deploy/server/README.md +24 -0
- package/template/deploy/server/build.sh +24 -0
- package/template/deploy/server/nextdevtpl.service +19 -0
- package/template/deploy/server/start.sh +19 -0
- package/template/deploy/vercel/README.md +16 -0
- package/template/deploy/verify-production-health.mjs +86 -0
- package/template/drizzle.config.ts +47 -0
- package/template/gitignore +62 -0
- package/template/manifest.json +35 -0
- package/template/messages/en.json +766 -0
- package/template/messages/zh.json +762 -0
- package/template/next.config.mjs +28 -0
- package/template/open-next.config.ts +3 -0
- package/template/package.json +125 -0
- package/template/pnpm-lock.yaml +15901 -0
- package/template/postcss.config.mjs +7 -0
- package/template/public/file.svg +1 -0
- package/template/public/globe.svg +1 -0
- package/template/public/logo.svg +6 -0
- package/template/public/next.svg +1 -0
- package/template/public/vercel.svg +1 -0
- package/template/public/window.svg +1 -0
- package/template/sentry.client.config.ts +10 -0
- package/template/sentry.edge.config.ts +10 -0
- package/template/sentry.server.config.ts +10 -0
- package/template/source.config.ts +59 -0
- package/template/src/adapters/ai/anthropic.ts +113 -0
- package/template/src/adapters/ai/index.ts +6 -0
- package/template/src/adapters/ai/openai-compatible.ts +88 -0
- package/template/src/adapters/ai/workers-ai.ts +63 -0
- package/template/src/adapters/index.ts +10 -0
- package/template/src/adapters/jobs/cloudflare-workflows.ts +46 -0
- package/template/src/adapters/jobs/index.ts +5 -0
- package/template/src/adapters/jobs/inngest/adapter.ts +29 -0
- package/template/src/adapters/jobs/inngest/client.ts +8 -0
- package/template/src/adapters/jobs/inngest/functions.ts +17 -0
- package/template/src/adapters/jobs/inngest/handler.ts +6 -0
- package/template/src/adapters/jobs/inngest/index.ts +4 -0
- package/template/src/adapters/mail/cloudflare-email.ts +50 -0
- package/template/src/adapters/mail/disabled.ts +17 -0
- package/template/src/adapters/mail/index.ts +7 -0
- package/template/src/adapters/mail/resend.ts +76 -0
- package/template/src/adapters/mail/smtp.ts +82 -0
- package/template/src/adapters/payment/creem.ts +269 -0
- package/template/src/adapters/payment/index.ts +2 -0
- package/template/src/adapters/payment/stripe.ts +302 -0
- package/template/src/adapters/rate-limit/cloudflare.ts +42 -0
- package/template/src/adapters/rate-limit/index.ts +6 -0
- package/template/src/adapters/rate-limit/noop.ts +27 -0
- package/template/src/adapters/rate-limit/upstash.ts +113 -0
- package/template/src/adapters/registry.ts +228 -0
- package/template/src/adapters/storage/index.ts +3 -0
- package/template/src/adapters/storage/r2-binding.ts +105 -0
- package/template/src/adapters/storage/s3-compatible.ts +149 -0
- package/template/src/app/[locale]/(admin)/admin/layout.tsx +36 -0
- package/template/src/app/[locale]/(admin)/admin/page.tsx +345 -0
- package/template/src/app/[locale]/(admin)/admin/tickets/[id]/page.tsx +261 -0
- package/template/src/app/[locale]/(admin)/admin/tickets/page.tsx +236 -0
- package/template/src/app/[locale]/(admin)/admin/users/page.tsx +557 -0
- package/template/src/app/[locale]/(auth)/forgot-password/page.tsx +9 -0
- package/template/src/app/[locale]/(auth)/layout.tsx +28 -0
- package/template/src/app/[locale]/(auth)/sign-in/page.tsx +9 -0
- package/template/src/app/[locale]/(auth)/sign-up/page.tsx +9 -0
- package/template/src/app/[locale]/(dashboard)/dashboard/credits/buy/buy-credits-view.tsx +170 -0
- package/template/src/app/[locale]/(dashboard)/dashboard/credits/buy/page.tsx +12 -0
- package/template/src/app/[locale]/(dashboard)/dashboard/credits/page.tsx +5 -0
- package/template/src/app/[locale]/(dashboard)/dashboard/loading.tsx +41 -0
- package/template/src/app/[locale]/(dashboard)/dashboard/page.tsx +299 -0
- package/template/src/app/[locale]/(dashboard)/dashboard/settings/page.tsx +38 -0
- package/template/src/app/[locale]/(dashboard)/dashboard/support/[id]/page.tsx +220 -0
- package/template/src/app/[locale]/(dashboard)/dashboard/support/new/page.tsx +183 -0
- package/template/src/app/[locale]/(dashboard)/dashboard/support/page.tsx +145 -0
- package/template/src/app/[locale]/(dashboard)/layout.tsx +35 -0
- package/template/src/app/[locale]/(marketing)/blog/[slug]/page.tsx +178 -0
- package/template/src/app/[locale]/(marketing)/blog/blog-post-card.tsx +95 -0
- package/template/src/app/[locale]/(marketing)/blog/page.tsx +127 -0
- package/template/src/app/[locale]/(marketing)/demo/plan-badges/page.tsx +36 -0
- package/template/src/app/[locale]/(marketing)/layout.tsx +15 -0
- package/template/src/app/[locale]/(marketing)/legal/[slug]/page.tsx +130 -0
- package/template/src/app/[locale]/(marketing)/page.tsx +94 -0
- package/template/src/app/[locale]/(marketing)/pseo/[slug]/page.tsx +68 -0
- package/template/src/app/[locale]/(marketing)/pseo/page.tsx +137 -0
- package/template/src/app/[locale]/docs/[[...slug]]/page.tsx +63 -0
- package/template/src/app/[locale]/docs/layout.tsx +39 -0
- package/template/src/app/[locale]/layout.tsx +80 -0
- package/template/src/app/[locale]/opengraph-image.tsx +20 -0
- package/template/src/app/[locale]/twitter-image.tsx +20 -0
- package/template/src/app/api/auth/[...all]/route.ts +20 -0
- package/template/src/app/api/health/route.ts +45 -0
- package/template/src/app/api/inngest/route.ts +12 -0
- package/template/src/app/api/jobs/credits/expire/route.ts +102 -0
- package/template/src/app/api/search/route.ts +17 -0
- package/template/src/app/api/upload/presigned/route.ts +98 -0
- package/template/src/app/api/webhooks/payment/route.ts +363 -0
- package/template/src/app/globals.css +406 -0
- package/template/src/app/icon.svg +6 -0
- package/template/src/app/image-proxy/[...path]/route.ts +137 -0
- package/template/src/app/layout.tsx +73 -0
- package/template/src/app/robots.ts +29 -0
- package/template/src/app/sitemap.ts +68 -0
- package/template/src/components/motion/reveal.tsx +49 -0
- package/template/src/components/seo/json-ld.tsx +87 -0
- package/template/src/components/seo/og-image-template.tsx +118 -0
- package/template/src/components/ui/accordion.tsx +66 -0
- package/template/src/components/ui/alert-dialog.tsx +195 -0
- package/template/src/components/ui/avatar.tsx +53 -0
- package/template/src/components/ui/badge.tsx +46 -0
- package/template/src/components/ui/button.tsx +65 -0
- package/template/src/components/ui/card.tsx +92 -0
- package/template/src/components/ui/checkbox.tsx +32 -0
- package/template/src/components/ui/collapsible.tsx +33 -0
- package/template/src/components/ui/dialog.tsx +124 -0
- package/template/src/components/ui/dropdown-menu.tsx +257 -0
- package/template/src/components/ui/form.tsx +233 -0
- package/template/src/components/ui/index.ts +2 -0
- package/template/src/components/ui/input.tsx +21 -0
- package/template/src/components/ui/label.tsx +24 -0
- package/template/src/components/ui/navigation-menu.tsx +167 -0
- package/template/src/components/ui/pagination.tsx +125 -0
- package/template/src/components/ui/popover.tsx +48 -0
- package/template/src/components/ui/progress.tsx +27 -0
- package/template/src/components/ui/radio-group.tsx +45 -0
- package/template/src/components/ui/select.tsx +190 -0
- package/template/src/components/ui/separator.tsx +28 -0
- package/template/src/components/ui/sheet.tsx +140 -0
- package/template/src/components/ui/switch.tsx +31 -0
- package/template/src/components/ui/tabs.tsx +75 -0
- package/template/src/components/ui/textarea.tsx +18 -0
- package/template/src/config/index.ts +31 -0
- package/template/src/config/nav.ts +238 -0
- package/template/src/config/payment.ts +282 -0
- package/template/src/config/site.ts +53 -0
- package/template/src/config/subscription-plan.ts +164 -0
- package/template/src/content/blog/en/hello-world.mdx +48 -0
- package/template/src/content/blog/zh/hello-world.mdx +48 -0
- package/template/src/content/blog/zh/nextdevtpl-linuxdo-intro.mdx +98 -0
- package/template/src/content/docs/en/admin-and-support.mdx +65 -0
- package/template/src/content/docs/en/authentication.mdx +71 -0
- package/template/src/content/docs/en/background-jobs.mdx +53 -0
- package/template/src/content/docs/en/configuration.mdx +71 -0
- package/template/src/content/docs/en/credits.mdx +69 -0
- package/template/src/content/docs/en/customization.mdx +95 -0
- package/template/src/content/docs/en/database.mdx +66 -0
- package/template/src/content/docs/en/deployment.mdx +62 -0
- package/template/src/content/docs/en/email.mdx +48 -0
- package/template/src/content/docs/en/index.mdx +48 -0
- package/template/src/content/docs/en/internationalization.mdx +78 -0
- package/template/src/content/docs/en/meta.json +22 -0
- package/template/src/content/docs/en/observability.mdx +69 -0
- package/template/src/content/docs/en/payments.mdx +64 -0
- package/template/src/content/docs/en/project-structure.mdx +82 -0
- package/template/src/content/docs/en/quick-start.mdx +113 -0
- package/template/src/content/docs/en/storage.mdx +51 -0
- package/template/src/content/docs/zh/admin-and-support.mdx +65 -0
- package/template/src/content/docs/zh/authentication.mdx +71 -0
- package/template/src/content/docs/zh/background-jobs.mdx +53 -0
- package/template/src/content/docs/zh/configuration.mdx +70 -0
- package/template/src/content/docs/zh/credits.mdx +69 -0
- package/template/src/content/docs/zh/customization.mdx +95 -0
- package/template/src/content/docs/zh/database.mdx +66 -0
- package/template/src/content/docs/zh/deployment.mdx +61 -0
- package/template/src/content/docs/zh/email.mdx +47 -0
- package/template/src/content/docs/zh/index.mdx +48 -0
- package/template/src/content/docs/zh/internationalization.mdx +78 -0
- package/template/src/content/docs/zh/meta.json +22 -0
- package/template/src/content/docs/zh/observability.mdx +68 -0
- package/template/src/content/docs/zh/payments.mdx +64 -0
- package/template/src/content/docs/zh/project-structure.mdx +82 -0
- package/template/src/content/docs/zh/quick-start.mdx +110 -0
- package/template/src/content/docs/zh/storage.mdx +51 -0
- package/template/src/content/legal/en/cookie-policy.mdx +78 -0
- package/template/src/content/legal/en/privacy.mdx +131 -0
- package/template/src/content/legal/en/terms.mdx +93 -0
- package/template/src/content/legal/zh/cookie-policy.mdx +78 -0
- package/template/src/content/legal/zh/privacy.mdx +131 -0
- package/template/src/content/legal/zh/terms.mdx +92 -0
- package/template/src/core/modules/contract.ts +225 -0
- package/template/src/core/modules/index.ts +1 -0
- package/template/src/core/services/ai.ts +31 -0
- package/template/src/core/services/common.ts +112 -0
- package/template/src/core/services/index.ts +8 -0
- package/template/src/core/services/jobs.ts +24 -0
- package/template/src/core/services/mail.ts +35 -0
- package/template/src/core/services/manifest.ts +51 -0
- package/template/src/core/services/payment.ts +92 -0
- package/template/src/core/services/rate-limit.ts +47 -0
- package/template/src/core/services/storage.ts +42 -0
- package/template/src/db/index.ts +71 -0
- package/template/src/db/schema/auth.ts +67 -0
- package/template/src/db/schema/credits.ts +94 -0
- package/template/src/db/schema/index.ts +5 -0
- package/template/src/db/schema/mail.ts +14 -0
- package/template/src/db/schema/subscription.ts +21 -0
- package/template/src/db/schema/support.ts +56 -0
- package/template/src/db/schema.ts +2 -0
- package/template/src/features/admin/components/admin-sidebar.tsx +213 -0
- package/template/src/features/admin/components/index.ts +2 -0
- package/template/src/features/admin/index.ts +3 -0
- package/template/src/features/admin/manifest.ts +41 -0
- package/template/src/features/analytics/components/analytics.tsx +62 -0
- package/template/src/features/analytics/components/index.ts +2 -0
- package/template/src/features/analytics/index.ts +3 -0
- package/template/src/features/analytics/manifest.ts +13 -0
- package/template/src/features/auth/components/auth-brand-panel.tsx +82 -0
- package/template/src/features/auth/components/auth-error-alert.tsx +28 -0
- package/template/src/features/auth/components/auth-footer.tsx +52 -0
- package/template/src/features/auth/components/auth-logo.tsx +30 -0
- package/template/src/features/auth/components/forgot-password-form.tsx +146 -0
- package/template/src/features/auth/components/index.ts +9 -0
- package/template/src/features/auth/components/sign-in-form.tsx +241 -0
- package/template/src/features/auth/components/sign-up-form.tsx +307 -0
- package/template/src/features/auth/index.ts +3 -0
- package/template/src/features/auth/manifest.ts +30 -0
- package/template/src/features/blog/components/blog-post-item.tsx +72 -0
- package/template/src/features/blog/components/index.ts +1 -0
- package/template/src/features/blog/data/mock-posts.ts +62 -0
- package/template/src/features/blog/index.ts +3 -0
- package/template/src/features/blog/manifest.ts +22 -0
- package/template/src/features/credits/account.ts +76 -0
- package/template/src/features/credits/actions.ts +427 -0
- package/template/src/features/credits/components/credit-balance-badge.tsx +54 -0
- package/template/src/features/credits/components/credit-usage-section.tsx +160 -0
- package/template/src/features/credits/components/index.ts +7 -0
- package/template/src/features/credits/components/transaction-history.tsx +346 -0
- package/template/src/features/credits/config.ts +70 -0
- package/template/src/features/credits/consume.ts +140 -0
- package/template/src/features/credits/core.ts +23 -0
- package/template/src/features/credits/errors.ts +26 -0
- package/template/src/features/credits/expire.ts +112 -0
- package/template/src/features/credits/grant.ts +168 -0
- package/template/src/features/credits/index.ts +6 -0
- package/template/src/features/credits/manifest.ts +36 -0
- package/template/src/features/credits/query.ts +65 -0
- package/template/src/features/credits/types.ts +48 -0
- package/template/src/features/dashboard/components/index.ts +3 -0
- package/template/src/features/dashboard/components/main-wrapper.tsx +100 -0
- package/template/src/features/dashboard/components/sidebar.tsx +341 -0
- package/template/src/features/dashboard/context/index.ts +2 -0
- package/template/src/features/dashboard/context/sidebar-context.tsx +72 -0
- package/template/src/features/dashboard/index.ts +4 -0
- package/template/src/features/dashboard/manifest.ts +28 -0
- package/template/src/features/mail/actions.ts +175 -0
- package/template/src/features/mail/index.ts +5 -0
- package/template/src/features/mail/manifest.ts +13 -0
- package/template/src/features/mail/server.ts +8 -0
- package/template/src/features/mail/templates/index.ts +11 -0
- package/template/src/features/mail/templates/primary-action-email.tsx +224 -0
- package/template/src/features/mail/templates/welcome-email.tsx +121 -0
- package/template/src/features/mail/utils.ts +190 -0
- package/template/src/features/marketing/components/animated-price.tsx +51 -0
- package/template/src/features/marketing/components/cookie-consent.tsx +255 -0
- package/template/src/features/marketing/components/cta-section.tsx +50 -0
- package/template/src/features/marketing/components/faq-section.tsx +59 -0
- package/template/src/features/marketing/components/feature-grid.tsx +80 -0
- package/template/src/features/marketing/components/footer.tsx +128 -0
- package/template/src/features/marketing/components/header.tsx +255 -0
- package/template/src/features/marketing/components/hero-section.tsx +323 -0
- package/template/src/features/marketing/components/how-it-works.tsx +115 -0
- package/template/src/features/marketing/components/index.ts +14 -0
- package/template/src/features/marketing/components/nav-menu.tsx +236 -0
- package/template/src/features/marketing/components/pricing-section.tsx +446 -0
- package/template/src/features/marketing/components/testimonials.tsx +59 -0
- package/template/src/features/marketing/components/use-cases-section.tsx +78 -0
- package/template/src/features/marketing/index.ts +3 -0
- package/template/src/features/marketing/manifest.ts +35 -0
- package/template/src/features/payment/actions.ts +182 -0
- package/template/src/features/payment/index.ts +4 -0
- package/template/src/features/payment/manifest.ts +18 -0
- package/template/src/features/payment/server.ts +7 -0
- package/template/src/features/payment/types.ts +202 -0
- package/template/src/features/pseo/components/index.ts +6 -0
- package/template/src/features/pseo/components/pseo-cta.tsx +51 -0
- package/template/src/features/pseo/components/pseo-faq.tsx +40 -0
- package/template/src/features/pseo/components/pseo-feature-grid.tsx +74 -0
- package/template/src/features/pseo/components/pseo-hero.tsx +106 -0
- package/template/src/features/pseo/components/pseo-related.tsx +62 -0
- package/template/src/features/pseo/components/pseo-use-cases.tsx +50 -0
- package/template/src/features/pseo/data/pseo-pages.json +534 -0
- package/template/src/features/pseo/index.ts +4 -0
- package/template/src/features/pseo/lib/pseo-data.ts +140 -0
- package/template/src/features/pseo/manifest.ts +22 -0
- package/template/src/features/settings/actions/delete-account.ts +50 -0
- package/template/src/features/settings/actions/index.ts +3 -0
- package/template/src/features/settings/actions/update-profile.ts +49 -0
- package/template/src/features/settings/components/billing-section.tsx +283 -0
- package/template/src/features/settings/components/index.ts +3 -0
- package/template/src/features/settings/components/profile-form.tsx +154 -0
- package/template/src/features/settings/components/security-section.tsx +158 -0
- package/template/src/features/settings/components/settings-profile-view.tsx +506 -0
- package/template/src/features/settings/index.ts +5 -0
- package/template/src/features/settings/manifest.ts +28 -0
- package/template/src/features/settings/schemas/index.ts +2 -0
- package/template/src/features/settings/schemas/update-profile.ts +21 -0
- package/template/src/features/shared/components/cookie-settings-dialog.tsx +282 -0
- package/template/src/features/shared/components/index.ts +5 -0
- package/template/src/features/shared/components/language-switcher.tsx +82 -0
- package/template/src/features/shared/components/max-width-wrapper.tsx +49 -0
- package/template/src/features/shared/components/mode-toggle.tsx +119 -0
- package/template/src/features/shared/icons/google-icon.tsx +39 -0
- package/template/src/features/shared/icons/index.ts +7 -0
- package/template/src/features/shared/index.ts +5 -0
- package/template/src/features/shared/manifest.ts +13 -0
- package/template/src/features/shared/providers.tsx +59 -0
- package/template/src/features/storage/actions.ts +107 -0
- package/template/src/features/storage/index.ts +6 -0
- package/template/src/features/storage/manifest.ts +22 -0
- package/template/src/features/storage/types.ts +143 -0
- package/template/src/features/storage/utils.ts +85 -0
- package/template/src/features/storage/validation.ts +151 -0
- package/template/src/features/subscription/actions/get-user-plan.ts +26 -0
- package/template/src/features/subscription/actions/index.ts +5 -0
- package/template/src/features/subscription/components/current-plan-badge.tsx +18 -0
- package/template/src/features/subscription/components/index.ts +6 -0
- package/template/src/features/subscription/components/plan-badge.tsx +98 -0
- package/template/src/features/subscription/index.ts +25 -0
- package/template/src/features/subscription/manifest.ts +13 -0
- package/template/src/features/subscription/services/user-plan.ts +181 -0
- package/template/src/features/support/actions/admin-ticket.ts +172 -0
- package/template/src/features/support/actions/admin-users.ts +295 -0
- package/template/src/features/support/actions/index.ts +22 -0
- package/template/src/features/support/actions/ticket.ts +12 -0
- package/template/src/features/support/actions/user-ticket.ts +153 -0
- package/template/src/features/support/components/admin-ticket-reply-form.tsx +109 -0
- package/template/src/features/support/components/admin-ticket-status-select.tsx +119 -0
- package/template/src/features/support/components/index.ts +6 -0
- package/template/src/features/support/components/ticket-message-form.tsx +99 -0
- package/template/src/features/support/components/user-role-select.tsx +107 -0
- package/template/src/features/support/index.ts +5 -0
- package/template/src/features/support/manifest.ts +53 -0
- package/template/src/features/support/schemas/index.ts +15 -0
- package/template/src/features/support/schemas/ticket.ts +81 -0
- package/template/src/hooks/index.ts +2 -0
- package/template/src/i18n/index.ts +12 -0
- package/template/src/i18n/request.ts +24 -0
- package/template/src/i18n/routing.ts +23 -0
- package/template/src/instrumentation.ts +19 -0
- package/template/src/lib/ai/index.ts +16 -0
- package/template/src/lib/api-logger.ts +24 -0
- package/template/src/lib/auth/admin.ts +54 -0
- package/template/src/lib/auth/api.ts +17 -0
- package/template/src/lib/auth/client.ts +227 -0
- package/template/src/lib/auth/edge.ts +84 -0
- package/template/src/lib/auth/errors.ts +99 -0
- package/template/src/lib/auth/index.ts +159 -0
- package/template/src/lib/auth/server.ts +46 -0
- package/template/src/lib/auth/session-context.tsx +96 -0
- package/template/src/lib/cloudflare/bindings.ts +31 -0
- package/template/src/lib/cookie-consent.ts +33 -0
- package/template/src/lib/file-utils.ts +45 -0
- package/template/src/lib/fingerprint/index.ts +73 -0
- package/template/src/lib/health/checks.ts +6 -0
- package/template/src/lib/health/core.ts +86 -0
- package/template/src/lib/health/index.ts +11 -0
- package/template/src/lib/health/types.ts +13 -0
- package/template/src/lib/index.ts +2 -0
- package/template/src/lib/logger/index.ts +258 -0
- package/template/src/lib/monitoring/index.ts +384 -0
- package/template/src/lib/rate-limit/anonymous.ts +85 -0
- package/template/src/lib/rate-limit/index.ts +111 -0
- package/template/src/lib/safe-action.ts +127 -0
- package/template/src/lib/seo/json-ld.ts +188 -0
- package/template/src/lib/source.ts +122 -0
- package/template/src/lib/utils.ts +6 -0
- package/template/src/middleware.ts +162 -0
- package/template/src/modules/index.ts +10 -0
- package/template/src/modules/presets.ts +8 -0
- package/template/src/modules/registry.ts +34 -0
- package/template/src/modules/selection.ts +45 -0
- package/template/src/services/ai.ts +49 -0
- package/template/src/services/index.ts +6 -0
- package/template/src/services/jobs.ts +3 -0
- package/template/src/services/mail.ts +7 -0
- package/template/src/services/payment.ts +3 -0
- package/template/src/services/rate-limit.ts +12 -0
- package/template/src/services/storage.ts +3 -0
- package/template/src/types/fumadocs-source.d.ts +14 -0
- package/template/src/types/index.ts +2 -0
- package/template/tsconfig.json +53 -0
- package/template/vercel.json +11 -0
- package/template/vitest.config.ts +51 -0
- package/template/wrangler.jsonc +30 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# ============================================
|
|
2
|
+
# NextjsTpl 环境变量配置
|
|
3
|
+
# ============================================
|
|
4
|
+
# 复制此文件为 .env.local 并填写实际值
|
|
5
|
+
# cp .env.example .env.local
|
|
6
|
+
#
|
|
7
|
+
# 快速开始 (开发环境):
|
|
8
|
+
# 1. 数据库: 使用本地 PostgreSQL 或 Neon
|
|
9
|
+
# 2. 认证: 配置 GitHub/Google OAuth (可选,可用邮箱登录)
|
|
10
|
+
# 3. AI: 配置 OpenAI 或 DeepSeek API Key
|
|
11
|
+
# 4. 启动: pnpm dev
|
|
12
|
+
#
|
|
13
|
+
|
|
14
|
+
# ============================================
|
|
15
|
+
# 应用配置
|
|
16
|
+
# ============================================
|
|
17
|
+
# 应用 URL (用于 OAuth 回调和 API 请求)
|
|
18
|
+
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
|
19
|
+
|
|
20
|
+
# 应用名称 (显示在邮件、通知等)
|
|
21
|
+
NEXT_PUBLIC_APP_NAME=NextDevTpl
|
|
22
|
+
|
|
23
|
+
# 部署版本标签(可使用 Git commit 或发布版本)
|
|
24
|
+
APP_VERSION=local
|
|
25
|
+
|
|
26
|
+
# Docker Compose 可选覆盖项;生产环境必须修改数据库密码
|
|
27
|
+
# PORT=3000
|
|
28
|
+
# POSTGRES_DB=nextdevtpl
|
|
29
|
+
# POSTGRES_USER=nextdevtpl
|
|
30
|
+
# POSTGRES_PASSWORD=replace-with-a-long-random-password
|
|
31
|
+
|
|
32
|
+
# 社交与联系链接 (显示在页脚和元数据)
|
|
33
|
+
NEXT_PUBLIC_TWITTER_URL=https://twitter.com/example
|
|
34
|
+
NEXT_PUBLIC_GITHUB_URL=https://github.com/evepupil/NextDevTpl
|
|
35
|
+
NEXT_PUBLIC_DISCORD_URL=https://discord.gg/example
|
|
36
|
+
NEXT_PUBLIC_SUPPORT_EMAIL=hello@example.com
|
|
37
|
+
|
|
38
|
+
# 默认用户积分 (新用户注册时赠送)
|
|
39
|
+
# DEFAULT_USER_CREDITS=100
|
|
40
|
+
|
|
41
|
+
# ============================================
|
|
42
|
+
# 数据库配置 (PostgreSQL)
|
|
43
|
+
# ============================================
|
|
44
|
+
# 本地 Docker PostgreSQL 示例:
|
|
45
|
+
# DATABASE_URL=postgresql://postgres:password@localhost:5432/nextdevtpl
|
|
46
|
+
|
|
47
|
+
# Neon Serverless PostgreSQL 示例 (注意: 使用非 pooler 端点以支持事务):
|
|
48
|
+
# DATABASE_URL=postgresql://user:password@ep-xxx.us-east-1.aws.neon.tech/neondb?sslmode=require
|
|
49
|
+
|
|
50
|
+
DATABASE_URL=postgresql://postgres:password@localhost:5432/nextdevtpl
|
|
51
|
+
|
|
52
|
+
# ============================================
|
|
53
|
+
# Better Auth 配置
|
|
54
|
+
# ============================================
|
|
55
|
+
# 认证密钥 (用于签名会话 Cookie)
|
|
56
|
+
# 生成方法: openssl rand -base64 32
|
|
57
|
+
BETTER_AUTH_SECRET=your-super-secret-key-change-in-production
|
|
58
|
+
|
|
59
|
+
# 认证 URL (通常与 NEXT_PUBLIC_APP_URL 相同)
|
|
60
|
+
BETTER_AUTH_URL=http://localhost:3000
|
|
61
|
+
|
|
62
|
+
# ============================================
|
|
63
|
+
# GitHub OAuth 配置
|
|
64
|
+
# ============================================
|
|
65
|
+
# 1. 访问 https://github.com/settings/developers
|
|
66
|
+
# 2. 点击 "New OAuth App"
|
|
67
|
+
# 3. 填写:
|
|
68
|
+
# - Application name: NextDevTpl (或你的应用名)
|
|
69
|
+
# - Homepage URL: http://localhost:3000
|
|
70
|
+
# - Authorization callback URL: http://localhost:3000/api/auth/callback/github
|
|
71
|
+
# 4. 获取 Client ID 和 Client Secret
|
|
72
|
+
|
|
73
|
+
GITHUB_CLIENT_ID=your-github-client-id
|
|
74
|
+
GITHUB_CLIENT_SECRET=your-github-client-secret
|
|
75
|
+
|
|
76
|
+
# ============================================
|
|
77
|
+
# Google OAuth 配置
|
|
78
|
+
# ============================================
|
|
79
|
+
# 1. 访问 https://console.cloud.google.com/apis/credentials
|
|
80
|
+
# 2. 创建项目 (如果还没有)
|
|
81
|
+
# 3. 点击 "Create Credentials" -> "OAuth client ID"
|
|
82
|
+
# 4. 选择 "Web application"
|
|
83
|
+
# 5. 添加:
|
|
84
|
+
# - Authorized JavaScript origins: http://localhost:3000
|
|
85
|
+
# - Authorized redirect URIs: http://localhost:3000/api/auth/callback/google
|
|
86
|
+
# 6. 获取 Client ID 和 Client Secret
|
|
87
|
+
|
|
88
|
+
GOOGLE_CLIENT_ID=your-google-client-id
|
|
89
|
+
GOOGLE_CLIENT_SECRET=your-google-client-secret
|
|
90
|
+
|
|
91
|
+
# ============================================
|
|
92
|
+
# Creem 支付配置
|
|
93
|
+
# ============================================
|
|
94
|
+
# 1. 访问 https://dashboard.creem.io 获取 API Key
|
|
95
|
+
# 2. 创建 Webhook 并获取 Secret
|
|
96
|
+
|
|
97
|
+
CREEM_API_KEY=creem_api_key_xxx
|
|
98
|
+
CREEM_WEBHOOK_SECRET=creem_webhook_secret_xxx
|
|
99
|
+
|
|
100
|
+
# Stripe 支付适配器(选择 Stripe 时启用)
|
|
101
|
+
# STRIPE_SECRET_KEY=sk_test_xxx
|
|
102
|
+
# STRIPE_WEBHOOK_SECRET=whsec_xxx
|
|
103
|
+
|
|
104
|
+
# 支付供应商价格 ID
|
|
105
|
+
# 可选: 如果不配置,对应的计划将不可用
|
|
106
|
+
NEXT_PUBLIC_PRICE_STARTER_MONTHLY=price_xxx
|
|
107
|
+
NEXT_PUBLIC_PRICE_STARTER_YEARLY=price_xxx
|
|
108
|
+
NEXT_PUBLIC_PRICE_PRO_MONTHLY=price_xxx
|
|
109
|
+
NEXT_PUBLIC_PRICE_PRO_YEARLY=price_xxx
|
|
110
|
+
NEXT_PUBLIC_PRICE_ULTRA_MONTHLY=price_xxx
|
|
111
|
+
NEXT_PUBLIC_PRICE_ULTRA_YEARLY=price_xxx
|
|
112
|
+
|
|
113
|
+
# ============================================
|
|
114
|
+
# 邮件服务配置 (Resend)
|
|
115
|
+
# ============================================
|
|
116
|
+
# 1. 访问 https://resend.com
|
|
117
|
+
# 2. 创建 API Key
|
|
118
|
+
# 3. 配置发件域名 (用于生产环境)
|
|
119
|
+
|
|
120
|
+
RESEND_API_KEY=re_your-resend-api-key
|
|
121
|
+
|
|
122
|
+
# 发件人地址 (格式: "Name <email@domain.com>")
|
|
123
|
+
EMAIL_FROM="NextDevTpl <noreply@your-domain.com>"
|
|
124
|
+
|
|
125
|
+
# SMTP 邮件适配器(选择 SMTP 时启用)
|
|
126
|
+
# SMTP_HOST=smtp.example.com
|
|
127
|
+
# SMTP_PORT=587
|
|
128
|
+
# SMTP_SECURE=false
|
|
129
|
+
# SMTP_USER=your-smtp-user
|
|
130
|
+
# SMTP_PASS=your-smtp-password
|
|
131
|
+
|
|
132
|
+
# Cloudflare Email 使用 Worker 的 send_email Binding,无需 API Key。
|
|
133
|
+
# 发件域名和 Binding 在 Cloudflare Workers 部署配置中完成。
|
|
134
|
+
|
|
135
|
+
# ============================================
|
|
136
|
+
# 存储配置 (S3 兼容: AWS S3 / Cloudflare R2 / MinIO)
|
|
137
|
+
# ============================================
|
|
138
|
+
# NextjsTpl 使用对象存储保存用户上传的文件 (PDF, Word, Markdown)
|
|
139
|
+
#
|
|
140
|
+
# 本地开发可选,不配置则文件上传功能不可用
|
|
141
|
+
#
|
|
142
|
+
# Cloudflare R2 示例:
|
|
143
|
+
# STORAGE_ENDPOINT=https://your-account-id.r2.cloudflarestorage.com
|
|
144
|
+
# STORAGE_REGION=auto
|
|
145
|
+
|
|
146
|
+
# AWS S3 示例:
|
|
147
|
+
# STORAGE_ENDPOINT=https://s3.us-east-1.amazonaws.com
|
|
148
|
+
# STORAGE_REGION=us-east-1
|
|
149
|
+
|
|
150
|
+
STORAGE_ENDPOINT=https://your-account-id.r2.cloudflarestorage.com
|
|
151
|
+
STORAGE_REGION=auto
|
|
152
|
+
STORAGE_ACCESS_KEY_ID=your-access-key-id
|
|
153
|
+
STORAGE_SECRET_ACCESS_KEY=your-secret-access-key
|
|
154
|
+
|
|
155
|
+
# 头像存储桶名称 (需要预先在存储服务中创建)
|
|
156
|
+
NEXT_PUBLIC_AVATARS_BUCKET_NAME=avatars
|
|
157
|
+
|
|
158
|
+
# ============================================
|
|
159
|
+
# AI 配置 (OpenAI / DeepSeek / MiMo - 必需)
|
|
160
|
+
# ============================================
|
|
161
|
+
# Cloudflare AI Gateway (可选)
|
|
162
|
+
# 只有同时配置 CF_AIG_BASE_URL 和 CF_AIG_TOKEN 才会走网关
|
|
163
|
+
# baseURL 需要包含 /v1,并指向你在 CF 配置的 Provider Slug
|
|
164
|
+
# 通常形如: https://gateway.ai.cloudflare.com/v1/<account>/<gateway>/<provider>/v1
|
|
165
|
+
# CF_AIG_TOKEN 会作为 cf-aig-authorization 头使用,仍需配置各提供商 API Key
|
|
166
|
+
CF_AIG_BASE_URL=https://gateway.ai.cloudflare.com/v1/cb5d3307349a8fde7637f773906ad340/NextjsTpl/custom-xiaomi/v1
|
|
167
|
+
CF_AIG_TOKEN=cf_aig_token_xxx
|
|
168
|
+
|
|
169
|
+
# NextjsTpl 核心功能依赖 AI 生成闪卡
|
|
170
|
+
# 支持 OpenAI、DeepSeek、MiMo 三种提供商
|
|
171
|
+
#
|
|
172
|
+
# 支持的 AI 提供商: openai | deepseek | mimo
|
|
173
|
+
# 默认使用 OpenAI,设置为 deepseek 或 mimo 切换提供商
|
|
174
|
+
AI_PROVIDER=openai
|
|
175
|
+
|
|
176
|
+
# --- OpenAI 配置 ---
|
|
177
|
+
# 1. 访问 https://platform.openai.com/api-keys
|
|
178
|
+
# 2. 创建 API Key
|
|
179
|
+
OPENAI_API_KEY=sk-your-openai-api-key
|
|
180
|
+
|
|
181
|
+
# 可选: 指定 OpenAI 模型
|
|
182
|
+
# - gpt-4o-mini (默认,推荐,成本低)
|
|
183
|
+
# - gpt-4o
|
|
184
|
+
# - gpt-3.5-turbo
|
|
185
|
+
# OPENAI_MODEL=gpt-4o-mini
|
|
186
|
+
|
|
187
|
+
# --- DeepSeek 配置 ---
|
|
188
|
+
# 1. 访问 https://platform.deepseek.com/api_keys
|
|
189
|
+
# 2. 创建 API Key
|
|
190
|
+
DEEPSEEK_API_KEY=sk-your-deepseek-api-key
|
|
191
|
+
|
|
192
|
+
# 可选: 指定 DeepSeek 模型
|
|
193
|
+
# - deepseek-chat (默认,推荐)
|
|
194
|
+
# - deepseek-reasoner
|
|
195
|
+
# DEEPSEEK_MODEL=deepseek-chat
|
|
196
|
+
|
|
197
|
+
# --- 小米 MiMo 配置 ---
|
|
198
|
+
# 小米 MiMo 推理模型,使用 OpenAI 兼容 API
|
|
199
|
+
# API 地址: https://api.xiaomimimo.com/v1
|
|
200
|
+
MIMO_API_KEY=sk-your-mimo-api-key
|
|
201
|
+
|
|
202
|
+
# 可选: 指定 MiMo 模型
|
|
203
|
+
# - mimo-v2-flash (默认,推荐,快速推理)
|
|
204
|
+
# MIMO_MODEL=mimo-v2-flash
|
|
205
|
+
|
|
206
|
+
# --- Anthropic 配置(选择 Anthropic 时启用) ---
|
|
207
|
+
# ANTHROPIC_API_KEY=sk-ant-your-anthropic-api-key
|
|
208
|
+
# ANTHROPIC_MODEL=claude-model-id
|
|
209
|
+
|
|
210
|
+
# --- Cloudflare Workers AI(选择 Workers AI 时启用) ---
|
|
211
|
+
# 推理服务使用 Worker 的 AI Binding;这里只选择模型。
|
|
212
|
+
# WORKERS_AI_MODEL=@cf/meta/model-id
|
|
213
|
+
|
|
214
|
+
# ============================================
|
|
215
|
+
# Inngest 配置 (异步任务队列 - 必需)
|
|
216
|
+
# ============================================
|
|
217
|
+
# NextjsTpl 使用 Inngest 处理闪卡生成的后台任务
|
|
218
|
+
#
|
|
219
|
+
# 开发模式:
|
|
220
|
+
# 1. 安装并启动 Dev Server:
|
|
221
|
+
# npx inngest-cli@latest dev
|
|
222
|
+
# 2. 开发服务器会自动连接,无需额外配置
|
|
223
|
+
#
|
|
224
|
+
# 开发模式标志 (可选,用于明确启用开发模式)
|
|
225
|
+
# INNGEST_DEV=1
|
|
226
|
+
#
|
|
227
|
+
# 本地 Dev Server URL (如果 Dev Server 不在默认端口)
|
|
228
|
+
# INNGEST_BASE_URL=http://localhost:8288
|
|
229
|
+
|
|
230
|
+
# 生产环境密钥 (通过 Vercel Integration 自动设置,通常无需手动配置)
|
|
231
|
+
# INNGEST_EVENT_KEY=signkey-prod-xxx
|
|
232
|
+
# INNGEST_SIGNING_KEY=signkey-prod-xxx
|
|
233
|
+
|
|
234
|
+
# ============================================
|
|
235
|
+
# 可选配置
|
|
236
|
+
# ============================================
|
|
237
|
+
|
|
238
|
+
# 定时任务密钥 (用于保护 cron 端点)
|
|
239
|
+
# 生成方法: openssl rand -hex 32
|
|
240
|
+
# CRON_SECRET=your-cron-secret
|
|
241
|
+
|
|
242
|
+
# Google Analytics (可选)
|
|
243
|
+
# NEXT_PUBLIC_GA_ID=G-XXXXXXXXXX
|
|
244
|
+
|
|
245
|
+
# ============================================
|
|
246
|
+
# Rate Limiting 配置 (Upstash Redis) - 可选
|
|
247
|
+
# ============================================
|
|
248
|
+
# 用于 API 限流保护,防止滥用
|
|
249
|
+
# 未配置时将跳过限流检查
|
|
250
|
+
#
|
|
251
|
+
# 1. 访问 https://upstash.com
|
|
252
|
+
# 2. 创建 Redis 数据库
|
|
253
|
+
# 3. 获取 REST URL 和 Token
|
|
254
|
+
|
|
255
|
+
# UPSTASH_REDIS_REST_URL=https://xxx.upstash.io
|
|
256
|
+
# UPSTASH_REDIS_REST_TOKEN=xxx
|
|
257
|
+
|
|
258
|
+
# ============================================
|
|
259
|
+
# 日志服务配置 (Axiom) - 可选
|
|
260
|
+
# ============================================
|
|
261
|
+
# 用于结构化日志收集和查询
|
|
262
|
+
# 未配置时将使用 console 输出
|
|
263
|
+
#
|
|
264
|
+
# 1. 访问 https://axiom.co
|
|
265
|
+
# 2. 创建数据集 (Dataset)
|
|
266
|
+
# 3. 获取 API Token
|
|
267
|
+
|
|
268
|
+
# AXIOM_TOKEN=xaat-xxx
|
|
269
|
+
# AXIOM_DATASET=nextdevtpl
|
|
270
|
+
|
|
271
|
+
# ============================================
|
|
272
|
+
# 错误监控配置 (Sentry) - 可选
|
|
273
|
+
# ============================================
|
|
274
|
+
# 用于错误追踪和性能监控
|
|
275
|
+
# 未配置时将使用 console 输出错误
|
|
276
|
+
#
|
|
277
|
+
# 1. 访问 https://sentry.io
|
|
278
|
+
# 2. 创建项目 (选择 Next.js)
|
|
279
|
+
# 3. 获取 DSN
|
|
280
|
+
|
|
281
|
+
# NEXT_PUBLIC_SENTRY_DSN=https://xxx@xxx.ingest.sentry.io/xxx
|
|
282
|
+
# SENTRY_AUTH_TOKEN=sntrys_xxx
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
* text=auto eol=lf
|
|
2
|
+
|
|
3
|
+
*.bat text eol=crlf
|
|
4
|
+
*.cmd text eol=crlf
|
|
5
|
+
*.ps1 text eol=crlf
|
|
6
|
+
|
|
7
|
+
*.gif binary
|
|
8
|
+
*.ico binary
|
|
9
|
+
*.jpeg binary
|
|
10
|
+
*.jpg binary
|
|
11
|
+
*.pdf binary
|
|
12
|
+
*.png binary
|
|
13
|
+
*.wasm binary
|
|
14
|
+
*.webp binary
|
|
15
|
+
*.woff binary
|
|
16
|
+
*.woff2 binary
|
|
17
|
+
*.zip binary
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
24.18.0
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# syntax=docker/dockerfile:1
|
|
2
|
+
|
|
3
|
+
FROM node:24.18.0-alpine AS base
|
|
4
|
+
ENV PNPM_HOME=/pnpm
|
|
5
|
+
ENV PATH=$PNPM_HOME:$PATH
|
|
6
|
+
RUN corepack enable
|
|
7
|
+
WORKDIR /app
|
|
8
|
+
|
|
9
|
+
FROM base AS dependencies
|
|
10
|
+
COPY package.json pnpm-lock.yaml ./
|
|
11
|
+
RUN pnpm install --frozen-lockfile --ignore-scripts
|
|
12
|
+
|
|
13
|
+
FROM dependencies AS builder
|
|
14
|
+
COPY . .
|
|
15
|
+
ARG NEXT_PUBLIC_APP_URL=http://localhost:3000
|
|
16
|
+
ENV NEXT_TELEMETRY_DISABLED=1
|
|
17
|
+
ENV DATABASE_URL=postgresql://build:build@127.0.0.1:5432/build
|
|
18
|
+
ENV BETTER_AUTH_SECRET=build-only-secret
|
|
19
|
+
ENV BETTER_AUTH_URL=http://localhost:3000
|
|
20
|
+
ENV NEXT_PUBLIC_APP_URL=$NEXT_PUBLIC_APP_URL
|
|
21
|
+
RUN pnpm run --if-present postinstall
|
|
22
|
+
RUN pnpm build
|
|
23
|
+
|
|
24
|
+
FROM dependencies AS migrator
|
|
25
|
+
COPY . .
|
|
26
|
+
ENV NODE_ENV=production
|
|
27
|
+
CMD ["pnpm", "db:migrate"]
|
|
28
|
+
|
|
29
|
+
FROM node:24.18.0-alpine AS runner
|
|
30
|
+
WORKDIR /app
|
|
31
|
+
ENV NODE_ENV=production
|
|
32
|
+
ENV NEXT_TELEMETRY_DISABLED=1
|
|
33
|
+
ENV HOSTNAME=0.0.0.0
|
|
34
|
+
ENV PORT=3000
|
|
35
|
+
|
|
36
|
+
RUN addgroup --system --gid 1001 nodejs \
|
|
37
|
+
&& adduser --system --uid 1001 nextjs
|
|
38
|
+
|
|
39
|
+
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
|
|
40
|
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
|
41
|
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
|
42
|
+
|
|
43
|
+
USER nextjs
|
|
44
|
+
EXPOSE 3000
|
|
45
|
+
CMD ["node", "server.js"]
|
package/template/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 yeton
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<br>
|
|
3
|
+
<img src="public/logo.svg" alt="NextDevTpl" width="120">
|
|
4
|
+
<br>
|
|
5
|
+
<h1 align="center">NextDevTpl</h1>
|
|
6
|
+
<p align="center">
|
|
7
|
+
The production-ready Next.js SaaS starter — launch your SaaS in hours, not weeks.
|
|
8
|
+
</p>
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a href="https://github.com/evepupil/NextDevTpl/blob/master/LICENSE">
|
|
11
|
+
<img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT">
|
|
12
|
+
</a>
|
|
13
|
+
<a href="https://nextjs.org/">
|
|
14
|
+
<img src="https://img.shields.io/badge/Next.js-16-black?logo=nextdotjs" alt="Next.js 16">
|
|
15
|
+
</a>
|
|
16
|
+
<a href="https://www.typescriptlang.org/">
|
|
17
|
+
<img src="https://img.shields.io/badge/TypeScript-5-blue?logo=typescript" alt="TypeScript 5">
|
|
18
|
+
</a>
|
|
19
|
+
<a href="https://tailwindcss.com/">
|
|
20
|
+
<img src="https://img.shields.io/badge/Tailwind%20CSS-4-38bdf8?logo=tailwindcss" alt="Tailwind CSS 4">
|
|
21
|
+
</a>
|
|
22
|
+
<a href="https://pnpm.io/">
|
|
23
|
+
<img src="https://img.shields.io/badge/pnpm-9-orange?logo=pnpm" alt="pnpm">
|
|
24
|
+
</a>
|
|
25
|
+
</p>
|
|
26
|
+
<p align="center">
|
|
27
|
+
<a href="#-features">Features</a> •
|
|
28
|
+
<a href="#-why-nextdevtpl">Why NextDevTpl?</a> •
|
|
29
|
+
<a href="#-quick-start">Quick Start</a> •
|
|
30
|
+
<a href="#-project-structure">Structure</a> •
|
|
31
|
+
<a href="#-deployment">Deployment</a>
|
|
32
|
+
</p>
|
|
33
|
+
</p>
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 🚀 Features
|
|
38
|
+
|
|
39
|
+
| Category | Highlights |
|
|
40
|
+
|----------|-----------|
|
|
41
|
+
| **Framework** | Next.js 16 (App Router, Turbopack), React 19, TypeScript |
|
|
42
|
+
| **Styling** | Tailwind CSS 4, Shadcn/UI, Radix UI, dark mode |
|
|
43
|
+
| **Database** | PostgreSQL, Drizzle ORM, Neon serverless |
|
|
44
|
+
| **Auth** | Better Auth — email/password, GitHub/Google OAuth, role-based access |
|
|
45
|
+
| **Payments** | Creem subscription billing, webhooks, multi-tier pricing |
|
|
46
|
+
| **Credits** | Double-entry FIFO system with batch expiration tracking |
|
|
47
|
+
| **Email** | Resend delivery, React Email templates, dev preview |
|
|
48
|
+
| **Storage** | S3 / Cloudflare R2 compatible, presigned uploads |
|
|
49
|
+
| **Support** | Ticket system with threaded conversations |
|
|
50
|
+
| **Admin** | Dashboard, user CRUD, credit top-ups, ticket management |
|
|
51
|
+
| **i18n** | ~~next-intl~~ full en/zh bilingual routing |
|
|
52
|
+
| **AI** | ~~Remove~~ multi-provider chat (OpenAI, DeepSeek, MiMo) |
|
|
53
|
+
| **Rate Limiting** | Upstash Redis sliding window — automatically falls back to no-op when unconfigured |
|
|
54
|
+
| **Logging** | Pino structured logging → Axiom cloud — gracefully degrades to console |
|
|
55
|
+
| **Monitoring** | Sentry error tracking — auto-capture, user context, console fallback |
|
|
56
|
+
| **Async Jobs** | Inngest background queue with graceful degradation |
|
|
57
|
+
| **Tooling** | Biome (lint + format), pnpm, strict TypeScript |
|
|
58
|
+
|
|
59
|
+
> **Graceful degradation** — every optional service (rate limiting, logging, monitoring, async jobs) falls back to a safe local mode when its environment variable is missing. Start with 3 env vars and add services incrementally.
|
|
60
|
+
|
|
61
|
+
## ✨ Why NextDevTpl?
|
|
62
|
+
|
|
63
|
+
| | NextDevTpl | Other SaaS Templates |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| **AI integration** | Multi-provider, built-in | None or bolted on |
|
|
66
|
+
| **Double-entry credits** | FIFO + batch expiry | Shallow balance field |
|
|
67
|
+
| **i18n** | Full en/zh routing | Partial or add-on |
|
|
68
|
+
| **Async jobs** | Inngest, no blocking calls | Requests block on I/O |
|
|
69
|
+
| **Graceful degradation** | Every optional service self-silences | Hard dependency on Redis / Sentry / etc. |
|
|
70
|
+
| **Feature-based code** | `features/auth/`, `features/credits/` | Flat or role-based folders |
|
|
71
|
+
| **Real payment integration** | Creem (not Stripe mock) | Placeholder events |
|
|
72
|
+
| **PSEO demo** | ~~AnkiGenix~~ Phoenix-style programmatic SEO | None |
|
|
73
|
+
|
|
74
|
+
## 📦 Tech Stack
|
|
75
|
+
|
|
76
|
+
```mermaid
|
|
77
|
+
graph TD
|
|
78
|
+
Client[Browser / Client] --> Next["Next.js 16<br/>App Router + Server Actions"]
|
|
79
|
+
Next --> Auth[Better Auth]
|
|
80
|
+
Next --> DB[("PostgreSQL<br/>Drizzle ORM")]
|
|
81
|
+
Next --> Mail[Resend + React Email]
|
|
82
|
+
Next --> Storage[(S3 / R2)]
|
|
83
|
+
Next --> Payment[Creem]
|
|
84
|
+
Next --> RateLimit["Rate Limit<br/>Upstash Redis"]
|
|
85
|
+
Next --> Jobs[Inngest Queue]
|
|
86
|
+
Next --> Log[Pino → Axiom]
|
|
87
|
+
Next --> Monitor[Sentry]
|
|
88
|
+
Next --> AI["AI<br/>OpenAI / DeepSeek / MiMo"]
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## 🏁 Quick Start
|
|
92
|
+
|
|
93
|
+
Three env vars are enough to launch:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
git clone git@github.com:evepupil/NextDevTpl.git
|
|
97
|
+
cd NextDevTpl
|
|
98
|
+
pnpm install
|
|
99
|
+
cp .env.example .env.local
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Edit `.env.local`:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
DATABASE_URL=postgresql://...
|
|
106
|
+
BETTER_AUTH_SECRET="your-secret"
|
|
107
|
+
BETTER_AUTH_URL="http://localhost:3000"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
pnpm db:push # push Drizzle schema to your DB
|
|
112
|
+
pnpm dev # http://localhost:3000
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Optional Services
|
|
116
|
+
|
|
117
|
+
| Service | Env Var | What You Get |
|
|
118
|
+
|---------|---------|-------------|
|
|
119
|
+
| Inngest | `INNGEST_EVENT_KEY` | Background queue (credits delivery, email batching) |
|
|
120
|
+
| Upstash | `UPSTASH_REDIS_REST_URL` + `UPSTASH_REDIS_REST_TOKEN` | API rate limiting |
|
|
121
|
+
| Axiom | `AXIOM_TOKEN` + `AXIOM_DATASET` | Structured cloud logging |
|
|
122
|
+
| Sentry | `SENTRY_DSN` | Error monitoring |
|
|
123
|
+
| OpenAI | `OPENAI_API_KEY` | AI chat |
|
|
124
|
+
| Creem | `CREEM_API_KEY` + webhook secret | Subscription payments |
|
|
125
|
+
|
|
126
|
+
Every service that isn't configured simply skips its logic — no crash, no error, no blocked startup.
|
|
127
|
+
|
|
128
|
+
## 📁 Project Structure
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
src/
|
|
132
|
+
├── app/ # Next.js App Router
|
|
133
|
+
│ └── [locale]/ # i18n routing (en / zh)
|
|
134
|
+
│ ├── (marketing)/ # Public pages (landing, pricing, blog, docs)
|
|
135
|
+
│ ├── (dashboard)/ # Authenticated user area
|
|
136
|
+
│ └── (admin)/ # Admin-only area
|
|
137
|
+
├── components/ui/ # Shadcn/UI primitives
|
|
138
|
+
├── features/ # Feature-based modules
|
|
139
|
+
│ ├── marketing/ # header, footer, hero, pricing
|
|
140
|
+
│ ├── dashboard/ # sidebar, topbar, stat cards
|
|
141
|
+
│ ├── admin/ # admin sidebar, user table
|
|
142
|
+
│ ├── auth/ # sign-in, sign-up, auth client
|
|
143
|
+
│ ├── blog/ # blog list, post detail
|
|
144
|
+
│ ├── settings/ # profile, billing, account
|
|
145
|
+
│ ├── support/ # ticket CRUD
|
|
146
|
+
│ ├── analytics/ # admin dashboard charts
|
|
147
|
+
│ ├── shared/ # mode-toggle, language-switcher, icons
|
|
148
|
+
│ └── pseo/ # programmatic SEO demo
|
|
149
|
+
├── db/ # Drizzle schema definitions
|
|
150
|
+
├── lib/ # Shared utilities
|
|
151
|
+
│ ├── auth/ # Better Auth config + middleware
|
|
152
|
+
│ ├── rate-limit/ # Upstash sliding window
|
|
153
|
+
│ ├── logger/ # Pino logger wrapper
|
|
154
|
+
│ └── monitoring/ # Sentry instrumentation
|
|
155
|
+
├── credits/ # Double-entry FIFO credit engine
|
|
156
|
+
├── mail/ # React Email templates + Resend sender
|
|
157
|
+
├── storage/ # S3 / R2 abstraction
|
|
158
|
+
├── config/ # Site, nav, payment, subscription configs
|
|
159
|
+
└── test/ # Integration tests
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## 🧩 Feature Modules
|
|
163
|
+
|
|
164
|
+
### Auth
|
|
165
|
+
Email/password + GitHub/Google OAuth. Session management, `user` / `admin` roles, middleware protection.
|
|
166
|
+
|
|
167
|
+
### Payments
|
|
168
|
+
Creem subscription flow. Multi-tier pricing, webhook handling, subscription lifecycle, admin override.
|
|
169
|
+
|
|
170
|
+
### Credits
|
|
171
|
+
FIFO batch expiry + double-entry ledger. Every credit transaction is a balanced debit/credit pair with audit trail.
|
|
172
|
+
|
|
173
|
+
### Email
|
|
174
|
+
React Email templates with `<Html>`, `<Button>`, etc. Resend delivery. In dev mode, preview at `/api/emails/preview`.
|
|
175
|
+
|
|
176
|
+
### Storage
|
|
177
|
+
S3-compatible abstraction. Presigned upload URLs. Works with AWS S3, Cloudflare R2, MinIO, etc.
|
|
178
|
+
|
|
179
|
+
### Support Tickets
|
|
180
|
+
Threaded conversations, status workflow (open → in-progress → resolved), admin reply, email notifications.
|
|
181
|
+
|
|
182
|
+
### Admin Panel
|
|
183
|
+
Overview dashboard, user management (search, role toggle, ban), credit top-ups, ticket queue.
|
|
184
|
+
|
|
185
|
+
### i18n
|
|
186
|
+
`next-intl`-based routing. Current locales: `en`, `zh`. Add a locale by dropping a JSON file.
|
|
187
|
+
|
|
188
|
+
### Rate Limiting
|
|
189
|
+
Globally applied middleware. Route-level rate windows. Zero-config — unset `UPSTASH_*` env vars and it becomes a pass-through.
|
|
190
|
+
|
|
191
|
+
### Logging
|
|
192
|
+
Pino structured logger wrapped in `@/lib/logger`. Ships to Axiom when configured, otherwise writes to console.
|
|
193
|
+
|
|
194
|
+
### Error Monitoring
|
|
195
|
+
Sentry auto-instruments Server Actions & route handlers. Attaches authenticated user context. Falls back to `console.error` without a DSN.
|
|
196
|
+
|
|
197
|
+
## 🚢 Deployment
|
|
198
|
+
|
|
199
|
+
### Self-hosted (recommended)
|
|
200
|
+
|
|
201
|
+
The repo includes `deploy-build.bat` (Windows build machine) + `start-prod.sh` (Linux server). Edit the SSH host / key paths at the top of `deploy-build.bat`, then:
|
|
202
|
+
|
|
203
|
+
```bat
|
|
204
|
+
:: Windows local machine
|
|
205
|
+
deploy-build.bat
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
The script: builds → tars `.next` + config → SCPs → remote server unpacks → PM2 restarts.
|
|
209
|
+
|
|
210
|
+
### Vercel
|
|
211
|
+
|
|
212
|
+
Zero-config — push to `master`, Vercel auto-detects Next.js.
|
|
213
|
+
|
|
214
|
+
### Docker
|
|
215
|
+
|
|
216
|
+
Write a `Dockerfile`:
|
|
217
|
+
|
|
218
|
+
```dockerfile
|
|
219
|
+
FROM node:20-alpine AS base
|
|
220
|
+
# ... pnpm install, build, start
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## 📋 Scripts
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
pnpm dev # Next.js dev (Turbopack)
|
|
227
|
+
pnpm build # Production build
|
|
228
|
+
pnpm start # Production server
|
|
229
|
+
pnpm lint # Biome lint
|
|
230
|
+
pnpm format # Biome format
|
|
231
|
+
pnpm check # lint + format in fix mode
|
|
232
|
+
pnpm typecheck # tsc --noEmit
|
|
233
|
+
pnpm db:generate # Drizzle kit generate
|
|
234
|
+
pnpm db:push # Drizzle kit push (dev)
|
|
235
|
+
pnpm db:studio # Drizzle Studio UI
|
|
236
|
+
pnpm test # Run integration tests
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## 🗺️ Routes
|
|
240
|
+
|
|
241
|
+
| Route | Description | Access |
|
|
242
|
+
|-------|-------------|--------|
|
|
243
|
+
| `/` | Landing page | Public |
|
|
244
|
+
| `/pricing` | Subscription plans | Public |
|
|
245
|
+
| `/blog` | Blog index | Public |
|
|
246
|
+
| `/blog/[slug]` | Blog post | Public |
|
|
247
|
+
| `/docs` | Documentation | Public |
|
|
248
|
+
| `/sign-in` | Sign in | Public |
|
|
249
|
+
| `/sign-up` | Sign up | Public |
|
|
250
|
+
| `/dashboard` | User dashboard | Auth required |
|
|
251
|
+
| `/dashboard/support` | My tickets | Auth required |
|
|
252
|
+
| `/settings` | Account settings | Auth required |
|
|
253
|
+
| `/admin` | Admin dashboard | Admin only |
|
|
254
|
+
| `/admin/users` | User management | Admin only |
|
|
255
|
+
| `/admin/tickets` | Ticket queue | Admin only |
|
|
256
|
+
|
|
257
|
+
## 🤝 Contributing
|
|
258
|
+
|
|
259
|
+
- **Feature-based code**: place new modules under `src/features/<name>/`.
|
|
260
|
+
- **Server Components first**: only add `'use client'` when you need interactivity.
|
|
261
|
+
- **Server Actions**: all data mutations go through `next-safe-action`.
|
|
262
|
+
- **Type safety**: every prop, API response, and action schema must be typed.
|
|
263
|
+
- **Tests**: add integration tests in `src/test/`.
|
|
264
|
+
|
|
265
|
+
## 📄 License
|
|
266
|
+
|
|
267
|
+
MIT
|