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,17 @@
1
+ import type { ComponentProps } from "react";
2
+
3
+ import { cn } from "@/lib/utils";
4
+
5
+ export function Label({ className, ...props }: ComponentProps<"label">) {
6
+ return (
7
+ <label
8
+ data-slot="label"
9
+ className={cn(
10
+ "flex items-center gap-2 text-sm leading-none font-medium select-none",
11
+ "peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
12
+ className,
13
+ )}
14
+ {...props}
15
+ />
16
+ );
17
+ }
@@ -0,0 +1,13 @@
1
+ import type { ComponentProps } from "react";
2
+
3
+ import { cn } from "@/lib/utils";
4
+
5
+ export function Skeleton({ className, ...props }: ComponentProps<"div">) {
6
+ return (
7
+ <div
8
+ data-slot="skeleton"
9
+ className={cn("animate-pulse rounded-md bg-accent", className)}
10
+ {...props}
11
+ />
12
+ );
13
+ }
@@ -0,0 +1,94 @@
1
+ import * as React from "react";
2
+
3
+ import { cn } from "@/lib/utils";
4
+
5
+ const Table = React.forwardRef<HTMLTableElement, React.HTMLAttributes<HTMLTableElement>>(
6
+ ({ className, ...props }, ref) => (
7
+ <div className="relative w-full overflow-auto">
8
+ <table ref={ref} className={cn("w-full caption-bottom text-sm", className)} {...props} />
9
+ </div>
10
+ ),
11
+ );
12
+ Table.displayName = "Table";
13
+
14
+ const TableHeader = React.forwardRef<
15
+ HTMLTableSectionElement,
16
+ React.HTMLAttributes<HTMLTableSectionElement>
17
+ >(({ className, ...props }, ref) => (
18
+ <thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
19
+ ));
20
+ TableHeader.displayName = "TableHeader";
21
+
22
+ const TableBody = React.forwardRef<
23
+ HTMLTableSectionElement,
24
+ React.HTMLAttributes<HTMLTableSectionElement>
25
+ >(({ className, ...props }, ref) => (
26
+ <tbody ref={ref} className={cn("[&_tr:last-child]:border-0", className)} {...props} />
27
+ ));
28
+ TableBody.displayName = "TableBody";
29
+
30
+ const TableFooter = React.forwardRef<
31
+ HTMLTableSectionElement,
32
+ React.HTMLAttributes<HTMLTableSectionElement>
33
+ >(({ className, ...props }, ref) => (
34
+ <tfoot
35
+ ref={ref}
36
+ className={cn("border-t bg-muted/50 font-medium [&>tr]:last:border-b-0", className)}
37
+ {...props}
38
+ />
39
+ ));
40
+ TableFooter.displayName = "TableFooter";
41
+
42
+ const TableRow = React.forwardRef<HTMLTableRowElement, React.HTMLAttributes<HTMLTableRowElement>>(
43
+ ({ className, ...props }, ref) => (
44
+ <tr
45
+ ref={ref}
46
+ className={cn(
47
+ "border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
48
+ className,
49
+ )}
50
+ {...props}
51
+ />
52
+ ),
53
+ );
54
+ TableRow.displayName = "TableRow";
55
+
56
+ const TableHead = React.forwardRef<
57
+ HTMLTableCellElement,
58
+ React.ThHTMLAttributes<HTMLTableCellElement>
59
+ >(({ className, ...props }, ref) => (
60
+ <th
61
+ ref={ref}
62
+ className={cn(
63
+ "h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
64
+ className,
65
+ )}
66
+ {...props}
67
+ />
68
+ ));
69
+ TableHead.displayName = "TableHead";
70
+
71
+ const TableCell = React.forwardRef<
72
+ HTMLTableCellElement,
73
+ React.TdHTMLAttributes<HTMLTableCellElement>
74
+ >(({ className, ...props }, ref) => (
75
+ <td
76
+ ref={ref}
77
+ className={cn(
78
+ "p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
79
+ className,
80
+ )}
81
+ {...props}
82
+ />
83
+ ));
84
+ TableCell.displayName = "TableCell";
85
+
86
+ const TableCaption = React.forwardRef<
87
+ HTMLTableCaptionElement,
88
+ React.HTMLAttributes<HTMLTableCaptionElement>
89
+ >(({ className, ...props }, ref) => (
90
+ <caption ref={ref} className={cn("mt-4 text-sm text-muted-foreground", className)} {...props} />
91
+ ));
92
+ TableCaption.displayName = "TableCaption";
93
+
94
+ export { Table, TableHeader, TableBody, TableFooter, TableRow, TableHead, TableCell, TableCaption };
@@ -0,0 +1,46 @@
1
+ import type { ComponentProps } from "react";
2
+
3
+ import { Tabs as BaseTabs } from "@base-ui/react/tabs";
4
+
5
+ import { cn } from "@/lib/utils";
6
+
7
+ export function Tabs({ className, ...props }: ComponentProps<typeof BaseTabs.Root>) {
8
+ return (
9
+ <BaseTabs.Root data-slot="tabs" className={cn("flex flex-col gap-3", className)} {...props} />
10
+ );
11
+ }
12
+
13
+ export function TabsList({ className, ...props }: ComponentProps<typeof BaseTabs.List>) {
14
+ return (
15
+ <BaseTabs.List
16
+ data-slot="tabs-list"
17
+ className={cn(
18
+ "relative inline-flex h-9 w-fit items-center rounded-lg bg-muted p-[3px] text-muted-foreground",
19
+ className,
20
+ )}
21
+ {...props}
22
+ />
23
+ );
24
+ }
25
+
26
+ export function TabsTrigger({ className, ...props }: ComponentProps<typeof BaseTabs.Tab>) {
27
+ return (
28
+ <BaseTabs.Tab
29
+ data-slot="tabs-trigger"
30
+ className={cn(
31
+ "inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none",
32
+ "text-foreground data-[selected]:bg-background data-[selected]:shadow-sm",
33
+ "focus-visible:ring-[3px] focus-visible:ring-ring/50",
34
+ "disabled:pointer-events-none disabled:opacity-50",
35
+ className,
36
+ )}
37
+ {...props}
38
+ />
39
+ );
40
+ }
41
+
42
+ export function TabsContent({ className, ...props }: ComponentProps<typeof BaseTabs.Panel>) {
43
+ return (
44
+ <BaseTabs.Panel data-slot="tabs-content" className={cn("outline-none", className)} {...props} />
45
+ );
46
+ }
@@ -0,0 +1,37 @@
1
+ import type { Metadata } from "next";
2
+
3
+ import { siteConfig } from "@/config/site.config";
4
+
5
+ export const defaultMetadata: Metadata = {
6
+ metadataBase: new URL(siteConfig.url),
7
+ title: {
8
+ default: siteConfig.name,
9
+ template: `%s · ${siteConfig.name}`,
10
+ },
11
+ description: siteConfig.description,
12
+ keywords: ["Next.js", "React", "TypeScript", "Tailwind CSS", "ViraStack", "Boilerplate"],
13
+ authors: [{ name: "ViraStack", url: siteConfig.url }],
14
+ creator: "ViraStack",
15
+ openGraph: {
16
+ type: "website",
17
+ locale: "en_US",
18
+ url: siteConfig.url,
19
+ title: siteConfig.name,
20
+ description: siteConfig.description,
21
+ siteName: siteConfig.name,
22
+ images: [{ url: siteConfig.ogImage, width: 1200, height: 630, alt: siteConfig.name }],
23
+ },
24
+ twitter: {
25
+ card: "summary_large_image",
26
+ title: siteConfig.name,
27
+ description: siteConfig.description,
28
+ images: [siteConfig.ogImage],
29
+ },
30
+ icons: {
31
+ icon: "/logo.webp",
32
+ },
33
+ robots: {
34
+ index: true,
35
+ follow: true,
36
+ },
37
+ };
@@ -0,0 +1,15 @@
1
+ import type { SiteConfig } from "@/types/site-config.types";
2
+ import { env } from "@/env";
3
+
4
+ // FIXME: replace with your own site metadata.
5
+ export const siteConfig: SiteConfig = {
6
+ name: env.NEXT_PUBLIC_APP_NAME,
7
+ description:
8
+ "Premium Next.js boilerplate built for scalable UI/UX, clean architecture, and agent-ready developer experience.",
9
+ url: env.NEXT_PUBLIC_APP_URL,
10
+ ogImage: `${env.NEXT_PUBLIC_APP_URL}/og.png`,
11
+ links: {
12
+ github: "https://github.com/virastack/start",
13
+ twitter: "https://x.com/virastack",
14
+ },
15
+ };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Shared constants promoted out of features (Rule of Three).
3
+ * Feature-scoped constants live under `src/features/[feature]/constants`.
4
+ */
5
+ export {};
@@ -0,0 +1,41 @@
1
+ import { z } from "zod";
2
+
3
+ /**
4
+ * Type-safe environment variable schema.
5
+ *
6
+ * Server-only variables MUST NOT be prefixed with `NEXT_PUBLIC_`.
7
+ * Client-exposed variables MUST be prefixed with `NEXT_PUBLIC_` and
8
+ * explicitly re-read via `process.env.NEXT_PUBLIC_*` at usage sites
9
+ * (Next.js inlines these at build time; dynamic access does not work).
10
+ */
11
+ const serverSchema = z.object({
12
+ NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
13
+ });
14
+
15
+ const clientSchema = z.object({
16
+ NEXT_PUBLIC_APP_URL: z.string().url().default("http://localhost:3000"),
17
+ NEXT_PUBLIC_APP_NAME: z.string().min(1).default("ViraStack Start - Next.js Edition"),
18
+ });
19
+
20
+ const serverParsed = serverSchema.safeParse({
21
+ NODE_ENV: process.env.NODE_ENV,
22
+ });
23
+
24
+ const clientParsed = clientSchema.safeParse({
25
+ NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL,
26
+ NEXT_PUBLIC_APP_NAME: process.env.NEXT_PUBLIC_APP_NAME,
27
+ });
28
+
29
+ if (!serverParsed.success || !clientParsed.success) {
30
+ console.error(
31
+ "❌ Invalid environment variables:",
32
+ serverParsed.error?.flatten().fieldErrors,
33
+ clientParsed.error?.flatten().fieldErrors,
34
+ );
35
+ throw new Error("Invalid environment variables. Check src/env.ts");
36
+ }
37
+
38
+ export const env = {
39
+ ...serverParsed.data,
40
+ ...clientParsed.data,
41
+ };
@@ -0,0 +1,7 @@
1
+ import { api } from "@/lib/api";
2
+
3
+ import type { User } from "@/features/landing/types";
4
+
5
+ export function getUsers(signal?: AbortSignal) {
6
+ return api.get<User[]>("https://jsonplaceholder.typicode.com/users?_limit=5", { signal });
7
+ }
@@ -0,0 +1,2 @@
1
+ export { getUsers } from "@/features/landing/api/get-users.api";
2
+ export { userKeys } from "@/features/landing/api/query-keys";
@@ -0,0 +1,7 @@
1
+ export const userKeys = {
2
+ all: ["users"] as const,
3
+ lists: () => [...userKeys.all, "list"] as const,
4
+ list: (filters?: object) => [...userKeys.lists(), { filters }] as const,
5
+ details: () => [...userKeys.all, "detail"] as const,
6
+ detail: (id: string) => [...userKeys.details(), id] as const,
7
+ };
@@ -0,0 +1,66 @@
1
+ "use client";
2
+
3
+ import { MinusIcon, PlusIcon, ShirtIcon, Trash2Icon } from "lucide-react";
4
+
5
+ import { Button } from "@/components/ui/button";
6
+ import { useCounterStore } from "@/features/landing/stores";
7
+
8
+ /**
9
+ * Demonstrates global client state with Zustand via a mini cart UI.
10
+ */
11
+ export function CartDemo() {
12
+ const { count, increment, decrement, reset } = useCounterStore();
13
+
14
+ return (
15
+ <div className="flex flex-col gap-4">
16
+ <div className="flex items-center gap-4 rounded-xl border border-border/50 bg-background/50 p-3">
17
+ <div className="flex h-12 w-12 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-primary">
18
+ <ShirtIcon className="size-6" />
19
+ </div>
20
+ <div className="flex flex-1 flex-col">
21
+ <h5 className="font-medium text-foreground">Cotton T-Shirt</h5>
22
+ <p className="text-sm text-muted-foreground">White / XL</p>
23
+ </div>
24
+ <div className="flex flex-col items-end gap-1">
25
+ <span className="font-semibold text-foreground">{count * 350}</span>
26
+ <span className="text-xs text-muted-foreground">Total</span>
27
+ </div>
28
+ </div>
29
+
30
+ <div className="flex items-center justify-between">
31
+ <div className="flex items-center gap-2">
32
+ <Button
33
+ variant="outline"
34
+ size="icon"
35
+ className="h-8 w-8 rounded-full"
36
+ aria-label="Decrement"
37
+ onClick={decrement}
38
+ disabled={count === 0}
39
+ >
40
+ <MinusIcon className="size-4" />
41
+ </Button>
42
+ <span className="w-6 text-center font-medium tabular-nums">{count}</span>
43
+ <Button
44
+ variant="outline"
45
+ size="icon"
46
+ className="h-8 w-8 rounded-full"
47
+ aria-label="Increment"
48
+ onClick={increment}
49
+ >
50
+ <PlusIcon className="size-4" />
51
+ </Button>
52
+ </div>
53
+ <Button
54
+ variant="ghost"
55
+ size="sm"
56
+ className="h-8 gap-1.5 px-2 text-muted-foreground hover:text-destructive"
57
+ onClick={reset}
58
+ disabled={count === 0}
59
+ >
60
+ <Trash2Icon className="size-3.5" />
61
+ <span className="text-xs">Clear</span>
62
+ </Button>
63
+ </div>
64
+ </div>
65
+ );
66
+ }
@@ -0,0 +1,39 @@
1
+ import { RevealGroup, RevealItem } from "@/features/landing/components/Reveal";
2
+ import { FEATURES } from "@/features/landing/data";
3
+ import { featureCardClassName } from "@/features/landing/helpers";
4
+
5
+ export function Features() {
6
+ return (
7
+ <section id="features" className="mx-auto max-w-5xl px-6 py-16">
8
+ <RevealGroup className="mb-16 text-center">
9
+ <RevealItem>
10
+ <h2 className="text-3xl font-semibold tracking-tight text-balance">Features</h2>
11
+ </RevealItem>
12
+ <RevealItem>
13
+ <p className="mx-auto mt-3 max-w-xl text-base text-balance text-muted-foreground">
14
+ Everything you need to build a modern web application, already configured with the best
15
+ practices.
16
+ </p>
17
+ </RevealItem>
18
+ </RevealGroup>
19
+
20
+ <RevealGroup className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
21
+ {FEATURES.map((feature) => (
22
+ <RevealItem key={feature.title} className={featureCardClassName}>
23
+ <div className="mb-2 flex h-12 w-12 items-center justify-center rounded-xl bg-primary/10 transition-transform duration-200 ease-out group-hover:scale-105">
24
+ {feature.icon}
25
+ </div>
26
+ <div className="flex flex-col gap-1.5">
27
+ <h3 className="text-base font-semibold text-balance text-foreground md:text-lg">
28
+ {feature.title}
29
+ </h3>
30
+ <p className="text-sm leading-relaxed text-pretty text-muted-foreground">
31
+ {feature.description}
32
+ </p>
33
+ </div>
34
+ </RevealItem>
35
+ ))}
36
+ </RevealGroup>
37
+ </section>
38
+ );
39
+ }
@@ -0,0 +1,65 @@
1
+ import Link from "next/link";
2
+
3
+ import { siteConfig } from "@/config/site.config";
4
+
5
+ import { ThemeToggle } from "@/components/shared/ThemeToggle";
6
+ import { Button } from "@/components/ui/button";
7
+ import { Reveal } from "@/features/landing/components/Reveal";
8
+ import { NextjsIcon, ReactIcon, TailwindIcon } from "@/features/landing/icons";
9
+
10
+ export function Hero() {
11
+ return (
12
+ <section className="mx-auto flex max-w-3xl flex-col items-center gap-6 px-6 pt-24 pb-16 text-center">
13
+ <Reveal mode="mount" delay={0} y={-8}>
14
+ <span className="rounded-full border border-border px-3 py-1 text-xs font-medium text-muted-foreground">
15
+ Premium UI/UX · Agent-ready · Zero bloat
16
+ </span>
17
+ </Reveal>
18
+
19
+ <h1 className="mb-2 text-center text-4xl lg:text-6xl">
20
+ <span className="font-black text-primary">ViraStack</span>{" "}
21
+ <span className="font-medium text-teal-500 italic">Start</span>
22
+ <span className="mt-2 block text-lg font-normal text-muted-foreground lg:text-xl">
23
+ Next.js Edition
24
+ </span>
25
+ </h1>
26
+
27
+ <p className="max-w-2xl text-base leading-relaxed text-balance text-muted-foreground sm:text-lg">
28
+ Built with{" "}
29
+ <span className="inline-flex items-center gap-1 font-semibold text-foreground">
30
+ <NextjsIcon className="h-4 w-4" />
31
+ Next.js 16
32
+ </span>
33
+ ,{" "}
34
+ <span className="inline-flex items-center gap-1 font-semibold text-foreground">
35
+ <ReactIcon className="h-4 w-4" />
36
+ React 19
37
+ </span>
38
+ , and{" "}
39
+ <span className="inline-flex items-center gap-1 font-semibold text-foreground">
40
+ <TailwindIcon className="h-4 w-4" />
41
+ Tailwind CSS 4
42
+ </span>{" "}
43
+ - wired together with <span className="font-medium text-foreground italic">
44
+ Zustand
45
+ </span>, <span className="font-medium text-foreground italic">TanStack Query</span>, and{" "}
46
+ <span className="font-medium text-foreground italic">React Hook Form</span> so you can ship
47
+ a polished product from day one.
48
+ </p>
49
+
50
+ <Reveal mode="mount" delay={0.1} className="mt-2 flex items-center gap-2">
51
+ <Button
52
+ className="h-10 px-4 py-2"
53
+ nativeButton={false}
54
+ render={<Link href={siteConfig.links.github} target="_blank" rel="noreferrer" />}
55
+ >
56
+ <span>⭐</span>
57
+ <span>Star on GitHub</span>
58
+ </Button>
59
+ <div className="h-10 w-10 [&>button]:h-full [&>button]:w-full">
60
+ <ThemeToggle />
61
+ </div>
62
+ </Reveal>
63
+ </section>
64
+ );
65
+ }
@@ -0,0 +1,17 @@
1
+ import { Features } from "@/features/landing/components/Features";
2
+ import { Hero } from "@/features/landing/components/Hero";
3
+ import { Showcase } from "@/features/landing/components/Showcase";
4
+
5
+ /**
6
+ * Demo landing surface. Delete `src/features/landing` and replace
7
+ * `src/app/page.tsx` when you start your own product UI.
8
+ */
9
+ export function LandingPage() {
10
+ return (
11
+ <main className="flex-1">
12
+ <Hero />
13
+ <Features />
14
+ <Showcase />
15
+ </main>
16
+ );
17
+ }
@@ -0,0 +1,62 @@
1
+ "use client";
2
+
3
+ import { zodResolver } from "@hookform/resolvers/zod";
4
+ import { Controller, useForm } from "react-hook-form";
5
+ import { toast } from "sonner";
6
+
7
+ import { Button } from "@/components/ui/button";
8
+ import { FieldDescription, FieldError } from "@/components/ui/field";
9
+ import { Input } from "@/components/ui/input";
10
+ import { Label } from "@/components/ui/label";
11
+ import { projectSchema, type ProjectInput } from "@/features/landing/schemas";
12
+
13
+ export function ProjectFormDemo() {
14
+ const {
15
+ control,
16
+ handleSubmit,
17
+ reset,
18
+ formState: { errors, isSubmitting },
19
+ } = useForm<ProjectInput>({
20
+ resolver: zodResolver(projectSchema),
21
+ defaultValues: { name: "" },
22
+ });
23
+
24
+ async function onSubmit(values: ProjectInput) {
25
+ await new Promise((resolve) => setTimeout(resolve, 600));
26
+ toast.success(`Created project: ${values.name}`);
27
+ reset();
28
+ }
29
+
30
+ return (
31
+ <form onSubmit={handleSubmit(onSubmit)} noValidate className="flex flex-col gap-4">
32
+ <div className="flex flex-col gap-2.5 text-left">
33
+ <Label htmlFor="name">Project Name</Label>
34
+ <Controller
35
+ control={control}
36
+ name="name"
37
+ render={({ field }) => (
38
+ <Input
39
+ id="name"
40
+ type="text"
41
+ placeholder="virastack-app"
42
+ aria-invalid={!!errors.name}
43
+ value={field.value}
44
+ onChange={(event) => field.onChange(event.target.value)}
45
+ onBlur={field.onBlur}
46
+ ref={field.ref}
47
+ />
48
+ )}
49
+ />
50
+ {errors.name ? (
51
+ <FieldError>{errors.name.message}</FieldError>
52
+ ) : (
53
+ <FieldDescription>Use 3–50 characters for the project name.</FieldDescription>
54
+ )}
55
+ </div>
56
+
57
+ <Button type="submit" disabled={isSubmitting}>
58
+ {isSubmitting ? "Creating…" : "Create Project"}
59
+ </Button>
60
+ </form>
61
+ );
62
+ }
@@ -0,0 +1,83 @@
1
+ "use client";
2
+
3
+ import type { ReactNode } from "react";
4
+
5
+ import { motion } from "framer-motion";
6
+
7
+ import { fadeInUp, staggerContainer, viewport } from "@/features/landing/helpers";
8
+
9
+ type RevealProps = {
10
+ children: ReactNode;
11
+ className?: string;
12
+ /** Mount animation delay in seconds (hero-style). Ignored when `mode="view"`. */
13
+ delay?: number;
14
+ /** `mount` = animate on load; `view` = animate when scrolled into view. */
15
+ mode?: "mount" | "view";
16
+ /** Initial Y offset for mount animations. */
17
+ y?: number;
18
+ /**
19
+ * When false (mount mode), only translate — keep opacity at 1 so LCP text
20
+ * is painted on first frame. Default true.
21
+ */
22
+ fadeOpacity?: boolean;
23
+ };
24
+
25
+ /**
26
+ * Client-only motion shell. Keep copy/markup in Server Components and wrap
27
+ * animated regions with this so the page stays SSR-first.
28
+ */
29
+ export function Reveal({
30
+ children,
31
+ className,
32
+ delay = 0,
33
+ mode = "view",
34
+ y = 12,
35
+ fadeOpacity = true,
36
+ }: RevealProps) {
37
+ if (mode === "mount") {
38
+ return (
39
+ <motion.div
40
+ className={className}
41
+ initial={fadeOpacity ? { opacity: 0, y } : { y }}
42
+ animate={fadeOpacity ? { opacity: 1, y: 0 } : { y: 0 }}
43
+ transition={{ duration: 0.45, delay, ease: "easeOut" }}
44
+ >
45
+ {children}
46
+ </motion.div>
47
+ );
48
+ }
49
+
50
+ return (
51
+ <motion.div
52
+ className={className}
53
+ initial="hidden"
54
+ whileInView="visible"
55
+ viewport={viewport}
56
+ variants={fadeInUp}
57
+ >
58
+ {children}
59
+ </motion.div>
60
+ );
61
+ }
62
+
63
+ export function RevealGroup({ children, className }: { children: ReactNode; className?: string }) {
64
+ return (
65
+ <motion.div
66
+ className={className}
67
+ initial="hidden"
68
+ whileInView="visible"
69
+ viewport={viewport}
70
+ variants={staggerContainer}
71
+ >
72
+ {children}
73
+ </motion.div>
74
+ );
75
+ }
76
+
77
+ export function RevealItem({ children, className }: { children: ReactNode; className?: string }) {
78
+ return (
79
+ <motion.div className={className} variants={fadeInUp}>
80
+ {children}
81
+ </motion.div>
82
+ );
83
+ }