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
+ allowBuilds:
2
+ esbuild: true
3
+ lightningcss: true
@@ -0,0 +1,86 @@
1
+ # ViraStack Start — TanStack Start Edition
2
+
3
+ > Premium TanStack Start + 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 TanStack Router file-based routing with type-safe loaders, nested layouts, and SSR via TanStack Start. 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: TanStack Start, TanStack Router, React 19, Tailwind CSS 4, TypeScript (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` (`VITE_*` public vars)
13
+ - Tooling: ESLint 9, Prettier 3, Husky, Knip, Commitlint, Changesets, Vite 8
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, 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/tanstack): 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/): ViraStack
23
+
24
+ ## Key Files & Entry Points
25
+ - [`src/routes/__root.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/routes/__root.tsx): Root route, document shell, providers, SEO head
26
+ - [`src/routes/index.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/routes/index.tsx): Home route → `<LandingPage />`
27
+ - [`src/routes/robots[.]txt.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/src/routes/robots%5B.%5Dtxt.ts): Dynamic robots.txt from `siteConfig`
28
+ - [`src/routes/sitemap[.]xml.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/src/routes/sitemap%5B.%5Dxml.ts): Dynamic sitemap from `siteConfig`
29
+ - [`src/routes/site[.]webmanifest.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/src/routes/site%5B.%5Dwebmanifest.ts): Dynamic web manifest from `siteConfig`
30
+ - [`src/start.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/src/start.ts): Global request middleware (baseline security headers)
31
+ - [`src/router.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/router.tsx): Router factory + TanStack Query SSR integration
32
+ - [`src/env.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/src/env.ts): Zod-validated environment schema (`VITE_*` public vars)
33
+ - [`src/config/site.config.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/src/config/site.config.ts): Site config (name, URL, links)
34
+ - [`src/config/seo.config.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/src/config/seo.config.ts): Default SEO meta helpers
35
+ - [`src/lib/api.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/src/lib/api.ts): Native `fetch` wrapper with retry & typed `ApiError`
36
+ - [`src/lib/query-client.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/src/lib/query-client.ts): QueryClient factory & defaults
37
+ - [`src/providers/Providers.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/providers/Providers.tsx): App-wide providers (Theme, Nuqs, Toaster)
38
+ - [`vite.config.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/vite.config.ts): Vite + TanStack Start + Tailwind
39
+
40
+ ## Landing Feature (demo — delete when building)
41
+ Canonical tree under `src/features/landing/`. Home route composes `LandingPage`.
42
+
43
+ - [`src/features/landing/index.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/src/features/landing/index.ts): Public export (`LandingPage`)
44
+ - [`src/features/landing/components/LandingPage.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/features/landing/components/LandingPage.tsx): Page composition (Header + sections + Footer)
45
+ - [`src/features/landing/components/Hero.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/features/landing/components/Hero.tsx): Hero section
46
+ - [`src/features/landing/components/Features.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/features/landing/components/Features.tsx): Feature grid
47
+ - [`src/features/landing/components/Showcase.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/features/landing/components/Showcase.tsx): Stack demos host (Query, Zustand, forms, nuqs)
48
+ - [`src/features/landing/components/UsersDemo.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/features/landing/components/UsersDemo.tsx): TanStack Query + `nuqs` demo
49
+ - [`src/features/landing/components/CartDemo.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/features/landing/components/CartDemo.tsx): Zustand demo
50
+ - [`src/features/landing/components/ProjectFormDemo.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/features/landing/components/ProjectFormDemo.tsx): RHF + Zod demo
51
+
52
+ Quick start: delete `src/features/landing`, replace `src/routes/index.tsx`, keep `components/layout` if you still want chrome.
53
+
54
+ ## UI & Shared Layers
55
+ - [`src/components/ui`](https://github.com/virastack/start/tree/main/templates/tanstack/src/components/ui): Base UI primitives (Button, Input, Field, Dialog, Tabs, Skeleton, Label, Avatar, Table)
56
+ - [`src/components/layout`](https://github.com/virastack/start/tree/main/templates/tanstack/src/components/layout): Header / Footer (reusable; Header accepts optional `links`)
57
+ - [`src/components/shared`](https://github.com/virastack/start/tree/main/templates/tanstack/src/components/shared): Cross-feature components (ThemeToggle, NotFound, DefaultCatchBoundary)
58
+ - [`src/hooks`](https://github.com/virastack/start/tree/main/templates/tanstack/src/hooks), [`src/stores`](https://github.com/virastack/start/tree/main/templates/tanstack/src/stores), [`src/schemas`](https://github.com/virastack/start/tree/main/templates/tanstack/src/schemas): Shared barrels (promote via Rule of Three)
59
+ - [`src/helpers`](https://github.com/virastack/start/tree/main/templates/tanstack/src/helpers): Shared helpers
60
+ - [`src/styles/tailwind.css`](https://github.com/virastack/start/blob/main/templates/tanstack/src/styles/tailwind.css): Tailwind v4 entry + design tokens
61
+ - Assets: [`public/logo.webp`](https://github.com/virastack/start/blob/main/templates/tanstack/public/logo.webp), [`public/og.png`](https://github.com/virastack/start/blob/main/templates/tanstack/public/og.png), [`public/favicon.ico`](https://github.com/virastack/start/blob/main/templates/tanstack/public/favicon.ico)
62
+
63
+ ## Customization & Imports
64
+ - Search the project for `FIXME:` (site config, auth attachment on the API client).
65
+ - Prefer short path aliases: `@/ui`, `@/hooks`, `@/schemas`, `@/layout` over long forms. Prefer feature-local imports under `@/features/[feature]/…` for demo-scoped code.
66
+ - Default scope is `features/[feature]/` — promote to global `src/` only when a second feature needs it. No cross-feature imports.
67
+
68
+ ## ViraStack AI
69
+ - Install or refresh: `npx @virastack/ai init --force`
70
+ - `AGENTS.md`: Agent operating guide (all agents)
71
+ - `CLAUDE.md`: Claude Code entry point (`@AGENTS.md`)
72
+ - `.cursor/rules/*.mdc`: Scoped coding rules (Cursor auto-loads)
73
+ - `docs/architecture-guide.md`, `docs/MEMORIES.md`: Architecture and project memory
74
+ - Skills: [emilkowalski/skills](https://github.com/emilkowalski/skills) (7 design-engineering skills) + [make-interfaces-feel-better](https://github.com/jakubkrehel/make-interfaces-feel-better)
75
+ - Package: [`@virastack/ai`](https://github.com/virastack/ai)
76
+
77
+ ## External References
78
+ - [TanStack Start Docs](https://tanstack.com/start/latest): Routing, SSR, server functions
79
+ - [TanStack Router](https://tanstack.com/router/latest): File-based routing, loaders, type safety
80
+ - [React](https://react.dev/): Modern React APIs
81
+ - [Tailwind CSS v4](https://tailwindcss.com/): Design tokens & utility-first styling
82
+ - [Base UI](https://base-ui.com/): Unstyled, accessible React components
83
+ - [TanStack Query](https://tanstack.com/query/latest): Server-state syncing & caching
84
+ - [nuqs](https://nuqs.dev/): Type-safe URL search param state
85
+ - [Zod](https://zod.dev/): Runtime validation and parsing
86
+ - [ViraStack AI](https://github.com/virastack/ai): Shared agent rules package (`@virastack/ai`)
Binary file
@@ -0,0 +1,36 @@
1
+ import type { ErrorComponentProps } from "@tanstack/react-router";
2
+ import { Link, rootRouteId, useMatch, useRouter } from "@tanstack/react-router";
3
+
4
+ import { Button } from "@/components/ui/button";
5
+
6
+ export function DefaultCatchBoundary({ error }: ErrorComponentProps) {
7
+ const router = useRouter();
8
+ const isRoot = useMatch({
9
+ strict: false,
10
+ select: (state) => state.id === rootRouteId,
11
+ });
12
+
13
+ console.error(error);
14
+
15
+ return (
16
+ <div className="mx-auto flex flex-1 flex-col items-center justify-center gap-4 px-6 py-24 text-center">
17
+ <h1 className="text-2xl font-semibold tracking-tight">Something went wrong</h1>
18
+ <p className="max-w-md text-sm text-muted-foreground">
19
+ An unexpected error occurred while rendering this page. You can try again, or head back to
20
+ the homepage.
21
+ </p>
22
+ <div className="flex gap-3">
23
+ <Button onClick={() => router.invalidate()}>Try again</Button>
24
+ {isRoot ? (
25
+ <Button variant="outline" nativeButton={false} render={<Link to="/" />}>
26
+ Go home
27
+ </Button>
28
+ ) : (
29
+ <Button variant="outline" onClick={() => window.history.back()}>
30
+ Go back
31
+ </Button>
32
+ )}
33
+ </div>
34
+ </div>
35
+ );
36
+ }
@@ -0,0 +1,18 @@
1
+ import { Link } from "@tanstack/react-router";
2
+
3
+ import { Button } from "@/components/ui/button";
4
+
5
+ export 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 to="/" />}>
14
+ Go home
15
+ </Button>
16
+ </div>
17
+ );
18
+ }
@@ -0,0 +1,13 @@
1
+ import { Skeleton } from "@/components/ui/skeleton";
2
+
3
+ /** Route-level pending UI (TanStack equivalent of Next.js `loading.tsx`). */
4
+ export function Pending() {
5
+ return (
6
+ <div className="mx-auto flex w-full max-w-3xl flex-1 flex-col items-center gap-4 px-6 py-24">
7
+ <Skeleton className="h-10 w-2/3" />
8
+ <Skeleton className="h-4 w-full" />
9
+ <Skeleton className="h-4 w-5/6" />
10
+ <Skeleton className="mt-6 h-40 w-full" />
11
+ </div>
12
+ );
13
+ }
@@ -0,0 +1,31 @@
1
+ "use client";
2
+
3
+ import { MoonIcon, SunIcon } from "lucide-react";
4
+ import { useIsClient } from "usehooks-ts";
5
+
6
+ import { useTheme } from "@/providers/ThemeProvider";
7
+
8
+ import { Button } from "@/components/ui/button";
9
+
10
+ export function ThemeToggle() {
11
+ const { resolvedTheme, setTheme } = useTheme();
12
+ const isClient = useIsClient();
13
+
14
+ if (!isClient) {
15
+ return <Button variant="outline" size="icon" aria-hidden className="size-8 opacity-0" />;
16
+ }
17
+
18
+ const isDark = resolvedTheme === "dark";
19
+
20
+ return (
21
+ <Button
22
+ variant="outline"
23
+ size="icon"
24
+ className="size-8"
25
+ aria-label={isDark ? "Switch to light theme" : "Switch to dark theme"}
26
+ onClick={() => setTheme(isDark ? "light" : "dark")}
27
+ >
28
+ {isDark ? <SunIcon className="size-3.5" /> : <MoonIcon className="size-3.5" />}
29
+ </Button>
30
+ );
31
+ }
@@ -0,0 +1,52 @@
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
+ <img
26
+ ref={ref}
27
+ src={src}
28
+ alt={alt}
29
+ className={cn("aspect-square h-full w-full", status !== "loaded" && "hidden", className)}
30
+ onLoad={() => setStatus("loaded")}
31
+ onError={() => setStatus("error")}
32
+ {...props}
33
+ />
34
+ );
35
+ });
36
+ AvatarImage.displayName = "AvatarImage";
37
+
38
+ const AvatarFallback = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
39
+ ({ className, ...props }, ref) => (
40
+ <div
41
+ ref={ref}
42
+ className={cn(
43
+ "flex h-full w-full items-center justify-center rounded-full bg-muted text-xs",
44
+ className,
45
+ )}
46
+ {...props}
47
+ />
48
+ ),
49
+ );
50
+ AvatarFallback.displayName = "AvatarFallback";
51
+
52
+ export { Avatar, AvatarImage, AvatarFallback };
@@ -0,0 +1,47 @@
1
+ import type { ComponentProps } from "react";
2
+
3
+ import { Button as BaseButton } from "@base-ui/react/button";
4
+ import { cva } from "class-variance-authority";
5
+ import type { VariantProps } from "class-variance-authority";
6
+
7
+ import { cn } from "@/lib/utils";
8
+
9
+ export const buttonVariants = cva(
10
+ "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",
11
+ {
12
+ variants: {
13
+ variant: {
14
+ default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
15
+ destructive:
16
+ "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20",
17
+ outline:
18
+ "border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground",
19
+ secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
20
+ ghost: "hover:bg-accent hover:text-accent-foreground",
21
+ link: "text-primary underline-offset-4 hover:underline",
22
+ },
23
+ size: {
24
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
25
+ sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
26
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
27
+ icon: "size-9",
28
+ },
29
+ },
30
+ defaultVariants: {
31
+ variant: "default",
32
+ size: "default",
33
+ },
34
+ },
35
+ );
36
+
37
+ export type ButtonProps = ComponentProps<typeof BaseButton> & VariantProps<typeof buttonVariants>;
38
+
39
+ export function Button({ className, variant, size, ...props }: ButtonProps) {
40
+ return (
41
+ <BaseButton
42
+ data-slot="button"
43
+ className={cn(buttonVariants({ variant, size, className }))}
44
+ {...props}
45
+ />
46
+ );
47
+ }
@@ -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
+ }
@@ -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 };