create-nolly-template 1.0.3 → 1.0.5
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.
- package/dist/builder.js +7 -0
- package/dist/registry/index.js +2 -2
- package/dist/registry/web/backend/fastify/base.js +7 -7
- package/dist/registry/web/backend/fastify/{features/mongodb.js → mongodb.js} +1 -1
- package/dist/registry/web/backend/fastify/{features/swagger.js → swagger.js} +1 -1
- package/dist/registry/web/backend/fastify/{features/websocket.js → websocket.js} +1 -1
- package/dist/registry/web/backend/index.js +5 -3
- package/dist/registry/web/frontend/index.js +9 -0
- package/dist/registry/web/frontend/vite/base.js +15 -0
- package/dist/registry/web/frontend/vite/react.js +71 -0
- package/dist/registry/web/frontend/vite/seo.js +39 -0
- package/dist/registry/web/fullstack/index.js +9 -0
- package/dist/registry/web/fullstack/next.js/base.js +10 -0
- package/dist/registry/web/index.js +10 -4
- package/package.json +1 -1
- package/templates/web/frontend/vite/base/index.html +17 -0
- package/templates/web/frontend/vite/base/package.json +20 -0
- package/templates/web/frontend/vite/base/public/favicon.svg +4 -0
- package/templates/web/frontend/vite/base/src/globals.css +1 -0
- package/templates/web/frontend/vite/base/src/main.ts +54 -0
- package/templates/web/frontend/vite/base/src/vite-env.d.ts +1 -0
- package/templates/web/frontend/vite/base/tsconfig.app.json +26 -0
- package/templates/web/frontend/vite/base/tsconfig.json +7 -0
- package/templates/web/frontend/vite/base/tsconfig.node.json +16 -0
- package/templates/web/frontend/vite/base/vite.config.ts +51 -0
- package/templates/web/frontend/vite/react/components.json +25 -0
- package/templates/web/frontend/vite/react/pnpm-workspace.yaml +2 -0
- package/templates/web/frontend/vite/react/src/app.tsx +30 -0
- package/templates/web/frontend/vite/react/src/globals.css +131 -0
- package/templates/web/frontend/vite/react/src/lib/utils.ts +6 -0
- package/templates/web/frontend/vite/react/src/main.tsx +15 -0
- package/templates/web/frontend/vite/seo/seo.config.ts +24 -0
- package/templates/web/frontend/vite/seo/vite-plugin-seo.ts +86 -0
- package/templates/web/fullstack/nextjs/base/app/favicon.svg +4 -0
- package/templates/web/fullstack/nextjs/base/app/globals.css +126 -0
- package/templates/web/fullstack/nextjs/base/app/globals.d.ts +9 -0
- package/templates/web/fullstack/nextjs/base/app/layout.tsx +23 -0
- package/templates/web/fullstack/nextjs/base/app/page.tsx +30 -0
- package/templates/web/fullstack/nextjs/base/components.json +25 -0
- package/templates/web/fullstack/nextjs/base/lib/utils.ts +6 -0
- package/templates/web/fullstack/nextjs/base/next-env.d.ts +6 -0
- package/templates/web/fullstack/nextjs/base/next.config.ts +8 -0
- package/templates/web/fullstack/nextjs/base/package.json +31 -0
- package/templates/web/fullstack/nextjs/base/pnpm-workspace.yaml +3 -0
- package/templates/web/fullstack/nextjs/base/postcss.config.mjs +7 -0
- 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;
|
package/dist/registry/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
export const
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
swagger,
|
|
14
|
+
websocket,
|
|
15
|
+
mongodb
|
|
16
16
|
]
|
|
17
17
|
};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export const
|
|
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: [
|
|
6
|
+
templates: [
|
|
7
|
+
fastify
|
|
8
|
+
],
|
|
7
9
|
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { react } from './react.js';
|
|
2
|
+
import { seo } from './seo.js';
|
|
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,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 {
|
|
2
|
-
|
|
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: '
|
|
6
|
-
subCategories: [
|
|
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
|
@@ -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 @@
|
|
|
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,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,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,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,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,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,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,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
|
+
}
|