@codabytez/create-next-template 0.1.0

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 (37) hide show
  1. package/README.md +548 -0
  2. package/dist/index.js +407 -0
  3. package/package.json +31 -0
  4. package/templates/animations/components/motion/fade-in.tsx +28 -0
  5. package/templates/appwrite/.env.example +3 -0
  6. package/templates/appwrite/lib/appwrite.ts +11 -0
  7. package/templates/auth/.env.example +6 -0
  8. package/templates/auth/app/(auth)/sign-in/[[...sign-in]]/page.tsx +9 -0
  9. package/templates/auth/app/(auth)/sign-up/[[...sign-up]]/page.tsx +9 -0
  10. package/templates/auth/middleware.ts +17 -0
  11. package/templates/base/.env.example +1 -0
  12. package/templates/base/.husky/pre-commit +19 -0
  13. package/templates/base/.husky/pre-push +11 -0
  14. package/templates/base/.prettierignore +8 -0
  15. package/templates/base/.prettierrc.json +9 -0
  16. package/templates/base/CONTRIBUTING.md +120 -0
  17. package/templates/base/app/globals.css +28 -0
  18. package/templates/base/app/page.tsx +7 -0
  19. package/templates/base/components/ui/button.tsx +40 -0
  20. package/templates/base/eslint.config.mjs +51 -0
  21. package/templates/base/lib/env.ts +7 -0
  22. package/templates/base/lib/utils.ts +6 -0
  23. package/templates/base/next.config.ts +5 -0
  24. package/templates/base/postcss.config.mjs +7 -0
  25. package/templates/base/tsconfig.json +23 -0
  26. package/templates/convex/.env.example +1 -0
  27. package/templates/convex/convex/schema.ts +10 -0
  28. package/templates/convex/convex/users.ts +19 -0
  29. package/templates/convex/providers/convex-provider.tsx +15 -0
  30. package/templates/data-fetching/lib/api.ts +18 -0
  31. package/templates/data-fetching/providers/query-provider.tsx +22 -0
  32. package/templates/forms/components/forms/example-form.tsx +58 -0
  33. package/templates/forms/lib/validations/example.ts +8 -0
  34. package/templates/prisma/.env.example +1 -0
  35. package/templates/prisma/lib/db.ts +11 -0
  36. package/templates/prisma/prisma/schema.prisma +16 -0
  37. package/templates/ui/components.json +20 -0
package/dist/index.js ADDED
@@ -0,0 +1,407 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
25
+
26
+ // src/index.ts
27
+ var p2 = __toESM(require("@clack/prompts"));
28
+ var import_chalk2 = __toESM(require("chalk"));
29
+ var import_path6 = __toESM(require("path"));
30
+
31
+ // src/installer.ts
32
+ var p = __toESM(require("@clack/prompts"));
33
+ var import_chalk = __toESM(require("chalk"));
34
+ var import_fs_extra5 = __toESM(require("fs-extra"));
35
+ var import_path5 = __toESM(require("path"));
36
+
37
+ // src/helpers/copy.ts
38
+ var import_fs_extra = __toESM(require("fs-extra"));
39
+ var import_path = __toESM(require("path"));
40
+ var TEMPLATES_DIR = import_path.default.join(__dirname, "../../templates");
41
+ async function copyTemplate(templateName, destPath) {
42
+ const templatePath = import_path.default.join(TEMPLATES_DIR, templateName);
43
+ if (!await import_fs_extra.default.pathExists(templatePath)) return;
44
+ await import_fs_extra.default.copy(templatePath, destPath, { overwrite: true });
45
+ }
46
+
47
+ // src/helpers/env.ts
48
+ var import_fs_extra2 = __toESM(require("fs-extra"));
49
+ var import_path2 = __toESM(require("path"));
50
+ async function mergeEnvExamples(projectPath, features) {
51
+ const TEMPLATES_DIR2 = import_path2.default.join(__dirname, "../../templates");
52
+ const destEnv = import_path2.default.join(projectPath, ".env.example");
53
+ let combined = await import_fs_extra2.default.readFile(destEnv, "utf-8").catch(() => "");
54
+ const featureEnvDirs = {
55
+ auth: "auth",
56
+ prisma: "prisma",
57
+ convex: "convex",
58
+ appwrite: "appwrite"
59
+ };
60
+ for (const feature of features) {
61
+ const templateDir = featureEnvDirs[feature];
62
+ if (!templateDir) continue;
63
+ const src = import_path2.default.join(TEMPLATES_DIR2, templateDir, ".env.example");
64
+ if (!await import_fs_extra2.default.pathExists(src)) continue;
65
+ const content = await import_fs_extra2.default.readFile(src, "utf-8");
66
+ combined += `
67
+ # ${feature}
68
+ ${content}`;
69
+ }
70
+ await import_fs_extra2.default.writeFile(destEnv, combined.trim() + "\n");
71
+ }
72
+
73
+ // src/helpers/packages.ts
74
+ var import_fs_extra3 = __toESM(require("fs-extra"));
75
+ var import_path3 = __toESM(require("path"));
76
+
77
+ // src/helpers/run.ts
78
+ var import_execa = require("execa");
79
+ async function runCommand(command, args, cwd) {
80
+ await (0, import_execa.execa)(command, args, { cwd, stdio: "inherit" });
81
+ }
82
+
83
+ // src/helpers/packages.ts
84
+ var BASE_DEPS = {
85
+ next: "^15.0.0",
86
+ react: "^18.3.0",
87
+ "react-dom": "^18.3.0",
88
+ clsx: "^2.1.1",
89
+ "tailwind-merge": "^2.4.0",
90
+ "class-variance-authority": "^0.7.0",
91
+ zod: "^3.23.0",
92
+ "date-fns": "^3.6.0",
93
+ "cookies-next": "^4.2.1",
94
+ "lucide-react": "^0.400.0"
95
+ };
96
+ var BASE_DEV_DEPS = {
97
+ typescript: "^5.5.0",
98
+ "@types/node": "^20.14.0",
99
+ "@types/react": "^18.3.0",
100
+ "@types/react-dom": "^18.3.0",
101
+ tailwindcss: "^4.0.0",
102
+ "@tailwindcss/postcss": "^4.0.0",
103
+ postcss: "^8.4.0",
104
+ // Code quality
105
+ "@eslint/eslintrc": "^3.2.0",
106
+ prettier: "^3.3.0",
107
+ "eslint-config-prettier": "^9.1.0",
108
+ "eslint-plugin-prettier": "^5.2.0",
109
+ // Git hooks
110
+ husky: "^9.1.0",
111
+ "lint-staged": "^15.2.0"
112
+ };
113
+ var FEATURE_DEPS = {
114
+ animations: {
115
+ "framer-motion": "^11.3.0"
116
+ },
117
+ dataFetching: {
118
+ "@tanstack/react-query": "^5.51.0",
119
+ axios: "^1.7.0"
120
+ },
121
+ forms: {
122
+ "react-hook-form": "^7.52.0",
123
+ "@hookform/resolvers": "^3.9.0"
124
+ },
125
+ extraIcons: {
126
+ "iconsax-reactjs": "^1.0.1"
127
+ },
128
+ auth: {
129
+ "@clerk/nextjs": "^5.2.0"
130
+ },
131
+ prisma: {
132
+ "@prisma/client": "^5.16.0"
133
+ },
134
+ convex: {
135
+ convex: "^1.13.0"
136
+ },
137
+ appwrite: {
138
+ appwrite: "^16.0.0"
139
+ }
140
+ };
141
+ var FEATURE_DEV_DEPS = {
142
+ prisma: {
143
+ prisma: "^5.16.0"
144
+ }
145
+ };
146
+ function buildPackageJson(projectName, features) {
147
+ const deps = { ...BASE_DEPS };
148
+ const devDeps = { ...BASE_DEV_DEPS };
149
+ for (const feature of features) {
150
+ Object.assign(deps, FEATURE_DEPS[feature] ?? {});
151
+ Object.assign(devDeps, FEATURE_DEV_DEPS[feature] ?? {});
152
+ }
153
+ return {
154
+ name: projectName,
155
+ version: "0.1.0",
156
+ private: true,
157
+ scripts: {
158
+ dev: "next dev",
159
+ build: "next build",
160
+ start: "next start",
161
+ lint: "next lint",
162
+ prepare: "husky",
163
+ format: "prettier --write .",
164
+ "check-format": "prettier --check .",
165
+ "check-types": "tsc --noEmit"
166
+ },
167
+ dependencies: deps,
168
+ devDependencies: devDeps,
169
+ "lint-staged": {
170
+ "*.{js,jsx,ts,tsx,mjs}": ["eslint --fix", "prettier --write"],
171
+ "*.{json,md,mdx,css}": ["prettier --write"]
172
+ }
173
+ };
174
+ }
175
+ async function writePackageJson(projectPath, projectName, features) {
176
+ const pkg = buildPackageJson(projectName, features);
177
+ await import_fs_extra3.default.writeJSON(import_path3.default.join(projectPath, "package.json"), pkg, {
178
+ spaces: 2
179
+ });
180
+ }
181
+ async function installDependencies(projectPath, packageManager) {
182
+ if (packageManager === "npm" || packageManager === "pnpm") {
183
+ await runCommand(packageManager, ["install"], projectPath);
184
+ } else {
185
+ await runCommand(packageManager, ["install"], projectPath);
186
+ }
187
+ }
188
+
189
+ // src/generators/layout.ts
190
+ var import_fs_extra4 = __toESM(require("fs-extra"));
191
+ var import_path4 = __toESM(require("path"));
192
+ async function generateLayout(projectPath, features) {
193
+ const hasAuth = features.includes("auth");
194
+ const hasDataFetching = features.includes("dataFetching");
195
+ const hasConvex = features.includes("convex");
196
+ const imports = [`import type { Metadata } from "next"`, `import "./globals.css"`];
197
+ const wrappers = [];
198
+ if (hasAuth) {
199
+ imports.push(`import { ClerkProvider } from "@clerk/nextjs"`);
200
+ wrappers.push("ClerkProvider");
201
+ }
202
+ if (hasConvex) {
203
+ imports.push(`import { ConvexClientProvider } from "@/providers/convex-provider"`);
204
+ wrappers.push("ConvexClientProvider");
205
+ }
206
+ if (hasDataFetching) {
207
+ imports.push(`import { QueryProvider } from "@/providers/query-provider"`);
208
+ wrappers.push("QueryProvider");
209
+ }
210
+ const metadataBlock = `
211
+ export const metadata: Metadata = {
212
+ title: "My App",
213
+ description: "Generated by create-next-template",
214
+ };`;
215
+ function wrapChildren(wrappers2, content) {
216
+ if (wrappers2.length === 0) return content;
217
+ const [first, ...rest] = wrappers2;
218
+ const inner = wrapChildren(rest, content);
219
+ return `<${first}>
220
+ ${inner}
221
+ </${first}>`;
222
+ }
223
+ const body = wrapChildren(wrappers, "{children}");
224
+ const layoutContent = `${imports.join("\n")}
225
+ ${metadataBlock}
226
+
227
+ export default function RootLayout({
228
+ children,
229
+ }: {
230
+ children: React.ReactNode;
231
+ }) {
232
+ return (
233
+ <html lang="en">
234
+ <body>
235
+ ${body}
236
+ </body>
237
+ </html>
238
+ );
239
+ }
240
+ `;
241
+ const appDir = import_path4.default.join(projectPath, "app");
242
+ await import_fs_extra4.default.ensureDir(appDir);
243
+ await import_fs_extra4.default.writeFile(import_path4.default.join(appDir, "layout.tsx"), layoutContent);
244
+ }
245
+
246
+ // src/installer.ts
247
+ var FEATURE_TEMPLATE_MAP = {
248
+ animations: "animations",
249
+ dataFetching: "data-fetching",
250
+ forms: "forms",
251
+ extraIcons: "extra-icons",
252
+ auth: "auth",
253
+ prisma: "prisma",
254
+ convex: "convex",
255
+ appwrite: "appwrite",
256
+ ui: "ui"
257
+ };
258
+ async function runInstaller({
259
+ projectName,
260
+ projectPath,
261
+ packageManager,
262
+ features
263
+ }) {
264
+ const s = p.spinner();
265
+ if (await import_fs_extra5.default.pathExists(projectPath)) {
266
+ const overwrite = await p.confirm({
267
+ message: `Directory "${projectName}" already exists. Overwrite?`
268
+ });
269
+ if (!overwrite || p.isCancel(overwrite)) {
270
+ p.cancel("Operation cancelled");
271
+ process.exit(0);
272
+ }
273
+ await import_fs_extra5.default.remove(projectPath);
274
+ }
275
+ await import_fs_extra5.default.ensureDir(projectPath);
276
+ s.start("Scaffolding project structure");
277
+ await copyTemplate("base", projectPath);
278
+ for (const feature of features) {
279
+ const templateName = FEATURE_TEMPLATE_MAP[feature];
280
+ if (templateName) {
281
+ await copyTemplate(templateName, projectPath);
282
+ }
283
+ }
284
+ await generateLayout(projectPath, features);
285
+ await mergeEnvExamples(projectPath, features);
286
+ const huskyDir = import_path5.default.join(projectPath, ".husky");
287
+ for (const hook of ["pre-commit", "pre-push"]) {
288
+ const hookPath = import_path5.default.join(huskyDir, hook);
289
+ if (await import_fs_extra5.default.pathExists(hookPath)) {
290
+ await import_fs_extra5.default.chmod(hookPath, 493);
291
+ }
292
+ }
293
+ s.stop("Project structure scaffolded");
294
+ s.start("Writing package.json");
295
+ await writePackageJson(projectPath, projectName, features);
296
+ s.stop("package.json written");
297
+ s.start("Installing dependencies");
298
+ await installDependencies(projectPath, packageManager);
299
+ s.stop("Dependencies installed");
300
+ if (features.includes("prisma")) {
301
+ s.start("Running prisma generate");
302
+ await runCommand("npx", ["prisma", "generate"], projectPath);
303
+ s.stop("Prisma client generated");
304
+ }
305
+ s.start("Initializing git repository");
306
+ await runCommand("git", ["init"], projectPath);
307
+ await runCommand("git", ["add", "-A"], projectPath);
308
+ await runCommand(
309
+ "git",
310
+ ["commit", "-m", "chore: initial commit from create-next-template"],
311
+ projectPath
312
+ );
313
+ s.stop("Git repository initialized");
314
+ const hasShadcn = features.includes("ui");
315
+ const hasPrisma = features.includes("prisma");
316
+ const hasConvex = features.includes("convex");
317
+ const hasAppwrite = features.includes("appwrite");
318
+ console.log();
319
+ p.outro(
320
+ import_chalk.default.green("\u2714 Project created successfully!\n\n") + ` ${import_chalk.default.cyan("cd")} ${projectName}
321
+ ` + (hasShadcn ? ` ${import_chalk.default.cyan("npx shadcn@latest init")} ${import_chalk.default.gray("# set up shadcn/ui")}
322
+ ` : "") + (hasPrisma ? ` ${import_chalk.default.gray("# update DATABASE_URL in .env, then:")}
323
+ ${import_chalk.default.cyan("npx prisma migrate dev")}
324
+ ` : "") + (hasConvex ? ` ${import_chalk.default.cyan("npx convex dev")} ${import_chalk.default.gray("# start Convex backend")}
325
+ ` : "") + (hasAppwrite ? ` ${import_chalk.default.gray("# fill in NEXT_PUBLIC_APPWRITE_* vars in .env")}
326
+ ` : "") + ` ${import_chalk.default.cyan(`${packageManager} run dev`)}`
327
+ );
328
+ }
329
+
330
+ // src/index.ts
331
+ async function main() {
332
+ console.log();
333
+ p2.intro(import_chalk2.default.bgCyan(import_chalk2.default.black(" create-next-template ")));
334
+ const projectName = await p2.text({
335
+ message: "What is your project name?",
336
+ placeholder: "my-next-app",
337
+ validate(value) {
338
+ if (!value) return "Project name is required";
339
+ if (!/^[a-z0-9-_]+$/.test(value))
340
+ return "Only lowercase letters, numbers, hyphens, and underscores";
341
+ }
342
+ });
343
+ if (p2.isCancel(projectName)) {
344
+ p2.cancel("Operation cancelled");
345
+ process.exit(0);
346
+ }
347
+ const packageManager = await p2.select({
348
+ message: "Which package manager?",
349
+ options: [
350
+ { value: "npm", label: "npm" },
351
+ { value: "pnpm", label: "pnpm" },
352
+ { value: "yarn", label: "yarn" },
353
+ { value: "bun", label: "bun" }
354
+ ]
355
+ });
356
+ if (p2.isCancel(packageManager)) {
357
+ p2.cancel("Operation cancelled");
358
+ process.exit(0);
359
+ }
360
+ const features = await p2.multiselect({
361
+ message: "Which features do you want? (space to select)",
362
+ options: [
363
+ { value: "animations", label: "Animations", hint: "framer-motion" },
364
+ {
365
+ value: "dataFetching",
366
+ label: "Data Fetching",
367
+ hint: "TanStack Query + Axios"
368
+ },
369
+ {
370
+ value: "forms",
371
+ label: "Forms",
372
+ hint: "React Hook Form + Zod resolver"
373
+ },
374
+ { value: "extraIcons", label: "Extra Icons", hint: "iconsax-reactjs" },
375
+ { value: "auth", label: "Auth", hint: "Clerk" },
376
+ { value: "prisma", label: "Database \u2014 Prisma", hint: "Prisma + PostgreSQL" },
377
+ { value: "convex", label: "Database \u2014 Convex", hint: "Convex real-time backend" },
378
+ { value: "appwrite", label: "Database \u2014 Appwrite", hint: "Appwrite BaaS" },
379
+ { value: "ui", label: "UI Components", hint: "shadcn/ui" }
380
+ ],
381
+ required: false
382
+ });
383
+ if (p2.isCancel(features)) {
384
+ p2.cancel("Operation cancelled");
385
+ process.exit(0);
386
+ }
387
+ const selectedFeatures = features ?? [];
388
+ const dbChoices = ["prisma", "convex", "appwrite"].filter(
389
+ (db) => selectedFeatures.includes(db)
390
+ );
391
+ if (dbChoices.length > 1) {
392
+ p2.log.warn(
393
+ `You selected multiple databases (${dbChoices.join(", ")}). This is supported but may require manual configuration.`
394
+ );
395
+ }
396
+ const projectPath = import_path6.default.resolve(process.cwd(), projectName);
397
+ await runInstaller({
398
+ projectName,
399
+ projectPath,
400
+ packageManager,
401
+ features: selectedFeatures
402
+ });
403
+ }
404
+ main().catch((err) => {
405
+ console.error(err);
406
+ process.exit(1);
407
+ });
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@codabytez/create-next-template",
3
+ "version": "0.1.0",
4
+ "description": "CLI to scaffold Next.js projects with your preferred stack",
5
+ "bin": {
6
+ "create-next-template": "./dist/index.js"
7
+ },
8
+ "files": [
9
+ "dist",
10
+ "templates"
11
+ ],
12
+ "dependencies": {
13
+ "@clack/prompts": "^0.7.0",
14
+ "chalk": "^5.3.0",
15
+ "execa": "^8.0.1",
16
+ "fs-extra": "^11.2.0",
17
+ "picocolors": "^1.1.0"
18
+ },
19
+ "devDependencies": {
20
+ "@types/fs-extra": "^11.0.4",
21
+ "@types/node": "^20.0.0",
22
+ "tsup": "^8.0.0",
23
+ "tsx": "^4.7.0",
24
+ "typescript": "^5.4.0"
25
+ },
26
+ "scripts": {
27
+ "build": "tsup src/index.ts --format cjs --clean",
28
+ "dev": "tsx src/index.ts",
29
+ "lint": "tsc --noEmit"
30
+ }
31
+ }
@@ -0,0 +1,28 @@
1
+ "use client";
2
+
3
+ import { motion } from "framer-motion";
4
+
5
+ interface FadeInProps {
6
+ children: React.ReactNode;
7
+ delay?: number;
8
+ duration?: number;
9
+ className?: string;
10
+ }
11
+
12
+ export function FadeIn({
13
+ children,
14
+ delay = 0,
15
+ duration = 0.4,
16
+ className,
17
+ }: FadeInProps) {
18
+ return (
19
+ <motion.div
20
+ initial={{ opacity: 0, y: 10 }}
21
+ animate={{ opacity: 1, y: 0 }}
22
+ transition={{ duration, delay, ease: "easeOut" }}
23
+ className={className}
24
+ >
25
+ {children}
26
+ </motion.div>
27
+ );
28
+ }
@@ -0,0 +1,3 @@
1
+ NEXT_PUBLIC_APPWRITE_ENDPOINT=https://cloud.appwrite.io/v1
2
+ NEXT_PUBLIC_APPWRITE_PROJECT_ID=your-project-id
3
+ NEXT_PUBLIC_APPWRITE_DATABASE_ID=your-database-id
@@ -0,0 +1,11 @@
1
+ import { Client, Account, Databases, Storage } from "appwrite";
2
+
3
+ const client = new Client()
4
+ .setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT as string)
5
+ .setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID as string);
6
+
7
+ export const account = new Account(client);
8
+ export const databases = new Databases(client);
9
+ export const storage = new Storage(client);
10
+
11
+ export { client };
@@ -0,0 +1,6 @@
1
+ NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
2
+ CLERK_SECRET_KEY=sk_test_...
3
+ NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
4
+ NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
5
+ NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/
6
+ NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/
@@ -0,0 +1,9 @@
1
+ import { SignIn } from "@clerk/nextjs";
2
+
3
+ export default function SignInPage() {
4
+ return (
5
+ <div className="flex min-h-screen items-center justify-center">
6
+ <SignIn />
7
+ </div>
8
+ );
9
+ }
@@ -0,0 +1,9 @@
1
+ import { SignUp } from "@clerk/nextjs";
2
+
3
+ export default function SignUpPage() {
4
+ return (
5
+ <div className="flex min-h-screen items-center justify-center">
6
+ <SignUp />
7
+ </div>
8
+ );
9
+ }
@@ -0,0 +1,17 @@
1
+ import { clerkMiddleware, createRouteMatcher } from "@clerk/nextjs/server";
2
+
3
+ const isPublicRoute = createRouteMatcher([
4
+ "/",
5
+ "/sign-in(.*)",
6
+ "/sign-up(.*)",
7
+ ]);
8
+
9
+ export default clerkMiddleware(async (auth, request) => {
10
+ if (!isPublicRoute(request)) {
11
+ await auth.protect();
12
+ }
13
+ });
14
+
15
+ export const config = {
16
+ matcher: ["/((?!.*\\..*|_next).*)", "/", "/(api|trpc)(.*)"],
17
+ };
@@ -0,0 +1 @@
1
+ NODE_ENV=development
@@ -0,0 +1,19 @@
1
+ echo '🏗️👷 Running checks on your code before committing 🔍🧐'
2
+
3
+ echo '🎨✨ Checking formatting...'
4
+ pnpm run check-format ||
5
+ (
6
+ echo '🤢🤮 Your formatting is off. Running Prettier...'
7
+ pnpm run format
8
+ git add .
9
+ echo '✨ Formatting fixed and changes staged.'
10
+ )
11
+
12
+ echo '🔍 Running lint-staged...'
13
+ pnpm exec lint-staged ||
14
+ (
15
+ echo '😤 ESLint or type errors found. Fix the issues above and try again.'
16
+ false
17
+ )
18
+
19
+ echo '✅ All checks passed! Committing...'
@@ -0,0 +1,11 @@
1
+ echo '🚀🔍 Running final checks before pushing...'
2
+
3
+ echo '📦 Building the project...'
4
+ pnpm run build ||
5
+ (
6
+ echo '❌🔥 Build failed! Fix the errors above before pushing.'
7
+ false
8
+ )
9
+
10
+ echo '✅ Build passed! Pushing to remote...'
11
+ echo '🎉 Great work!'
@@ -0,0 +1,8 @@
1
+ node_modules
2
+ .next
3
+ out
4
+ build
5
+ dist
6
+ *.lock
7
+ package-lock.json
8
+ pnpm-lock.yaml
@@ -0,0 +1,9 @@
1
+ {
2
+ "semi": true,
3
+ "trailingComma": "es5",
4
+ "singleQuote": false,
5
+ "tabWidth": 2,
6
+ "useTabs": false,
7
+ "printWidth": 80,
8
+ "arrowParens": "always"
9
+ }