virastack 0.0.1 → 1.0.1

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 (447) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +94 -18
  3. package/bin/virastack.js +7 -0
  4. package/package.json +43 -9
  5. package/src/commands/add.js +64 -0
  6. package/src/commands/init.js +286 -0
  7. package/src/i18n.js +231 -0
  8. package/src/index.js +64 -0
  9. package/src/utils/args.js +60 -0
  10. package/src/utils/copy-template.js +81 -0
  11. package/src/utils/exec.js +29 -0
  12. package/src/utils/git.js +38 -0
  13. package/src/utils/is-online.js +14 -0
  14. package/src/utils/package-info.js +12 -0
  15. package/src/utils/package-manager.js +33 -0
  16. package/src/utils/setup-env.js +25 -0
  17. package/src/utils/telemetry.js +86 -0
  18. package/src/utils/tools.js +48 -0
  19. package/src/utils/update-package-json.js +44 -0
  20. package/src/utils/update-readme.js +25 -0
  21. package/src/utils/validate-project-name.js +26 -0
  22. package/templates/nextjs/.changeset/README.md +8 -0
  23. package/templates/nextjs/.changeset/config.json +11 -0
  24. package/templates/nextjs/.env.example +6 -0
  25. package/templates/nextjs/.env.local +6 -0
  26. package/templates/nextjs/.eslintcache +1 -0
  27. package/templates/nextjs/.github/workflows/ci.yml +41 -0
  28. package/templates/nextjs/.husky/commit-msg +1 -0
  29. package/templates/nextjs/.husky/pre-commit +1 -0
  30. package/templates/nextjs/.husky/pre-push +1 -0
  31. package/templates/nextjs/.prettierignore +6 -0
  32. package/templates/nextjs/.prettierrc +42 -0
  33. package/templates/nextjs/.vscode/extensions.json +7 -0
  34. package/templates/nextjs/.vscode/settings.json +20 -0
  35. package/templates/nextjs/LICENSE +21 -0
  36. package/templates/nextjs/README.md +202 -0
  37. package/templates/nextjs/_gitignore +45 -0
  38. package/templates/nextjs/commitlint.config.js +6 -0
  39. package/templates/nextjs/eslint.config.mjs +27 -0
  40. package/templates/nextjs/knip.config.js +25 -0
  41. package/templates/nextjs/next-env.d.ts +6 -0
  42. package/templates/nextjs/next.config.ts +39 -0
  43. package/templates/nextjs/package.json +115 -0
  44. package/templates/nextjs/pnpm-lock.yaml +6467 -0
  45. package/templates/nextjs/pnpm-workspace.yaml +3 -0
  46. package/templates/nextjs/postcss.config.mjs +7 -0
  47. package/templates/nextjs/public/favicon.ico +0 -0
  48. package/templates/nextjs/public/llms.txt +96 -0
  49. package/templates/nextjs/public/logo.png +0 -0
  50. package/templates/nextjs/public/logo.webp +0 -0
  51. package/templates/nextjs/public/og.png +0 -0
  52. package/templates/nextjs/src/app/error.tsx +34 -0
  53. package/templates/nextjs/src/app/favicon.ico +0 -0
  54. package/templates/nextjs/src/app/global-error.tsx +32 -0
  55. package/templates/nextjs/src/app/layout.tsx +37 -0
  56. package/templates/nextjs/src/app/loading.tsx +12 -0
  57. package/templates/nextjs/src/app/manifest.ts +22 -0
  58. package/templates/nextjs/src/app/not-found.tsx +18 -0
  59. package/templates/nextjs/src/app/page.tsx +5 -0
  60. package/templates/nextjs/src/app/robots.ts +13 -0
  61. package/templates/nextjs/src/app/sitemap.ts +14 -0
  62. package/templates/nextjs/src/components/shared/ThemeToggle.tsx +30 -0
  63. package/templates/nextjs/src/components/ui/avatar.tsx +54 -0
  64. package/templates/nextjs/src/components/ui/button.tsx +46 -0
  65. package/templates/nextjs/src/components/ui/dialog.tsx +107 -0
  66. package/templates/nextjs/src/components/ui/field.tsx +24 -0
  67. package/templates/nextjs/src/components/ui/index.ts +27 -0
  68. package/templates/nextjs/src/components/ui/input.tsx +23 -0
  69. package/templates/nextjs/src/components/ui/label.tsx +17 -0
  70. package/templates/nextjs/src/components/ui/skeleton.tsx +13 -0
  71. package/templates/nextjs/src/components/ui/table.tsx +94 -0
  72. package/templates/nextjs/src/components/ui/tabs.tsx +46 -0
  73. package/templates/nextjs/src/config/seo.config.ts +37 -0
  74. package/templates/nextjs/src/config/site.config.ts +15 -0
  75. package/templates/nextjs/src/constants/index.ts +5 -0
  76. package/templates/nextjs/src/env.ts +41 -0
  77. package/templates/nextjs/src/features/landing/api/get-users.api.ts +7 -0
  78. package/templates/nextjs/src/features/landing/api/index.ts +2 -0
  79. package/templates/nextjs/src/features/landing/api/query-keys.ts +7 -0
  80. package/templates/nextjs/src/features/landing/components/CartDemo.tsx +66 -0
  81. package/templates/nextjs/src/features/landing/components/Features.tsx +39 -0
  82. package/templates/nextjs/src/features/landing/components/Hero.tsx +65 -0
  83. package/templates/nextjs/src/features/landing/components/LandingPage.tsx +17 -0
  84. package/templates/nextjs/src/features/landing/components/ProjectFormDemo.tsx +62 -0
  85. package/templates/nextjs/src/features/landing/components/Reveal.tsx +83 -0
  86. package/templates/nextjs/src/features/landing/components/Showcase.tsx +66 -0
  87. package/templates/nextjs/src/features/landing/components/UsersDemo.tsx +188 -0
  88. package/templates/nextjs/src/features/landing/data/features.data.tsx +47 -0
  89. package/templates/nextjs/src/features/landing/data/index.ts +1 -0
  90. package/templates/nextjs/src/features/landing/helpers/get-initials.ts +15 -0
  91. package/templates/nextjs/src/features/landing/helpers/index.ts +7 -0
  92. package/templates/nextjs/src/features/landing/helpers/motion.ts +21 -0
  93. package/templates/nextjs/src/features/landing/hooks/index.ts +1 -0
  94. package/templates/nextjs/src/features/landing/hooks/use-users.ts +16 -0
  95. package/templates/nextjs/src/features/landing/icons/index.ts +6 -0
  96. package/templates/nextjs/src/features/landing/icons/nextjs.tsx +68 -0
  97. package/templates/nextjs/src/features/landing/icons/react-hook-form.tsx +18 -0
  98. package/templates/nextjs/src/features/landing/icons/react.tsx +20 -0
  99. package/templates/nextjs/src/features/landing/icons/tailwind.tsx +14 -0
  100. package/templates/nextjs/src/features/landing/icons/tanstack.tsx +321 -0
  101. package/templates/nextjs/src/features/landing/icons/typescript.tsx +16 -0
  102. package/templates/nextjs/src/features/landing/index.ts +1 -0
  103. package/templates/nextjs/src/features/landing/schemas/index.ts +1 -0
  104. package/templates/nextjs/src/features/landing/schemas/project.schema.ts +7 -0
  105. package/templates/nextjs/src/features/landing/stores/counter.store.ts +18 -0
  106. package/templates/nextjs/src/features/landing/stores/index.ts +1 -0
  107. package/templates/nextjs/src/features/landing/types/index.ts +1 -0
  108. package/templates/nextjs/src/features/landing/types/user.types.ts +9 -0
  109. package/templates/nextjs/src/helpers/format-date.ts +13 -0
  110. package/templates/nextjs/src/helpers/index.ts +1 -0
  111. package/templates/nextjs/src/hooks/index.ts +5 -0
  112. package/templates/nextjs/src/lib/api.ts +97 -0
  113. package/templates/nextjs/src/lib/query-client.ts +18 -0
  114. package/templates/nextjs/src/lib/utils.ts +12 -0
  115. package/templates/nextjs/src/providers/Providers.tsx +15 -0
  116. package/templates/nextjs/src/providers/QueryProvider.tsx +19 -0
  117. package/templates/nextjs/src/providers/ThemeProvider.tsx +9 -0
  118. package/templates/nextjs/src/providers/index.ts +1 -0
  119. package/templates/nextjs/src/proxy.ts +6 -0
  120. package/templates/nextjs/src/schemas/index.ts +5 -0
  121. package/templates/nextjs/src/stores/index.ts +5 -0
  122. package/templates/nextjs/src/styles/tailwind.css +122 -0
  123. package/templates/nextjs/src/types/site-config.types.ts +10 -0
  124. package/templates/nextjs/tsconfig.json +45 -0
  125. package/templates/nextjs/tsconfig.tsbuildinfo +1 -0
  126. package/templates/tanstack/.changeset/README.md +8 -0
  127. package/templates/tanstack/.changeset/config.json +11 -0
  128. package/templates/tanstack/.env.example +6 -0
  129. package/templates/tanstack/.env.local +6 -0
  130. package/templates/tanstack/.eslintcache +1 -0
  131. package/templates/tanstack/.github/workflows/ci.yml +41 -0
  132. package/templates/tanstack/.husky/commit-msg +1 -0
  133. package/templates/tanstack/.husky/pre-commit +1 -0
  134. package/templates/tanstack/.husky/pre-push +1 -0
  135. package/templates/tanstack/.prettierignore +7 -0
  136. package/templates/tanstack/.prettierrc +41 -0
  137. package/templates/tanstack/.vscode/extensions.json +7 -0
  138. package/templates/tanstack/.vscode/settings.json +22 -0
  139. package/templates/tanstack/LICENSE +21 -0
  140. package/templates/tanstack/README.md +204 -0
  141. package/templates/tanstack/_gitignore +52 -0
  142. package/templates/tanstack/commitlint.config.js +6 -0
  143. package/templates/tanstack/eslint.config.js +28 -0
  144. package/templates/tanstack/knip.config.js +22 -0
  145. package/templates/tanstack/package.json +130 -0
  146. package/templates/tanstack/pnpm-lock.yaml +5835 -0
  147. package/templates/tanstack/pnpm-workspace.yaml +3 -0
  148. package/templates/tanstack/public/favicon.ico +0 -0
  149. package/templates/tanstack/public/llms.txt +86 -0
  150. package/templates/tanstack/public/logo.png +0 -0
  151. package/templates/tanstack/public/logo.webp +0 -0
  152. package/templates/tanstack/public/og.png +0 -0
  153. package/templates/tanstack/src/components/shared/DefaultCatchBoundary.tsx +36 -0
  154. package/templates/tanstack/src/components/shared/NotFound.tsx +18 -0
  155. package/templates/tanstack/src/components/shared/Pending.tsx +13 -0
  156. package/templates/tanstack/src/components/shared/ThemeToggle.tsx +31 -0
  157. package/templates/tanstack/src/components/ui/avatar.tsx +52 -0
  158. package/templates/tanstack/src/components/ui/button.tsx +47 -0
  159. package/templates/tanstack/src/components/ui/dialog.tsx +107 -0
  160. package/templates/tanstack/src/components/ui/field.tsx +24 -0
  161. package/templates/tanstack/src/components/ui/index.ts +27 -0
  162. package/templates/tanstack/src/components/ui/input.tsx +23 -0
  163. package/templates/tanstack/src/components/ui/label.tsx +17 -0
  164. package/templates/tanstack/src/components/ui/skeleton.tsx +13 -0
  165. package/templates/tanstack/src/components/ui/table.tsx +94 -0
  166. package/templates/tanstack/src/components/ui/tabs.tsx +46 -0
  167. package/templates/tanstack/src/config/seo.config.ts +52 -0
  168. package/templates/tanstack/src/config/site.config.ts +15 -0
  169. package/templates/tanstack/src/constants/index.ts +5 -0
  170. package/templates/tanstack/src/env.ts +47 -0
  171. package/templates/tanstack/src/features/landing/api/get-users.api.ts +7 -0
  172. package/templates/tanstack/src/features/landing/api/index.ts +2 -0
  173. package/templates/tanstack/src/features/landing/api/query-keys.ts +7 -0
  174. package/templates/tanstack/src/features/landing/components/CartDemo.tsx +66 -0
  175. package/templates/tanstack/src/features/landing/components/Features.tsx +39 -0
  176. package/templates/tanstack/src/features/landing/components/Hero.tsx +63 -0
  177. package/templates/tanstack/src/features/landing/components/LandingPage.tsx +17 -0
  178. package/templates/tanstack/src/features/landing/components/ProjectFormDemo.tsx +63 -0
  179. package/templates/tanstack/src/features/landing/components/Reveal.tsx +83 -0
  180. package/templates/tanstack/src/features/landing/components/Showcase.tsx +66 -0
  181. package/templates/tanstack/src/features/landing/components/UsersDemo.tsx +191 -0
  182. package/templates/tanstack/src/features/landing/data/features.data.tsx +45 -0
  183. package/templates/tanstack/src/features/landing/data/index.ts +1 -0
  184. package/templates/tanstack/src/features/landing/helpers/get-initials.ts +15 -0
  185. package/templates/tanstack/src/features/landing/helpers/index.ts +7 -0
  186. package/templates/tanstack/src/features/landing/helpers/motion.ts +21 -0
  187. package/templates/tanstack/src/features/landing/hooks/index.ts +1 -0
  188. package/templates/tanstack/src/features/landing/hooks/use-users.ts +19 -0
  189. package/templates/tanstack/src/features/landing/icons/index.ts +5 -0
  190. package/templates/tanstack/src/features/landing/icons/react-hook-form.tsx +18 -0
  191. package/templates/tanstack/src/features/landing/icons/react.tsx +20 -0
  192. package/templates/tanstack/src/features/landing/icons/tailwind.tsx +14 -0
  193. package/templates/tanstack/src/features/landing/icons/tanstack.tsx +321 -0
  194. package/templates/tanstack/src/features/landing/icons/typescript.tsx +16 -0
  195. package/templates/tanstack/src/features/landing/index.ts +1 -0
  196. package/templates/tanstack/src/features/landing/schemas/index.ts +1 -0
  197. package/templates/tanstack/src/features/landing/schemas/project.schema.ts +7 -0
  198. package/templates/tanstack/src/features/landing/stores/counter.store.ts +18 -0
  199. package/templates/tanstack/src/features/landing/stores/index.ts +1 -0
  200. package/templates/tanstack/src/features/landing/types/index.ts +1 -0
  201. package/templates/tanstack/src/features/landing/types/user.types.ts +9 -0
  202. package/templates/tanstack/src/helpers/format-date.ts +13 -0
  203. package/templates/tanstack/src/helpers/index.ts +1 -0
  204. package/templates/tanstack/src/hooks/index.ts +5 -0
  205. package/templates/tanstack/src/lib/api.ts +97 -0
  206. package/templates/tanstack/src/lib/query-client.ts +18 -0
  207. package/templates/tanstack/src/lib/utils.ts +13 -0
  208. package/templates/tanstack/src/providers/Providers.tsx +12 -0
  209. package/templates/tanstack/src/providers/ThemeProvider.tsx +98 -0
  210. package/templates/tanstack/src/providers/devtools.tsx +6 -0
  211. package/templates/tanstack/src/providers/index.ts +1 -0
  212. package/templates/tanstack/src/providers/root-provider.ts +9 -0
  213. package/templates/tanstack/src/routeTree.gen.ts +123 -0
  214. package/templates/tanstack/src/router.tsx +27 -0
  215. package/templates/tanstack/src/routes/__root.tsx +78 -0
  216. package/templates/tanstack/src/routes/index.tsx +13 -0
  217. package/templates/tanstack/src/routes/robots[.]txt.ts +21 -0
  218. package/templates/tanstack/src/routes/site[.]webmanifest.ts +32 -0
  219. package/templates/tanstack/src/routes/sitemap[.]xml.ts +27 -0
  220. package/templates/tanstack/src/schemas/index.ts +5 -0
  221. package/templates/tanstack/src/start.ts +20 -0
  222. package/templates/tanstack/src/stores/index.ts +5 -0
  223. package/templates/tanstack/src/styles/tailwind.css +123 -0
  224. package/templates/tanstack/src/types/site-config.types.ts +10 -0
  225. package/templates/tanstack/tsconfig.json +25 -0
  226. package/templates/tanstack/tsr.config.json +3 -0
  227. package/templates/tanstack/vite.config.ts +12 -0
  228. package/templates-i18n/nextjs/.changeset/README.md +8 -0
  229. package/templates-i18n/nextjs/.changeset/config.json +11 -0
  230. package/templates-i18n/nextjs/.env.example +6 -0
  231. package/templates-i18n/nextjs/.eslintcache +1 -0
  232. package/templates-i18n/nextjs/.github/workflows/ci.yml +41 -0
  233. package/templates-i18n/nextjs/.husky/commit-msg +1 -0
  234. package/templates-i18n/nextjs/.husky/pre-commit +1 -0
  235. package/templates-i18n/nextjs/.husky/pre-push +1 -0
  236. package/templates-i18n/nextjs/.prettierignore +6 -0
  237. package/templates-i18n/nextjs/.prettierrc +42 -0
  238. package/templates-i18n/nextjs/.vscode/extensions.json +7 -0
  239. package/templates-i18n/nextjs/.vscode/settings.json +20 -0
  240. package/templates-i18n/nextjs/LICENSE +21 -0
  241. package/templates-i18n/nextjs/README.md +202 -0
  242. package/templates-i18n/nextjs/_gitignore +45 -0
  243. package/templates-i18n/nextjs/commitlint.config.js +6 -0
  244. package/templates-i18n/nextjs/eslint.config.mjs +27 -0
  245. package/templates-i18n/nextjs/knip.config.js +29 -0
  246. package/templates-i18n/nextjs/next-env.d.ts +6 -0
  247. package/templates-i18n/nextjs/next.config.ts +42 -0
  248. package/templates-i18n/nextjs/package.json +117 -0
  249. package/templates-i18n/nextjs/pnpm-lock.yaml +6854 -0
  250. package/templates-i18n/nextjs/pnpm-workspace.yaml +3 -0
  251. package/templates-i18n/nextjs/postcss.config.mjs +7 -0
  252. package/templates-i18n/nextjs/public/favicon.ico +0 -0
  253. package/templates-i18n/nextjs/public/llms.txt +96 -0
  254. package/templates-i18n/nextjs/public/logo.png +0 -0
  255. package/templates-i18n/nextjs/public/logo.webp +0 -0
  256. package/templates-i18n/nextjs/public/og.png +0 -0
  257. package/templates-i18n/nextjs/src/app/[locale]/error.tsx +34 -0
  258. package/templates-i18n/nextjs/src/app/[locale]/layout.tsx +60 -0
  259. package/templates-i18n/nextjs/src/app/[locale]/loading.tsx +12 -0
  260. package/templates-i18n/nextjs/src/app/[locale]/not-found.tsx +18 -0
  261. package/templates-i18n/nextjs/src/app/[locale]/page.tsx +10 -0
  262. package/templates-i18n/nextjs/src/app/favicon.ico +0 -0
  263. package/templates-i18n/nextjs/src/app/global-error.tsx +32 -0
  264. package/templates-i18n/nextjs/src/app/manifest.ts +22 -0
  265. package/templates-i18n/nextjs/src/app/robots.ts +13 -0
  266. package/templates-i18n/nextjs/src/app/sitemap.ts +14 -0
  267. package/templates-i18n/nextjs/src/components/shared/LanguageSwitcher.tsx +48 -0
  268. package/templates-i18n/nextjs/src/components/shared/ThemeToggle.tsx +30 -0
  269. package/templates-i18n/nextjs/src/components/ui/avatar.tsx +54 -0
  270. package/templates-i18n/nextjs/src/components/ui/button.tsx +46 -0
  271. package/templates-i18n/nextjs/src/components/ui/dialog.tsx +107 -0
  272. package/templates-i18n/nextjs/src/components/ui/field.tsx +24 -0
  273. package/templates-i18n/nextjs/src/components/ui/index.ts +27 -0
  274. package/templates-i18n/nextjs/src/components/ui/input.tsx +23 -0
  275. package/templates-i18n/nextjs/src/components/ui/label.tsx +17 -0
  276. package/templates-i18n/nextjs/src/components/ui/skeleton.tsx +13 -0
  277. package/templates-i18n/nextjs/src/components/ui/table.tsx +94 -0
  278. package/templates-i18n/nextjs/src/components/ui/tabs.tsx +46 -0
  279. package/templates-i18n/nextjs/src/config/seo.config.ts +37 -0
  280. package/templates-i18n/nextjs/src/config/site.config.ts +15 -0
  281. package/templates-i18n/nextjs/src/constants/index.ts +5 -0
  282. package/templates-i18n/nextjs/src/env.ts +41 -0
  283. package/templates-i18n/nextjs/src/features/landing/api/get-users.api.ts +7 -0
  284. package/templates-i18n/nextjs/src/features/landing/api/index.ts +2 -0
  285. package/templates-i18n/nextjs/src/features/landing/api/query-keys.ts +7 -0
  286. package/templates-i18n/nextjs/src/features/landing/components/CartDemo.tsx +68 -0
  287. package/templates-i18n/nextjs/src/features/landing/components/Features.tsx +84 -0
  288. package/templates-i18n/nextjs/src/features/landing/components/Hero.tsx +76 -0
  289. package/templates-i18n/nextjs/src/features/landing/components/LandingPage.tsx +17 -0
  290. package/templates-i18n/nextjs/src/features/landing/components/ProjectFormDemo.tsx +64 -0
  291. package/templates-i18n/nextjs/src/features/landing/components/Reveal.tsx +83 -0
  292. package/templates-i18n/nextjs/src/features/landing/components/Showcase.tsx +83 -0
  293. package/templates-i18n/nextjs/src/features/landing/components/UsersDemo.tsx +191 -0
  294. package/templates-i18n/nextjs/src/features/landing/data/features.data.tsx +47 -0
  295. package/templates-i18n/nextjs/src/features/landing/data/index.ts +1 -0
  296. package/templates-i18n/nextjs/src/features/landing/helpers/get-initials.ts +15 -0
  297. package/templates-i18n/nextjs/src/features/landing/helpers/index.ts +7 -0
  298. package/templates-i18n/nextjs/src/features/landing/helpers/motion.ts +21 -0
  299. package/templates-i18n/nextjs/src/features/landing/hooks/index.ts +1 -0
  300. package/templates-i18n/nextjs/src/features/landing/hooks/use-users.ts +16 -0
  301. package/templates-i18n/nextjs/src/features/landing/icons/index.ts +6 -0
  302. package/templates-i18n/nextjs/src/features/landing/icons/nextjs.tsx +68 -0
  303. package/templates-i18n/nextjs/src/features/landing/icons/react-hook-form.tsx +18 -0
  304. package/templates-i18n/nextjs/src/features/landing/icons/react.tsx +20 -0
  305. package/templates-i18n/nextjs/src/features/landing/icons/tailwind.tsx +14 -0
  306. package/templates-i18n/nextjs/src/features/landing/icons/tanstack.tsx +321 -0
  307. package/templates-i18n/nextjs/src/features/landing/icons/typescript.tsx +16 -0
  308. package/templates-i18n/nextjs/src/features/landing/index.ts +1 -0
  309. package/templates-i18n/nextjs/src/features/landing/schemas/index.ts +1 -0
  310. package/templates-i18n/nextjs/src/features/landing/schemas/project.schema.ts +9 -0
  311. package/templates-i18n/nextjs/src/features/landing/stores/counter.store.ts +18 -0
  312. package/templates-i18n/nextjs/src/features/landing/stores/index.ts +1 -0
  313. package/templates-i18n/nextjs/src/features/landing/types/index.ts +1 -0
  314. package/templates-i18n/nextjs/src/features/landing/types/user.types.ts +9 -0
  315. package/templates-i18n/nextjs/src/helpers/format-date.ts +13 -0
  316. package/templates-i18n/nextjs/src/helpers/index.ts +1 -0
  317. package/templates-i18n/nextjs/src/hooks/index.ts +5 -0
  318. package/templates-i18n/nextjs/src/i18n/request.ts +16 -0
  319. package/templates-i18n/nextjs/src/i18n/routing.ts +11 -0
  320. package/templates-i18n/nextjs/src/lib/api.ts +97 -0
  321. package/templates-i18n/nextjs/src/lib/query-client.ts +18 -0
  322. package/templates-i18n/nextjs/src/lib/utils.ts +12 -0
  323. package/templates-i18n/nextjs/src/messages/en.json +55 -0
  324. package/templates-i18n/nextjs/src/messages/tr.json +55 -0
  325. package/templates-i18n/nextjs/src/providers/Providers.tsx +15 -0
  326. package/templates-i18n/nextjs/src/providers/QueryProvider.tsx +19 -0
  327. package/templates-i18n/nextjs/src/providers/ThemeProvider.tsx +9 -0
  328. package/templates-i18n/nextjs/src/providers/index.ts +1 -0
  329. package/templates-i18n/nextjs/src/proxy.ts +16 -0
  330. package/templates-i18n/nextjs/src/schemas/index.ts +5 -0
  331. package/templates-i18n/nextjs/src/stores/index.ts +5 -0
  332. package/templates-i18n/nextjs/src/styles/tailwind.css +122 -0
  333. package/templates-i18n/nextjs/src/types/site-config.types.ts +10 -0
  334. package/templates-i18n/nextjs/tsconfig.json +45 -0
  335. package/templates-i18n/nextjs/tsconfig.tsbuildinfo +1 -0
  336. package/templates-i18n/tanstack/.changeset/README.md +8 -0
  337. package/templates-i18n/tanstack/.changeset/config.json +11 -0
  338. package/templates-i18n/tanstack/.env.example +6 -0
  339. package/templates-i18n/tanstack/.eslintcache +1 -0
  340. package/templates-i18n/tanstack/.github/workflows/ci.yml +41 -0
  341. package/templates-i18n/tanstack/.husky/commit-msg +1 -0
  342. package/templates-i18n/tanstack/.husky/pre-commit +1 -0
  343. package/templates-i18n/tanstack/.husky/pre-push +1 -0
  344. package/templates-i18n/tanstack/.prettierignore +7 -0
  345. package/templates-i18n/tanstack/.prettierrc +41 -0
  346. package/templates-i18n/tanstack/.vscode/extensions.json +7 -0
  347. package/templates-i18n/tanstack/.vscode/settings.json +22 -0
  348. package/templates-i18n/tanstack/LICENSE +21 -0
  349. package/templates-i18n/tanstack/README.md +204 -0
  350. package/templates-i18n/tanstack/_gitignore +52 -0
  351. package/templates-i18n/tanstack/commitlint.config.js +6 -0
  352. package/templates-i18n/tanstack/eslint.config.js +29 -0
  353. package/templates-i18n/tanstack/knip.config.js +26 -0
  354. package/templates-i18n/tanstack/messages/en.json +65 -0
  355. package/templates-i18n/tanstack/messages/tr.json +65 -0
  356. package/templates-i18n/tanstack/package.json +132 -0
  357. package/templates-i18n/tanstack/pnpm-lock.yaml +5998 -0
  358. package/templates-i18n/tanstack/pnpm-workspace.yaml +3 -0
  359. package/templates-i18n/tanstack/project.inlang/README.md +157 -0
  360. package/templates-i18n/tanstack/project.inlang/settings.json +9 -0
  361. package/templates-i18n/tanstack/public/favicon.ico +0 -0
  362. package/templates-i18n/tanstack/public/llms.txt +86 -0
  363. package/templates-i18n/tanstack/public/logo.png +0 -0
  364. package/templates-i18n/tanstack/public/logo.webp +0 -0
  365. package/templates-i18n/tanstack/public/og.png +0 -0
  366. package/templates-i18n/tanstack/src/components/shared/DefaultCatchBoundary.tsx +36 -0
  367. package/templates-i18n/tanstack/src/components/shared/LanguageSwitcher.tsx +57 -0
  368. package/templates-i18n/tanstack/src/components/shared/NotFound.tsx +18 -0
  369. package/templates-i18n/tanstack/src/components/shared/Pending.tsx +13 -0
  370. package/templates-i18n/tanstack/src/components/shared/ThemeToggle.tsx +31 -0
  371. package/templates-i18n/tanstack/src/components/ui/avatar.tsx +52 -0
  372. package/templates-i18n/tanstack/src/components/ui/button.tsx +47 -0
  373. package/templates-i18n/tanstack/src/components/ui/dialog.tsx +107 -0
  374. package/templates-i18n/tanstack/src/components/ui/field.tsx +24 -0
  375. package/templates-i18n/tanstack/src/components/ui/index.ts +27 -0
  376. package/templates-i18n/tanstack/src/components/ui/input.tsx +23 -0
  377. package/templates-i18n/tanstack/src/components/ui/label.tsx +17 -0
  378. package/templates-i18n/tanstack/src/components/ui/skeleton.tsx +13 -0
  379. package/templates-i18n/tanstack/src/components/ui/table.tsx +94 -0
  380. package/templates-i18n/tanstack/src/components/ui/tabs.tsx +46 -0
  381. package/templates-i18n/tanstack/src/config/seo.config.ts +52 -0
  382. package/templates-i18n/tanstack/src/config/site.config.ts +15 -0
  383. package/templates-i18n/tanstack/src/constants/index.ts +5 -0
  384. package/templates-i18n/tanstack/src/env.ts +47 -0
  385. package/templates-i18n/tanstack/src/features/landing/api/get-users.api.ts +7 -0
  386. package/templates-i18n/tanstack/src/features/landing/api/index.ts +2 -0
  387. package/templates-i18n/tanstack/src/features/landing/api/query-keys.ts +7 -0
  388. package/templates-i18n/tanstack/src/features/landing/components/CartDemo.tsx +67 -0
  389. package/templates-i18n/tanstack/src/features/landing/components/Features.tsx +79 -0
  390. package/templates-i18n/tanstack/src/features/landing/components/Hero.tsx +68 -0
  391. package/templates-i18n/tanstack/src/features/landing/components/LandingPage.tsx +17 -0
  392. package/templates-i18n/tanstack/src/features/landing/components/ProjectFormDemo.tsx +64 -0
  393. package/templates-i18n/tanstack/src/features/landing/components/Reveal.tsx +83 -0
  394. package/templates-i18n/tanstack/src/features/landing/components/Showcase.tsx +81 -0
  395. package/templates-i18n/tanstack/src/features/landing/components/UsersDemo.tsx +191 -0
  396. package/templates-i18n/tanstack/src/features/landing/data/features.data.tsx +45 -0
  397. package/templates-i18n/tanstack/src/features/landing/data/index.ts +1 -0
  398. package/templates-i18n/tanstack/src/features/landing/helpers/get-initials.ts +15 -0
  399. package/templates-i18n/tanstack/src/features/landing/helpers/index.ts +7 -0
  400. package/templates-i18n/tanstack/src/features/landing/helpers/motion.ts +21 -0
  401. package/templates-i18n/tanstack/src/features/landing/hooks/index.ts +1 -0
  402. package/templates-i18n/tanstack/src/features/landing/hooks/use-users.ts +19 -0
  403. package/templates-i18n/tanstack/src/features/landing/icons/index.ts +5 -0
  404. package/templates-i18n/tanstack/src/features/landing/icons/react-hook-form.tsx +18 -0
  405. package/templates-i18n/tanstack/src/features/landing/icons/react.tsx +20 -0
  406. package/templates-i18n/tanstack/src/features/landing/icons/tailwind.tsx +14 -0
  407. package/templates-i18n/tanstack/src/features/landing/icons/tanstack.tsx +321 -0
  408. package/templates-i18n/tanstack/src/features/landing/icons/typescript.tsx +16 -0
  409. package/templates-i18n/tanstack/src/features/landing/index.ts +1 -0
  410. package/templates-i18n/tanstack/src/features/landing/schemas/index.ts +1 -0
  411. package/templates-i18n/tanstack/src/features/landing/schemas/project.schema.ts +10 -0
  412. package/templates-i18n/tanstack/src/features/landing/stores/counter.store.ts +18 -0
  413. package/templates-i18n/tanstack/src/features/landing/stores/index.ts +1 -0
  414. package/templates-i18n/tanstack/src/features/landing/types/index.ts +1 -0
  415. package/templates-i18n/tanstack/src/features/landing/types/user.types.ts +9 -0
  416. package/templates-i18n/tanstack/src/helpers/format-date.ts +13 -0
  417. package/templates-i18n/tanstack/src/helpers/index.ts +1 -0
  418. package/templates-i18n/tanstack/src/hooks/index.ts +5 -0
  419. package/templates-i18n/tanstack/src/lib/api.ts +97 -0
  420. package/templates-i18n/tanstack/src/lib/query-client.ts +18 -0
  421. package/templates-i18n/tanstack/src/lib/utils.ts +13 -0
  422. package/templates-i18n/tanstack/src/paraglide/README.md +162 -0
  423. package/templates-i18n/tanstack/src/providers/Providers.tsx +12 -0
  424. package/templates-i18n/tanstack/src/providers/ThemeProvider.tsx +98 -0
  425. package/templates-i18n/tanstack/src/providers/devtools.tsx +6 -0
  426. package/templates-i18n/tanstack/src/providers/index.ts +1 -0
  427. package/templates-i18n/tanstack/src/providers/root-provider.ts +9 -0
  428. package/templates-i18n/tanstack/src/routeTree.gen.ts +179 -0
  429. package/templates-i18n/tanstack/src/router.tsx +27 -0
  430. package/templates-i18n/tanstack/src/routes/$lang/index.tsx +13 -0
  431. package/templates-i18n/tanstack/src/routes/$lang.tsx +22 -0
  432. package/templates-i18n/tanstack/src/routes/__root.tsx +80 -0
  433. package/templates-i18n/tanstack/src/routes/index.tsx +13 -0
  434. package/templates-i18n/tanstack/src/routes/robots[.]txt.ts +21 -0
  435. package/templates-i18n/tanstack/src/routes/site[.]webmanifest.ts +32 -0
  436. package/templates-i18n/tanstack/src/routes/sitemap[.]xml.ts +27 -0
  437. package/templates-i18n/tanstack/src/schemas/index.ts +5 -0
  438. package/templates-i18n/tanstack/src/server.ts +10 -0
  439. package/templates-i18n/tanstack/src/start.ts +20 -0
  440. package/templates-i18n/tanstack/src/stores/index.ts +5 -0
  441. package/templates-i18n/tanstack/src/styles/tailwind.css +123 -0
  442. package/templates-i18n/tanstack/src/types/site-config.types.ts +10 -0
  443. package/templates-i18n/tanstack/tsconfig.json +26 -0
  444. package/templates-i18n/tanstack/tsr.config.json +3 -0
  445. package/templates-i18n/tanstack/vite.config.ts +31 -0
  446. package/index.js +0 -3
  447. package/public/start.jpg +0 -0
@@ -0,0 +1,3 @@
1
+ ignoredBuiltDependencies:
2
+ - sharp
3
+ - unrs-resolver
@@ -0,0 +1,7 @@
1
+ const config = {
2
+ plugins: {
3
+ "@tailwindcss/postcss": {},
4
+ },
5
+ };
6
+
7
+ export default config;
@@ -0,0 +1,96 @@
1
+ # ViraStack Start — Next.js Edition
2
+
3
+ > Premium Next.js 16 + React 19 + Tailwind CSS 4 boilerplate focused on clean architecture, UI/UX, and agent-ready developer experience. Auth, database/ORM, i18n, and testing are intentionally omitted — bring the solution that fits your project.
4
+
5
+ Built on the App Router with Server/Client Components, streaming, and the Metadata API. UI primitives use **Base UI** (unstyled, accessible) styled with Tailwind CSS 4 design tokens. State is split by job: TanStack Query for server state, Zustand for client state, `nuqs` for URL state. Forms use React Hook Form + Zod. The home route renders a deletable `features/landing` demo that follows the canonical ViraStack feature tree. **ViraStack AI** (`@virastack/ai`) adds agent rules on scaffold; design skills come from [emilkowalski/skills](https://github.com/emilkowalski/skills) and [make-interfaces-feel-better](https://github.com/jakubkrehel/make-interfaces-feel-better).
6
+
7
+ - Tech stack: Next.js 16, React 19, Tailwind CSS 4, TypeScript 5 (strict + `noUncheckedIndexedAccess`), Node.js `>=20.9`
8
+ - UI: Base UI, Framer Motion, Sonner, Lucide React, `next-themes`, `class-variance-authority`
9
+ - Data & state: TanStack Query 5, Zustand, `nuqs`
10
+ - Forms: React Hook Form + Zod (+ `@hookform/resolvers`)
11
+ - API: Native `fetch` wrapper in `src/lib/api.ts` (`ApiError` with `message`, `status`, `data`); Axios is optional, not installed
12
+ - Env: Hand-rolled Zod schema in `src/env.ts` (no `@t3-oss/env-nextjs`)
13
+ - Tooling: ESLint 9, Prettier 3, Husky, Knip, Commitlint, Changesets, `@next/bundle-analyzer`
14
+ - Quality scripts: `pnpm typecheck`, `pnpm lint` / `lint:ci`, `pnpm knip`, `pnpm build`
15
+ - ViraStack AI (via `npx @virastack/ai init`): `AGENTS.md`, `CLAUDE.md`, `.cursor/rules/*.mdc`, `docs/*`
16
+ - Not included by default: Auth, DB/ORM, i18n (`next-intl` not installed), test runner, CSP
17
+
18
+ ## Docs
19
+ - [Repository (GitHub)](https://github.com/virastack/start): CLI and templates
20
+ - [README](https://github.com/virastack/start/tree/main/templates/nextjs): Features, structure, and conventions
21
+ - [Architecture guide](https://github.com/virastack/ai/blob/main/templates/core/docs/architecture-guide.md): Placement rules and import conventions
22
+ - [Product docs](https://www.virastack.com/nextjs-boilerplate/): ViraStack Next.js boilerplate
23
+
24
+ ## Key Files & Entry Points
25
+ - [`src/app/layout.tsx`](https://github.com/virastack/start/blob/main/templates/nextjs/src/app/layout.tsx): Root layout, fonts, providers
26
+ - [`src/app/page.tsx`](https://github.com/virastack/start/blob/main/templates/nextjs/src/app/page.tsx): Home route → `<LandingPage />`
27
+ - [`src/app/loading.tsx`](https://github.com/virastack/start/blob/main/templates/nextjs/src/app/loading.tsx): Route-level skeleton
28
+ - [`src/app/error.tsx`](https://github.com/virastack/start/blob/main/templates/nextjs/src/app/error.tsx): Route-level error boundary
29
+ - [`src/app/not-found.tsx`](https://github.com/virastack/start/blob/main/templates/nextjs/src/app/not-found.tsx): 404 boundary
30
+ - [`src/app/global-error.tsx`](https://github.com/virastack/start/blob/main/templates/nextjs/src/app/global-error.tsx): Root error boundary
31
+ - [`src/app/robots.ts`](https://github.com/virastack/start/blob/main/templates/nextjs/src/app/robots.ts): Robots configuration
32
+ - [`src/app/sitemap.ts`](https://github.com/virastack/start/blob/main/templates/nextjs/src/app/sitemap.ts): Sitemap generation
33
+ - [`src/app/manifest.ts`](https://github.com/virastack/start/blob/main/templates/nextjs/src/app/manifest.ts): Web app manifest (titles from `siteConfig`)
34
+ - [`src/proxy.ts`](https://github.com/virastack/start/blob/main/templates/nextjs/src/proxy.ts): Next.js 16 network boundary scaffold (passthrough)
35
+ - [`src/env.ts`](https://github.com/virastack/start/blob/main/templates/nextjs/src/env.ts): Zod-validated environment schema
36
+ - [`src/config/site.config.ts`](https://github.com/virastack/start/blob/main/templates/nextjs/src/config/site.config.ts): Site config (name, URL, links)
37
+ - [`src/config/seo.config.ts`](https://github.com/virastack/start/blob/main/templates/nextjs/src/config/seo.config.ts): Default Metadata object (OG/icons via `/og.png`, `/logo.webp`)
38
+ - [`src/lib/api.ts`](https://github.com/virastack/start/blob/main/templates/nextjs/src/lib/api.ts): Native `fetch` wrapper with retry & typed `ApiError`
39
+ - [`src/lib/query-client.ts`](https://github.com/virastack/start/blob/main/templates/nextjs/src/lib/query-client.ts): QueryClient factory & defaults
40
+ - [`src/providers/Providers.tsx`](https://github.com/virastack/start/blob/main/templates/nextjs/src/providers/Providers.tsx): App-wide providers (Theme, Query, Nuqs, Toaster)
41
+ - [`next.config.ts`](https://github.com/virastack/start/blob/main/templates/nextjs/next.config.ts): Next config + baseline security headers (no CSP by default)
42
+
43
+ ## Landing Feature (demo — delete when building)
44
+ Canonical tree under `src/features/landing/`. Home page composes `LandingPage`.
45
+
46
+ - [`src/features/landing/index.ts`](https://github.com/virastack/start/blob/main/templates/nextjs/src/features/landing/index.ts): Public export (`LandingPage`)
47
+ - [`src/features/landing/components/LandingPage.tsx`](https://github.com/virastack/start/blob/main/templates/nextjs/src/features/landing/components/LandingPage.tsx): Page composition (Header + sections + Footer)
48
+ - [`src/features/landing/components/Hero.tsx`](https://github.com/virastack/start/blob/main/templates/nextjs/src/features/landing/components/Hero.tsx): Hero section
49
+ - [`src/features/landing/components/Features.tsx`](https://github.com/virastack/start/blob/main/templates/nextjs/src/features/landing/components/Features.tsx): Feature grid
50
+ - [`src/features/landing/components/Showcase.tsx`](https://github.com/virastack/start/blob/main/templates/nextjs/src/features/landing/components/Showcase.tsx): Stack demos host (Query, Zustand, forms, nuqs)
51
+ - [`src/features/landing/components/UsersDemo.tsx`](https://github.com/virastack/start/blob/main/templates/nextjs/src/features/landing/components/UsersDemo.tsx): TanStack Query + `nuqs` demo
52
+ - [`src/features/landing/components/CartDemo.tsx`](https://github.com/virastack/start/blob/main/templates/nextjs/src/features/landing/components/CartDemo.tsx): Zustand demo
53
+ - [`src/features/landing/components/ProjectFormDemo.tsx`](https://github.com/virastack/start/blob/main/templates/nextjs/src/features/landing/components/ProjectFormDemo.tsx): RHF + Zod demo
54
+ - [`src/features/landing/api/get-users.api.ts`](https://github.com/virastack/start/blob/main/templates/nextjs/src/features/landing/api/get-users.api.ts): Feature API function
55
+ - [`src/features/landing/hooks/use-users.ts`](https://github.com/virastack/start/blob/main/templates/nextjs/src/features/landing/hooks/use-users.ts): Feature TanStack Query hook
56
+ - [`src/features/landing/stores/counter.store.ts`](https://github.com/virastack/start/blob/main/templates/nextjs/src/features/landing/stores/counter.store.ts): Feature Zustand store
57
+ - [`src/features/landing/schemas/project.schema.ts`](https://github.com/virastack/start/blob/main/templates/nextjs/src/features/landing/schemas/project.schema.ts): Feature Zod schema
58
+ - [`src/features/landing/data/features.data.tsx`](https://github.com/virastack/start/blob/main/templates/nextjs/src/features/landing/data/features.data.tsx): Feature static data
59
+ - [`src/features/landing/helpers/`](https://github.com/virastack/start/tree/main/templates/nextjs/src/features/landing/helpers): Feature helpers (motion tokens, initials)
60
+ - [`src/features/landing/icons/`](https://github.com/virastack/start/tree/main/templates/nextjs/src/features/landing/icons): Brand SVGs used only by the landing demo
61
+ - [`src/features/landing/types/user.types.ts`](https://github.com/virastack/start/blob/main/templates/nextjs/src/features/landing/types/user.types.ts): Feature types
62
+
63
+ Quick start: delete `src/features/landing`, replace `src/app/page.tsx`, keep `components/layout` if you still want chrome.
64
+
65
+ ## UI & Shared Layers
66
+ - [`src/components/ui`](https://github.com/virastack/start/tree/main/templates/nextjs/src/components/ui): Base UI primitives (Button, Input, Field, Dialog, Tabs, Skeleton, Label, Avatar, Table)
67
+ - [`src/components/layout`](https://github.com/virastack/start/tree/main/templates/nextjs/src/components/layout): Header / Footer (reusable; Header accepts optional `links`)
68
+ - [`src/components/shared`](https://github.com/virastack/start/tree/main/templates/nextjs/src/components/shared): Cross-feature components (ThemeToggle)
69
+ - [`src/hooks`](https://github.com/virastack/start/tree/main/templates/nextjs/src/hooks), [`src/stores`](https://github.com/virastack/start/tree/main/templates/nextjs/src/stores), [`src/schemas`](https://github.com/virastack/start/tree/main/templates/nextjs/src/schemas): Shared barrels (promote via Rule of Three)
70
+ - [`src/helpers`](https://github.com/virastack/start/tree/main/templates/nextjs/src/helpers): Shared helpers
71
+ - [`src/styles/tailwind.css`](https://github.com/virastack/start/blob/main/templates/nextjs/src/styles/tailwind.css): Tailwind v4 entry + design tokens
72
+ - Assets: [`public/logo.webp`](https://github.com/virastack/start/blob/main/templates/nextjs/public/logo.webp), [`public/og.png`](https://github.com/virastack/start/blob/main/templates/nextjs/public/og.png), [`public/favicon.ico`](https://github.com/virastack/start/blob/main/templates/nextjs/public/favicon.ico)
73
+
74
+ ## Customization & Imports
75
+ - Search the project for `FIXME:` (site config, remote images, auth attachment on the API client).
76
+ - Prefer short path aliases: `@/ui`, `@/hooks`, `@/schemas`, `@/layout` over long forms. Prefer feature-local imports under `@/features/[feature]/…` for demo-scoped code.
77
+ - Default scope is `features/[feature]/` — promote to global `src/` only when a second feature needs it. No cross-feature imports.
78
+
79
+ ## ViraStack AI
80
+ - Install or refresh: `npx @virastack/ai init --force`
81
+ - `AGENTS.md`: Agent operating guide (all agents)
82
+ - `CLAUDE.md`: Claude Code entry point (`@AGENTS.md`)
83
+ - `.cursor/rules/*.mdc`: Scoped coding rules (Cursor auto-loads)
84
+ - `docs/architecture-guide.md`, `docs/MEMORIES.md`: Architecture and project memory
85
+ - Skills: [emilkowalski/skills](https://github.com/emilkowalski/skills) (7 design-engineering skills) + [make-interfaces-feel-better](https://github.com/jakubkrehel/make-interfaces-feel-better)
86
+ - Package: [`@virastack/ai`](https://github.com/virastack/ai)
87
+
88
+ ## External References
89
+ - [Next.js Docs](https://nextjs.org/docs): App Router, Server/Client Components, routing, metadata, images, fonts
90
+ - [React](https://react.dev/): Modern React APIs and RSC foundations
91
+ - [Tailwind CSS v4](https://tailwindcss.com/): Design tokens & utility-first styling
92
+ - [Base UI](https://base-ui.com/): Unstyled, accessible React components
93
+ - [TanStack Query](https://tanstack.com/query/latest): Server-state syncing & caching
94
+ - [nuqs](https://nuqs.dev/): Type-safe URL search param state
95
+ - [Zod](https://zod.dev/): Runtime validation and parsing
96
+ - [ViraStack AI](https://github.com/virastack/ai): Shared agent rules package (`@virastack/ai`)
Binary file
Binary file
@@ -0,0 +1,34 @@
1
+ "use client";
2
+
3
+ import { useEffect } from "react";
4
+ import Link from "next/link";
5
+
6
+ import { Button } from "@/components/ui/button";
7
+
8
+ export default function Error({
9
+ error,
10
+ reset,
11
+ }: {
12
+ error: Error & { digest?: string };
13
+ reset: () => void;
14
+ }) {
15
+ useEffect(() => {
16
+ console.error(error);
17
+ }, [error]);
18
+
19
+ return (
20
+ <div className="mx-auto flex flex-1 flex-col items-center justify-center gap-4 px-6 py-24 text-center">
21
+ <h1 className="text-2xl font-semibold tracking-tight">Something went wrong</h1>
22
+ <p className="max-w-md text-sm text-muted-foreground">
23
+ An unexpected error occurred while rendering this page. You can try again, or head back to
24
+ the homepage.
25
+ </p>
26
+ <div className="flex gap-3">
27
+ <Button onClick={reset}>Try again</Button>
28
+ <Button variant="outline" nativeButton={false} render={<Link href="/" />}>
29
+ Go home
30
+ </Button>
31
+ </div>
32
+ </div>
33
+ );
34
+ }
@@ -0,0 +1,32 @@
1
+ "use client";
2
+
3
+ import { useEffect } from "react";
4
+
5
+ export default function GlobalError({
6
+ error,
7
+ reset,
8
+ }: {
9
+ error: Error & { digest?: string };
10
+ reset: () => void;
11
+ }) {
12
+ useEffect(() => {
13
+ console.error(error);
14
+ }, [error]);
15
+
16
+ return (
17
+ <html lang="en" data-scroll-behavior="smooth">
18
+ <body className="flex min-h-screen flex-col items-center justify-center gap-4 px-6 text-center">
19
+ <h1 className="text-2xl font-semibold tracking-tight">A critical error occurred</h1>
20
+ <p className="max-w-md text-sm text-neutral-500">
21
+ The application failed to render. Please try again.
22
+ </p>
23
+ <button
24
+ onClick={reset}
25
+ className="rounded-md bg-neutral-900 px-4 py-2 text-sm font-medium text-white"
26
+ >
27
+ Try again
28
+ </button>
29
+ </body>
30
+ </html>
31
+ );
32
+ }
@@ -0,0 +1,37 @@
1
+ import type { Metadata } from "next";
2
+ import { Inter } from "next/font/google";
3
+
4
+ import { NuqsAdapter } from "nuqs/adapters/next/app";
5
+
6
+ import { defaultMetadata } from "@/config/seo.config";
7
+
8
+ import { Providers } from "@/providers";
9
+
10
+ import "@/styles/tailwind.css";
11
+
12
+ const inter = Inter({
13
+ variable: "--font-inter",
14
+ subsets: ["latin"],
15
+ display: "swap",
16
+ preload: true,
17
+ adjustFontFallback: true,
18
+ });
19
+
20
+ export const metadata: Metadata = defaultMetadata;
21
+
22
+ export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) {
23
+ return (
24
+ <html
25
+ lang="en"
26
+ className={`${inter.variable} h-full`}
27
+ suppressHydrationWarning
28
+ data-scroll-behavior="smooth"
29
+ >
30
+ <body className="flex min-h-full flex-col antialiased" suppressHydrationWarning>
31
+ <NuqsAdapter>
32
+ <Providers>{children}</Providers>
33
+ </NuqsAdapter>
34
+ </body>
35
+ </html>
36
+ );
37
+ }
@@ -0,0 +1,12 @@
1
+ import { Skeleton } from "@/components/ui/skeleton";
2
+
3
+ export default function Loading() {
4
+ return (
5
+ <div className="mx-auto flex w-full max-w-3xl flex-1 flex-col items-center gap-4 px-6 py-24">
6
+ <Skeleton className="h-10 w-2/3" />
7
+ <Skeleton className="h-4 w-full" />
8
+ <Skeleton className="h-4 w-5/6" />
9
+ <Skeleton className="mt-6 h-40 w-full" />
10
+ </div>
11
+ );
12
+ }
@@ -0,0 +1,22 @@
1
+ import type { MetadataRoute } from "next";
2
+
3
+ import { siteConfig } from "@/config/site.config";
4
+
5
+ export default function manifest(): MetadataRoute.Manifest {
6
+ return {
7
+ name: siteConfig.name,
8
+ short_name: siteConfig.name,
9
+ description: siteConfig.description,
10
+ start_url: "/",
11
+ display: "standalone",
12
+ background_color: "#ffffff",
13
+ theme_color: "#ffffff",
14
+ icons: [
15
+ {
16
+ src: "/logo.webp",
17
+ sizes: "96x96",
18
+ type: "image/webp",
19
+ },
20
+ ],
21
+ };
22
+ }
@@ -0,0 +1,18 @@
1
+ import Link from "next/link";
2
+
3
+ import { Button } from "@/components/ui/button";
4
+
5
+ export default function NotFound() {
6
+ return (
7
+ <div className="mx-auto flex flex-1 flex-col items-center justify-center gap-4 px-6 py-24 text-center">
8
+ <p className="text-sm font-medium text-muted-foreground">404</p>
9
+ <h1 className="text-2xl font-semibold tracking-tight">Page not found</h1>
10
+ <p className="max-w-md text-sm text-muted-foreground">
11
+ The page you&apos;re looking for doesn&apos;t exist or has been moved.
12
+ </p>
13
+ <Button nativeButton={false} render={<Link href="/" />}>
14
+ Go home
15
+ </Button>
16
+ </div>
17
+ );
18
+ }
@@ -0,0 +1,5 @@
1
+ import { LandingPage } from "@/features/landing";
2
+
3
+ export default function HomePage() {
4
+ return <LandingPage />;
5
+ }
@@ -0,0 +1,13 @@
1
+ import type { MetadataRoute } from "next";
2
+
3
+ import { siteConfig } from "@/config/site.config";
4
+
5
+ export default function robots(): MetadataRoute.Robots {
6
+ return {
7
+ rules: {
8
+ userAgent: "*",
9
+ allow: "/",
10
+ },
11
+ sitemap: `${siteConfig.url}/sitemap.xml`,
12
+ };
13
+ }
@@ -0,0 +1,14 @@
1
+ import type { MetadataRoute } from "next";
2
+
3
+ import { siteConfig } from "@/config/site.config";
4
+
5
+ export default function sitemap(): MetadataRoute.Sitemap {
6
+ return [
7
+ {
8
+ url: siteConfig.url,
9
+ lastModified: new Date(),
10
+ changeFrequency: "monthly",
11
+ priority: 1,
12
+ },
13
+ ];
14
+ }
@@ -0,0 +1,30 @@
1
+ "use client";
2
+
3
+ import { MoonIcon, SunIcon } from "lucide-react";
4
+ import { useTheme } from "next-themes";
5
+ import { useIsClient } from "usehooks-ts";
6
+
7
+ import { Button } from "@/components/ui/button";
8
+
9
+ export function ThemeToggle() {
10
+ const { resolvedTheme, setTheme } = useTheme();
11
+ const isClient = useIsClient();
12
+
13
+ if (!isClient) {
14
+ return <Button variant="outline" size="icon" aria-hidden className="size-8 opacity-0" />;
15
+ }
16
+
17
+ const isDark = resolvedTheme === "dark";
18
+
19
+ return (
20
+ <Button
21
+ variant="outline"
22
+ size="icon"
23
+ className="size-8"
24
+ aria-label={isDark ? "Switch to light theme" : "Switch to dark theme"}
25
+ onClick={() => setTheme(isDark ? "light" : "dark")}
26
+ >
27
+ {isDark ? <SunIcon className="size-3.5" /> : <MoonIcon className="size-3.5" />}
28
+ </Button>
29
+ );
30
+ }
@@ -0,0 +1,54 @@
1
+ import * as React from "react";
2
+
3
+ import { cn } from "@/lib/utils";
4
+
5
+ const Avatar = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
6
+ ({ className, ...props }, ref) => (
7
+ <div
8
+ ref={ref}
9
+ className={cn("relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", className)}
10
+ {...props}
11
+ />
12
+ ),
13
+ );
14
+ Avatar.displayName = "Avatar";
15
+
16
+ const AvatarImage = React.forwardRef<
17
+ HTMLImageElement,
18
+ React.ImgHTMLAttributes<HTMLImageElement> & {
19
+ onLoadingStatusChange?: (status: "loading" | "loaded" | "error") => void;
20
+ }
21
+ >(({ className, src, alt = "", ...props }, ref) => {
22
+ const [status, setStatus] = React.useState<"loading" | "loaded" | "error">("loading");
23
+
24
+ return (
25
+ // Avatar primitives accept arbitrary remote URLs; next/image needs a configured domain list.
26
+ // eslint-disable-next-line @next/next/no-img-element -- intentional for flexible avatar sources
27
+ <img
28
+ ref={ref}
29
+ src={src}
30
+ alt={alt}
31
+ className={cn("aspect-square h-full w-full", status !== "loaded" && "hidden", className)}
32
+ onLoad={() => setStatus("loaded")}
33
+ onError={() => setStatus("error")}
34
+ {...props}
35
+ />
36
+ );
37
+ });
38
+ AvatarImage.displayName = "AvatarImage";
39
+
40
+ const AvatarFallback = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
41
+ ({ className, ...props }, ref) => (
42
+ <div
43
+ ref={ref}
44
+ className={cn(
45
+ "flex h-full w-full items-center justify-center rounded-full bg-muted text-xs",
46
+ className,
47
+ )}
48
+ {...props}
49
+ />
50
+ ),
51
+ );
52
+ AvatarFallback.displayName = "AvatarFallback";
53
+
54
+ export { Avatar, AvatarImage, AvatarFallback };
@@ -0,0 +1,46 @@
1
+ import type { ComponentProps } from "react";
2
+
3
+ import { Button as BaseButton } from "@base-ui/react/button";
4
+ import { cva, type VariantProps } from "class-variance-authority";
5
+
6
+ import { cn } from "@/lib/utils";
7
+
8
+ export const buttonVariants = cva(
9
+ "inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
10
+ {
11
+ variants: {
12
+ variant: {
13
+ default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
14
+ destructive:
15
+ "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20",
16
+ outline:
17
+ "border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground",
18
+ secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
19
+ ghost: "hover:bg-accent hover:text-accent-foreground",
20
+ link: "text-primary underline-offset-4 hover:underline",
21
+ },
22
+ size: {
23
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
24
+ sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
25
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
26
+ icon: "size-9",
27
+ },
28
+ },
29
+ defaultVariants: {
30
+ variant: "default",
31
+ size: "default",
32
+ },
33
+ },
34
+ );
35
+
36
+ export type ButtonProps = ComponentProps<typeof BaseButton> & VariantProps<typeof buttonVariants>;
37
+
38
+ export function Button({ className, variant, size, ...props }: ButtonProps) {
39
+ return (
40
+ <BaseButton
41
+ data-slot="button"
42
+ className={cn(buttonVariants({ variant, size, className }))}
43
+ {...props}
44
+ />
45
+ );
46
+ }
@@ -0,0 +1,107 @@
1
+ import type { ComponentProps } from "react";
2
+
3
+ import { XIcon } from "lucide-react";
4
+ import { Dialog as BaseDialog } from "@base-ui/react/dialog";
5
+
6
+ import { cn } from "@/lib/utils";
7
+
8
+ export function Dialog(props: ComponentProps<typeof BaseDialog.Root>) {
9
+ return <BaseDialog.Root data-slot="dialog" {...props} />;
10
+ }
11
+
12
+ export function DialogTrigger(props: ComponentProps<typeof BaseDialog.Trigger>) {
13
+ return <BaseDialog.Trigger data-slot="dialog-trigger" {...props} />;
14
+ }
15
+
16
+ export function DialogClose(props: ComponentProps<typeof BaseDialog.Close>) {
17
+ return <BaseDialog.Close data-slot="dialog-close" {...props} />;
18
+ }
19
+
20
+ export function DialogContent({
21
+ className,
22
+ children,
23
+ showCloseButton = true,
24
+ ...props
25
+ }: ComponentProps<typeof BaseDialog.Popup> & { showCloseButton?: boolean }) {
26
+ return (
27
+ <BaseDialog.Portal>
28
+ <BaseDialog.Backdrop
29
+ data-slot="dialog-backdrop"
30
+ className={cn(
31
+ "fixed inset-0 z-50 bg-black/50",
32
+ "data-[ending-style]:opacity-0 data-[starting-style]:opacity-0",
33
+ "transition-opacity duration-150",
34
+ )}
35
+ />
36
+ <BaseDialog.Popup
37
+ data-slot="dialog-content"
38
+ className={cn(
39
+ "fixed top-1/2 left-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4",
40
+ "rounded-lg border border-border bg-background p-6 shadow-lg",
41
+ "data-[starting-style]:scale-95 data-[starting-style]:opacity-0",
42
+ "data-[ending-style]:scale-95 data-[ending-style]:opacity-0",
43
+ "transition-all duration-150",
44
+ className,
45
+ )}
46
+ {...props}
47
+ >
48
+ {children}
49
+ {showCloseButton && (
50
+ <BaseDialog.Close
51
+ data-slot="dialog-close"
52
+ className={cn(
53
+ "absolute top-4 right-4 rounded-xs opacity-70 transition-opacity outline-none",
54
+ "hover:opacity-100 focus-visible:ring-[3px] focus-visible:ring-ring/50",
55
+ )}
56
+ >
57
+ <XIcon className="size-4" />
58
+ <span className="sr-only">Close</span>
59
+ </BaseDialog.Close>
60
+ )}
61
+ </BaseDialog.Popup>
62
+ </BaseDialog.Portal>
63
+ );
64
+ }
65
+
66
+ export function DialogHeader({ className, ...props }: ComponentProps<"div">) {
67
+ return (
68
+ <div
69
+ data-slot="dialog-header"
70
+ className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
71
+ {...props}
72
+ />
73
+ );
74
+ }
75
+
76
+ export function DialogFooter({ className, ...props }: ComponentProps<"div">) {
77
+ return (
78
+ <div
79
+ data-slot="dialog-footer"
80
+ className={cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className)}
81
+ {...props}
82
+ />
83
+ );
84
+ }
85
+
86
+ export function DialogTitle({ className, ...props }: ComponentProps<typeof BaseDialog.Title>) {
87
+ return (
88
+ <BaseDialog.Title
89
+ data-slot="dialog-title"
90
+ className={cn("text-lg leading-none font-semibold", className)}
91
+ {...props}
92
+ />
93
+ );
94
+ }
95
+
96
+ export function DialogDescription({
97
+ className,
98
+ ...props
99
+ }: ComponentProps<typeof BaseDialog.Description>) {
100
+ return (
101
+ <BaseDialog.Description
102
+ data-slot="dialog-description"
103
+ className={cn("text-sm text-muted-foreground", className)}
104
+ {...props}
105
+ />
106
+ );
107
+ }
@@ -0,0 +1,24 @@
1
+ import type { ComponentProps } from "react";
2
+
3
+ import { cn } from "@/lib/utils";
4
+
5
+ export function FieldDescription({ className, ...props }: ComponentProps<"p">) {
6
+ return (
7
+ <p
8
+ data-slot="field-description"
9
+ className={cn("text-sm font-normal text-muted-foreground", className)}
10
+ {...props}
11
+ />
12
+ );
13
+ }
14
+
15
+ export function FieldError({ className, ...props }: ComponentProps<"p">) {
16
+ return (
17
+ <p
18
+ role="alert"
19
+ data-slot="field-error"
20
+ className={cn("text-sm font-normal text-destructive", className)}
21
+ {...props}
22
+ />
23
+ );
24
+ }
@@ -0,0 +1,27 @@
1
+ export { Button, buttonVariants, type ButtonProps } from "@/components/ui/button";
2
+ export { FieldDescription, FieldError } from "@/components/ui/field";
3
+ export { Input } from "@/components/ui/input";
4
+ export { Label } from "@/components/ui/label";
5
+ export { Skeleton } from "@/components/ui/skeleton";
6
+ export {
7
+ Dialog,
8
+ DialogClose,
9
+ DialogContent,
10
+ DialogDescription,
11
+ DialogFooter,
12
+ DialogHeader,
13
+ DialogTitle,
14
+ DialogTrigger,
15
+ } from "@/components/ui/dialog";
16
+ export { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
17
+ export { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
18
+ export {
19
+ Table,
20
+ TableBody,
21
+ TableCaption,
22
+ TableCell,
23
+ TableFooter,
24
+ TableHead,
25
+ TableHeader,
26
+ TableRow,
27
+ } from "@/components/ui/table";
@@ -0,0 +1,23 @@
1
+ import type { ComponentProps } from "react";
2
+
3
+ import { Input as BaseInput } from "@base-ui/react/input";
4
+
5
+ import { cn } from "@/lib/utils";
6
+
7
+ export function Input({ className, ...props }: ComponentProps<typeof BaseInput>) {
8
+ return (
9
+ <BaseInput
10
+ data-slot="input"
11
+ className={cn(
12
+ "flex h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-xs transition-[color,box-shadow] outline-none",
13
+ "placeholder:text-muted-foreground",
14
+ "focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50",
15
+ "disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
16
+ "aria-invalid:border-destructive aria-invalid:ring-destructive/20",
17
+ "file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground",
18
+ className,
19
+ )}
20
+ {...props}
21
+ />
22
+ );
23
+ }