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.
Files changed (425) hide show
  1. package/README.md +29 -0
  2. package/catalog.json +385 -0
  3. package/dist/catalog.d.ts +3 -0
  4. package/dist/catalog.js +112 -0
  5. package/dist/catalog.js.map +1 -0
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.js +115 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/filesystem.d.ts +10 -0
  10. package/dist/filesystem.js +86 -0
  11. package/dist/filesystem.js.map +1 -0
  12. package/dist/generate.d.ts +5 -0
  13. package/dist/generate.js +758 -0
  14. package/dist/generate.js.map +1 -0
  15. package/dist/index.d.ts +4 -0
  16. package/dist/index.js +4 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/selection.d.ts +2 -0
  19. package/dist/selection.js +111 -0
  20. package/dist/selection.js.map +1 -0
  21. package/dist/service-templates.d.ts +4 -0
  22. package/dist/service-templates.js +180 -0
  23. package/dist/service-templates.js.map +1 -0
  24. package/dist/types.d.ts +65 -0
  25. package/dist/types.js +2 -0
  26. package/dist/types.js.map +1 -0
  27. package/package.json +54 -0
  28. package/template/.dockerignore +14 -0
  29. package/template/.env.example +282 -0
  30. package/template/.gitattributes +17 -0
  31. package/template/.node-version +1 -0
  32. package/template/Dockerfile +45 -0
  33. package/template/LICENSE +21 -0
  34. package/template/README.md +267 -0
  35. package/template/biome.json +68 -0
  36. package/template/cloudflare/templates/logger.ts +162 -0
  37. package/template/cloudflare/templates/mail/server.ts +6 -0
  38. package/template/cloudflare/templates/mail/templates.ts +87 -0
  39. package/template/cloudflare/templates/mail/utils.ts +69 -0
  40. package/template/cloudflare/worker.mjs +25 -0
  41. package/template/components.json +22 -0
  42. package/template/compose.yaml +74 -0
  43. package/template/deploy/check-health.mjs +25 -0
  44. package/template/deploy/docker/README.md +14 -0
  45. package/template/deploy/server/README.md +24 -0
  46. package/template/deploy/server/build.sh +24 -0
  47. package/template/deploy/server/nextdevtpl.service +19 -0
  48. package/template/deploy/server/start.sh +19 -0
  49. package/template/deploy/vercel/README.md +16 -0
  50. package/template/deploy/verify-production-health.mjs +86 -0
  51. package/template/drizzle.config.ts +47 -0
  52. package/template/gitignore +62 -0
  53. package/template/manifest.json +35 -0
  54. package/template/messages/en.json +766 -0
  55. package/template/messages/zh.json +762 -0
  56. package/template/next.config.mjs +28 -0
  57. package/template/open-next.config.ts +3 -0
  58. package/template/package.json +125 -0
  59. package/template/pnpm-lock.yaml +15901 -0
  60. package/template/postcss.config.mjs +7 -0
  61. package/template/public/file.svg +1 -0
  62. package/template/public/globe.svg +1 -0
  63. package/template/public/logo.svg +6 -0
  64. package/template/public/next.svg +1 -0
  65. package/template/public/vercel.svg +1 -0
  66. package/template/public/window.svg +1 -0
  67. package/template/sentry.client.config.ts +10 -0
  68. package/template/sentry.edge.config.ts +10 -0
  69. package/template/sentry.server.config.ts +10 -0
  70. package/template/source.config.ts +59 -0
  71. package/template/src/adapters/ai/anthropic.ts +113 -0
  72. package/template/src/adapters/ai/index.ts +6 -0
  73. package/template/src/adapters/ai/openai-compatible.ts +88 -0
  74. package/template/src/adapters/ai/workers-ai.ts +63 -0
  75. package/template/src/adapters/index.ts +10 -0
  76. package/template/src/adapters/jobs/cloudflare-workflows.ts +46 -0
  77. package/template/src/adapters/jobs/index.ts +5 -0
  78. package/template/src/adapters/jobs/inngest/adapter.ts +29 -0
  79. package/template/src/adapters/jobs/inngest/client.ts +8 -0
  80. package/template/src/adapters/jobs/inngest/functions.ts +17 -0
  81. package/template/src/adapters/jobs/inngest/handler.ts +6 -0
  82. package/template/src/adapters/jobs/inngest/index.ts +4 -0
  83. package/template/src/adapters/mail/cloudflare-email.ts +50 -0
  84. package/template/src/adapters/mail/disabled.ts +17 -0
  85. package/template/src/adapters/mail/index.ts +7 -0
  86. package/template/src/adapters/mail/resend.ts +76 -0
  87. package/template/src/adapters/mail/smtp.ts +82 -0
  88. package/template/src/adapters/payment/creem.ts +269 -0
  89. package/template/src/adapters/payment/index.ts +2 -0
  90. package/template/src/adapters/payment/stripe.ts +302 -0
  91. package/template/src/adapters/rate-limit/cloudflare.ts +42 -0
  92. package/template/src/adapters/rate-limit/index.ts +6 -0
  93. package/template/src/adapters/rate-limit/noop.ts +27 -0
  94. package/template/src/adapters/rate-limit/upstash.ts +113 -0
  95. package/template/src/adapters/registry.ts +228 -0
  96. package/template/src/adapters/storage/index.ts +3 -0
  97. package/template/src/adapters/storage/r2-binding.ts +105 -0
  98. package/template/src/adapters/storage/s3-compatible.ts +149 -0
  99. package/template/src/app/[locale]/(admin)/admin/layout.tsx +36 -0
  100. package/template/src/app/[locale]/(admin)/admin/page.tsx +345 -0
  101. package/template/src/app/[locale]/(admin)/admin/tickets/[id]/page.tsx +261 -0
  102. package/template/src/app/[locale]/(admin)/admin/tickets/page.tsx +236 -0
  103. package/template/src/app/[locale]/(admin)/admin/users/page.tsx +557 -0
  104. package/template/src/app/[locale]/(auth)/forgot-password/page.tsx +9 -0
  105. package/template/src/app/[locale]/(auth)/layout.tsx +28 -0
  106. package/template/src/app/[locale]/(auth)/sign-in/page.tsx +9 -0
  107. package/template/src/app/[locale]/(auth)/sign-up/page.tsx +9 -0
  108. package/template/src/app/[locale]/(dashboard)/dashboard/credits/buy/buy-credits-view.tsx +170 -0
  109. package/template/src/app/[locale]/(dashboard)/dashboard/credits/buy/page.tsx +12 -0
  110. package/template/src/app/[locale]/(dashboard)/dashboard/credits/page.tsx +5 -0
  111. package/template/src/app/[locale]/(dashboard)/dashboard/loading.tsx +41 -0
  112. package/template/src/app/[locale]/(dashboard)/dashboard/page.tsx +299 -0
  113. package/template/src/app/[locale]/(dashboard)/dashboard/settings/page.tsx +38 -0
  114. package/template/src/app/[locale]/(dashboard)/dashboard/support/[id]/page.tsx +220 -0
  115. package/template/src/app/[locale]/(dashboard)/dashboard/support/new/page.tsx +183 -0
  116. package/template/src/app/[locale]/(dashboard)/dashboard/support/page.tsx +145 -0
  117. package/template/src/app/[locale]/(dashboard)/layout.tsx +35 -0
  118. package/template/src/app/[locale]/(marketing)/blog/[slug]/page.tsx +178 -0
  119. package/template/src/app/[locale]/(marketing)/blog/blog-post-card.tsx +95 -0
  120. package/template/src/app/[locale]/(marketing)/blog/page.tsx +127 -0
  121. package/template/src/app/[locale]/(marketing)/demo/plan-badges/page.tsx +36 -0
  122. package/template/src/app/[locale]/(marketing)/layout.tsx +15 -0
  123. package/template/src/app/[locale]/(marketing)/legal/[slug]/page.tsx +130 -0
  124. package/template/src/app/[locale]/(marketing)/page.tsx +94 -0
  125. package/template/src/app/[locale]/(marketing)/pseo/[slug]/page.tsx +68 -0
  126. package/template/src/app/[locale]/(marketing)/pseo/page.tsx +137 -0
  127. package/template/src/app/[locale]/docs/[[...slug]]/page.tsx +63 -0
  128. package/template/src/app/[locale]/docs/layout.tsx +39 -0
  129. package/template/src/app/[locale]/layout.tsx +80 -0
  130. package/template/src/app/[locale]/opengraph-image.tsx +20 -0
  131. package/template/src/app/[locale]/twitter-image.tsx +20 -0
  132. package/template/src/app/api/auth/[...all]/route.ts +20 -0
  133. package/template/src/app/api/health/route.ts +45 -0
  134. package/template/src/app/api/inngest/route.ts +12 -0
  135. package/template/src/app/api/jobs/credits/expire/route.ts +102 -0
  136. package/template/src/app/api/search/route.ts +17 -0
  137. package/template/src/app/api/upload/presigned/route.ts +98 -0
  138. package/template/src/app/api/webhooks/payment/route.ts +363 -0
  139. package/template/src/app/globals.css +406 -0
  140. package/template/src/app/icon.svg +6 -0
  141. package/template/src/app/image-proxy/[...path]/route.ts +137 -0
  142. package/template/src/app/layout.tsx +73 -0
  143. package/template/src/app/robots.ts +29 -0
  144. package/template/src/app/sitemap.ts +68 -0
  145. package/template/src/components/motion/reveal.tsx +49 -0
  146. package/template/src/components/seo/json-ld.tsx +87 -0
  147. package/template/src/components/seo/og-image-template.tsx +118 -0
  148. package/template/src/components/ui/accordion.tsx +66 -0
  149. package/template/src/components/ui/alert-dialog.tsx +195 -0
  150. package/template/src/components/ui/avatar.tsx +53 -0
  151. package/template/src/components/ui/badge.tsx +46 -0
  152. package/template/src/components/ui/button.tsx +65 -0
  153. package/template/src/components/ui/card.tsx +92 -0
  154. package/template/src/components/ui/checkbox.tsx +32 -0
  155. package/template/src/components/ui/collapsible.tsx +33 -0
  156. package/template/src/components/ui/dialog.tsx +124 -0
  157. package/template/src/components/ui/dropdown-menu.tsx +257 -0
  158. package/template/src/components/ui/form.tsx +233 -0
  159. package/template/src/components/ui/index.ts +2 -0
  160. package/template/src/components/ui/input.tsx +21 -0
  161. package/template/src/components/ui/label.tsx +24 -0
  162. package/template/src/components/ui/navigation-menu.tsx +167 -0
  163. package/template/src/components/ui/pagination.tsx +125 -0
  164. package/template/src/components/ui/popover.tsx +48 -0
  165. package/template/src/components/ui/progress.tsx +27 -0
  166. package/template/src/components/ui/radio-group.tsx +45 -0
  167. package/template/src/components/ui/select.tsx +190 -0
  168. package/template/src/components/ui/separator.tsx +28 -0
  169. package/template/src/components/ui/sheet.tsx +140 -0
  170. package/template/src/components/ui/switch.tsx +31 -0
  171. package/template/src/components/ui/tabs.tsx +75 -0
  172. package/template/src/components/ui/textarea.tsx +18 -0
  173. package/template/src/config/index.ts +31 -0
  174. package/template/src/config/nav.ts +238 -0
  175. package/template/src/config/payment.ts +282 -0
  176. package/template/src/config/site.ts +53 -0
  177. package/template/src/config/subscription-plan.ts +164 -0
  178. package/template/src/content/blog/en/hello-world.mdx +48 -0
  179. package/template/src/content/blog/zh/hello-world.mdx +48 -0
  180. package/template/src/content/blog/zh/nextdevtpl-linuxdo-intro.mdx +98 -0
  181. package/template/src/content/docs/en/admin-and-support.mdx +65 -0
  182. package/template/src/content/docs/en/authentication.mdx +71 -0
  183. package/template/src/content/docs/en/background-jobs.mdx +53 -0
  184. package/template/src/content/docs/en/configuration.mdx +71 -0
  185. package/template/src/content/docs/en/credits.mdx +69 -0
  186. package/template/src/content/docs/en/customization.mdx +95 -0
  187. package/template/src/content/docs/en/database.mdx +66 -0
  188. package/template/src/content/docs/en/deployment.mdx +62 -0
  189. package/template/src/content/docs/en/email.mdx +48 -0
  190. package/template/src/content/docs/en/index.mdx +48 -0
  191. package/template/src/content/docs/en/internationalization.mdx +78 -0
  192. package/template/src/content/docs/en/meta.json +22 -0
  193. package/template/src/content/docs/en/observability.mdx +69 -0
  194. package/template/src/content/docs/en/payments.mdx +64 -0
  195. package/template/src/content/docs/en/project-structure.mdx +82 -0
  196. package/template/src/content/docs/en/quick-start.mdx +113 -0
  197. package/template/src/content/docs/en/storage.mdx +51 -0
  198. package/template/src/content/docs/zh/admin-and-support.mdx +65 -0
  199. package/template/src/content/docs/zh/authentication.mdx +71 -0
  200. package/template/src/content/docs/zh/background-jobs.mdx +53 -0
  201. package/template/src/content/docs/zh/configuration.mdx +70 -0
  202. package/template/src/content/docs/zh/credits.mdx +69 -0
  203. package/template/src/content/docs/zh/customization.mdx +95 -0
  204. package/template/src/content/docs/zh/database.mdx +66 -0
  205. package/template/src/content/docs/zh/deployment.mdx +61 -0
  206. package/template/src/content/docs/zh/email.mdx +47 -0
  207. package/template/src/content/docs/zh/index.mdx +48 -0
  208. package/template/src/content/docs/zh/internationalization.mdx +78 -0
  209. package/template/src/content/docs/zh/meta.json +22 -0
  210. package/template/src/content/docs/zh/observability.mdx +68 -0
  211. package/template/src/content/docs/zh/payments.mdx +64 -0
  212. package/template/src/content/docs/zh/project-structure.mdx +82 -0
  213. package/template/src/content/docs/zh/quick-start.mdx +110 -0
  214. package/template/src/content/docs/zh/storage.mdx +51 -0
  215. package/template/src/content/legal/en/cookie-policy.mdx +78 -0
  216. package/template/src/content/legal/en/privacy.mdx +131 -0
  217. package/template/src/content/legal/en/terms.mdx +93 -0
  218. package/template/src/content/legal/zh/cookie-policy.mdx +78 -0
  219. package/template/src/content/legal/zh/privacy.mdx +131 -0
  220. package/template/src/content/legal/zh/terms.mdx +92 -0
  221. package/template/src/core/modules/contract.ts +225 -0
  222. package/template/src/core/modules/index.ts +1 -0
  223. package/template/src/core/services/ai.ts +31 -0
  224. package/template/src/core/services/common.ts +112 -0
  225. package/template/src/core/services/index.ts +8 -0
  226. package/template/src/core/services/jobs.ts +24 -0
  227. package/template/src/core/services/mail.ts +35 -0
  228. package/template/src/core/services/manifest.ts +51 -0
  229. package/template/src/core/services/payment.ts +92 -0
  230. package/template/src/core/services/rate-limit.ts +47 -0
  231. package/template/src/core/services/storage.ts +42 -0
  232. package/template/src/db/index.ts +71 -0
  233. package/template/src/db/schema/auth.ts +67 -0
  234. package/template/src/db/schema/credits.ts +94 -0
  235. package/template/src/db/schema/index.ts +5 -0
  236. package/template/src/db/schema/mail.ts +14 -0
  237. package/template/src/db/schema/subscription.ts +21 -0
  238. package/template/src/db/schema/support.ts +56 -0
  239. package/template/src/db/schema.ts +2 -0
  240. package/template/src/features/admin/components/admin-sidebar.tsx +213 -0
  241. package/template/src/features/admin/components/index.ts +2 -0
  242. package/template/src/features/admin/index.ts +3 -0
  243. package/template/src/features/admin/manifest.ts +41 -0
  244. package/template/src/features/analytics/components/analytics.tsx +62 -0
  245. package/template/src/features/analytics/components/index.ts +2 -0
  246. package/template/src/features/analytics/index.ts +3 -0
  247. package/template/src/features/analytics/manifest.ts +13 -0
  248. package/template/src/features/auth/components/auth-brand-panel.tsx +82 -0
  249. package/template/src/features/auth/components/auth-error-alert.tsx +28 -0
  250. package/template/src/features/auth/components/auth-footer.tsx +52 -0
  251. package/template/src/features/auth/components/auth-logo.tsx +30 -0
  252. package/template/src/features/auth/components/forgot-password-form.tsx +146 -0
  253. package/template/src/features/auth/components/index.ts +9 -0
  254. package/template/src/features/auth/components/sign-in-form.tsx +241 -0
  255. package/template/src/features/auth/components/sign-up-form.tsx +307 -0
  256. package/template/src/features/auth/index.ts +3 -0
  257. package/template/src/features/auth/manifest.ts +30 -0
  258. package/template/src/features/blog/components/blog-post-item.tsx +72 -0
  259. package/template/src/features/blog/components/index.ts +1 -0
  260. package/template/src/features/blog/data/mock-posts.ts +62 -0
  261. package/template/src/features/blog/index.ts +3 -0
  262. package/template/src/features/blog/manifest.ts +22 -0
  263. package/template/src/features/credits/account.ts +76 -0
  264. package/template/src/features/credits/actions.ts +427 -0
  265. package/template/src/features/credits/components/credit-balance-badge.tsx +54 -0
  266. package/template/src/features/credits/components/credit-usage-section.tsx +160 -0
  267. package/template/src/features/credits/components/index.ts +7 -0
  268. package/template/src/features/credits/components/transaction-history.tsx +346 -0
  269. package/template/src/features/credits/config.ts +70 -0
  270. package/template/src/features/credits/consume.ts +140 -0
  271. package/template/src/features/credits/core.ts +23 -0
  272. package/template/src/features/credits/errors.ts +26 -0
  273. package/template/src/features/credits/expire.ts +112 -0
  274. package/template/src/features/credits/grant.ts +168 -0
  275. package/template/src/features/credits/index.ts +6 -0
  276. package/template/src/features/credits/manifest.ts +36 -0
  277. package/template/src/features/credits/query.ts +65 -0
  278. package/template/src/features/credits/types.ts +48 -0
  279. package/template/src/features/dashboard/components/index.ts +3 -0
  280. package/template/src/features/dashboard/components/main-wrapper.tsx +100 -0
  281. package/template/src/features/dashboard/components/sidebar.tsx +341 -0
  282. package/template/src/features/dashboard/context/index.ts +2 -0
  283. package/template/src/features/dashboard/context/sidebar-context.tsx +72 -0
  284. package/template/src/features/dashboard/index.ts +4 -0
  285. package/template/src/features/dashboard/manifest.ts +28 -0
  286. package/template/src/features/mail/actions.ts +175 -0
  287. package/template/src/features/mail/index.ts +5 -0
  288. package/template/src/features/mail/manifest.ts +13 -0
  289. package/template/src/features/mail/server.ts +8 -0
  290. package/template/src/features/mail/templates/index.ts +11 -0
  291. package/template/src/features/mail/templates/primary-action-email.tsx +224 -0
  292. package/template/src/features/mail/templates/welcome-email.tsx +121 -0
  293. package/template/src/features/mail/utils.ts +190 -0
  294. package/template/src/features/marketing/components/animated-price.tsx +51 -0
  295. package/template/src/features/marketing/components/cookie-consent.tsx +255 -0
  296. package/template/src/features/marketing/components/cta-section.tsx +50 -0
  297. package/template/src/features/marketing/components/faq-section.tsx +59 -0
  298. package/template/src/features/marketing/components/feature-grid.tsx +80 -0
  299. package/template/src/features/marketing/components/footer.tsx +128 -0
  300. package/template/src/features/marketing/components/header.tsx +255 -0
  301. package/template/src/features/marketing/components/hero-section.tsx +323 -0
  302. package/template/src/features/marketing/components/how-it-works.tsx +115 -0
  303. package/template/src/features/marketing/components/index.ts +14 -0
  304. package/template/src/features/marketing/components/nav-menu.tsx +236 -0
  305. package/template/src/features/marketing/components/pricing-section.tsx +446 -0
  306. package/template/src/features/marketing/components/testimonials.tsx +59 -0
  307. package/template/src/features/marketing/components/use-cases-section.tsx +78 -0
  308. package/template/src/features/marketing/index.ts +3 -0
  309. package/template/src/features/marketing/manifest.ts +35 -0
  310. package/template/src/features/payment/actions.ts +182 -0
  311. package/template/src/features/payment/index.ts +4 -0
  312. package/template/src/features/payment/manifest.ts +18 -0
  313. package/template/src/features/payment/server.ts +7 -0
  314. package/template/src/features/payment/types.ts +202 -0
  315. package/template/src/features/pseo/components/index.ts +6 -0
  316. package/template/src/features/pseo/components/pseo-cta.tsx +51 -0
  317. package/template/src/features/pseo/components/pseo-faq.tsx +40 -0
  318. package/template/src/features/pseo/components/pseo-feature-grid.tsx +74 -0
  319. package/template/src/features/pseo/components/pseo-hero.tsx +106 -0
  320. package/template/src/features/pseo/components/pseo-related.tsx +62 -0
  321. package/template/src/features/pseo/components/pseo-use-cases.tsx +50 -0
  322. package/template/src/features/pseo/data/pseo-pages.json +534 -0
  323. package/template/src/features/pseo/index.ts +4 -0
  324. package/template/src/features/pseo/lib/pseo-data.ts +140 -0
  325. package/template/src/features/pseo/manifest.ts +22 -0
  326. package/template/src/features/settings/actions/delete-account.ts +50 -0
  327. package/template/src/features/settings/actions/index.ts +3 -0
  328. package/template/src/features/settings/actions/update-profile.ts +49 -0
  329. package/template/src/features/settings/components/billing-section.tsx +283 -0
  330. package/template/src/features/settings/components/index.ts +3 -0
  331. package/template/src/features/settings/components/profile-form.tsx +154 -0
  332. package/template/src/features/settings/components/security-section.tsx +158 -0
  333. package/template/src/features/settings/components/settings-profile-view.tsx +506 -0
  334. package/template/src/features/settings/index.ts +5 -0
  335. package/template/src/features/settings/manifest.ts +28 -0
  336. package/template/src/features/settings/schemas/index.ts +2 -0
  337. package/template/src/features/settings/schemas/update-profile.ts +21 -0
  338. package/template/src/features/shared/components/cookie-settings-dialog.tsx +282 -0
  339. package/template/src/features/shared/components/index.ts +5 -0
  340. package/template/src/features/shared/components/language-switcher.tsx +82 -0
  341. package/template/src/features/shared/components/max-width-wrapper.tsx +49 -0
  342. package/template/src/features/shared/components/mode-toggle.tsx +119 -0
  343. package/template/src/features/shared/icons/google-icon.tsx +39 -0
  344. package/template/src/features/shared/icons/index.ts +7 -0
  345. package/template/src/features/shared/index.ts +5 -0
  346. package/template/src/features/shared/manifest.ts +13 -0
  347. package/template/src/features/shared/providers.tsx +59 -0
  348. package/template/src/features/storage/actions.ts +107 -0
  349. package/template/src/features/storage/index.ts +6 -0
  350. package/template/src/features/storage/manifest.ts +22 -0
  351. package/template/src/features/storage/types.ts +143 -0
  352. package/template/src/features/storage/utils.ts +85 -0
  353. package/template/src/features/storage/validation.ts +151 -0
  354. package/template/src/features/subscription/actions/get-user-plan.ts +26 -0
  355. package/template/src/features/subscription/actions/index.ts +5 -0
  356. package/template/src/features/subscription/components/current-plan-badge.tsx +18 -0
  357. package/template/src/features/subscription/components/index.ts +6 -0
  358. package/template/src/features/subscription/components/plan-badge.tsx +98 -0
  359. package/template/src/features/subscription/index.ts +25 -0
  360. package/template/src/features/subscription/manifest.ts +13 -0
  361. package/template/src/features/subscription/services/user-plan.ts +181 -0
  362. package/template/src/features/support/actions/admin-ticket.ts +172 -0
  363. package/template/src/features/support/actions/admin-users.ts +295 -0
  364. package/template/src/features/support/actions/index.ts +22 -0
  365. package/template/src/features/support/actions/ticket.ts +12 -0
  366. package/template/src/features/support/actions/user-ticket.ts +153 -0
  367. package/template/src/features/support/components/admin-ticket-reply-form.tsx +109 -0
  368. package/template/src/features/support/components/admin-ticket-status-select.tsx +119 -0
  369. package/template/src/features/support/components/index.ts +6 -0
  370. package/template/src/features/support/components/ticket-message-form.tsx +99 -0
  371. package/template/src/features/support/components/user-role-select.tsx +107 -0
  372. package/template/src/features/support/index.ts +5 -0
  373. package/template/src/features/support/manifest.ts +53 -0
  374. package/template/src/features/support/schemas/index.ts +15 -0
  375. package/template/src/features/support/schemas/ticket.ts +81 -0
  376. package/template/src/hooks/index.ts +2 -0
  377. package/template/src/i18n/index.ts +12 -0
  378. package/template/src/i18n/request.ts +24 -0
  379. package/template/src/i18n/routing.ts +23 -0
  380. package/template/src/instrumentation.ts +19 -0
  381. package/template/src/lib/ai/index.ts +16 -0
  382. package/template/src/lib/api-logger.ts +24 -0
  383. package/template/src/lib/auth/admin.ts +54 -0
  384. package/template/src/lib/auth/api.ts +17 -0
  385. package/template/src/lib/auth/client.ts +227 -0
  386. package/template/src/lib/auth/edge.ts +84 -0
  387. package/template/src/lib/auth/errors.ts +99 -0
  388. package/template/src/lib/auth/index.ts +159 -0
  389. package/template/src/lib/auth/server.ts +46 -0
  390. package/template/src/lib/auth/session-context.tsx +96 -0
  391. package/template/src/lib/cloudflare/bindings.ts +31 -0
  392. package/template/src/lib/cookie-consent.ts +33 -0
  393. package/template/src/lib/file-utils.ts +45 -0
  394. package/template/src/lib/fingerprint/index.ts +73 -0
  395. package/template/src/lib/health/checks.ts +6 -0
  396. package/template/src/lib/health/core.ts +86 -0
  397. package/template/src/lib/health/index.ts +11 -0
  398. package/template/src/lib/health/types.ts +13 -0
  399. package/template/src/lib/index.ts +2 -0
  400. package/template/src/lib/logger/index.ts +258 -0
  401. package/template/src/lib/monitoring/index.ts +384 -0
  402. package/template/src/lib/rate-limit/anonymous.ts +85 -0
  403. package/template/src/lib/rate-limit/index.ts +111 -0
  404. package/template/src/lib/safe-action.ts +127 -0
  405. package/template/src/lib/seo/json-ld.ts +188 -0
  406. package/template/src/lib/source.ts +122 -0
  407. package/template/src/lib/utils.ts +6 -0
  408. package/template/src/middleware.ts +162 -0
  409. package/template/src/modules/index.ts +10 -0
  410. package/template/src/modules/presets.ts +8 -0
  411. package/template/src/modules/registry.ts +34 -0
  412. package/template/src/modules/selection.ts +45 -0
  413. package/template/src/services/ai.ts +49 -0
  414. package/template/src/services/index.ts +6 -0
  415. package/template/src/services/jobs.ts +3 -0
  416. package/template/src/services/mail.ts +7 -0
  417. package/template/src/services/payment.ts +3 -0
  418. package/template/src/services/rate-limit.ts +12 -0
  419. package/template/src/services/storage.ts +3 -0
  420. package/template/src/types/fumadocs-source.d.ts +14 -0
  421. package/template/src/types/index.ts +2 -0
  422. package/template/tsconfig.json +53 -0
  423. package/template/vercel.json +11 -0
  424. package/template/vitest.config.ts +51 -0
  425. 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"]
@@ -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