create-next-mui 0.0.5 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +15 -1
  2. package/{next-mui-template-ts/esling.config.mjs → next-mui-template-js/eslint.config.mjs} +7 -7
  3. package/next-mui-template-js/jsconfig.json +11 -0
  4. package/next-mui-template-js/next.config.js +5 -0
  5. package/next-mui-template-js/package.json +2 -1
  6. package/next-mui-template-js/public/mui.svg +11 -0
  7. package/next-mui-template-js/public/next.svg +23 -1
  8. package/next-mui-template-js/src/app/{layout.tsx → layout.jsx} +3 -9
  9. package/next-mui-template-js/src/config-global.js +6 -0
  10. package/next-mui-template-js/src/lib/router-link/index.js +5 -0
  11. package/next-mui-template-js/src/sections/home/view.jsx +160 -0
  12. package/next-mui-template-js/src/theme/core/components/{button.ts → button.js} +1 -5
  13. package/next-mui-template-js/src/theme/core/components/{card.ts → card.js} +1 -5
  14. package/next-mui-template-js/src/theme/core/{palette.ts → palette.js} +0 -11
  15. package/next-mui-template-js/src/theme/{create-theme.ts → create-theme.js} +5 -1
  16. package/next-mui-template-js/src/theme/{theme-provider.tsx → theme-provider.jsx} +1 -1
  17. package/next-mui-template-ts/.vscode/settings.json +1 -1
  18. package/next-mui-template-ts/package.json +2 -1
  19. package/next-mui-template-ts/public/mui.svg +11 -0
  20. package/next-mui-template-ts/public/next.svg +23 -1
  21. package/next-mui-template-ts/src/app/layout.tsx +1 -1
  22. package/next-mui-template-ts/src/config-global.ts +7 -0
  23. package/next-mui-template-ts/src/sections/home/view.tsx +143 -32
  24. package/next-mui-template-ts/src/theme/core/components/button.ts +9 -1
  25. package/next-mui-template-ts/src/theme/create-theme.ts +6 -2
  26. package/package.json +1 -1
  27. package/src/index.js +63 -12
  28. package/next-mui-template-js/next.config.ts +0 -7
  29. package/next-mui-template-js/src/lib/router-link/index.ts +0 -5
  30. package/next-mui-template-js/src/sections/home/view.tsx +0 -49
  31. package/next-mui-template-js/tsconfig.json +0 -34
  32. /package/next-mui-template-js/src/app/{page.tsx → page.jsx} +0 -0
  33. /package/next-mui-template-js/src/theme/core/components/{index.ts → index.js} +0 -0
  34. /package/next-mui-template-js/src/theme/core/{typography.ts → typography.js} +0 -0
  35. /package/{next-mui-template-js/esling.config.mjs → next-mui-template-ts/eslint.config.mjs} +0 -0
package/README.md CHANGED
@@ -1,5 +1,11 @@
1
+ <img width="1420" height="308" alt="CREATE-NEXT-MUI-BANNER" src="https://github.com/user-attachments/assets/11e72fc8-6b6d-40c4-97a1-c05f7b943e02" />
2
+
1
3
  # create-next-mui 🚀
2
4
 
5
+ [![npm version](https://img.shields.io/npm/v/create-next-mui?style=flat&logo=npm&color=CB3837)](https://www.npmjs.com/package/create-next-mui)
6
+ [![Next.js v19](https://img.shields.io/badge/Next.js-v19-000000?style=flat&logo=nextdotjs&logoColor=white)](https://nextjs.org/)
7
+ [![MUI v9](https://img.shields.io/badge/MUI-v9-007FFF?style=flat&logo=mui&logoColor=white)](https://mui.com/)
8
+
3
9
  A blazing-fast, interactive CLI tool to instantly scaffold production-ready **Next.js** applications pre-configured with **Material UI (MUI)**, robust theme providers, and an elite architectural linting layout.
4
10
 
5
11
  Stop wasting time wiring up Emotion caches, Next.js App Router layout configs, or sorting your imports manually. Launch your next project perfectly in under 10 seconds.
@@ -11,10 +17,18 @@ Stop wasting time wiring up Emotion caches, Next.js App Router layout configs, o
11
17
  You don't need to install anything globally. Just run the following command in your terminal:
12
18
 
13
19
  ```bash
20
+ npx create-next-mui my-next-mui-app
21
+
22
+ # or use prompts
23
+
14
24
  npx create-next-mui
25
+
26
+ # or
27
+
28
+ npm init next-mui
15
29
  ```
16
30
 
17
- The interactive prompt engine (powered by `@clack/prompts`) will guide you through naming your project and selecting your preferred flavor.
31
+ Passing a project name creates that folder and uses the same name in the generated project metadata. If you omit the name, the interactive prompt engine (powered by `@clack/prompts`) will guide you through naming your project and selecting your preferred flavor.
18
32
 
19
33
  ---
20
34
 
@@ -18,7 +18,7 @@ const eslintConfig = defineConfig([
18
18
  "no-unused-vars": "off",
19
19
  "@typescript-eslint/no-unused-vars": "off",
20
20
  "unused-imports/no-unused-vars": [
21
- "off",
21
+ "warn",
22
22
  {
23
23
  args: "after-used",
24
24
  argsIgnorePattern: "^_",
@@ -26,13 +26,16 @@ const eslintConfig = defineConfig([
26
26
  varsIgnorePattern: "^_",
27
27
  },
28
28
  ],
29
- "perfectionist/sort-exports": [1, { order: "asc", type: "line-length" }],
29
+ "perfectionist/sort-exports": [
30
+ "warn",
31
+ { order: "asc", type: "line-length" },
32
+ ],
30
33
  "perfectionist/sort-named-imports": [
31
- 1,
34
+ "warn",
32
35
  { order: "asc", type: "line-length" },
33
36
  ],
34
37
  "perfectionist/sort-named-exports": [
35
- 1,
38
+ "warn",
36
39
  { order: "asc", type: "line-length" },
37
40
  ],
38
41
  "perfectionist/sort-imports": [
@@ -50,8 +53,6 @@ const eslintConfig = defineConfig([
50
53
  "next",
51
54
  "mui",
52
55
  "external",
53
- "type",
54
- "internal-types",
55
56
  "internal-lib",
56
57
  "internal-hooks",
57
58
  "internal-actions",
@@ -71,7 +72,6 @@ const eslintConfig = defineConfig([
71
72
  next: ["^next", "^next/.*", "cookies-next"],
72
73
  mui: ["^@mui/.*", "^@emotion/.*"],
73
74
  icons: ["^lucide-react$"],
74
- "internal-types": ["^@/types/.*"],
75
75
  "internal-lib": ["^@/lib/.*"],
76
76
  "internal-actions": ["^@/actions/.*"],
77
77
  "internal-hooks": ["^@/hooks/.*"],
@@ -0,0 +1,11 @@
1
+ {
2
+ "compilerOptions": {
3
+ "baseUrl": ".",
4
+ "paths": {
5
+ "@/*": ["./src/*"]
6
+ },
7
+ "ignoreDeprecations": "6.0"
8
+ },
9
+ "include": ["**/*.js", "**/*.jsx", "**/*.mjs", "**/*.json"],
10
+ "exclude": ["node_modules", ".next", "out", "build"]
11
+ }
@@ -0,0 +1,5 @@
1
+ const nextConfig = {
2
+ trailingSlash: true,
3
+ };
4
+
5
+ export default nextConfig;
@@ -6,7 +6,8 @@
6
6
  "dev": "next dev",
7
7
  "build": "next build",
8
8
  "start": "next start",
9
- "lint": "eslint ./src --fix "
9
+ "lint": "eslint ./src",
10
+ "lint:fix": "eslint ./src --fix"
10
11
  },
11
12
  "dependencies": {
12
13
  "@emotion/react": "^11.14.0",
@@ -0,0 +1,11 @@
1
+ <svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M4.16602 20.8334L29.166 37.5V120.833L4.16602 104.167V20.8334Z" fill="#29B6F6"/>
3
+ <path d="M195.834 83.3333L170.834 100V154.167L195.834 137.5V83.3333Z" fill="#0288D1"/>
4
+ <path d="M195.834 25L170.834 41.6667V70.8333L195.834 54.1667V25Z" fill="#0288D1"/>
5
+ <path d="M145.834 20.8334L120.834 37.5V120.833L145.834 104.167V20.8334Z" fill="#0288D1"/>
6
+ <path d="M4.16602 50L74.9993 95.8334V66.6667L4.16602 20.8334V50Z" fill="#29B6F6"/>
7
+ <path d="M145.833 50L75 95.8334V66.6667L145.833 20.8334V50Z" fill="#0288D1"/>
8
+ <path d="M145.833 108.333L75 154.167V125L145.833 79.1666V108.333Z" fill="#0288D1"/>
9
+ <path d="M195.833 141.667L125 187.5V158.333L195.833 112.5V141.667Z" fill="#0288D1"/>
10
+ <path d="M125 157.354L75 125V154.167L125 186.521V157.354Z" fill="#29B6F6"/>
11
+ </svg>
@@ -1 +1,23 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
1
+ <svg width="212" height="212" viewBox="0 0 212 212" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M106 193.158C154.137 193.158 193.159 154.136 193.159 106C193.159 57.8637 154.137 18.8415 106 18.8415C57.864 18.8415 18.8418 57.8637 18.8418 106C18.8418 154.136 57.864 193.158 106 193.158Z" fill="url(#paint0_linear_694_4)"/>
3
+ <path d="M83.9824 70.7859H70.6309V141.435H83.9824V70.7859Z" fill="white"/>
4
+ <path d="M141.281 70.4767H128.238V134.916H141.281V70.4767Z" fill="url(#paint1_linear_694_4)"/>
5
+ <path d="M162.449 168.248L150.908 172.647L70.6309 70.7859H86.1599L162.449 168.248Z" fill="url(#paint2_linear_694_4)"/>
6
+ <defs>
7
+ <linearGradient id="paint0_linear_694_4" x1="106" y1="193.158" x2="106" y2="18.8415" gradientUnits="userSpaceOnUse">
8
+ <stop stop-color="#0A070A"/>
9
+ <stop offset="0.465" stop-color="#2B2B2B"/>
10
+ <stop offset="1" stop-color="#4B4B4B"/>
11
+ </linearGradient>
12
+ <linearGradient id="paint1_linear_694_4" x1="134.762" y1="145.843" x2="134.762" y2="81.4036" gradientUnits="userSpaceOnUse">
13
+ <stop offset="0.377" stop-color="white" stop-opacity="0"/>
14
+ <stop offset="0.666" stop-color="white" stop-opacity="0.3"/>
15
+ <stop offset="0.988" stop-color="white"/>
16
+ </linearGradient>
17
+ <linearGradient id="paint2_linear_694_4" x1="97.6167" y1="94.7065" x2="161.919" y2="179.003" gradientUnits="userSpaceOnUse">
18
+ <stop offset="0.296" stop-color="white"/>
19
+ <stop offset="0.521" stop-color="white" stop-opacity="0.5"/>
20
+ <stop offset="0.838" stop-color="white" stop-opacity="0"/>
21
+ </linearGradient>
22
+ </defs>
23
+ </svg>
@@ -2,8 +2,6 @@ import "./globals.css";
2
2
 
3
3
  import { Geist, Geist_Mono } from "next/font/google";
4
4
 
5
- import type { Metadata } from "next";
6
-
7
5
  import { ThemeProvider } from "@/theme/theme-provider";
8
6
 
9
7
  // ---------------------------------------------------------------
@@ -18,16 +16,12 @@ const geistMono = Geist_Mono({
18
16
  subsets: ["latin"],
19
17
  });
20
18
 
21
- export const metadata: Metadata = {
19
+ export const metadata = {
22
20
  title: "create-next-mui",
23
- description: "create your nextjs project with mui setup",
21
+ description: "The fastest way to scaffold Nextjs + MUI",
24
22
  };
25
23
 
26
- export default function RootLayout({
27
- children,
28
- }: Readonly<{
29
- children: React.ReactNode;
30
- }>) {
24
+ export default function RootLayout({ children }) {
31
25
  return (
32
26
  <html
33
27
  lang="en"
@@ -0,0 +1,6 @@
1
+ export const CONFIG = {
2
+ /**
3
+ * @defaultMode "dark" | "light"
4
+ */
5
+ defaultMode: "dark",
6
+ };
@@ -0,0 +1,5 @@
1
+ "use client";
2
+
3
+ import Link from "next/link";
4
+
5
+ export { Link as RouterLink };
@@ -0,0 +1,160 @@
1
+ "use client";
2
+
3
+ import Image from "next/image";
4
+
5
+ import Box from "@mui/material/Box";
6
+ import Link from "@mui/material/Link";
7
+ import Paper from "@mui/material/Paper";
8
+ import Stack from "@mui/material/Stack";
9
+ import Button from "@mui/material/Button";
10
+ import SvgIcon from "@mui/material/SvgIcon";
11
+ import Container from "@mui/material/Container";
12
+ import Typography from "@mui/material/Typography";
13
+ import { alpha as hexAlpha } from "@mui/material/styles";
14
+
15
+ import { RouterLink } from "@/lib/router-link";
16
+
17
+ // ---------------------------------------------------------------
18
+
19
+ export function HomeView() {
20
+ return (
21
+ <Box>
22
+ <Container maxWidth="md">
23
+ <Stack
24
+ sx={{
25
+ minHeight: "100vh",
26
+ alignItems: "center",
27
+ justifyContent: "center",
28
+ }}
29
+ spacing={8}
30
+ >
31
+ <Stack direction="row" sx={{ alignItems: "center" }} spacing={8}>
32
+ <Box>
33
+ <Image
34
+ width={180}
35
+ height={180}
36
+ alt="nextjs"
37
+ src="/next.svg"
38
+ loading="eager"
39
+ />
40
+ </Box>
41
+
42
+ <Box>
43
+ <SvgIcon
44
+ fill="none"
45
+ stroke="#fff"
46
+ strokeWidth="2"
47
+ viewBox="0 0 24 24"
48
+ strokeLinecap="round"
49
+ strokeLinejoin="round"
50
+ sx={{ width: 80, height: 80 }}
51
+ className="lucide lucide-plus-icon lucide-plus"
52
+ >
53
+ <path d="M5 12h14" />
54
+ <path d="M12 5v14" />
55
+ </SvgIcon>
56
+ </Box>
57
+
58
+ <Box>
59
+ <Image
60
+ width={150}
61
+ height={150}
62
+ alt="nextjs"
63
+ src="/mui.svg"
64
+ loading="eager"
65
+ />
66
+ </Box>
67
+ </Stack>
68
+
69
+ <Stack spacing={4} sx={{ alignItems: "center" }}>
70
+ <Stack direction="row" spacing={2}>
71
+ <Button
72
+ variant="outlined"
73
+ LinkComponent={RouterLink}
74
+ href="https://github.com/thatonevikash/create-next-mui/"
75
+ target="_blank"
76
+ sx={(theme) => ({
77
+ px: 1.5,
78
+ borderRadius: 4,
79
+ border: `1px solid ${theme.palette.divider}`,
80
+ })}
81
+ >
82
+ <SvgIcon
83
+ fill="none"
84
+ viewBox="0 0 200 200"
85
+ sx={{ width: 44, height: 44 }}
86
+ >
87
+ <path
88
+ fill="white"
89
+ d="M100 20C55.82 20 20 55.82 20 100C20 137.487 45.8133 168.853 80.6133 177.533C80.24 176.453 80 175.2 80 173.647V159.973C76.7533 159.973 71.3133 159.973 69.9467 159.973C64.4733 159.973 59.6067 157.62 57.2467 153.247C54.6267 148.387 54.1733 140.953 47.68 136.407C45.7533 134.893 47.22 133.167 49.44 133.4C53.54 134.56 56.94 137.373 60.14 141.547C63.3267 145.727 64.8267 146.673 70.78 146.673C73.6667 146.673 77.9867 146.507 82.0533 145.867C84.24 140.313 88.02 135.2 92.64 132.787C66 130.047 53.2867 116.793 53.2867 98.8C53.2867 91.0534 56.5867 83.56 62.1933 77.2467C60.3533 70.98 58.04 58.2 62.9 53.3333C74.8867 53.3333 82.1333 61.1067 83.8733 63.2067C89.8467 61.16 96.4067 60 103.3 60C110.207 60 116.793 61.16 122.78 63.22C124.5 61.1334 131.753 53.3333 143.767 53.3333C148.647 58.2067 146.307 71.04 144.447 77.2934C150.02 83.5934 153.3 91.0667 153.3 98.8C153.3 116.78 140.607 130.027 114.007 132.78C121.327 136.6 126.667 147.333 126.667 155.42V173.647C126.667 174.34 126.513 174.84 126.433 175.433C157.607 164.507 180 134.907 180 100C180 55.82 144.18 20 100 20Z"
90
+ />
91
+ </SvgIcon>
92
+ </Button>
93
+ <Paper variant="outlined" sx={{ px: 4, py: 2, borderRadius: 4 }}>
94
+ <Typography
95
+ variant="h5"
96
+ sx={{
97
+ display: "flex",
98
+ alignItems: "center",
99
+ gap: 1.2,
100
+ }}
101
+ >
102
+ <Box component="span" sx={{ color: "text.secondary" }}>
103
+ npx
104
+ </Box>
105
+
106
+ <Box component="span">create-next-mui</Box>
107
+
108
+ <Box
109
+ sx={(theme) => ({
110
+ p: 1,
111
+ ml: 1,
112
+ borderRadius: 2,
113
+ cursor: "pointer",
114
+ bgcolor: hexAlpha(theme.palette.grey["800"], 0.2),
115
+ display: "flex",
116
+ alignItems: "center",
117
+ justifyContent: "center",
118
+ })}
119
+ >
120
+ <SvgIcon
121
+ strokeWidth="2"
122
+ stroke="#dadada"
123
+ viewBox="0 0 24 24"
124
+ strokeLinecap="round"
125
+ strokeLinejoin="round"
126
+ sx={{ fill: "transparent" }}
127
+ className="lucide lucide-copy-icon lucide-copy"
128
+ >
129
+ <rect width="14" height="14" x="8" y="8" rx="2" ry="2" />
130
+ <path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" />
131
+ </SvgIcon>
132
+ </Box>
133
+ </Typography>
134
+ </Paper>
135
+ </Stack>
136
+
137
+ <Typography variant="caption" sx={{ color: "text.disabled" }}>
138
+ The fastest way to scaffold&nbsp;
139
+ <Link
140
+ component={RouterLink}
141
+ href="https://nextjs.org/"
142
+ target="_blank"
143
+ >
144
+ Nextjs
145
+ </Link>
146
+ &nbsp;+&nbsp;
147
+ <Link
148
+ component={RouterLink}
149
+ href="https://mui.com/"
150
+ target="_blank"
151
+ >
152
+ MUI
153
+ </Link>
154
+ </Typography>
155
+ </Stack>
156
+ </Stack>
157
+ </Container>
158
+ </Box>
159
+ );
160
+ }
@@ -1,10 +1,6 @@
1
- import { Theme, Components } from "@mui/material";
2
-
3
- import type {} from "@mui/material/themeCssVarsAugmentation";
4
-
5
1
  // ---------------------------------------------------------------
6
2
 
7
- const MuiButton: Components<Theme>["MuiButton"] = {
3
+ const MuiButton = {
8
4
  styleOverrides: {
9
5
  root: ({ theme }) => ({
10
6
  textTransform: "unset",
@@ -1,10 +1,6 @@
1
- import { Theme, Components } from "@mui/material";
2
-
3
- import type {} from "@mui/material/themeCssVarsAugmentation";
4
-
5
1
  // ---------------------------------------------------------------
6
2
 
7
- const MuiCard: Components<Theme>["MuiCard"] = {
3
+ const MuiCard = {
8
4
  styleOverrides: {
9
5
  root: ({ theme }) => ({
10
6
  borderRadius: theme.spacing(2.5),
@@ -21,14 +21,3 @@ export const palette = {
21
21
  success: SUCCESS,
22
22
  warning: WARNING,
23
23
  };
24
-
25
- // ---------------------------------------------------------------
26
-
27
- declare module "@mui/material/styles" {
28
- interface Palette {
29
- purple: Palette["primary"];
30
- }
31
- interface PaletteOptions {
32
- purple?: PaletteOptions["primary"];
33
- }
34
- }
@@ -1,9 +1,13 @@
1
1
  import { createTheme } from "@mui/material";
2
2
 
3
+ import { CONFIG } from "@/config-global";
4
+
3
5
  import { palette } from "./core/palette";
4
6
  import { typography } from "./core/typography";
5
7
  import { components } from "./core/components";
6
8
 
9
+ const { defaultMode } = CONFIG;
10
+
7
11
  // ---------------------------------------------------------------
8
12
 
9
13
  const defaultFont = "var(--font-geist-sans), Arial, sans-serif";
@@ -11,7 +15,7 @@ const defaultFont = "var(--font-geist-sans), Arial, sans-serif";
11
15
  export const theme = createTheme({
12
16
  cssVariables: true,
13
17
 
14
- palette: { mode: "light", ...palette },
18
+ palette: { mode: defaultMode, ...palette },
15
19
 
16
20
  typography: {
17
21
  fontFamily: defaultFont,
@@ -7,7 +7,7 @@ import { theme } from "./create-theme";
7
7
 
8
8
  // ---------------------------------------------------------------
9
9
 
10
- export function ThemeProvider({ children }: { children: React.ReactNode }) {
10
+ export function ThemeProvider({ children }) {
11
11
  return (
12
12
  <AppRouterCacheProvider>
13
13
  <MuiThemeProvider theme={theme}>
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "editor.quickSuggestions": {
3
- "other": false,
3
+ "other": true,
4
4
  "comments": false,
5
5
  "strings": false
6
6
  }
@@ -6,7 +6,8 @@
6
6
  "dev": "next dev",
7
7
  "build": "next build",
8
8
  "start": "next start",
9
- "lint": "eslint ./src --fix "
9
+ "lint": "eslint ./src",
10
+ "lint:fix": "eslint ./src --fix"
10
11
  },
11
12
  "dependencies": {
12
13
  "@emotion/react": "^11.14.0",
@@ -0,0 +1,11 @@
1
+ <svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M4.16602 20.8334L29.166 37.5V120.833L4.16602 104.167V20.8334Z" fill="#29B6F6"/>
3
+ <path d="M195.834 83.3333L170.834 100V154.167L195.834 137.5V83.3333Z" fill="#0288D1"/>
4
+ <path d="M195.834 25L170.834 41.6667V70.8333L195.834 54.1667V25Z" fill="#0288D1"/>
5
+ <path d="M145.834 20.8334L120.834 37.5V120.833L145.834 104.167V20.8334Z" fill="#0288D1"/>
6
+ <path d="M4.16602 50L74.9993 95.8334V66.6667L4.16602 20.8334V50Z" fill="#29B6F6"/>
7
+ <path d="M145.833 50L75 95.8334V66.6667L145.833 20.8334V50Z" fill="#0288D1"/>
8
+ <path d="M145.833 108.333L75 154.167V125L145.833 79.1666V108.333Z" fill="#0288D1"/>
9
+ <path d="M195.833 141.667L125 187.5V158.333L195.833 112.5V141.667Z" fill="#0288D1"/>
10
+ <path d="M125 157.354L75 125V154.167L125 186.521V157.354Z" fill="#29B6F6"/>
11
+ </svg>
@@ -1 +1,23 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
1
+ <svg width="212" height="212" viewBox="0 0 212 212" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M106 193.158C154.137 193.158 193.159 154.136 193.159 106C193.159 57.8637 154.137 18.8415 106 18.8415C57.864 18.8415 18.8418 57.8637 18.8418 106C18.8418 154.136 57.864 193.158 106 193.158Z" fill="url(#paint0_linear_694_4)"/>
3
+ <path d="M83.9824 70.7859H70.6309V141.435H83.9824V70.7859Z" fill="white"/>
4
+ <path d="M141.281 70.4767H128.238V134.916H141.281V70.4767Z" fill="url(#paint1_linear_694_4)"/>
5
+ <path d="M162.449 168.248L150.908 172.647L70.6309 70.7859H86.1599L162.449 168.248Z" fill="url(#paint2_linear_694_4)"/>
6
+ <defs>
7
+ <linearGradient id="paint0_linear_694_4" x1="106" y1="193.158" x2="106" y2="18.8415" gradientUnits="userSpaceOnUse">
8
+ <stop stop-color="#0A070A"/>
9
+ <stop offset="0.465" stop-color="#2B2B2B"/>
10
+ <stop offset="1" stop-color="#4B4B4B"/>
11
+ </linearGradient>
12
+ <linearGradient id="paint1_linear_694_4" x1="134.762" y1="145.843" x2="134.762" y2="81.4036" gradientUnits="userSpaceOnUse">
13
+ <stop offset="0.377" stop-color="white" stop-opacity="0"/>
14
+ <stop offset="0.666" stop-color="white" stop-opacity="0.3"/>
15
+ <stop offset="0.988" stop-color="white"/>
16
+ </linearGradient>
17
+ <linearGradient id="paint2_linear_694_4" x1="97.6167" y1="94.7065" x2="161.919" y2="179.003" gradientUnits="userSpaceOnUse">
18
+ <stop offset="0.296" stop-color="white"/>
19
+ <stop offset="0.521" stop-color="white" stop-opacity="0.5"/>
20
+ <stop offset="0.838" stop-color="white" stop-opacity="0"/>
21
+ </linearGradient>
22
+ </defs>
23
+ </svg>
@@ -20,7 +20,7 @@ const geistMono = Geist_Mono({
20
20
 
21
21
  export const metadata: Metadata = {
22
22
  title: "create-next-mui",
23
- description: "create your nextjs project with mui setup",
23
+ description: "The fastest way to scaffold Nextjs + MUI",
24
24
  };
25
25
 
26
26
  export default function RootLayout({
@@ -0,0 +1,7 @@
1
+ interface GlobalConfig {
2
+ defaultMode: "light" | "dark";
3
+ }
4
+
5
+ export const CONFIG: GlobalConfig = {
6
+ defaultMode: "dark",
7
+ };
@@ -1,49 +1,160 @@
1
1
  "use client";
2
2
 
3
+ import Image from "next/image";
4
+
3
5
  import Box from "@mui/material/Box";
6
+ import Link from "@mui/material/Link";
7
+ import Paper from "@mui/material/Paper";
4
8
  import Stack from "@mui/material/Stack";
5
9
  import Button from "@mui/material/Button";
10
+ import SvgIcon from "@mui/material/SvgIcon";
6
11
  import Container from "@mui/material/Container";
7
12
  import Typography from "@mui/material/Typography";
13
+ import { alpha as hexAlpha } from "@mui/material/styles";
14
+
8
15
  import { RouterLink } from "@/lib/router-link";
9
16
 
10
17
  // ---------------------------------------------------------------
11
18
 
12
19
  export function HomeView() {
13
20
  return (
14
- <Container maxWidth="md">
15
- <Box
16
- sx={{
17
- minHeight: "100vh",
18
- display: "flex",
19
- alignItems: "center",
20
- justifyContent: "center",
21
- }}
22
- >
23
- <Stack spacing={3} sx={{ alignItems: "center", textAlign: "center" }}>
24
- <Typography variant="h2" component="h1">
25
- Workspace Scaffolded Successfully!
26
- </Typography>
27
- <Typography variant="h6" color="text.secondary">
28
- Next.js App Router + Modular MUI Theming System + Perfectionist
29
- Linting Rules are locked and loaded.
30
- </Typography>
31
- <Stack direction="row" spacing={2}>
32
- <Button variant="contained" color="primary" size="large">
33
- Explore Theme Configuration
34
- </Button>
35
- <Button
36
- size="large"
37
- color="secondary"
38
- variant="outlined"
39
- LinkComponent={RouterLink}
40
- href="/"
41
- >
42
- Read Documentation
43
- </Button>
21
+ <Box>
22
+ <Container maxWidth="md">
23
+ <Stack
24
+ sx={{
25
+ minHeight: "100vh",
26
+ alignItems: "center",
27
+ justifyContent: "center",
28
+ }}
29
+ spacing={8}
30
+ >
31
+ <Stack direction="row" sx={{ alignItems: "center" }} spacing={8}>
32
+ <Box>
33
+ <Image
34
+ width={180}
35
+ height={180}
36
+ alt="nextjs"
37
+ src="/next.svg"
38
+ loading="eager"
39
+ />
40
+ </Box>
41
+
42
+ <Box>
43
+ <SvgIcon
44
+ fill="none"
45
+ stroke="#fff"
46
+ strokeWidth="2"
47
+ viewBox="0 0 24 24"
48
+ strokeLinecap="round"
49
+ strokeLinejoin="round"
50
+ sx={{ width: 80, height: 80 }}
51
+ className="lucide lucide-plus-icon lucide-plus"
52
+ >
53
+ <path d="M5 12h14" />
54
+ <path d="M12 5v14" />
55
+ </SvgIcon>
56
+ </Box>
57
+
58
+ <Box>
59
+ <Image
60
+ width={150}
61
+ height={150}
62
+ alt="nextjs"
63
+ src="/mui.svg"
64
+ loading="eager"
65
+ />
66
+ </Box>
67
+ </Stack>
68
+
69
+ <Stack spacing={4} sx={{ alignItems: "center" }}>
70
+ <Stack direction="row" spacing={2}>
71
+ <Button
72
+ variant="outlined"
73
+ LinkComponent={RouterLink}
74
+ href="https://github.com/thatonevikash/create-next-mui/"
75
+ target="_blank"
76
+ sx={(theme) => ({
77
+ px: 1.5,
78
+ borderRadius: 4,
79
+ border: `1px solid ${theme.palette.divider}`,
80
+ })}
81
+ >
82
+ <SvgIcon
83
+ fill="none"
84
+ viewBox="0 0 200 200"
85
+ sx={{ width: 44, height: 44 }}
86
+ >
87
+ <path
88
+ fill="white"
89
+ d="M100 20C55.82 20 20 55.82 20 100C20 137.487 45.8133 168.853 80.6133 177.533C80.24 176.453 80 175.2 80 173.647V159.973C76.7533 159.973 71.3133 159.973 69.9467 159.973C64.4733 159.973 59.6067 157.62 57.2467 153.247C54.6267 148.387 54.1733 140.953 47.68 136.407C45.7533 134.893 47.22 133.167 49.44 133.4C53.54 134.56 56.94 137.373 60.14 141.547C63.3267 145.727 64.8267 146.673 70.78 146.673C73.6667 146.673 77.9867 146.507 82.0533 145.867C84.24 140.313 88.02 135.2 92.64 132.787C66 130.047 53.2867 116.793 53.2867 98.8C53.2867 91.0534 56.5867 83.56 62.1933 77.2467C60.3533 70.98 58.04 58.2 62.9 53.3333C74.8867 53.3333 82.1333 61.1067 83.8733 63.2067C89.8467 61.16 96.4067 60 103.3 60C110.207 60 116.793 61.16 122.78 63.22C124.5 61.1334 131.753 53.3333 143.767 53.3333C148.647 58.2067 146.307 71.04 144.447 77.2934C150.02 83.5934 153.3 91.0667 153.3 98.8C153.3 116.78 140.607 130.027 114.007 132.78C121.327 136.6 126.667 147.333 126.667 155.42V173.647C126.667 174.34 126.513 174.84 126.433 175.433C157.607 164.507 180 134.907 180 100C180 55.82 144.18 20 100 20Z"
90
+ />
91
+ </SvgIcon>
92
+ </Button>
93
+ <Paper variant="outlined" sx={{ px: 4, py: 2, borderRadius: 4 }}>
94
+ <Typography
95
+ variant="h5"
96
+ sx={{
97
+ display: "flex",
98
+ alignItems: "center",
99
+ gap: 1.2,
100
+ }}
101
+ >
102
+ <Box component="span" sx={{ color: "text.secondary" }}>
103
+ npx
104
+ </Box>
105
+
106
+ <Box component="span">create-next-mui</Box>
107
+
108
+ <Box
109
+ sx={(theme) => ({
110
+ p: 1,
111
+ ml: 1,
112
+ borderRadius: 2,
113
+ cursor: "pointer",
114
+ bgcolor: hexAlpha(theme.palette.grey["800"], 0.2),
115
+ display: "flex",
116
+ alignItems: "center",
117
+ justifyContent: "center",
118
+ })}
119
+ >
120
+ <SvgIcon
121
+ strokeWidth="2"
122
+ stroke="#dadada"
123
+ viewBox="0 0 24 24"
124
+ strokeLinecap="round"
125
+ strokeLinejoin="round"
126
+ sx={{ fill: "transparent" }}
127
+ className="lucide lucide-copy-icon lucide-copy"
128
+ >
129
+ <rect width="14" height="14" x="8" y="8" rx="2" ry="2" />
130
+ <path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" />
131
+ </SvgIcon>
132
+ </Box>
133
+ </Typography>
134
+ </Paper>
135
+ </Stack>
136
+
137
+ <Typography variant="caption" sx={{ color: "text.disabled" }}>
138
+ The fastest way to scaffold&nbsp;
139
+ <Link
140
+ component={RouterLink}
141
+ href="https://nextjs.org/"
142
+ target="_blank"
143
+ >
144
+ Nextjs
145
+ </Link>
146
+ &nbsp;+&nbsp;
147
+ <Link
148
+ component={RouterLink}
149
+ href="https://mui.com/"
150
+ target="_blank"
151
+ >
152
+ MUI
153
+ </Link>
154
+ </Typography>
44
155
  </Stack>
45
156
  </Stack>
46
- </Box>
47
- </Container>
157
+ </Container>
158
+ </Box>
48
159
  );
49
160
  }
@@ -17,6 +17,10 @@ const MuiButton: Components<Theme>["MuiButton"] = {
17
17
  borderRadius: theme.spacing(1.5),
18
18
  color: theme.vars.palette.common.white,
19
19
  backgroundColor: theme.vars.palette.grey[900],
20
+ ...theme.applyStyles("dark", {
21
+ color: theme.vars.palette.common.black,
22
+ backgroundColor: theme.vars.palette.grey[100],
23
+ }),
20
24
  },
21
25
  },
22
26
  {
@@ -24,7 +28,11 @@ const MuiButton: Components<Theme>["MuiButton"] = {
24
28
  style: {
25
29
  borderRadius: theme.spacing(1.5),
26
30
  color: theme.vars.palette.common.black,
27
- borderColor: theme.vars.palette.common.black,
31
+ borderColor: theme.vars.palette.grey[900],
32
+ ...theme.applyStyles("dark", {
33
+ color: theme.vars.palette.common.white,
34
+ borderColor: theme.vars.palette.grey[100],
35
+ }),
28
36
  },
29
37
  },
30
38
  ],
@@ -1,17 +1,21 @@
1
1
  import { createTheme } from "@mui/material";
2
2
 
3
+ import { CONFIG } from "@/config-global";
4
+
3
5
  import { palette } from "./core/palette";
4
- import { typography } from "./core/typography";
5
6
  import { components } from "./core/components";
7
+ import { typography } from "./core/typography";
6
8
 
7
9
  // ---------------------------------------------------------------
8
10
 
11
+ const { defaultMode } = CONFIG;
12
+
9
13
  const defaultFont = "var(--font-geist-sans), Arial, sans-serif";
10
14
 
11
15
  export const theme = createTheme({
12
16
  cssVariables: true,
13
17
 
14
- palette: { mode: "light", ...palette },
18
+ palette: { mode: defaultMode, ...palette },
15
19
 
16
20
  typography: {
17
21
  fontFamily: defaultFont,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-next-mui",
3
- "version": "0.0.5",
3
+ "version": "0.1.1",
4
4
  "description": "spin up your nextjs project with mui setup",
5
5
  "keywords": [
6
6
  "nextjs",
package/src/index.js CHANGED
@@ -10,25 +10,74 @@ import { fileURLToPath } from "node:url";
10
10
  const __filename = fileURLToPath(import.meta.url);
11
11
  const __dirname = path.dirname(__filename);
12
12
 
13
+ const initialProjectName = process.argv[2];
14
+ const hasInitialProjectName = typeof initialProjectName === "string";
15
+
16
+ function validateProjectName(value) {
17
+ if (value.length === 0) return "Project name is required!";
18
+
19
+ if (value !== "." && value.match(/[^a-zA-Z0-9-_]/g)) {
20
+ return "Keep it URL safe or use '.' for the current folder";
21
+ }
22
+ }
23
+
24
+ function getPackageName(projectName, targetProjectDir) {
25
+ const rawName =
26
+ projectName === "." ? path.basename(targetProjectDir) : projectName;
27
+
28
+ return rawName.toLowerCase();
29
+ }
30
+
31
+ async function updateProjectName(targetProjectDir, packageName) {
32
+ const files = ["package.json", "package-lock.json"];
33
+
34
+ await Promise.all(
35
+ files.map(async (file) => {
36
+ const filePath = path.join(targetProjectDir, file);
37
+
38
+ try {
39
+ const content = await fs.readFile(filePath, "utf8");
40
+ const json = JSON.parse(content);
41
+
42
+ json.name = packageName;
43
+
44
+ if (json.packages?.[""]?.name) {
45
+ json.packages[""].name = packageName;
46
+ }
47
+
48
+ await fs.writeFile(filePath, `${JSON.stringify(json, null, 2)}\n`);
49
+ } catch (error) {
50
+ if (error.code === "ENOENT") return;
51
+
52
+ throw error;
53
+ }
54
+ }),
55
+ );
56
+ }
57
+
13
58
  async function main() {
14
59
  console.clear();
15
60
  p.intro(color.bgBlue(color.white(" create-next-mui ")));
16
61
 
62
+ const projectNameError = hasInitialProjectName
63
+ ? validateProjectName(initialProjectName)
64
+ : undefined;
65
+
66
+ if (projectNameError) {
67
+ p.cancel(projectNameError);
68
+ process.exit(1);
69
+ }
70
+
17
71
  const project = await p.group(
18
72
  {
19
73
  name: () =>
20
- p.text({
21
- message: "What is your project name?",
22
- placeholder: "my-next-mui-app (or '.' for current directory)",
23
- validate(value) {
24
- if (value.length === 0) return "Project name is required!";
25
-
26
- // ✅ Allow exactly "." otherwise apply your safe character regex
27
- if (value !== "." && value.match(/[^a-zA-Z0-9-_]/g)) {
28
- return "Keep it URL safe or use '.' for the current folder";
29
- }
30
- },
31
- }),
74
+ hasInitialProjectName
75
+ ? Promise.resolve(initialProjectName)
76
+ : p.text({
77
+ message: "What is your project name?",
78
+ placeholder: "my-next-mui-app (or '.' for current directory)",
79
+ validate: validateProjectName,
80
+ }),
32
81
  language: () =>
33
82
  p.select({
34
83
  message: "Choose your language flavor:",
@@ -61,6 +110,7 @@ async function main() {
61
110
 
62
111
  // Define destination paths (where the user is running the command)
63
112
  const targetProjectDir = path.resolve(process.cwd(), project.name);
113
+ const packageName = getPackageName(project.name, targetProjectDir);
64
114
 
65
115
  // If targeting current directory, make sure it's clean
66
116
  if (project.name === ".") {
@@ -97,6 +147,7 @@ async function main() {
97
147
  );
98
148
  },
99
149
  });
150
+ await updateProjectName(targetProjectDir, packageName);
100
151
 
101
152
  s.stop(color.green("Workspace scaffolded successfully!"));
102
153
  } catch (error) {
@@ -1,7 +0,0 @@
1
- import type { NextConfig } from "next";
2
-
3
- const nextConfig: NextConfig = {
4
- trailingSlash: true,
5
- };
6
-
7
- export default nextConfig;
@@ -1,5 +0,0 @@
1
- "use client";
2
-
3
- import Link, { type LinkProps } from "next/link";
4
-
5
- export { Link as RouterLink, LinkProps as RouterLinkProps };
@@ -1,49 +0,0 @@
1
- "use client";
2
-
3
- import Box from "@mui/material/Box";
4
- import Stack from "@mui/material/Stack";
5
- import Button from "@mui/material/Button";
6
- import Container from "@mui/material/Container";
7
- import Typography from "@mui/material/Typography";
8
- import { RouterLink } from "@/lib/router-link";
9
-
10
- // ---------------------------------------------------------------
11
-
12
- export function HomeView() {
13
- return (
14
- <Container maxWidth="md">
15
- <Box
16
- sx={{
17
- minHeight: "100vh",
18
- display: "flex",
19
- alignItems: "center",
20
- justifyContent: "center",
21
- }}
22
- >
23
- <Stack spacing={3} sx={{ alignItems: "center", textAlign: "center" }}>
24
- <Typography variant="h2" component="h1">
25
- Workspace Scaffolded Successfully!
26
- </Typography>
27
- <Typography variant="h6" color="text.secondary">
28
- Next.js App Router + Modular MUI Theming System + Perfectionist
29
- Linting Rules are locked and loaded.
30
- </Typography>
31
- <Stack direction="row" spacing={2}>
32
- <Button variant="contained" color="primary" size="large">
33
- Explore Theme Configuration
34
- </Button>
35
- <Button
36
- size="large"
37
- color="secondary"
38
- variant="outlined"
39
- LinkComponent={RouterLink}
40
- href="/"
41
- >
42
- Read Documentation
43
- </Button>
44
- </Stack>
45
- </Stack>
46
- </Box>
47
- </Container>
48
- );
49
- }
@@ -1,34 +0,0 @@
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": [
17
- {
18
- "name": "next"
19
- }
20
- ],
21
- "paths": {
22
- "@/*": ["./src/*"]
23
- }
24
- },
25
- "include": [
26
- "next-env.d.ts",
27
- "**/*.ts",
28
- "**/*.tsx",
29
- ".next/types/**/*.ts",
30
- ".next/dev/types/**/*.ts",
31
- "**/*.mts"
32
- ],
33
- "exclude": ["node_modules"]
34
- }