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,164 @@
1
+ /**
2
+ * 订阅计划权限配置
3
+ *
4
+ * 定义各计划的特权限制和功能访问权限
5
+ */
6
+
7
+ import { PRICE_IDS } from "./payment";
8
+
9
+ // ============================================
10
+ // 计划类型定义
11
+ // ============================================
12
+
13
+ /**
14
+ * 订阅计划类型
15
+ */
16
+ export type SubscriptionPlan = "free" | "starter" | "pro" | "ultra";
17
+
18
+ /**
19
+ * 队列优先级
20
+ */
21
+ export type QueuePriority = "normal" | "priority" | "highest";
22
+
23
+ /**
24
+ * 计划特权配置
25
+ */
26
+ export interface PlanPrivileges {
27
+ /** 计划名称 */
28
+ name: string;
29
+ /** 单文件大小上限 (bytes) */
30
+ maxFileSizeBytes: number;
31
+ /** 队列优先级 */
32
+ queuePriority: QueuePriority;
33
+ /** 月度积分配额 (免费版为一次性) */
34
+ monthlyCredits: number;
35
+ }
36
+
37
+ // ============================================
38
+ // 计划特权配置
39
+ // ============================================
40
+
41
+ /**
42
+ * 各计划的特权配置
43
+ */
44
+ export const PLAN_PRIVILEGES: Record<SubscriptionPlan, PlanPrivileges> = {
45
+ free: {
46
+ name: "Free",
47
+ maxFileSizeBytes: 5 * 1024 * 1024, // 5MB
48
+ queuePriority: "normal",
49
+ monthlyCredits: 200, // 一次性
50
+ },
51
+ starter: {
52
+ name: "Starter",
53
+ maxFileSizeBytes: 20 * 1024 * 1024, // 20MB
54
+ queuePriority: "normal",
55
+ monthlyCredits: 3_000,
56
+ },
57
+ pro: {
58
+ name: "Pro",
59
+ maxFileSizeBytes: 50 * 1024 * 1024, // 50MB
60
+ queuePriority: "priority",
61
+ monthlyCredits: 8_000,
62
+ },
63
+ ultra: {
64
+ name: "Ultra",
65
+ maxFileSizeBytes: 100 * 1024 * 1024, // 100MB
66
+ queuePriority: "highest",
67
+ monthlyCredits: 16_000,
68
+ },
69
+ };
70
+
71
+ // ============================================
72
+ // Price ID 到计划的映射
73
+ // ============================================
74
+
75
+ /**
76
+ * 根据 Price ID 获取计划类型
77
+ *
78
+ * @param priceId - 价格/产品 ID
79
+ * @returns 计划类型,如果未找到则返回 null
80
+ */
81
+ export function getPlanFromPriceId(priceId: string): SubscriptionPlan | null {
82
+ // Starter
83
+ if (
84
+ priceId === PRICE_IDS.STARTER_MONTHLY ||
85
+ priceId === PRICE_IDS.STARTER_YEARLY
86
+ ) {
87
+ return "starter";
88
+ }
89
+
90
+ // Pro
91
+ if (priceId === PRICE_IDS.PRO_MONTHLY || priceId === PRICE_IDS.PRO_YEARLY) {
92
+ return "pro";
93
+ }
94
+
95
+ // Ultra
96
+ if (
97
+ priceId === PRICE_IDS.ULTRA_MONTHLY ||
98
+ priceId === PRICE_IDS.ULTRA_YEARLY
99
+ ) {
100
+ return "ultra";
101
+ }
102
+
103
+ return null;
104
+ }
105
+
106
+ // ============================================
107
+ // 特权检查工具函数
108
+ // ============================================
109
+
110
+ /**
111
+ * 获取计划的特权配置
112
+ *
113
+ * @param plan - 订阅计划
114
+ * @returns 计划特权配置
115
+ */
116
+ export function getPlanPrivileges(plan: SubscriptionPlan): PlanPrivileges {
117
+ return PLAN_PRIVILEGES[plan];
118
+ }
119
+
120
+ /**
121
+ * 检查文件大小是否在限制内
122
+ *
123
+ * @param plan - 订阅计划
124
+ * @param fileSizeBytes - 文件大小(字节)
125
+ * @returns 是否在限制内
126
+ */
127
+ export function isWithinFileSizeLimit(
128
+ plan: SubscriptionPlan,
129
+ fileSizeBytes: number
130
+ ): boolean {
131
+ return fileSizeBytes <= PLAN_PRIVILEGES[plan].maxFileSizeBytes;
132
+ }
133
+
134
+ /**
135
+ * 格式化文件大小限制(用于错误消息)
136
+ *
137
+ * @param plan - 订阅计划
138
+ * @returns 格式化的文件大小字符串(如 "5MB")
139
+ */
140
+ export function formatFileSizeLimit(plan: SubscriptionPlan): string {
141
+ const bytes = PLAN_PRIVILEGES[plan].maxFileSizeBytes;
142
+ return `${bytes / (1024 * 1024)}MB`;
143
+ }
144
+
145
+ /**
146
+ * 获取升级建议(当特权不足时)
147
+ *
148
+ * @param currentPlan - 当前计划
149
+ * @param requiredFeature - 需要的功能描述
150
+ * @returns 升级建议消息
151
+ */
152
+ export function getUpgradeMessage(
153
+ currentPlan: SubscriptionPlan,
154
+ requiredFeature: string
155
+ ): string {
156
+ const upgradeTo =
157
+ currentPlan === "free"
158
+ ? "Starter"
159
+ : currentPlan === "starter"
160
+ ? "Pro"
161
+ : "Ultra";
162
+
163
+ return `${requiredFeature} requires ${upgradeTo} plan or higher. Please upgrade to continue.`;
164
+ }
@@ -0,0 +1,48 @@
1
+ ---
2
+ title: Hello World
3
+ description: Welcome to our blog! This is our first post introducing NextDevTpl.
4
+ date: 2024-01-15
5
+ author: NextDevTpl Team
6
+ tags:
7
+ - announcement
8
+ - getting-started
9
+ ---
10
+
11
+ # Hello World
12
+
13
+ Welcome to the NextDevTpl blog! We're excited to share our journey of building the ultimate Next.js starter kit.
14
+
15
+ ## What is NextDevTpl?
16
+
17
+ NextDevTpl is a modern, production-ready SaaS boilerplate built with:
18
+
19
+ - **Next.js 16** - The React framework for production
20
+ - **TypeScript** - Type-safe development
21
+ - **Tailwind CSS** - Utility-first styling
22
+ - **Better Auth** - Modern authentication
23
+ - **Drizzle ORM** - Type-safe database access
24
+
25
+ ## Why We Built This
26
+
27
+ Building a SaaS application from scratch is time-consuming. You need to set up authentication, database connections, styling, and countless other features before you can even start working on your actual product.
28
+
29
+ NextDevTpl solves this by providing a solid foundation that includes:
30
+
31
+ 1. **Authentication** - Email/password, OAuth providers
32
+ 2. **Database** - PostgreSQL with Drizzle ORM
33
+ 3. **UI Components** - Beautiful, accessible components
34
+ 4. **Internationalization** - Multi-language support
35
+ 5. **SEO** - Optimized for search engines
36
+
37
+ ## Getting Started
38
+
39
+ To get started with NextDevTpl, simply clone the repository and follow the setup instructions in our documentation.
40
+
41
+ ```bash
42
+ git clone https://github.com/nextdevtpl/nextdevtpl.git
43
+ cd nextdevtpl
44
+ pnpm install
45
+ pnpm dev
46
+ ```
47
+
48
+ Stay tuned for more updates and tutorials!
@@ -0,0 +1,48 @@
1
+ ---
2
+ title: 你好世界
3
+ description: 欢迎来到我们的博客!这是我们介绍 NextDevTpl 的第一篇文章。
4
+ date: 2024-01-15
5
+ author: NextDevTpl 团队
6
+ tags:
7
+ - 公告
8
+ - 入门指南
9
+ ---
10
+
11
+ # 你好世界
12
+
13
+ 欢迎来到 NextDevTpl 博客!我们很高兴与您分享构建终极 Next.js 启动模板的旅程。
14
+
15
+ ## 什么是 NextDevTpl?
16
+
17
+ NextDevTpl 是一个现代化、生产就绪的 SaaS 模板,采用以下技术构建:
18
+
19
+ - **Next.js 16** - 用于生产环境的 React 框架
20
+ - **TypeScript** - 类型安全的开发体验
21
+ - **Tailwind CSS** - 实用优先的样式方案
22
+ - **Better Auth** - 现代化认证方案
23
+ - **Drizzle ORM** - 类型安全的数据库访问
24
+
25
+ ## 为什么我们要构建它
26
+
27
+ 从零开始构建 SaaS 应用程序非常耗时。在开始开发实际产品之前,您需要设置身份验证、数据库连接、样式和无数其他功能。
28
+
29
+ NextDevTpl 通过提供坚实的基础来解决这个问题,包括:
30
+
31
+ 1. **身份验证** - 邮箱/密码、OAuth 提供商
32
+ 2. **数据库** - PostgreSQL 配合 Drizzle ORM
33
+ 3. **UI 组件** - 美观、无障碍的组件
34
+ 4. **国际化** - 多语言支持
35
+ 5. **SEO** - 搜索引擎优化
36
+
37
+ ## 开始使用
38
+
39
+ 要开始使用 NextDevTpl,只需克隆仓库并按照文档中的设置说明操作。
40
+
41
+ ```bash
42
+ git clone https://github.com/nextdevtpl/nextdevtpl.git
43
+ cd nextdevtpl
44
+ pnpm install
45
+ pnpm dev
46
+ ```
47
+
48
+ 敬请期待更多更新和教程!
@@ -0,0 +1,98 @@
1
+ ---
2
+ title: "[开源] NextDevTpl:一个面向独立开发者的 Next.js 全栈 SaaS 模板"
3
+ description: "不是能跑 Demo 的脚手架,而是可直接落地业务的全栈模板。内置认证、支付、积分、邮件、存储、工单与后台管理。"
4
+ date: 2026-02-16
5
+ author: NextDevTpl 团队
6
+ tags:
7
+ - 开源
8
+ - SaaS
9
+ - Next.js
10
+ - 独立开发
11
+ ---
12
+
13
+ # [开源] NextDevTpl:一个面向独立开发者的 Next.js 全栈 SaaS 模板
14
+
15
+ 大家好,最近我把自己在多个项目里反复打磨的一套模板整理成了开源项目:`NextDevTpl`。
16
+ 目标很明确:它不是“能跑起来的 Demo”,而是“可以直接承接真实业务”的全栈模板。
17
+
18
+ ## 为什么做这个模板?
19
+
20
+ 做过几次从 0 到 1 的朋友应该都懂:最耗时间的往往不是业务本身,而是重复基建。
21
+
22
+ - 登录注册、权限和会话管理
23
+ - 支付订阅、Webhook、账单状态同步
24
+ - 积分扣减、发放、过期与流水
25
+ - 邮件通知、文件上传、用户工单
26
+ - 管理后台、日志监控、错误告警
27
+
28
+ 这些内容每次都要重做,不仅耗时,也容易在上线后暴露隐患。
29
+ 所以我把这些高频模块统一抽成一套可复用模板,尽量做到开箱即用、可持续扩展。
30
+
31
+ ## 技术栈(当前版本)
32
+
33
+ - **Next.js 16 + React 19 + TypeScript**
34
+ - **Tailwind CSS 4 + Shadcn/UI**
35
+ - **Drizzle ORM + PostgreSQL**
36
+ - **Better Auth(账号体系)**
37
+ - **next-intl(国际化)**
38
+ - **S3/R2 兼容对象存储**
39
+ - **Vitest + Biome 工程化支持**
40
+
41
+ ## 已内置能力(不是空壳)
42
+
43
+ ### 1) 用户与权限
44
+
45
+ - 邮箱注册/登录与 OAuth
46
+ - 会话管理与角色隔离(user/admin)
47
+
48
+ ### 2) 商业化能力
49
+
50
+ - 订阅支付流程
51
+ - Webhook 处理
52
+ - 积分账本与扣费逻辑
53
+
54
+ ### 3) 运营支持能力
55
+
56
+ - 邮件模板与发送
57
+ - 文件上传与管理
58
+ - 工单系统(用户侧 + 管理侧)
59
+ - 管理后台(用户管理、数据面板)
60
+
61
+ ### 4) 工程保障能力
62
+
63
+ - API 限流(可选)
64
+ - 结构化日志(可选)
65
+ - 错误监控(可选)
66
+ - 外部服务未配置时可自动降级,便于本地开发与调试
67
+
68
+ ## 适合谁使用?
69
+
70
+ - 想快速上线 MVP 的独立开发者
71
+ - 想统一技术底座的小团队
72
+ - 不想每次项目都从认证、支付、后台重复造轮子的开发者
73
+
74
+ ## 快速启动
75
+
76
+ ```bash
77
+ git clone git@github.com:evepupil/NextDevTpl.git
78
+ cd NextDevTpl
79
+ pnpm install
80
+ cp .env.example .env.local
81
+ pnpm db:push
82
+ pnpm dev
83
+ ```
84
+
85
+ ## 我希望它解决的问题
86
+
87
+ 我做这个项目的核心目标并不是“堆技术名词”,而是帮你把时间真正花在更重要的事情上:
88
+
89
+ 1. 业务闭环和核心价值
90
+ 2. 用户反馈与迭代效率
91
+ 3. 商业化验证与增长
92
+
93
+ ## 欢迎交流与共建
94
+
95
+ 如果你愿意试用,欢迎直接反馈真实问题:
96
+ 你最在意哪些模块?哪些地方还不够生产可用?你希望优先补齐什么能力?
97
+
98
+ 也欢迎提交 Issue / PR,一起把它打磨成真正可落地的生产级模板。欢迎在 linux.do 交流想法,我会持续迭代。
@@ -0,0 +1,65 @@
1
+ ---
2
+ title: Admin and Support
3
+ description: Manage users, roles, tickets, and customer support workflows.
4
+ ---
5
+
6
+ # Admin and Support
7
+
8
+ The template includes a simple but practical admin area and support ticket system.
9
+
10
+ ## Admin area
11
+
12
+ Admin routes live under:
13
+
14
+ ```txt
15
+ src/app/[locale]/(admin)/admin
16
+ ```
17
+
18
+ Main components:
19
+
20
+ | Path | Purpose |
21
+ | --- | --- |
22
+ | `src/features/admin/components/admin-sidebar.tsx` | Admin navigation |
23
+ | `src/app/[locale]/(admin)/admin/page.tsx` | Admin overview |
24
+ | `src/app/[locale]/(admin)/admin/users/page.tsx` | User management |
25
+ | `src/app/[locale]/(admin)/admin/tickets/page.tsx` | Ticket queue |
26
+ | `src/app/[locale]/(admin)/admin/tickets/[id]/page.tsx` | Ticket detail |
27
+
28
+ ## Support tickets
29
+
30
+ User ticket routes live under:
31
+
32
+ ```txt
33
+ src/app/[locale]/(dashboard)/dashboard/support
34
+ ```
35
+
36
+ Feature files:
37
+
38
+ | Path | Purpose |
39
+ | --- | --- |
40
+ | `src/features/support/actions/ticket.ts` | Ticket actions |
41
+ | `src/features/support/actions/admin-users.ts` | Admin user helpers |
42
+ | `src/features/support/components` | Ticket forms, replies, status controls |
43
+ | `src/features/support/schemas` | Validation schemas |
44
+ | `src/test/support` | Ticket and admin user tests |
45
+
46
+ ## Ticket lifecycle
47
+
48
+ Recommended status flow:
49
+
50
+ ```txt
51
+ open -> in_progress -> resolved
52
+ ```
53
+
54
+ Keep user-facing replies clear and avoid exposing internal logs or secrets.
55
+
56
+ ## Admin access
57
+
58
+ Admin access depends on the authenticated user's role. For local testing, create a user and set `role = 'admin'` in the database.
59
+
60
+ ## Tests
61
+
62
+ ```bash
63
+ pnpm test:run src/test/support
64
+ ```
65
+
@@ -0,0 +1,71 @@
1
+ ---
2
+ title: Authentication
3
+ description: Understand Better Auth integration, auth routes, roles, and protected pages.
4
+ ---
5
+
6
+ # Authentication
7
+
8
+ Authentication is built with Better Auth and integrated into the App Router, middleware, dashboard, and admin area.
9
+
10
+ ## Main files
11
+
12
+ | Path | Purpose |
13
+ | --- | --- |
14
+ | `src/lib/auth/api.ts` | Better Auth API configuration |
15
+ | `src/lib/auth/client.ts` | Client-side auth helpers |
16
+ | `src/lib/auth/server.ts` | Server-side session helpers |
17
+ | `src/lib/auth/edge.ts` | Middleware-safe auth checks and public route config |
18
+ | `src/lib/auth/admin.ts` | Admin-specific helpers |
19
+ | `src/app/api/auth/[...all]/route.ts` | Better Auth route handler |
20
+ | `src/features/auth/components` | Sign-in, sign-up, forgot-password UI |
21
+
22
+ ## Supported flows
23
+
24
+ | Flow | Notes |
25
+ | --- | --- |
26
+ | Email/password | Baseline local auth flow |
27
+ | GitHub OAuth | Requires GitHub OAuth app credentials |
28
+ | Google OAuth | Requires Google Cloud OAuth credentials |
29
+ | Password reset | Requires email delivery to send reset messages |
30
+ | Role-based access | `user` and `admin` roles are used by dashboard/admin protection |
31
+
32
+ ## Public and protected routes
33
+
34
+ The middleware/auth edge helpers decide which routes are public and which need a session. Public routes include marketing pages, auth pages, blog, legal pages, docs, and selected API endpoints.
35
+
36
+ Authenticated pages live under:
37
+
38
+ ```txt
39
+ src/app/[locale]/(dashboard)/dashboard
40
+ ```
41
+
42
+ Admin pages live under:
43
+
44
+ ```txt
45
+ src/app/[locale]/(admin)/admin
46
+ ```
47
+
48
+ ## Make yourself an admin
49
+
50
+ After creating a local user, update the user's role in the database:
51
+
52
+ ```sql
53
+ update "user"
54
+ set role = 'admin'
55
+ where email = 'you@example.com';
56
+ ```
57
+
58
+ Then visit:
59
+
60
+ ```txt
61
+ /en/admin
62
+ ```
63
+
64
+ ## Adding an OAuth provider
65
+
66
+ 1. Create credentials in the provider console.
67
+ 2. Add the provider credentials to `.env.local`.
68
+ 3. Register callback URLs that match `BETTER_AUTH_URL`.
69
+ 4. Update the auth UI if you want to expose a new provider button.
70
+ 5. Test sign-in locally before enabling it in production.
71
+
@@ -0,0 +1,53 @@
1
+ ---
2
+ title: Background Jobs
3
+ description: Run async product workflows with Inngest.
4
+ ---
5
+
6
+ # Background Jobs
7
+
8
+ Background jobs are powered by Inngest. Use jobs for workflows that should not block a request, such as credit expiration, delivery retries, email batching, or async product processing.
9
+
10
+ ## Main files
11
+
12
+ | Path | Purpose |
13
+ | --- | --- |
14
+ | `src/inngest/client.ts` | Inngest client |
15
+ | `src/inngest/functions.ts` | Function definitions |
16
+ | `src/inngest/index.ts` | Exports |
17
+ | `src/app/api/inngest/route.ts` | Inngest route handler |
18
+ | `src/app/api/jobs/credits/expire/route.ts` | Credit expiration job endpoint |
19
+ | `src/test/jobs/cron-expire.test.ts` | Job test coverage |
20
+
21
+ ## Local development
22
+
23
+ Start the app:
24
+
25
+ ```bash
26
+ pnpm dev
27
+ ```
28
+
29
+ Then use the Inngest dev server if you need to inspect or trigger functions locally.
30
+
31
+ ## Production variables
32
+
33
+ | Variable | Purpose |
34
+ | --- | --- |
35
+ | `INNGEST_EVENT_KEY` | Sends events to Inngest |
36
+ | `INNGEST_SIGNING_KEY` | Verifies requests from Inngest |
37
+
38
+ ## Job design rules
39
+
40
+ - Keep jobs idempotent.
41
+ - Store enough state to recover from retries.
42
+ - Do not grant credits or change subscription state twice for the same external event.
43
+ - Prefer small composable functions over one large workflow.
44
+ - Log job identifiers and external event IDs.
45
+
46
+ ## Testing
47
+
48
+ Run job tests after touching expiration logic:
49
+
50
+ ```bash
51
+ pnpm test:run src/test/jobs
52
+ ```
53
+
@@ -0,0 +1,71 @@
1
+ ---
2
+ title: Configuration
3
+ description: Configure the required and optional services used by NextDevTpl.
4
+ ---
5
+
6
+ # Configuration
7
+
8
+ Configuration is environment-variable driven. Start with the required variables, then enable optional services as needed.
9
+
10
+ ## Required for local boot
11
+
12
+ | Variable | Purpose |
13
+ | --- | --- |
14
+ | `DATABASE_URL` | PostgreSQL connection string used by Drizzle and Better Auth |
15
+ | `BETTER_AUTH_SECRET` | Secret used to sign auth/session data |
16
+ | `BETTER_AUTH_URL` | Base URL for Better Auth callbacks and cookies |
17
+
18
+ Example:
19
+
20
+ ```bash
21
+ DATABASE_URL="postgresql://postgres:password@localhost:5432/nextdevtpl"
22
+ BETTER_AUTH_SECRET="replace-with-a-random-secret"
23
+ BETTER_AUTH_URL="http://localhost:3000"
24
+ ```
25
+
26
+ ## Recommended during development
27
+
28
+ | Service | Variables | Notes |
29
+ | --- | --- | --- |
30
+ | GitHub OAuth | `GITHUB_CLIENT_ID`, `GITHUB_CLIENT_SECRET` | Callback: `/api/auth/callback/github` |
31
+ | Google OAuth | `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET` | Callback: `/api/auth/callback/google` |
32
+ | Resend | `RESEND_API_KEY`, `EMAIL_FROM` | Enables real email verification and reset emails |
33
+
34
+ If email is not configured, test authentication flows that do not require delivery first.
35
+
36
+ ## Optional product services
37
+
38
+ | Service | Variables | Used by |
39
+ | --- | --- | --- |
40
+ | Creem | `CREEM_API_KEY`, `CREEM_WEBHOOK_SECRET` | Subscription checkout, credit purchases, webhooks |
41
+ | S3/R2 | `STORAGE_ENDPOINT`, `STORAGE_REGION`, `STORAGE_BUCKET`, `STORAGE_ACCESS_KEY_ID`, `STORAGE_SECRET_ACCESS_KEY` | File uploads and proxy routes |
42
+ | Upstash Redis | `UPSTASH_REDIS_REST_URL`, `UPSTASH_REDIS_REST_TOKEN` | API and anonymous rate limiting |
43
+ | Axiom | `AXIOM_TOKEN`, `AXIOM_DATASET` | Structured cloud logs |
44
+ | Sentry | `NEXT_PUBLIC_SENTRY_DSN`, `SENTRY_AUTH_TOKEN` | Error capture and release uploads |
45
+ | OpenAI-compatible AI | `OPENAI_API_KEY`, provider-specific base URL/model vars if configured | AI abstraction in `src/lib/ai` |
46
+ | Inngest | `INNGEST_EVENT_KEY`, `INNGEST_SIGNING_KEY` | Background jobs in production |
47
+
48
+ ## Degradation model
49
+
50
+ Optional services should not block a basic local boot. The intended behavior is:
51
+
52
+ | Missing service | Expected behavior |
53
+ | --- | --- |
54
+ | Redis | Rate limiter falls back instead of crashing |
55
+ | Axiom | Logger writes locally |
56
+ | Sentry | Monitoring hooks become no-op or console-only |
57
+ | Storage | Upload flows are unavailable, app shell still runs |
58
+ | Creem | Payment flows are unavailable, non-payment pages still run |
59
+ | Inngest keys | Local development can run without production signing keys |
60
+
61
+ ## Where configuration lives
62
+
63
+ | Path | What to edit |
64
+ | --- | --- |
65
+ | `src/config/site.ts` | Site name, URL, metadata, social links |
66
+ | `src/config/nav.ts` | Header, footer, dashboard, and admin navigation |
67
+ | `src/config/payment.ts` | Payment product and checkout configuration |
68
+ | `src/config/subscription-plan.ts` | Plan limits and pricing display |
69
+ | `messages/*.json` | UI copy |
70
+ | `.env.local` | Local secrets and service credentials |
71
+
@@ -0,0 +1,69 @@
1
+ ---
2
+ title: Credits
3
+ description: Understand the built-in credit system, ledger entries, and expiration model.
4
+ ---
5
+
6
+ # Credits
7
+
8
+ The credits module is one of the main product primitives in NextDevTpl. It is designed for AI tools, usage-based SaaS products, paid exports, and other metered features.
9
+
10
+ ## Main files
11
+
12
+ | Path | Purpose |
13
+ | --- | --- |
14
+ | `src/features/credits/core.ts` | Core balance and transaction logic |
15
+ | `src/features/credits/actions.ts` | Server Actions for credit operations |
16
+ | `src/features/credits/config.ts` | Credit packages and display config |
17
+ | `src/features/credits/components` | Balance, usage, purchase, and history UI |
18
+ | `src/app/[locale]/(dashboard)/dashboard/credits/buy` | Credit purchase page |
19
+ | `src/test/credits` | Credit integrity and purchase tests |
20
+
21
+ ## Concepts
22
+
23
+ | Concept | Meaning |
24
+ | --- | --- |
25
+ | Balance | Current spendable credits for a user |
26
+ | Transaction | A recorded credit movement |
27
+ | Batch | Credits granted together with shared expiration metadata |
28
+ | FIFO expiration | Older credits are consumed before newer credits |
29
+ | Purchase package | A configured one-time purchase amount |
30
+
31
+ ## Typical flows
32
+
33
+ ### Purchase credits
34
+
35
+ 1. User opens `/dashboard/credits/buy`.
36
+ 2. User selects a package.
37
+ 3. The app creates a checkout through the payment layer.
38
+ 4. The webhook confirms payment.
39
+ 5. Credits are granted to the user.
40
+ 6. Transaction history reflects the purchase.
41
+
42
+ ### Spend credits
43
+
44
+ Feature code should use the credits core instead of manually decrementing a number. This keeps transactions auditable and preserves expiration rules.
45
+
46
+ ### Expire credits
47
+
48
+ Expiration is handled by batch metadata and background jobs. See [Background Jobs](/en/docs/background-jobs) for the job route and Inngest integration.
49
+
50
+ ## Customizing packages
51
+
52
+ Edit:
53
+
54
+ ```txt
55
+ src/features/credits/config.ts
56
+ ```
57
+
58
+ Keep package IDs stable once they are used in payment or audit records.
59
+
60
+ ## Testing
61
+
62
+ Run focused tests when touching credits:
63
+
64
+ ```bash
65
+ pnpm test:run src/test/credits
66
+ ```
67
+
68
+ Always preserve transaction integrity. Bugs in credits are financial/accounting bugs, not only UI bugs.
69
+