create-lumen 2.0.0-alpha.2 → 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 +24 -6
- package/bin/cli.js +2 -1
- package/package.json +2 -2
- package/src/cli-args.js +105 -5
- package/src/configure.js +8 -4
- package/src/dependencies.js +8 -2
- package/src/engine/capabilities.js +22 -1
- package/src/engine/composition.js +92 -0
- package/src/engine/providers/base-provider.js +4 -4
- package/src/main.js +33 -10
- package/src/manifest/emit.js +1 -1
- package/src/prompts.js +154 -23
- 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
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import Head from "next/head";
|
|
2
|
+
import Link from "next/link";
|
|
3
|
+
|
|
4
|
+
export default function Custom404() {
|
|
5
|
+
return (
|
|
6
|
+
<>
|
|
7
|
+
<Head>
|
|
8
|
+
<title>404 - Page Not Found</title>
|
|
9
|
+
</Head>
|
|
10
|
+
<div
|
|
11
|
+
style={{
|
|
12
|
+
display: "flex",
|
|
13
|
+
flexDirection: "column",
|
|
14
|
+
alignItems: "center",
|
|
15
|
+
justifyContent: "center",
|
|
16
|
+
minHeight: "100vh",
|
|
17
|
+
fontFamily: "var(--font-geist-sans, sans-serif)",
|
|
18
|
+
padding: "2rem",
|
|
19
|
+
textAlign: "center",
|
|
20
|
+
}}
|
|
21
|
+
>
|
|
22
|
+
<h1>404 - Page Not Found</h1>
|
|
23
|
+
<p style={{ marginTop: "1rem" }}>
|
|
24
|
+
The page you are looking for does not exist.
|
|
25
|
+
</p>
|
|
26
|
+
<Link
|
|
27
|
+
href="/"
|
|
28
|
+
style={{ marginTop: "1.5rem", textDecoration: "underline" }}
|
|
29
|
+
>
|
|
30
|
+
Go back home
|
|
31
|
+
</Link>
|
|
32
|
+
</div>
|
|
33
|
+
</>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import Head from "next/head";
|
|
2
|
+
import Link from "next/link";
|
|
3
|
+
|
|
4
|
+
export default function Custom500() {
|
|
5
|
+
return (
|
|
6
|
+
<>
|
|
7
|
+
<Head>
|
|
8
|
+
<title>500 - Server Error</title>
|
|
9
|
+
</Head>
|
|
10
|
+
<div
|
|
11
|
+
style={{
|
|
12
|
+
display: "flex",
|
|
13
|
+
flexDirection: "column",
|
|
14
|
+
alignItems: "center",
|
|
15
|
+
justifyContent: "center",
|
|
16
|
+
minHeight: "100vh",
|
|
17
|
+
fontFamily: "var(--font-geist-sans, sans-serif)",
|
|
18
|
+
padding: "2rem",
|
|
19
|
+
textAlign: "center",
|
|
20
|
+
}}
|
|
21
|
+
>
|
|
22
|
+
<h1>500 - Server-side error occurred</h1>
|
|
23
|
+
<p style={{ marginTop: "1rem" }}>
|
|
24
|
+
Something went wrong on our end.
|
|
25
|
+
</p>
|
|
26
|
+
<Link
|
|
27
|
+
href="/"
|
|
28
|
+
style={{ marginTop: "1.5rem", textDecoration: "underline" }}
|
|
29
|
+
>
|
|
30
|
+
Go back home
|
|
31
|
+
</Link>
|
|
32
|
+
</div>
|
|
33
|
+
</>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
@@ -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,15 @@
|
|
|
1
|
+
import { Html, Head, Main, NextScript } from "next/document";
|
|
2
|
+
|
|
3
|
+
export default function Document() {
|
|
4
|
+
return (
|
|
5
|
+
<Html lang="en">
|
|
6
|
+
<Head>
|
|
7
|
+
<link rel="icon" href="/favicon.ico" />
|
|
8
|
+
</Head>
|
|
9
|
+
<body>
|
|
10
|
+
<Main />
|
|
11
|
+
<NextScript />
|
|
12
|
+
</body>
|
|
13
|
+
</Html>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
|
2
|
+
import type { NextApiRequest, NextApiResponse } from "next";
|
|
3
|
+
|
|
4
|
+
type Data = {
|
|
5
|
+
hello: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export default function handler(
|
|
9
|
+
req: NextApiRequest,
|
|
10
|
+
res: NextApiResponse<Data>,
|
|
11
|
+
) {
|
|
12
|
+
res.status(200).json({ hello: "lumen" });
|
|
13
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { GetServerSideProps, InferGetServerSidePropsType } from "next";
|
|
2
|
+
import Head from "next/head";
|
|
3
|
+
import Link from "next/link";
|
|
4
|
+
import { useRouter } from "next/router";
|
|
5
|
+
|
|
6
|
+
export const getServerSideProps: GetServerSideProps<{ slug: string }> = async (
|
|
7
|
+
context,
|
|
8
|
+
) => {
|
|
9
|
+
const slug = (context.params?.slug as string) || "";
|
|
10
|
+
return {
|
|
11
|
+
props: {
|
|
12
|
+
slug,
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default function BlogPost({
|
|
18
|
+
slug,
|
|
19
|
+
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
|
|
20
|
+
const router = useRouter();
|
|
21
|
+
const displaySlug = slug || (router.query.slug as string) || "";
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<>
|
|
25
|
+
<Head>
|
|
26
|
+
<title>{displaySlug}</title>
|
|
27
|
+
</Head>
|
|
28
|
+
<main
|
|
29
|
+
style={{
|
|
30
|
+
padding: "2rem",
|
|
31
|
+
fontFamily: "var(--font-geist-sans, sans-serif)",
|
|
32
|
+
maxWidth: "800px",
|
|
33
|
+
margin: "0 auto",
|
|
34
|
+
}}
|
|
35
|
+
>
|
|
36
|
+
<h1>{displaySlug}</h1>
|
|
37
|
+
<p style={{ marginTop: "1rem" }}>Post slug: {displaySlug}</p>
|
|
38
|
+
<p style={{ marginTop: "1.5rem" }}>
|
|
39
|
+
<Link href="/" style={{ textDecoration: "underline" }}>
|
|
40
|
+
Back to home
|
|
41
|
+
</Link>
|
|
42
|
+
</p>
|
|
43
|
+
</main>
|
|
44
|
+
</>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import Head from "next/head";
|
|
2
|
+
import Image from "next/image";
|
|
3
|
+
import styles from "@/styles/Home.module.css";
|
|
4
|
+
|
|
5
|
+
export default function Home() {
|
|
6
|
+
return (
|
|
7
|
+
<>
|
|
8
|
+
<Head>
|
|
9
|
+
<title>Create Next App</title>
|
|
10
|
+
<meta name="description" content="Generated by create next app" />
|
|
11
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
12
|
+
</Head>
|
|
13
|
+
<div className={styles.page}>
|
|
14
|
+
<main className={styles.main}>
|
|
15
|
+
<Image
|
|
16
|
+
className={styles.logo}
|
|
17
|
+
src="/next.svg"
|
|
18
|
+
alt="Next.js logo"
|
|
19
|
+
width={100}
|
|
20
|
+
height={20}
|
|
21
|
+
priority
|
|
22
|
+
/>
|
|
23
|
+
<div className={styles.intro}>
|
|
24
|
+
<h1>
|
|
25
|
+
To get started, edit the{" "}
|
|
26
|
+
<code className={styles.code}>index.tsx</code> file.
|
|
27
|
+
</h1>
|
|
28
|
+
<p>
|
|
29
|
+
Looking for a starting point or more instructions? Head over to{" "}
|
|
30
|
+
<a
|
|
31
|
+
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
|
32
|
+
target="_blank"
|
|
33
|
+
rel="noopener noreferrer"
|
|
34
|
+
>
|
|
35
|
+
Templates
|
|
36
|
+
</a>{" "}
|
|
37
|
+
or the{" "}
|
|
38
|
+
<a
|
|
39
|
+
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
|
40
|
+
target="_blank"
|
|
41
|
+
rel="noopener noreferrer"
|
|
42
|
+
>
|
|
43
|
+
Learning
|
|
44
|
+
</a>{" "}
|
|
45
|
+
center.
|
|
46
|
+
</p>
|
|
47
|
+
</div>
|
|
48
|
+
<div className={styles.ctas}>
|
|
49
|
+
<a
|
|
50
|
+
className={styles.primary}
|
|
51
|
+
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
|
|
52
|
+
target="_blank"
|
|
53
|
+
rel="noopener noreferrer"
|
|
54
|
+
>
|
|
55
|
+
<Image
|
|
56
|
+
className={styles.logo}
|
|
57
|
+
src="/vercel.svg"
|
|
58
|
+
alt="Vercel logomark"
|
|
59
|
+
width={16}
|
|
60
|
+
height={14}
|
|
61
|
+
/>
|
|
62
|
+
Deploy Now
|
|
63
|
+
</a>
|
|
64
|
+
<a
|
|
65
|
+
className={styles.secondary}
|
|
66
|
+
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
|
|
67
|
+
target="_blank"
|
|
68
|
+
rel="noopener noreferrer"
|
|
69
|
+
>
|
|
70
|
+
Documentation
|
|
71
|
+
</a>
|
|
72
|
+
</div>
|
|
73
|
+
</main>
|
|
74
|
+
</div>
|
|
75
|
+
</>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
@@ -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
|
+
}
|