create-lumen 2.0.0-alpha.1 → 2.0.0-beta.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.
- package/README.md +38 -12
- package/bin/cli.js +3 -1
- package/package.json +3 -3
- package/schema/fixtures/v2/invalid/shadcn-without-tailwind.json +1 -1
- package/schema/fixtures/v2/valid/react-vite-type-based.json +1 -1
- package/schema/lumen.config.v2.json +0 -1
- package/src/cli-args.js +169 -7
- package/src/configure.js +12 -4
- package/src/css.js +14 -30
- package/src/dependencies.js +36 -20
- package/src/engine/capabilities.js +195 -4
- package/src/engine/composition.js +736 -0
- package/src/engine/index.js +1 -0
- package/src/engine/providers/base-provider.js +4 -4
- package/src/injector.js +294 -446
- package/src/main.js +38 -16
- package/src/manifest/emit.js +1 -1
- package/src/manifest/schema.js +1 -1
- package/src/prompts.js +581 -238
- package/src/readme.js +23 -2
- package/src/scaffold.js +17 -0
- package/templates/architectures/hybrid/main.jsx +10 -0
- package/templates/architectures/hybrid/main.tsx +10 -0
- package/templates/architectures/hybrid/src/App.jsx +20 -0
- package/templates/architectures/hybrid/src/App.tsx +20 -0
- package/templates/architectures/hybrid/src/shared/components/ui/Button.jsx +31 -0
- package/templates/architectures/hybrid/src/shared/components/ui/Button.tsx +36 -0
- package/templates/architectures/hybrid/src/shared/components/ui/index.js +1 -0
- package/templates/architectures/hybrid/src/shared/components/ui/index.ts +1 -0
- package/templates/architectures/hybrid/src/shared/hooks/useLocalStorage.jsx +28 -0
- package/templates/architectures/hybrid/src/shared/hooks/useLocalStorage.ts +28 -0
- package/templates/architectures/hybrid/src/shared/layouts/.gitkeep +0 -0
- package/templates/architectures/hybrid/src/shared/stores/.gitkeep +0 -0
- package/templates/architectures/hybrid/src/shared/styles/.gitkeep +0 -0
- package/templates/architectures/hybrid/src/shared/types/index.js +20 -0
- package/templates/architectures/hybrid/src/shared/types/index.ts +16 -0
- package/templates/architectures/hybrid/src/shared/utils/cn.jsx +3 -0
- package/templates/architectures/hybrid/src/shared/utils/cn.ts +5 -0
- package/templates/architectures/none/main.jsx +10 -0
- package/templates/architectures/none/main.tsx +10 -0
- package/templates/architectures/none/src/App.jsx +15 -0
- package/templates/architectures/none/src/App.tsx +15 -0
- package/templates/architectures/none/src/styles/.gitkeep +1 -0
- package/templates/architectures/none/src/types/index.js +20 -0
- package/templates/architectures/none/src/types/index.ts +16 -0
- package/templates/bases/next/app-router/js/.provenance.json +19 -0
- package/templates/bases/next/app-router/js/README.md +36 -0
- package/templates/bases/next/app-router/js/jsconfig.json +7 -0
- package/templates/bases/next/app-router/js/next.config.mjs +6 -0
- package/templates/bases/next/app-router/js/package.json +15 -0
- package/templates/bases/next/app-router/js/public/file.svg +1 -0
- package/templates/bases/next/app-router/js/public/globe.svg +1 -0
- package/templates/bases/next/app-router/js/public/next.svg +1 -0
- package/templates/bases/next/app-router/js/public/vercel.svg +1 -0
- package/templates/bases/next/app-router/js/public/window.svg +1 -0
- package/templates/bases/next/app-router/js/src/app/api/hello/route.js +5 -0
- package/templates/bases/next/app-router/js/src/app/blog/[slug]/page.js +33 -0
- package/templates/bases/next/app-router/js/src/app/favicon.ico +0 -0
- package/templates/bases/next/app-router/js/src/app/globals.css +49 -0
- package/templates/bases/next/app-router/js/src/app/layout.js +25 -0
- package/templates/bases/next/app-router/js/src/app/loading.js +15 -0
- package/templates/bases/next/app-router/js/src/app/not-found.js +29 -0
- package/templates/bases/next/app-router/js/src/app/page.js +69 -0
- package/templates/bases/next/app-router/js/src/app/page.module.css +150 -0
- package/templates/bases/next/app-router/ts/.provenance.json +19 -0
- package/templates/bases/next/app-router/ts/README.md +36 -0
- package/templates/bases/next/app-router/ts/next.config.ts +7 -0
- package/templates/bases/next/app-router/ts/package.json +21 -0
- package/templates/bases/next/app-router/ts/public/file.svg +1 -0
- package/templates/bases/next/app-router/ts/public/globe.svg +1 -0
- package/templates/bases/next/app-router/ts/public/next.svg +1 -0
- package/templates/bases/next/app-router/ts/public/vercel.svg +1 -0
- package/templates/bases/next/app-router/ts/public/window.svg +1 -0
- package/templates/bases/next/app-router/ts/src/app/api/hello/route.ts +5 -0
- package/templates/bases/next/app-router/ts/src/app/blog/[slug]/page.tsx +38 -0
- package/templates/bases/next/app-router/ts/src/app/favicon.ico +0 -0
- package/templates/bases/next/app-router/ts/src/app/globals.css +49 -0
- package/templates/bases/next/app-router/ts/src/app/layout.tsx +30 -0
- package/templates/bases/next/app-router/ts/src/app/loading.tsx +15 -0
- package/templates/bases/next/app-router/ts/src/app/not-found.tsx +29 -0
- package/templates/bases/next/app-router/ts/src/app/page.module.css +150 -0
- package/templates/bases/next/app-router/ts/src/app/page.tsx +69 -0
- package/templates/bases/next/app-router/ts/tsconfig.json +34 -0
- package/templates/bases/next/pages-router/js/.provenance.json +19 -0
- package/templates/bases/next/pages-router/js/README.md +40 -0
- package/templates/bases/next/pages-router/js/jsconfig.json +7 -0
- package/templates/bases/next/pages-router/js/next.config.mjs +7 -0
- package/templates/bases/next/pages-router/js/package.json +15 -0
- package/templates/bases/next/pages-router/js/public/favicon.ico +0 -0
- package/templates/bases/next/pages-router/js/public/file.svg +1 -0
- package/templates/bases/next/pages-router/js/public/globe.svg +1 -0
- package/templates/bases/next/pages-router/js/public/next.svg +1 -0
- package/templates/bases/next/pages-router/js/public/vercel.svg +1 -0
- package/templates/bases/next/pages-router/js/public/window.svg +1 -0
- package/templates/bases/next/pages-router/js/src/pages/404.js +35 -0
- package/templates/bases/next/pages-router/js/src/pages/500.js +35 -0
- package/templates/bases/next/pages-router/js/src/pages/_app.js +20 -0
- package/templates/bases/next/pages-router/js/src/pages/_document.js +15 -0
- package/templates/bases/next/pages-router/js/src/pages/api/hello.js +5 -0
- package/templates/bases/next/pages-router/js/src/pages/blog/[slug].js +41 -0
- package/templates/bases/next/pages-router/js/src/pages/index.js +77 -0
- package/templates/bases/next/pages-router/js/src/styles/Home.module.css +149 -0
- package/templates/bases/next/pages-router/js/src/styles/globals.css +42 -0
- package/templates/bases/next/pages-router/ts/.provenance.json +19 -0
- package/templates/bases/next/pages-router/ts/README.md +40 -0
- package/templates/bases/next/pages-router/ts/next.config.ts +8 -0
- package/templates/bases/next/pages-router/ts/package.json +21 -0
- package/templates/bases/next/pages-router/ts/public/favicon.ico +0 -0
- package/templates/bases/next/pages-router/ts/public/file.svg +1 -0
- package/templates/bases/next/pages-router/ts/public/globe.svg +1 -0
- package/templates/bases/next/pages-router/ts/public/next.svg +1 -0
- package/templates/bases/next/pages-router/ts/public/vercel.svg +1 -0
- package/templates/bases/next/pages-router/ts/public/window.svg +1 -0
- package/templates/bases/next/pages-router/ts/src/pages/404.tsx +35 -0
- package/templates/bases/next/pages-router/ts/src/pages/500.tsx +35 -0
- package/templates/bases/next/pages-router/ts/src/pages/_app.tsx +21 -0
- package/templates/bases/next/pages-router/ts/src/pages/_document.tsx +15 -0
- package/templates/bases/next/pages-router/ts/src/pages/api/hello.ts +13 -0
- package/templates/bases/next/pages-router/ts/src/pages/blog/[slug].tsx +46 -0
- package/templates/bases/next/pages-router/ts/src/pages/index.tsx +77 -0
- package/templates/bases/next/pages-router/ts/src/styles/Home.module.css +149 -0
- package/templates/bases/next/pages-router/ts/src/styles/globals.css +42 -0
- package/templates/bases/next/pages-router/ts/tsconfig.json +29 -0
- package/templates/conditional/linting/biome/biome.json +31 -0
- package/templates/conditional/next/config/cloudflare/next.config.mjs +6 -0
- package/templates/conditional/next/config/cloudflare/next.config.ts +7 -0
- package/templates/conditional/next/config/node/next.config.mjs +6 -0
- package/templates/conditional/next/config/node/next.config.ts +7 -0
- package/templates/conditional/next/config/static/next.config.mjs +6 -0
- package/templates/conditional/next/config/static/next.config.ts +7 -0
- package/templates/conditional/next/config/turbopack/next.config.mjs +7 -0
- package/templates/conditional/next/config/turbopack/next.config.ts +8 -0
- package/templates/conditional/next/config/vercel/next.config.mjs +6 -0
- package/templates/conditional/next/config/vercel/next.config.ts +7 -0
- package/templates/conditional/next/config/webpack/next.config.mjs +9 -0
- package/templates/conditional/next/config/webpack/next.config.ts +10 -0
- package/templates/conditional/next/font/BUILD_SIZE_NOTE.md +17 -0
- package/templates/conditional/next/font/app-router/src/app/layout.js +25 -0
- package/templates/conditional/next/font/app-router/src/app/layout.tsx +30 -0
- package/templates/conditional/next/font/pages-router/src/pages/_app.js +20 -0
- package/templates/conditional/next/font/pages-router/src/pages/_app.tsx +21 -0
- package/templates/conditional/next/font/pages-router/src/pages/_document.js +18 -0
- package/templates/conditional/next/font/pages-router/src/pages/_document.tsx +18 -0
- package/templates/conditional/next/font/src/app/layout.js +25 -0
- package/templates/conditional/next/font/src/app/layout.tsx +30 -0
- package/templates/conditional/next/font/src/lib/fonts.js +11 -0
- package/templates/conditional/next/font/src/lib/fonts.ts +11 -0
- package/templates/conditional/next/font/src/pages/_app.js +20 -0
- package/templates/conditional/next/font/src/pages/_app.tsx +21 -0
- package/templates/conditional/next/font/src/pages/_document.js +18 -0
- package/templates/conditional/next/font/src/pages/_document.tsx +18 -0
- package/templates/conditional/next/image/BUILD_SIZE_NOTE.md +15 -0
- package/templates/conditional/next/image/app-router/src/components/ImageExample.jsx +34 -0
- package/templates/conditional/next/image/app-router/src/components/ImageExample.tsx +44 -0
- package/templates/conditional/next/image/pages-router/src/components/ImageExample.jsx +34 -0
- package/templates/conditional/next/image/pages-router/src/components/ImageExample.tsx +44 -0
- package/templates/conditional/next/image/src/components/ImageExample.jsx +44 -0
- package/templates/conditional/next/image/src/components/ImageExample.tsx +54 -0
- package/templates/conditional/next/image/src/components/image/index.js +1 -0
- package/templates/conditional/next/image/src/components/image/index.ts +2 -0
- package/templates/conditional/next/server-components/README.md +13 -0
- package/templates/conditional/next/server-components/eslint.config.mjs +47 -0
- package/templates/conditional/next/server-components/rules/no-server-imports-in-client.js +89 -0
- package/templates/conditional/next/server-components/rules/no-server-imports-in-client.mjs +88 -0
- package/templates/conditional/next/server-components/src/components/boundaries/ClientCounter.jsx +48 -0
- package/templates/conditional/next/server-components/src/components/boundaries/ClientCounter.tsx +53 -0
- package/templates/conditional/next/server-components/src/components/boundaries/ServerCard.jsx +41 -0
- package/templates/conditional/next/server-components/src/components/boundaries/ServerCard.tsx +46 -0
- package/templates/conditional/next/server-components/src/components/boundaries/index.js +2 -0
- package/templates/conditional/next/server-components/src/components/boundaries/index.ts +4 -0
- package/templates/conditional/testing/jest/hybrid/src/__tests__/App.test.jsx +11 -0
- package/templates/conditional/testing/jest/hybrid/src/__tests__/App.test.tsx +11 -0
- package/templates/conditional/testing/jest/none/src/__tests__/App.test.jsx +11 -0
- package/templates/conditional/testing/jest/none/src/__tests__/App.test.tsx +11 -0
- package/templates/conditional/testing/vitest/hybrid/src/__tests__/App.test.jsx +10 -0
- package/templates/conditional/testing/vitest/hybrid/src/__tests__/App.test.tsx +10 -0
- package/templates/conditional/testing/vitest/none/src/__tests__/App.test.jsx +10 -0
- package/templates/conditional/testing/vitest/none/src/__tests__/App.test.tsx +10 -0
- package/templates/css/tailwind/src/globals.css +10 -0
- package/templates/css/tailwind/src/themes.css +86 -4
- package/templates/ui/shadcn/lib/utils.js +6 -0
- package/templates/ui/shadcn/lib/utils.ts +6 -0
- package/templates/ui/shadcn/primitives/Button.jsx +48 -0
- package/templates/ui/shadcn/primitives/Button.tsx +59 -0
- package/templates/ui/shadcn/primitives/Card.jsx +55 -0
- package/templates/ui/shadcn/primitives/Card.tsx +73 -0
- package/templates/ui/shadcn/primitives/index.js +9 -0
- package/templates/ui/shadcn/primitives/index.ts +9 -0
- package/templates/css/bootstrap/src/themes.css +0 -14
- /package/templates/{css/bootstrap/src/globals.css → architectures/hybrid/src/features/.gitkeep} +0 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
.page {
|
|
2
|
+
--background: #fafafa;
|
|
3
|
+
--foreground: #fff;
|
|
4
|
+
|
|
5
|
+
--text-primary: #000;
|
|
6
|
+
--text-secondary: #666;
|
|
7
|
+
|
|
8
|
+
--button-primary-hover: #383838;
|
|
9
|
+
--button-secondary-hover: #f2f2f2;
|
|
10
|
+
--button-secondary-border: #ebebeb;
|
|
11
|
+
|
|
12
|
+
display: flex;
|
|
13
|
+
min-height: 100vh;
|
|
14
|
+
align-items: center;
|
|
15
|
+
justify-content: center;
|
|
16
|
+
font-family: var(--font-geist-sans);
|
|
17
|
+
background-color: var(--background);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.main {
|
|
21
|
+
display: flex;
|
|
22
|
+
min-height: 100vh;
|
|
23
|
+
width: 100%;
|
|
24
|
+
max-width: 800px;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
align-items: flex-start;
|
|
27
|
+
justify-content: space-between;
|
|
28
|
+
background-color: var(--foreground);
|
|
29
|
+
padding: 120px 60px;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.intro {
|
|
33
|
+
display: flex;
|
|
34
|
+
flex-direction: column;
|
|
35
|
+
align-items: flex-start;
|
|
36
|
+
text-align: left;
|
|
37
|
+
gap: 24px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.intro h1 {
|
|
41
|
+
max-width: 320px;
|
|
42
|
+
font-size: 40px;
|
|
43
|
+
font-weight: 600;
|
|
44
|
+
line-height: 48px;
|
|
45
|
+
letter-spacing: -2.4px;
|
|
46
|
+
text-wrap: balance;
|
|
47
|
+
color: var(--text-primary);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.intro p {
|
|
51
|
+
max-width: 440px;
|
|
52
|
+
font-size: 18px;
|
|
53
|
+
line-height: 32px;
|
|
54
|
+
text-wrap: balance;
|
|
55
|
+
color: var(--text-secondary);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.intro a {
|
|
59
|
+
font-weight: 500;
|
|
60
|
+
color: var(--text-primary);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.ctas {
|
|
64
|
+
display: flex;
|
|
65
|
+
flex-direction: row;
|
|
66
|
+
width: 100%;
|
|
67
|
+
max-width: 440px;
|
|
68
|
+
gap: 16px;
|
|
69
|
+
font-size: 14px;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.ctas a {
|
|
73
|
+
display: flex;
|
|
74
|
+
justify-content: center;
|
|
75
|
+
align-items: center;
|
|
76
|
+
height: 40px;
|
|
77
|
+
padding: 0 16px;
|
|
78
|
+
border-radius: 128px;
|
|
79
|
+
border: 1px solid transparent;
|
|
80
|
+
transition: 0.2s;
|
|
81
|
+
cursor: pointer;
|
|
82
|
+
width: fit-content;
|
|
83
|
+
font-weight: 500;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
a.primary {
|
|
87
|
+
background: var(--text-primary);
|
|
88
|
+
color: var(--background);
|
|
89
|
+
gap: 8px;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
a.secondary {
|
|
93
|
+
border-color: var(--button-secondary-border);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* Enable hover only on non-touch devices */
|
|
97
|
+
@media (hover: hover) and (pointer: fine) {
|
|
98
|
+
a.primary:hover {
|
|
99
|
+
background: var(--button-primary-hover);
|
|
100
|
+
border-color: transparent;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
a.secondary:hover {
|
|
104
|
+
background: var(--button-secondary-hover);
|
|
105
|
+
border-color: transparent;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@media (max-width: 600px) {
|
|
110
|
+
.main {
|
|
111
|
+
padding: 48px 24px;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.intro {
|
|
115
|
+
gap: 16px;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.intro h1 {
|
|
119
|
+
font-size: 32px;
|
|
120
|
+
line-height: 40px;
|
|
121
|
+
letter-spacing: -1.92px;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@media (prefers-color-scheme: dark) {
|
|
126
|
+
.logo {
|
|
127
|
+
filter: invert();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.page {
|
|
131
|
+
--background: #000;
|
|
132
|
+
--foreground: #000;
|
|
133
|
+
|
|
134
|
+
--text-primary: #ededed;
|
|
135
|
+
--text-secondary: #999;
|
|
136
|
+
|
|
137
|
+
--button-primary-hover: #ccc;
|
|
138
|
+
--button-secondary-hover: #1a1a1a;
|
|
139
|
+
--button-secondary-border: #1a1a1a;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.code {
|
|
144
|
+
font-family: var(--font-geist-mono);
|
|
145
|
+
font-size: 0.9em;
|
|
146
|
+
background: color-mix(in srgb, currentColor 8%, transparent);
|
|
147
|
+
padding: 0.1em 0.4em;
|
|
148
|
+
border-radius: 6px;
|
|
149
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--background: #ffffff;
|
|
3
|
+
--foreground: #171717;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
@media (prefers-color-scheme: dark) {
|
|
7
|
+
:root {
|
|
8
|
+
--background: #0a0a0a;
|
|
9
|
+
--foreground: #ededed;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
html,
|
|
14
|
+
body {
|
|
15
|
+
max-width: 100vw;
|
|
16
|
+
overflow-x: hidden;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
body {
|
|
20
|
+
color: var(--foreground);
|
|
21
|
+
background: var(--background);
|
|
22
|
+
font-family: Arial, Helvetica, sans-serif;
|
|
23
|
+
-webkit-font-smoothing: antialiased;
|
|
24
|
+
-moz-osx-font-smoothing: grayscale;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
* {
|
|
28
|
+
box-sizing: border-box;
|
|
29
|
+
padding: 0;
|
|
30
|
+
margin: 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
a {
|
|
34
|
+
color: inherit;
|
|
35
|
+
text-decoration: none;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@media (prefers-color-scheme: dark) {
|
|
39
|
+
html {
|
|
40
|
+
color-scheme: dark;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
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
|
+
"paths": {
|
|
17
|
+
"@/*": ["./src/*"]
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"include": [
|
|
21
|
+
"next-env.d.ts",
|
|
22
|
+
"**/*.ts",
|
|
23
|
+
"**/*.tsx",
|
|
24
|
+
".next/types/**/*.ts",
|
|
25
|
+
".next/dev/types/**/*.ts",
|
|
26
|
+
"**/*.mts"
|
|
27
|
+
],
|
|
28
|
+
"exclude": ["node_modules"]
|
|
29
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
|
|
3
|
+
"vcs": {
|
|
4
|
+
"enabled": false,
|
|
5
|
+
"clientKind": "git",
|
|
6
|
+
"useIgnoreFile": true
|
|
7
|
+
},
|
|
8
|
+
"files": {
|
|
9
|
+
"ignoreUnknown": false,
|
|
10
|
+
"ignore": []
|
|
11
|
+
},
|
|
12
|
+
"formatter": {
|
|
13
|
+
"enabled": true,
|
|
14
|
+
"indentStyle": "space",
|
|
15
|
+
"indentWidth": 2
|
|
16
|
+
},
|
|
17
|
+
"organizeImports": {
|
|
18
|
+
"enabled": true
|
|
19
|
+
},
|
|
20
|
+
"linter": {
|
|
21
|
+
"enabled": true,
|
|
22
|
+
"rules": {
|
|
23
|
+
"recommended": true
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"javascript": {
|
|
27
|
+
"formatter": {
|
|
28
|
+
"quoteStyle": "double"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# next/font Build Size and Performance Impact
|
|
2
|
+
|
|
3
|
+
## Zero Layout Shift & Self-Hosting
|
|
4
|
+
`next/font` (specifically `Geist` and `Geist_Mono` via `next/font/google`) automatically optimizes font loading:
|
|
5
|
+
1. **Self-Hosting at Build Time**: Google Fonts are downloaded during `next build` and hosted alongside your static assets directly from the same domain. No external requests are made to Google Fonts servers by the browser at runtime, improving privacy and removing DNS/TLS negotiation latency.
|
|
6
|
+
2. **Zero Cumulative Layout Shift (CLS)**: Uses CSS `size-adjust` to match fallback fonts automatically while custom fonts are loading.
|
|
7
|
+
3. **Preloaded Subsets**: Automatically subsets font glyphs (defaulting to `latin`) to reduce file weight.
|
|
8
|
+
|
|
9
|
+
## Bundle Footprint
|
|
10
|
+
- **Runtime JavaScript**: ~0 bytes (compiled away into CSS variables and HTML classes).
|
|
11
|
+
- **Static Assets**: ~20-30 KB compressed WOFF2 font payload served statically with aggressive caching (`Cache-Control: public, max-age=31536000, immutable`).
|
|
12
|
+
- **HTML/CSS Injection**: Inline CSS variable definitions (`--font-geist-sans`, `--font-geist-mono`) attached to root wrappers, eliminating render-blocking external stylesheet links.
|
|
13
|
+
|
|
14
|
+
## Parity Across Routers
|
|
15
|
+
- **App Router**: Wired into root `app/layout.tsx` (or `app/layout.js`) via `className={`${geistSans.variable} ${geistMono.variable}`}` on `<html>`.
|
|
16
|
+
- **Pages Router**: Wired into root `pages/_app.tsx` (or `pages/_app.js`) wrapping the page tree with `${geistSans.variable} ${geistMono.variable}`. (Note: Per Next.js compiler specifications, `next/font` is strictly prohibited inside `pages/_document.js` with a compile-time error and must be loaded in `_app.js` or page components).
|
|
17
|
+
- Both routers expose identical CSS custom properties for global and modular CSS styling.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Geist, Geist_Mono } from "next/font/google";
|
|
2
|
+
import "./globals.css";
|
|
3
|
+
|
|
4
|
+
const geistSans = Geist({
|
|
5
|
+
variable: "--font-geist-sans",
|
|
6
|
+
subsets: ["latin"],
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const geistMono = Geist_Mono({
|
|
10
|
+
variable: "--font-geist-mono",
|
|
11
|
+
subsets: ["latin"],
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export const metadata = {
|
|
15
|
+
title: "Create Lumen App",
|
|
16
|
+
description: "Generated by create-lumen",
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default function RootLayout({ children }) {
|
|
20
|
+
return (
|
|
21
|
+
<html lang="en" className={`${geistSans.variable} ${geistMono.variable}`}>
|
|
22
|
+
<body className="antialiased">{children}</body>
|
|
23
|
+
</html>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Metadata } from "next";
|
|
2
|
+
import { Geist, Geist_Mono } from "next/font/google";
|
|
3
|
+
import "./globals.css";
|
|
4
|
+
|
|
5
|
+
const geistSans = Geist({
|
|
6
|
+
variable: "--font-geist-sans",
|
|
7
|
+
subsets: ["latin"],
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const geistMono = Geist_Mono({
|
|
11
|
+
variable: "--font-geist-mono",
|
|
12
|
+
subsets: ["latin"],
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export const metadata: Metadata = {
|
|
16
|
+
title: "Create Lumen App",
|
|
17
|
+
description: "Generated by create-lumen",
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default function RootLayout({
|
|
21
|
+
children,
|
|
22
|
+
}: Readonly<{
|
|
23
|
+
children: React.ReactNode;
|
|
24
|
+
}>) {
|
|
25
|
+
return (
|
|
26
|
+
<html lang="en" className={`${geistSans.variable} ${geistMono.variable}`}>
|
|
27
|
+
<body className="antialiased">{children}</body>
|
|
28
|
+
</html>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import "@/styles/globals.css";
|
|
2
|
+
import { Geist, Geist_Mono } from "next/font/google";
|
|
3
|
+
|
|
4
|
+
const geistSans = Geist({
|
|
5
|
+
variable: "--font-geist-sans",
|
|
6
|
+
subsets: ["latin"],
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const geistMono = Geist_Mono({
|
|
10
|
+
variable: "--font-geist-mono",
|
|
11
|
+
subsets: ["latin"],
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export default function App({ Component, pageProps }) {
|
|
15
|
+
return (
|
|
16
|
+
<div className={`${geistSans.variable} ${geistMono.variable}`}>
|
|
17
|
+
<Component {...pageProps} />
|
|
18
|
+
</div>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import "@/styles/globals.css";
|
|
2
|
+
import type { AppProps } from "next/app";
|
|
3
|
+
import { Geist, Geist_Mono } from "next/font/google";
|
|
4
|
+
|
|
5
|
+
const geistSans = Geist({
|
|
6
|
+
variable: "--font-geist-sans",
|
|
7
|
+
subsets: ["latin"],
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const geistMono = Geist_Mono({
|
|
11
|
+
variable: "--font-geist-mono",
|
|
12
|
+
subsets: ["latin"],
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export default function App({ Component, pageProps }: AppProps) {
|
|
16
|
+
return (
|
|
17
|
+
<div className={`${geistSans.variable} ${geistMono.variable}`}>
|
|
18
|
+
<Component {...pageProps} />
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Html, Head, Main, NextScript } from "next/document";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pages Router Custom Document.
|
|
5
|
+
* Note: Per Next.js compiler specifications, next/font loaders are configured
|
|
6
|
+
* in pages/_app to avoid the 'Cannot be used within pages/_document' compile error.
|
|
7
|
+
*/
|
|
8
|
+
export default function Document() {
|
|
9
|
+
return (
|
|
10
|
+
<Html lang="en">
|
|
11
|
+
<Head />
|
|
12
|
+
<body className="antialiased">
|
|
13
|
+
<Main />
|
|
14
|
+
<NextScript />
|
|
15
|
+
</body>
|
|
16
|
+
</Html>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Html, Head, Main, NextScript } from "next/document";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pages Router Custom Document.
|
|
5
|
+
* Note: Per Next.js compiler specifications, next/font loaders are configured
|
|
6
|
+
* in pages/_app to avoid the 'Cannot be used within pages/_document' compile error.
|
|
7
|
+
*/
|
|
8
|
+
export default function Document() {
|
|
9
|
+
return (
|
|
10
|
+
<Html lang="en">
|
|
11
|
+
<Head />
|
|
12
|
+
<body className="antialiased">
|
|
13
|
+
<Main />
|
|
14
|
+
<NextScript />
|
|
15
|
+
</body>
|
|
16
|
+
</Html>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Geist, Geist_Mono } from "next/font/google";
|
|
2
|
+
import "./globals.css";
|
|
3
|
+
|
|
4
|
+
const geistSans = Geist({
|
|
5
|
+
variable: "--font-geist-sans",
|
|
6
|
+
subsets: ["latin"],
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const geistMono = Geist_Mono({
|
|
10
|
+
variable: "--font-geist-mono",
|
|
11
|
+
subsets: ["latin"],
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export const metadata = {
|
|
15
|
+
title: "Create Lumen App",
|
|
16
|
+
description: "Generated by create-lumen",
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default function RootLayout({ children }) {
|
|
20
|
+
return (
|
|
21
|
+
<html lang="en" className={`${geistSans.variable} ${geistMono.variable}`}>
|
|
22
|
+
<body className="antialiased">{children}</body>
|
|
23
|
+
</html>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Metadata } from "next";
|
|
2
|
+
import { Geist, Geist_Mono } from "next/font/google";
|
|
3
|
+
import "./globals.css";
|
|
4
|
+
|
|
5
|
+
const geistSans = Geist({
|
|
6
|
+
variable: "--font-geist-sans",
|
|
7
|
+
subsets: ["latin"],
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const geistMono = Geist_Mono({
|
|
11
|
+
variable: "--font-geist-mono",
|
|
12
|
+
subsets: ["latin"],
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export const metadata: Metadata = {
|
|
16
|
+
title: "Create Lumen App",
|
|
17
|
+
description: "Generated by create-lumen",
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default function RootLayout({
|
|
21
|
+
children,
|
|
22
|
+
}: Readonly<{
|
|
23
|
+
children: React.ReactNode;
|
|
24
|
+
}>) {
|
|
25
|
+
return (
|
|
26
|
+
<html lang="en" className={`${geistSans.variable} ${geistMono.variable}`}>
|
|
27
|
+
<body className="antialiased">{children}</body>
|
|
28
|
+
</html>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import "@/styles/globals.css";
|
|
2
|
+
import { Geist, Geist_Mono } from "next/font/google";
|
|
3
|
+
|
|
4
|
+
const geistSans = Geist({
|
|
5
|
+
variable: "--font-geist-sans",
|
|
6
|
+
subsets: ["latin"],
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const geistMono = Geist_Mono({
|
|
10
|
+
variable: "--font-geist-mono",
|
|
11
|
+
subsets: ["latin"],
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export default function App({ Component, pageProps }) {
|
|
15
|
+
return (
|
|
16
|
+
<div className={`${geistSans.variable} ${geistMono.variable}`}>
|
|
17
|
+
<Component {...pageProps} />
|
|
18
|
+
</div>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import "@/styles/globals.css";
|
|
2
|
+
import type { AppProps } from "next/app";
|
|
3
|
+
import { Geist, Geist_Mono } from "next/font/google";
|
|
4
|
+
|
|
5
|
+
const geistSans = Geist({
|
|
6
|
+
variable: "--font-geist-sans",
|
|
7
|
+
subsets: ["latin"],
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const geistMono = Geist_Mono({
|
|
11
|
+
variable: "--font-geist-mono",
|
|
12
|
+
subsets: ["latin"],
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export default function App({ Component, pageProps }: AppProps) {
|
|
16
|
+
return (
|
|
17
|
+
<div className={`${geistSans.variable} ${geistMono.variable}`}>
|
|
18
|
+
<Component {...pageProps} />
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Html, Head, Main, NextScript } from "next/document";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pages Router Custom Document.
|
|
5
|
+
* Note: Per Next.js compiler specifications, next/font loaders are configured
|
|
6
|
+
* in pages/_app to avoid the 'Cannot be used within pages/_document' compile error.
|
|
7
|
+
*/
|
|
8
|
+
export default function Document() {
|
|
9
|
+
return (
|
|
10
|
+
<Html lang="en">
|
|
11
|
+
<Head />
|
|
12
|
+
<body className="antialiased">
|
|
13
|
+
<Main />
|
|
14
|
+
<NextScript />
|
|
15
|
+
</body>
|
|
16
|
+
</Html>
|
|
17
|
+
);
|
|
18
|
+
}
|