create-nolly-template 1.0.3 → 1.0.4

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 (46) hide show
  1. package/dist/builder.js +7 -0
  2. package/dist/registry/index.js +2 -2
  3. package/dist/registry/web/backend/fastify/base.js +7 -7
  4. package/dist/registry/web/backend/fastify/{features/mongodb.js → mongodb.js} +1 -1
  5. package/dist/registry/web/backend/fastify/{features/swagger.js → swagger.js} +1 -1
  6. package/dist/registry/web/backend/fastify/{features/websocket.js → websocket.js} +1 -1
  7. package/dist/registry/web/backend/index.js +5 -3
  8. package/dist/registry/web/frontend/index.js +9 -0
  9. package/dist/registry/web/frontend/vite/base.js +15 -0
  10. package/dist/registry/web/frontend/vite/react.js +71 -0
  11. package/dist/registry/web/frontend/vite/seo.js +39 -0
  12. package/dist/registry/web/fullstack/index.js +9 -0
  13. package/dist/registry/web/fullstack/next.js/base.js +10 -0
  14. package/dist/registry/web/index.js +10 -4
  15. package/package.json +1 -1
  16. package/templates/web/frontend/vite/base/index.html +17 -0
  17. package/templates/web/frontend/vite/base/package.json +20 -0
  18. package/templates/web/frontend/vite/base/public/favicon.svg +4 -0
  19. package/templates/web/frontend/vite/base/src/globals.css +1 -0
  20. package/templates/web/frontend/vite/base/src/main.ts +54 -0
  21. package/templates/web/frontend/vite/base/src/vite-env.d.ts +1 -0
  22. package/templates/web/frontend/vite/base/tsconfig.app.json +26 -0
  23. package/templates/web/frontend/vite/base/tsconfig.json +7 -0
  24. package/templates/web/frontend/vite/base/tsconfig.node.json +16 -0
  25. package/templates/web/frontend/vite/base/vite.config.ts +51 -0
  26. package/templates/web/frontend/vite/react/components.json +25 -0
  27. package/templates/web/frontend/vite/react/pnpm-workspace.yaml +2 -0
  28. package/templates/web/frontend/vite/react/src/app.tsx +30 -0
  29. package/templates/web/frontend/vite/react/src/globals.css +131 -0
  30. package/templates/web/frontend/vite/react/src/lib/utils.ts +6 -0
  31. package/templates/web/frontend/vite/react/src/main.tsx +15 -0
  32. package/templates/web/frontend/vite/seo/seo.config.ts +24 -0
  33. package/templates/web/frontend/vite/seo/vite-plugin-seo.ts +86 -0
  34. package/templates/web/fullstack/nextjs/base/app/favicon.svg +4 -0
  35. package/templates/web/fullstack/nextjs/base/app/globals.css +126 -0
  36. package/templates/web/fullstack/nextjs/base/app/globals.d.ts +9 -0
  37. package/templates/web/fullstack/nextjs/base/app/layout.tsx +23 -0
  38. package/templates/web/fullstack/nextjs/base/app/page.tsx +30 -0
  39. package/templates/web/fullstack/nextjs/base/components.json +25 -0
  40. package/templates/web/fullstack/nextjs/base/lib/utils.ts +6 -0
  41. package/templates/web/fullstack/nextjs/base/next-env.d.ts +6 -0
  42. package/templates/web/fullstack/nextjs/base/next.config.ts +8 -0
  43. package/templates/web/fullstack/nextjs/base/package.json +31 -0
  44. package/templates/web/fullstack/nextjs/base/pnpm-workspace.yaml +3 -0
  45. package/templates/web/fullstack/nextjs/base/postcss.config.mjs +7 -0
  46. package/templates/web/fullstack/nextjs/base/tsconfig.json +34 -0
package/dist/builder.js CHANGED
@@ -19,6 +19,8 @@ function toRegExp(pattern) {
19
19
  function applyPatchOperations(content, operations) {
20
20
  let result = content;
21
21
  for (const op of operations) {
22
+ if (op.type === 'deleteFile')
23
+ continue;
22
24
  const regex = 'pattern' in op ? toRegExp(op.pattern) : undefined;
23
25
  if (op.type === 'replace' && regex) {
24
26
  result = result.replace(regex, op.replacement);
@@ -37,6 +39,11 @@ function applyPatchOperations(content, operations) {
37
39
  }
38
40
  function applyPatches(fileMap, patches) {
39
41
  for (const patch of patches) {
42
+ const hasDelete = patch.operations.some(op => op.type === 'deleteFile');
43
+ if (hasDelete) {
44
+ fileMap.delete(patch.targetPath);
45
+ continue;
46
+ }
40
47
  const current = fileMap.get(patch.targetPath);
41
48
  if (!current)
42
49
  continue;
@@ -1,4 +1,4 @@
1
- import { webCategory } from './web/index.js';
1
+ import { web } from './web/index.js';
2
2
  export const registry = [
3
- webCategory
3
+ web
4
4
  ];
@@ -1,7 +1,7 @@
1
- import { swaggerFeature } from './features/swagger.js';
2
- import { websocketFeature } from './features/websocket.js';
3
- import { mongodbFeature } from './features/mongodb.js';
4
- export const fastifyBase = {
1
+ import { swagger } from './swagger.js';
2
+ import { websocket } from './websocket.js';
3
+ import { mongodb } from './mongodb.js';
4
+ export const fastify = {
5
5
  key: 'fastify',
6
6
  name: 'Fastify TypeScript',
7
7
  description: 'Fastify with TypeScript, auto-registration, health check',
@@ -10,8 +10,8 @@ export const fastifyBase = {
10
10
  ],
11
11
  templateRoot: 'web/backend/fastify/base',
12
12
  features: [
13
- swaggerFeature,
14
- websocketFeature,
15
- mongodbFeature
13
+ swagger,
14
+ websocket,
15
+ mongodb
16
16
  ]
17
17
  };
@@ -1,4 +1,4 @@
1
- export const mongodbFeature = {
1
+ export const mongodb = {
2
2
  key: 'mongodb',
3
3
  name: 'MongoDB support',
4
4
  description: 'Adds MongoDB support',
@@ -1,4 +1,4 @@
1
- export const swaggerFeature = {
1
+ export const swagger = {
2
2
  key: 'swagger',
3
3
  name: 'Swagger / OpenAPI docs',
4
4
  description: 'Adds automatic API documentation with Swagger / OpenAPI',
@@ -1,4 +1,4 @@
1
- export const websocketFeature = {
1
+ export const websocket = {
2
2
  key: 'websocket',
3
3
  name: 'WebSocket support',
4
4
  description: 'Adds WebSocket support',
@@ -1,7 +1,9 @@
1
- import { fastifyBase } from './fastify/base.js';
2
- export const backendSubCategory = {
1
+ import { fastify } from './fastify/base.js';
2
+ export const backend = {
3
3
  key: 'backend',
4
4
  name: 'Backend',
5
5
  description: 'Backend related tools and frameworks',
6
- templates: [fastifyBase],
6
+ templates: [
7
+ fastify
8
+ ],
7
9
  };
@@ -0,0 +1,9 @@
1
+ import { vite } from './vite/base.js';
2
+ export const frontend = {
3
+ key: 'frontend',
4
+ name: 'Frontend',
5
+ description: 'Frontend related tools and frameworks',
6
+ templates: [
7
+ vite
8
+ ],
9
+ };
@@ -0,0 +1,15 @@
1
+ import { react } from './react';
2
+ import { seo } from './seo';
3
+ export const vite = {
4
+ key: 'vite',
5
+ name: 'Vite TypeScript',
6
+ description: 'Vite with TypeScript, React, auto-registration',
7
+ prompts: [
8
+ { type: 'text', name: 'name', message: 'Project name', initial: 'my-vite-app' }
9
+ ],
10
+ templateRoot: 'web/frontend/vite/base',
11
+ features: [
12
+ react,
13
+ seo
14
+ ]
15
+ };
@@ -0,0 +1,71 @@
1
+ export const react = {
2
+ key: 'react',
3
+ name: 'React support',
4
+ description: 'Adds React and Shadcn UI support',
5
+ templateRoot: 'web/frontend/vite/react',
6
+ devDependencies: {
7
+ '@vitejs/plugin-react': '^6.0.1',
8
+ '@types/node': '^20.11.1',
9
+ '@types/react': '^19.2.14',
10
+ '@types/react-dom': '^19.2.3'
11
+ },
12
+ dependencies: {
13
+ '@fontsource-variable/figtree': '^5.2.10',
14
+ 'class-variance-authority': '^0.7.1',
15
+ 'clsx': '^2.1.1',
16
+ 'lucide-react': '^0.577.0',
17
+ 'radix-ui': '^1.4.3',
18
+ 'react': '^19.2.4',
19
+ 'react-dom': '^19.2.4',
20
+ 'react-router-dom': '^7.13.1',
21
+ 'shadcn': '^4.0.8',
22
+ 'tailwind-merge': '^3.5.0',
23
+ 'tw-animate-css': '^1.4.0'
24
+ },
25
+ patches: [
26
+ {
27
+ targetPath: 'tsconfig.app.json',
28
+ operations: [
29
+ {
30
+ type: 'insertAfter',
31
+ pattern: '"skipLibCheck": true',
32
+ insert: ',\n\t\t"jsx": "react-jsx",\n\t\t"paths": {\n\t\t\t"@components/*": ["./src/components/*"],\n\t\t\t"@hooks/*": ["./src/hooks/*"],\n\t\t\t"@lib/*": ["./src/lib/*"]\n\t\t}\n'
33
+ }
34
+ ]
35
+ },
36
+ {
37
+ targetPath: 'vite.config.ts',
38
+ operations: [
39
+ {
40
+ type: 'insertAfter',
41
+ pattern: 'import obfuscator from \'vite-plugin-javascript-obfuscator\'',
42
+ insert: 'import react from \'@vitejs/plugin-react\'\nimport path from \'path\''
43
+ },
44
+ {
45
+ type: 'insertBefore',
46
+ pattern: 'tailwindcss\\(\\)',
47
+ insert: 'react(), '
48
+ },
49
+ {
50
+ type: 'insertAfter',
51
+ pattern: 'base: \'./\',',
52
+ insert: '\tresolve: {\n\t\talias: {\n\t\t\t\'@components\': path.resolve(__dirname, \'./src/components\'),\n\t\t\t\'@hooks\': path.resolve(__dirname, \'./src/hooks\'),\n\t\t\t\'@lib\': path.resolve(__dirname, \'./src/lib/\')\n\t\t}\n\t},'
53
+ }
54
+ ]
55
+ },
56
+ {
57
+ targetPath: 'index.html',
58
+ operations: [
59
+ {
60
+ type: 'replace',
61
+ pattern: 'main\.ts',
62
+ replacement: 'main.tsx'
63
+ }
64
+ ]
65
+ },
66
+ {
67
+ targetPath: 'src/main.ts',
68
+ operations: [{ type: 'deleteFile' }]
69
+ }
70
+ ]
71
+ };
@@ -0,0 +1,39 @@
1
+ export const seo = {
2
+ key: 'seo',
3
+ name: 'SEO optimization',
4
+ description: 'Adds a custom SEO vite plugin to optimize your app for search engines and social media sharing',
5
+ templateRoot: 'web/frontend/vite/seo',
6
+ dependencies: {
7
+ 'sitemap': '^9.0.1',
8
+ },
9
+ patches: [
10
+ {
11
+ targetPath: 'index.html',
12
+ operations: [
13
+ {
14
+ type: 'remove',
15
+ pattern: /<title>.*<\/title>/,
16
+ },
17
+ {
18
+ type: 'remove',
19
+ pattern: /<meta name='description' content='.*'>/,
20
+ }
21
+ ]
22
+ },
23
+ {
24
+ targetPath: 'vite.config.ts',
25
+ operations: [
26
+ {
27
+ type: 'insertAfter',
28
+ pattern: 'import obfuscator from \'vite-plugin-javascript-obfuscator\'',
29
+ insert: 'import { viteSEO } from \'./vite-plugin-seo\''
30
+ },
31
+ {
32
+ type: 'insertBefore',
33
+ pattern: 'tailwindcss\\(\\)',
34
+ insert: 'viteSEO(), '
35
+ }
36
+ ]
37
+ }
38
+ ]
39
+ };
@@ -0,0 +1,9 @@
1
+ import { nextJs } from './next.js/base.js';
2
+ export const fullstack = {
3
+ key: 'fullstack',
4
+ name: 'Fullstack',
5
+ description: 'Fullstack related tools and frameworks',
6
+ templates: [
7
+ nextJs,
8
+ ],
9
+ };
@@ -0,0 +1,10 @@
1
+ export const nextJs = {
2
+ key: 'nextjs',
3
+ name: 'Next.js',
4
+ description: 'Next.js with TypeScript, React, Tailwind CSS, and Shasdcn UI pre-configured',
5
+ prompts: [
6
+ { type: 'text', name: 'name', message: 'Project name', initial: 'my-nextjs-app' }
7
+ ],
8
+ templateRoot: 'web/fullstack/nextjs/base',
9
+ features: []
10
+ };
@@ -1,7 +1,13 @@
1
- import { backendSubCategory } from './backend/index.js';
2
- export const webCategory = {
1
+ import { frontend } from './frontend/index.js';
2
+ import { backend } from './backend/index.js';
3
+ import { fullstack } from './fullstack/index.js';
4
+ export const web = {
3
5
  key: 'web',
4
6
  name: 'Web',
5
- description: 'Web development templates and tools.',
6
- subCategories: [backendSubCategory],
7
+ description: 'A collection of web templates for frontend, backend, and fullstack development',
8
+ subCategories: [
9
+ frontend,
10
+ backend,
11
+ fullstack,
12
+ ],
7
13
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-nolly-template",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "All of my opiniated templates in one place. This is a CLI tool to create a new project based on one of my templates.",
5
5
  "keywords": [
6
6
  "template",
@@ -0,0 +1,17 @@
1
+ <!DOCTYPE html>
2
+ <html lang='en'>
3
+
4
+ <head>
5
+ <meta charset='UTF-8'>
6
+ <meta name='viewport' content='width=device-width, initial-scale=1.0'>
7
+
8
+ <title>{{name}}</title>
9
+ <link rel='icon' href='/favicon.svg' type='image/svg+xml'>
10
+
11
+ <script type='module' src='/src/main.ts'></script>
12
+ </head>
13
+
14
+ <body>
15
+ </body>
16
+
17
+ </html>
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "{{name}}",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "scripts": {
8
+ "dev": "vite",
9
+ "build": "tsc && vite build",
10
+ "preview": "vite preview"
11
+ },
12
+ "devDependencies": {
13
+ "@tailwindcss/vite": "^4.2.1",
14
+ "tailwindcss": "^4.2.1",
15
+ "terser": "^5.46.0",
16
+ "typescript": "^5.9.3",
17
+ "vite": "^8.0.0",
18
+ "vite-plugin-javascript-obfuscator": "^3.1.0"
19
+ }
20
+ }
@@ -0,0 +1,4 @@
1
+ <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'>
2
+ <rect width='32' height='32' rx='6' fill='#1a1a1a' />
3
+ <text x='50%' y='55%' dominant-baseline='middle' text-anchor='middle' font-size='18' fill='#ff88ff' font-family='sans-serif'>N</text>
4
+ </svg>
@@ -0,0 +1 @@
1
+ @import 'tailwindcss';
@@ -0,0 +1,54 @@
1
+ import './globals.css'
2
+
3
+ const container = document.createElement('div')
4
+ container.classList.add('min-h-screen', 'bg-gray-50', 'flex', 'items-center', 'justify-center')
5
+ document.body.appendChild(container)
6
+
7
+ const content = document.createElement('div')
8
+ content.classList.add('text-center', 'space-y-3')
9
+ container.appendChild(content)
10
+
11
+ const heading = document.createElement('h1')
12
+ heading.classList.add('text-6xl', 'font-extrabold', 'tracking-tight', 'text-gray-900')
13
+ heading.textContent = 'Welcome to your {{name}} App'
14
+ content.appendChild(heading)
15
+
16
+ const subHeading = document.createElement('h2')
17
+ subHeading.classList.add('text-4xl', 'font-bold', 'tracking-tight', 'text-gray-900')
18
+ subHeading.textContent = 'Vite + TypeScript + Tailwind'
19
+ content.appendChild(subHeading)
20
+
21
+ const paragraph = document.createElement('p')
22
+ paragraph.classList.add('text-gray-500', 'text-sm')
23
+ paragraph.innerHTML = `Edit <code class='bg-gray-100 px-1.5 py-0.5 rounded font-mono text-gray-700'>src/main.ts</code> to get started`
24
+ content.appendChild(paragraph)
25
+
26
+ const links = document.createElement('div')
27
+ links.classList.add('flex', 'justify-center', 'space-x-4', 'mt-4')
28
+ content.appendChild(links)
29
+
30
+ const viteLink = document.createElement('a')
31
+ viteLink.classList.add('text-sm', 'text-blue-600', 'hover:underline')
32
+ viteLink.href = 'https://vitejs.dev/guide/features.html'
33
+ viteLink.target = '_blank'
34
+ viteLink.textContent = 'Learn more about Vite'
35
+ links.appendChild(viteLink)
36
+
37
+ const tailwindLink = document.createElement('a')
38
+ tailwindLink.classList.add('text-sm', 'text-blue-600', 'hover:underline', 'ml-4')
39
+ tailwindLink.href = 'https://tailwindcss.com/docs'
40
+ tailwindLink.target = '_blank'
41
+ tailwindLink.textContent = 'Learn more about Tailwind'
42
+ links.appendChild(tailwindLink)
43
+
44
+ const tsLink = document.createElement('a')
45
+ tsLink.classList.add('text-sm', 'text-blue-600', 'hover:underline', 'ml-4')
46
+ tsLink.href = 'https://www.typescriptlang.org/docs/'
47
+ tsLink.target = '_blank'
48
+ tsLink.textContent = 'Learn more about TypeScript'
49
+ links.appendChild(tsLink)
50
+
51
+ const footer = document.createElement('footer')
52
+ footer.classList.add('text-center', 'text-gray-500', 'text-sm', 'mt-8')
53
+ footer.innerHTML = `Made with <a href='https://npmjs.com/create-nolly-template' class='text-rose-600 hover:underline' target='_blank'><code class='bg-gray-100 px-1.5 py-0.5 rounded font-mono text-gray-700'>Nolly's Template</code></a> by <a href='https://thenolle.com' class='text-pink-600 hover:underline' target='_blank'>Nolly</a>`
54
+ content.appendChild(footer)
@@ -0,0 +1 @@
1
+ /// <reference types='vite/client' />
@@ -0,0 +1,26 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "useDefineForClassFields": true,
5
+ "lib": [
6
+ "ES2022",
7
+ "DOM",
8
+ "DOM.Iterable"
9
+ ],
10
+ "module": "ESNext",
11
+ "moduleResolution": "bundler",
12
+ "allowImportingTsExtensions": true,
13
+ "isolatedModules": true,
14
+ "moduleDetection": "force",
15
+ "noEmit": true,
16
+ "strict": true,
17
+ "noUnusedLocals": true,
18
+ "noUnusedParameters": true,
19
+ "noFallthroughCasesInSwitch": true,
20
+ "noUncheckedSideEffectImports": true,
21
+ "skipLibCheck": true
22
+ },
23
+ "include": [
24
+ "src"
25
+ ]
26
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ { "path": "./tsconfig.app.json" },
5
+ { "path": "./tsconfig.node.json" }
6
+ ]
7
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": [
5
+ "ES2022"
6
+ ],
7
+ "module": "ESNext",
8
+ "moduleResolution": "bundler",
9
+ "noEmit": true,
10
+ "strict": true,
11
+ "skipLibCheck": true
12
+ },
13
+ "include": [
14
+ "vite.config.ts"
15
+ ]
16
+ }
@@ -0,0 +1,51 @@
1
+ import { defineConfig } from 'vite'
2
+ import tailwindcss from '@tailwindcss/vite'
3
+ import obfuscator from 'vite-plugin-javascript-obfuscator'
4
+
5
+ export default defineConfig({
6
+ plugins: [tailwindcss(), obfuscator({
7
+ options: {
8
+ compact: true,
9
+ controlFlowFlattening: true,
10
+ deadCodeInjection: true,
11
+ identifierNamesGenerator: 'hexadecimal',
12
+ renameGlobals: true,
13
+ selfDefending: true,
14
+ stringArray: true,
15
+ stringArrayEncoding: ['base64'],
16
+ stringArrayThreshold: 0.75
17
+ }
18
+ })],
19
+ base: './',
20
+ build: {
21
+ outDir: 'dist',
22
+ emptyOutDir: true,
23
+ minify: 'terser',
24
+ terserOptions: {
25
+ compress: {
26
+ passes: 3,
27
+ drop_console: true,
28
+ drop_debugger: true,
29
+ pure_funcs: ['console.log'],
30
+ unsafe: true,
31
+ unsafe_arrows: true,
32
+ unsafe_methods: true,
33
+ },
34
+ mangle: {
35
+ toplevel: true,
36
+ },
37
+ format: {
38
+ comments: false,
39
+ },
40
+ },
41
+ rolldownOptions: {
42
+ output: {
43
+ chunkFileNames: 'assets/js/[name]-[hash].js',
44
+ entryFileNames: 'assets/js/[name]-[hash].js',
45
+ assetFileNames: 'assets/[ext]/[name]-[hash].[ext]',
46
+ }
47
+ },
48
+ modulePreload: true,
49
+ sourcemap: false,
50
+ }
51
+ })
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema.json",
3
+ "style": "radix-mira",
4
+ "rsc": false,
5
+ "tsx": true,
6
+ "tailwind": {
7
+ "config": "",
8
+ "css": "src/globals.css",
9
+ "baseColor": "zinc",
10
+ "cssVariables": true,
11
+ "prefix": ""
12
+ },
13
+ "iconLibrary": "lucide",
14
+ "rtl": false,
15
+ "aliases": {
16
+ "components": "@components",
17
+ "utils": "@lib/utils",
18
+ "ui": "@components/ui",
19
+ "lib": "@lib",
20
+ "hooks": "@hooks"
21
+ },
22
+ "menuColor": "default-translucent",
23
+ "menuAccent": "subtle",
24
+ "registries": {}
25
+ }
@@ -0,0 +1,2 @@
1
+ onlyBuiltDependencies:
2
+ - msw
@@ -0,0 +1,30 @@
1
+ export function App(): React.ReactElement | null {
2
+ return (
3
+ <div className='min-h-screen bg-gray-50 flex items-center justify-center'>
4
+ <div className='text-center space-y-3'>
5
+ <h1 className='text-4xl font-bold tracking-tight text-gray-900'>Welcome to your {{name}} App</h1>
6
+ <h2 className='text-2xl font-semibold tracking-tight text-gray-900'>Vite + React + TypeScript + Tailwind + Shadcn UI</h2>
7
+ <p className='text-gray-500 text-sm'>
8
+ Edit{' '}
9
+ <code className='bg-gray-100 px-1.5 py-0.5 rounded font-mono text-gray-700'>src/App.tsx</code>
10
+ {' '}to get started
11
+ </p>
12
+ <div className='flex justify-center space-x-4 mt-4'>
13
+ <a className='text-sm text-blue-600 hover:underline' href='https://vitejs.dev/guide/features.html' target='_blank'>Learn more about Vite</a>
14
+ <a className='text-sm text-blue-600 hover:underline ml-4' href='https://react.dev/learn' target='_blank'>Learn more about React</a>
15
+ <a className='text-sm text-blue-600 hover:underline ml-4' href='https://www.typescriptlang.org/docs/' target='_blank'>Learn more about TypeScript</a>
16
+ <a className='text-sm text-blue-600 hover:underline ml-4' href='https://tailwindcss.com/docs' target='_blank'>Learn more about Tailwind</a>
17
+ <a className='text-sm text-blue-600 hover:underline ml-4' href='https://ui.shadcn.com/docs' target='_blank'>Learn more about Shadcn UI</a>
18
+ </div>
19
+ <footer className='text-center text-gray-500 text-sm mt-8'>
20
+ Made with{' '}
21
+ <a href='https://npmjs.com/create-nolly-template' className='text-rose-600 hover:underline' target='_blank'>
22
+ <code className='bg-gray-100 px-1.5 py-0.5 rounded font-mono text-gray-700'>Nolly's Template</code>
23
+ </a>{' '}
24
+ by{' '}
25
+ <a href='https://thenolle.com' className='text-pink-600 hover:underline' target='_blank'>Nolly</a>
26
+ </footer>
27
+ </div>
28
+ </div>
29
+ )
30
+ }
@@ -0,0 +1,131 @@
1
+ @import 'tailwindcss';
2
+ @import 'tw-animate-css';
3
+ @import 'shadcn/tailwind.css';
4
+ @import '@fontsource-variable/figtree';
5
+
6
+ @custom-variant dark (&:is(.dark *));
7
+
8
+ :root {
9
+ --background: oklch(1 0 0);
10
+ --foreground: oklch(0.141 0.005 285.823);
11
+ --card: oklch(1 0 0);
12
+ --card-foreground: oklch(0.141 0.005 285.823);
13
+ --popover: oklch(1 0 0);
14
+ --popover-foreground: oklch(0.141 0.005 285.823);
15
+ --primary: oklch(0.514 0.222 16.935);
16
+ --primary-foreground: oklch(0.969 0.015 12.422);
17
+ --secondary: oklch(0.967 0.001 286.375);
18
+ --secondary-foreground: oklch(0.21 0.006 285.885);
19
+ --muted: oklch(0.967 0.001 286.375);
20
+ --muted-foreground: oklch(0.552 0.016 285.938);
21
+ --accent: oklch(0.967 0.001 286.375);
22
+ --accent-foreground: oklch(0.21 0.006 285.885);
23
+ --destructive: oklch(0.577 0.245 27.325);
24
+ --border: oklch(0.92 0.004 286.32);
25
+ --input: oklch(0.92 0.004 286.32);
26
+ --ring: oklch(0.705 0.015 286.067);
27
+ --chart-1: oklch(0.81 0.117 11.638);
28
+ --chart-2: oklch(0.645 0.246 16.439);
29
+ --chart-3: oklch(0.586 0.253 17.585);
30
+ --chart-4: oklch(0.514 0.222 16.935);
31
+ --chart-5: oklch(0.455 0.188 13.697);
32
+ --radius: 0.45rem;
33
+ --sidebar: oklch(0.985 0 0);
34
+ --sidebar-foreground: oklch(0.141 0.005 285.823);
35
+ --sidebar-primary: oklch(0.586 0.253 17.585);
36
+ --sidebar-primary-foreground: oklch(0.969 0.015 12.422);
37
+ --sidebar-accent: oklch(0.967 0.001 286.375);
38
+ --sidebar-accent-foreground: oklch(0.21 0.006 285.885);
39
+ --sidebar-border: oklch(0.92 0.004 286.32);
40
+ --sidebar-ring: oklch(0.705 0.015 286.067);
41
+ }
42
+
43
+ .dark {
44
+ --background: oklch(0.141 0.005 285.823);
45
+ --foreground: oklch(0.985 0 0);
46
+ --card: oklch(0.21 0.006 285.885);
47
+ --card-foreground: oklch(0.985 0 0);
48
+ --popover: oklch(0.21 0.006 285.885);
49
+ --popover-foreground: oklch(0.985 0 0);
50
+ --primary: oklch(0.455 0.188 13.697);
51
+ --primary-foreground: oklch(0.969 0.015 12.422);
52
+ --secondary: oklch(0.274 0.006 286.033);
53
+ --secondary-foreground: oklch(0.985 0 0);
54
+ --muted: oklch(0.274 0.006 286.033);
55
+ --muted-foreground: oklch(0.705 0.015 286.067);
56
+ --accent: oklch(0.274 0.006 286.033);
57
+ --accent-foreground: oklch(0.985 0 0);
58
+ --destructive: oklch(0.704 0.191 22.216);
59
+ --border: oklch(1 0 0 / 10%);
60
+ --input: oklch(1 0 0 / 15%);
61
+ --ring: oklch(0.552 0.016 285.938);
62
+ --chart-1: oklch(0.81 0.117 11.638);
63
+ --chart-2: oklch(0.645 0.246 16.439);
64
+ --chart-3: oklch(0.586 0.253 17.585);
65
+ --chart-4: oklch(0.514 0.222 16.935);
66
+ --chart-5: oklch(0.455 0.188 13.697);
67
+ --sidebar: oklch(0.21 0.006 285.885);
68
+ --sidebar-foreground: oklch(0.985 0 0);
69
+ --sidebar-primary: oklch(0.645 0.246 16.439);
70
+ --sidebar-primary-foreground: oklch(0.969 0.015 12.422);
71
+ --sidebar-accent: oklch(0.274 0.006 286.033);
72
+ --sidebar-accent-foreground: oklch(0.985 0 0);
73
+ --sidebar-border: oklch(1 0 0 / 10%);
74
+ --sidebar-ring: oklch(0.552 0.016 285.938);
75
+ }
76
+
77
+ @theme inline {
78
+ --font-sans: 'Figtree Variable', sans-serif;
79
+ --color-sidebar-ring: var(--sidebar-ring);
80
+ --color-sidebar-border: var(--sidebar-border);
81
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
82
+ --color-sidebar-accent: var(--sidebar-accent);
83
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
84
+ --color-sidebar-primary: var(--sidebar-primary);
85
+ --color-sidebar-foreground: var(--sidebar-foreground);
86
+ --color-sidebar: var(--sidebar);
87
+ --color-chart-5: var(--chart-5);
88
+ --color-chart-4: var(--chart-4);
89
+ --color-chart-3: var(--chart-3);
90
+ --color-chart-2: var(--chart-2);
91
+ --color-chart-1: var(--chart-1);
92
+ --color-ring: var(--ring);
93
+ --color-input: var(--input);
94
+ --color-border: var(--border);
95
+ --color-destructive: var(--destructive);
96
+ --color-accent-foreground: var(--accent-foreground);
97
+ --color-accent: var(--accent);
98
+ --color-muted-foreground: var(--muted-foreground);
99
+ --color-muted: var(--muted);
100
+ --color-secondary-foreground: var(--secondary-foreground);
101
+ --color-secondary: var(--secondary);
102
+ --color-primary-foreground: var(--primary-foreground);
103
+ --color-primary: var(--primary);
104
+ --color-popover-foreground: var(--popover-foreground);
105
+ --color-popover: var(--popover);
106
+ --color-card-foreground: var(--card-foreground);
107
+ --color-card: var(--card);
108
+ --color-foreground: var(--foreground);
109
+ --color-background: var(--background);
110
+ --radius-sm: calc(var(--radius) * 0.6);
111
+ --radius-md: calc(var(--radius) * 0.8);
112
+ --radius-lg: var(--radius);
113
+ --radius-xl: calc(var(--radius) * 1.4);
114
+ --radius-2xl: calc(var(--radius) * 1.8);
115
+ --radius-3xl: calc(var(--radius) * 2.2);
116
+ --radius-4xl: calc(var(--radius) * 2.6);
117
+ }
118
+
119
+ @layer base {
120
+ * {
121
+ @apply border-border outline-ring/50;
122
+ }
123
+
124
+ body {
125
+ @apply bg-background text-foreground;
126
+ }
127
+
128
+ html {
129
+ @apply font-sans;
130
+ }
131
+ }
@@ -0,0 +1,6 @@
1
+ import { clsx, type ClassValue } from 'clsx'
2
+ import { twMerge } from 'tailwind-merge'
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs))
6
+ }
@@ -0,0 +1,15 @@
1
+ import './globals.css'
2
+
3
+ import React from 'react'
4
+ import ReactDOM from 'react-dom/client'
5
+ import {BrowserRouter} from 'react-router-dom'
6
+
7
+ import { App } from './app'
8
+
9
+ ReactDOM.createRoot(document.body).render(
10
+ <React.StrictMode>
11
+ <BrowserRouter>
12
+ <App />
13
+ </BrowserRouter>
14
+ </React.StrictMode>,
15
+ )
@@ -0,0 +1,24 @@
1
+ export const SEO = {
2
+ siteName: '{{name}}',
3
+ title: '{{name}} – An App made with Nolly\'s Template',
4
+ description: 'A Vite + TypeScript + Tailwind CSS boilerplate template for your next web app, made with love by Nolly',
5
+ siteUrl: 'https://npmjs.com/create-nolly-template',
6
+
7
+ author: 'Nolly',
8
+
9
+ keywords: [
10
+ 'vite.js',
11
+ 'typescript',
12
+ 'boilerplate',
13
+ 'template',
14
+ 'nolly',
15
+ ],
16
+
17
+ socialImage: '/favicon.svg',
18
+
19
+ locale: 'en_US',
20
+
21
+ pages: [
22
+ '/',
23
+ ]
24
+ }
@@ -0,0 +1,86 @@
1
+ import type { Plugin } from 'vite'
2
+ import { writeFileSync, mkdirSync } from 'fs'
3
+ import { resolve } from 'path'
4
+ import { SitemapStream, streamToPromise } from 'sitemap'
5
+ import { SEO } from './seo.config'
6
+
7
+ export function viteSEO(): Plugin {
8
+ return {
9
+ name: 'vite-seo',
10
+ transformIndexHtml(html) {
11
+ const meta = `
12
+ <title>${SEO.title}</title>
13
+
14
+ <meta name='description' content='${SEO.description}'>
15
+ <meta name='keywords' content='${SEO.keywords.join(', ')}'>
16
+ <meta name='author' content='${SEO.author}'>
17
+ <meta name='robots' content='index, follow'>
18
+
19
+ <link rel='canonical' href='${SEO.siteUrl}'>
20
+
21
+ <meta property='og:type' content='website'>
22
+ <meta property='og:title' content='${SEO.title}'>
23
+ <meta property='og:description' content='${SEO.description}'>
24
+ <meta property='og:url' content='${SEO.siteUrl}'>
25
+ <meta property='og:site_name' content='${SEO.siteName}'>
26
+ <meta property='og:image' content='${SEO.siteUrl}${SEO.socialImage}'>
27
+ <meta property='og:locale' content='${SEO.locale}'>
28
+
29
+ <script type='application/ld+json'>
30
+ ${JSON.stringify({
31
+ '@context': 'https://schema.org',
32
+ '@type': 'WebSite',
33
+ 'name': SEO.siteName,
34
+ 'url': SEO.siteUrl,
35
+ 'description': SEO.description,
36
+ 'publisher': {
37
+ '@type': 'Person',
38
+ 'name': SEO.author
39
+ }
40
+ }, null, 2)}
41
+ </script>
42
+ `
43
+ return html.replace('</head>', `${meta}\n</head>`)
44
+ },
45
+ async closeBundle() {
46
+ const sitemap = new SitemapStream({ hostname: SEO.siteUrl })
47
+ for (const page of SEO.pages) sitemap.write({ url: `${SEO.siteUrl}${page}`, changefreq: 'weekly', priority: 0.8 })
48
+ sitemap.end()
49
+ const data = await streamToPromise(sitemap)
50
+ const dist = resolve(process.cwd(), 'dist')
51
+ mkdirSync(dist, { recursive: true })
52
+ writeFileSync(resolve(dist, 'sitemap.xml'), data.toString())
53
+ createRobotsTxt()
54
+ }
55
+ }
56
+ }
57
+
58
+ function createRobotsTxt() {
59
+ const content = `User-agent: *
60
+ Allow: /
61
+
62
+ User-agent: GPTBot
63
+ Disallow: /
64
+
65
+ User-agent: Google-Extended
66
+ Disallow: /
67
+
68
+ User-agent: CCBot
69
+ Disallow: /
70
+
71
+ User-agent: ClaudeBot
72
+ Disallow: /
73
+
74
+ User-agent: PerplexityBot
75
+ Disallow: /
76
+
77
+ User-agent: Amazonbot
78
+ Disallow: /
79
+
80
+ Sitemap: ${SEO.siteUrl}/sitemap.xml
81
+ `
82
+
83
+ const dist = resolve(process.cwd(), 'dist')
84
+ mkdirSync(dist, { recursive: true })
85
+ writeFileSync(resolve(dist, 'robots.txt'), content)
86
+ }
@@ -0,0 +1,4 @@
1
+ <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'>
2
+ <rect width='32' height='32' rx='6' fill='#1a1a1a' />
3
+ <text x='50%' y='55%' dominant-baseline='middle' text-anchor='middle' font-size='18' fill='#ff88ff' font-family='sans-serif'>N</text>
4
+ </svg>
@@ -0,0 +1,126 @@
1
+ @import 'tailwindcss';
2
+ @import 'tw-animate-css';
3
+ @import 'shadcn/tailwind.css';
4
+
5
+ @custom-variant dark (&:is(.dark *));
6
+
7
+ @theme inline {
8
+ --color-background: var(--background);
9
+ --color-foreground: var(--foreground);
10
+ --font-sans: var(--font-sans);
11
+ --font-mono: var(--font-geist-mono);
12
+ --color-sidebar-ring: var(--sidebar-ring);
13
+ --color-sidebar-border: var(--sidebar-border);
14
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
15
+ --color-sidebar-accent: var(--sidebar-accent);
16
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
17
+ --color-sidebar-primary: var(--sidebar-primary);
18
+ --color-sidebar-foreground: var(--sidebar-foreground);
19
+ --color-sidebar: var(--sidebar);
20
+ --color-chart-5: var(--chart-5);
21
+ --color-chart-4: var(--chart-4);
22
+ --color-chart-3: var(--chart-3);
23
+ --color-chart-2: var(--chart-2);
24
+ --color-chart-1: var(--chart-1);
25
+ --color-ring: var(--ring);
26
+ --color-input: var(--input);
27
+ --color-border: var(--border);
28
+ --color-destructive: var(--destructive);
29
+ --color-accent-foreground: var(--accent-foreground);
30
+ --color-accent: var(--accent);
31
+ --color-muted-foreground: var(--muted-foreground);
32
+ --color-muted: var(--muted);
33
+ --color-secondary-foreground: var(--secondary-foreground);
34
+ --color-secondary: var(--secondary);
35
+ --color-primary-foreground: var(--primary-foreground);
36
+ --color-primary: var(--primary);
37
+ --color-popover-foreground: var(--popover-foreground);
38
+ --color-popover: var(--popover);
39
+ --color-card-foreground: var(--card-foreground);
40
+ --color-card: var(--card);
41
+ --radius-sm: calc(var(--radius) - 4px);
42
+ --radius-md: calc(var(--radius) - 2px);
43
+ --radius-lg: var(--radius);
44
+ --radius-xl: calc(var(--radius) + 4px);
45
+ --radius-2xl: calc(var(--radius) + 8px);
46
+ --radius-3xl: calc(var(--radius) + 12px);
47
+ --radius-4xl: calc(var(--radius) + 16px);
48
+ }
49
+
50
+ :root {
51
+ --background: oklch(1 0 0);
52
+ --foreground: oklch(0.145 0 0);
53
+ --card: oklch(1 0 0);
54
+ --card-foreground: oklch(0.145 0 0);
55
+ --popover: oklch(1 0 0);
56
+ --popover-foreground: oklch(0.145 0 0);
57
+ --primary: oklch(0.577 0.245 27.325);
58
+ --primary-foreground: oklch(0.971 0.013 17.38);
59
+ --secondary: oklch(0.967 0.001 286.375);
60
+ --secondary-foreground: oklch(0.21 0.006 285.885);
61
+ --muted: oklch(0.97 0 0);
62
+ --muted-foreground: oklch(0.556 0 0);
63
+ --accent: oklch(0.97 0 0);
64
+ --accent-foreground: oklch(0.205 0 0);
65
+ --destructive: oklch(0.58 0.22 27);
66
+ --border: oklch(0.922 0 0);
67
+ --input: oklch(0.922 0 0);
68
+ --ring: oklch(0.708 0 0);
69
+ --chart-1: oklch(0.808 0.114 19.571);
70
+ --chart-2: oklch(0.637 0.237 25.331);
71
+ --chart-3: oklch(0.577 0.245 27.325);
72
+ --chart-4: oklch(0.505 0.213 27.518);
73
+ --chart-5: oklch(0.444 0.177 26.899);
74
+ --radius: 0.45rem;
75
+ --sidebar: oklch(0.985 0 0);
76
+ --sidebar-foreground: oklch(0.145 0 0);
77
+ --sidebar-primary: oklch(0.577 0.245 27.325);
78
+ --sidebar-primary-foreground: oklch(0.971 0.013 17.38);
79
+ --sidebar-accent: oklch(0.97 0 0);
80
+ --sidebar-accent-foreground: oklch(0.205 0 0);
81
+ --sidebar-border: oklch(0.922 0 0);
82
+ --sidebar-ring: oklch(0.708 0 0);
83
+ }
84
+
85
+ .dark {
86
+ --background: oklch(0.145 0 0);
87
+ --foreground: oklch(0.985 0 0);
88
+ --card: oklch(0.205 0 0);
89
+ --card-foreground: oklch(0.985 0 0);
90
+ --popover: oklch(0.205 0 0);
91
+ --popover-foreground: oklch(0.985 0 0);
92
+ --primary: oklch(0.637 0.237 25.331);
93
+ --primary-foreground: oklch(0.971 0.013 17.38);
94
+ --secondary: oklch(0.274 0.006 286.033);
95
+ --secondary-foreground: oklch(0.985 0 0);
96
+ --muted: oklch(0.269 0 0);
97
+ --muted-foreground: oklch(0.708 0 0);
98
+ --accent: oklch(0.371 0 0);
99
+ --accent-foreground: oklch(0.985 0 0);
100
+ --destructive: oklch(0.704 0.191 22.216);
101
+ --border: oklch(1 0 0 / 10%);
102
+ --input: oklch(1 0 0 / 15%);
103
+ --ring: oklch(0.556 0 0);
104
+ --chart-1: oklch(0.808 0.114 19.571);
105
+ --chart-2: oklch(0.637 0.237 25.331);
106
+ --chart-3: oklch(0.577 0.245 27.325);
107
+ --chart-4: oklch(0.505 0.213 27.518);
108
+ --chart-5: oklch(0.444 0.177 26.899);
109
+ --sidebar: oklch(0.205 0 0);
110
+ --sidebar-foreground: oklch(0.985 0 0);
111
+ --sidebar-primary: oklch(0.637 0.237 25.331);
112
+ --sidebar-primary-foreground: oklch(0.971 0.013 17.38);
113
+ --sidebar-accent: oklch(0.269 0 0);
114
+ --sidebar-accent-foreground: oklch(0.985 0 0);
115
+ --sidebar-border: oklch(1 0 0 / 10%);
116
+ --sidebar-ring: oklch(0.556 0 0);
117
+ }
118
+
119
+ @layer base {
120
+ * {
121
+ @apply border-border outline-ring/50;
122
+ }
123
+ body {
124
+ @apply bg-background text-foreground;
125
+ }
126
+ }
@@ -0,0 +1,9 @@
1
+ declare module '*.module.css' {
2
+ const classes: { readonly [key: string]: string }
3
+ export default classes
4
+ }
5
+
6
+ declare module '*.css' {
7
+ const content: { [className: string]: string }
8
+ export default content
9
+ }
@@ -0,0 +1,23 @@
1
+ import './globals.css'
2
+ import { Geist, Geist_Mono, Outfit } from 'next/font/google'
3
+ import type { Metadata } from 'next'
4
+
5
+ const outfit = Outfit({ subsets: ['latin'], variable: '--font-sans' })
6
+ const geistSans = Geist({ subsets: ['latin'], variable: '--font-geist-sans' })
7
+ const geistMono = Geist_Mono({ subsets: ['latin'], variable: '--font-geist-mono' })
8
+
9
+ export const metadata: Metadata = {
10
+ title: '{{name}} – An App made with Nolly\'s Template',
11
+ description: 'A Next.js + TypeScript + Tailwind CSS boilerplate template for your next web app, made with love by Nolly',
12
+ icons: { icon: '/favicon.svg', apple: '/favicon.svg' },
13
+ }
14
+
15
+ export default async function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) {
16
+ return (
17
+ <html lang={'en'} suppressHydrationWarning>
18
+ <body className={`${outfit.variable} ${geistSans.variable} ${geistMono.variable} antialiased`}>
19
+ {children}
20
+ </body>
21
+ </html>
22
+ )
23
+ }
@@ -0,0 +1,30 @@
1
+ export default function Page(): React.ReactElement | null {
2
+ return (
3
+ <div className='min-h-screen bg-gray-50 flex items-center justify-center'>
4
+ <div className='text-center space-y-3'>
5
+ <h1 className='text-4xl font-bold tracking-tight text-gray-900'>Welcome to your {{name}} App</h1>
6
+ <h2 className='text-2xl font-semibold tracking-tight text-gray-900'>Next.js + React + TypeScript + Tailwind + Shadcn UI</h2>
7
+ <p className='text-gray-500 text-sm'>
8
+ Edit{' '}
9
+ <code className='bg-gray-100 px-1.5 py-0.5 rounded font-mono text-gray-700'>src/app/page.tsx</code>
10
+ {' '}to get started
11
+ </p>
12
+ <div className='flex justify-center space-x-4 mt-4'>
13
+ <a className='text-sm text-blue-600 hover:underline' href='https://nextjs.org/docs' target='_blank'>Learn more about Next.js</a>
14
+ <a className='text-sm text-blue-600 hover:underline ml-4' href='https://react.dev/learn' target='_blank'>Learn more about React</a>
15
+ <a className='text-sm text-blue-600 hover:underline ml-4' href='https://www.typescriptlang.org/docs/' target='_blank'>Learn more about TypeScript</a>
16
+ <a className='text-sm text-blue-600 hover:underline ml-4' href='https://tailwindcss.com/docs' target='_blank'>Learn more about Tailwind</a>
17
+ <a className='text-sm text-blue-600 hover:underline ml-4' href='https://ui.shadcn.com/docs' target='_blank'>Learn more about Shadcn UI</a>
18
+ </div>
19
+ <footer className='text-center text-gray-500 text-sm mt-8'>
20
+ Made with{' '}
21
+ <a href='https://npmjs.com/create-nolly-template' className='text-rose-600 hover:underline' target='_blank'>
22
+ <code className='bg-gray-100 px-1.5 py-0.5 rounded font-mono text-gray-700'>Nolly's Template</code>
23
+ </a>{' '}
24
+ by{' '}
25
+ <a href='https://thenolle.com' className='text-pink-600 hover:underline' target='_blank'>Nolly</a>
26
+ </footer>
27
+ </div>
28
+ </div>
29
+ )
30
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema.json",
3
+ "style": "radix-mira",
4
+ "rsc": false,
5
+ "tsx": true,
6
+ "tailwind": {
7
+ "config": "",
8
+ "css": "src/globals.css",
9
+ "baseColor": "zinc",
10
+ "cssVariables": true,
11
+ "prefix": ""
12
+ },
13
+ "iconLibrary": "lucide",
14
+ "rtl": false,
15
+ "aliases": {
16
+ "components": "@components",
17
+ "utils": "@lib/utils",
18
+ "ui": "@components/ui",
19
+ "lib": "@lib",
20
+ "hooks": "@hooks"
21
+ },
22
+ "menuColor": "default-translucent",
23
+ "menuAccent": "subtle",
24
+ "registries": {}
25
+ }
@@ -0,0 +1,6 @@
1
+ import { twMerge } from 'tailwind-merge'
2
+ import clsx, { ClassValue } from 'clsx'
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs))
6
+ }
@@ -0,0 +1,6 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+ import "./.next/dev/types/routes.d.ts";
4
+
5
+ // NOTE: This file should not be edited
6
+ // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
@@ -0,0 +1,8 @@
1
+ import type { NextConfig } from 'next'
2
+
3
+ const nextConfig: NextConfig = {
4
+ output: 'standalone',
5
+ reactStrictMode: false,
6
+ }
7
+
8
+ export default nextConfig
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "{{name}}",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "dev": "next dev",
7
+ "build": "next build",
8
+ "start": "next start"
9
+ },
10
+ "dependencies": {
11
+ "@base-ui/react": "^1.2.0",
12
+ "class-variance-authority": "^0.7.1",
13
+ "clsx": "^2.1.1",
14
+ "lucide-react": "^0.577.0",
15
+ "next": "16.1.6",
16
+ "radix-ui": "^1.4.3",
17
+ "react": "19.2.3",
18
+ "react-dom": "19.2.3",
19
+ "shadcn": "^3.8.5",
20
+ "tailwind-merge": "^3.5.0",
21
+ "tw-animate-css": "^1.4.0"
22
+ },
23
+ "devDependencies": {
24
+ "@tailwindcss/postcss": "^4",
25
+ "@types/node": "^20",
26
+ "@types/react": "^19",
27
+ "@types/react-dom": "^19",
28
+ "tailwindcss": "^4",
29
+ "typescript": "^5"
30
+ }
31
+ }
@@ -0,0 +1,3 @@
1
+ onlyBuiltDependencies:
2
+ - msw
3
+ - sharp
@@ -0,0 +1,7 @@
1
+ const config = {
2
+ plugins: {
3
+ '@tailwindcss/postcss': {},
4
+ },
5
+ }
6
+
7
+ export default config
@@ -0,0 +1,34 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2017",
4
+ "lib": [ "dom", "dom.iterable", "esnext" ],
5
+ "allowJs": true,
6
+ "skipLibCheck": true,
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "esModuleInterop": true,
10
+ "module": "esnext",
11
+ "moduleResolution": "bundler",
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "jsx": "react-jsx",
15
+ "incremental": true,
16
+ "plugins": [ { "name": "next" } ],
17
+ "paths": {
18
+ "@app/*": [ "./app/*" ],
19
+ "@components/*": [ "./components/*" ],
20
+ "@lib/*": [ "./lib/*" ],
21
+ }
22
+ },
23
+ "include": [
24
+ "next-env.d.ts",
25
+ "**/*.ts",
26
+ "**/*.tsx",
27
+ ".next/types/**/*.ts",
28
+ ".next/dev/types/**/*.ts",
29
+ "**/*.mts"
30
+ ],
31
+ "exclude": [
32
+ "node_modules"
33
+ ]
34
+ }