create-vitnode-app 1.2.0-canary.3 → 1.2.0-canary.31

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 (42) hide show
  1. package/README.md +6 -0
  2. package/copy-of-vitnode-app/docker/docker-compose.yml +20 -0
  3. package/copy-of-vitnode-app/eslint/.prettierrc.mjs +1 -1
  4. package/copy-of-vitnode-app/eslint/eslint.config.mjs +1 -1
  5. package/copy-of-vitnode-app/root/.env.example +10 -0
  6. package/copy-of-vitnode-app/root/.gitignore_template +28 -0
  7. package/copy-of-vitnode-app/root/.prettierrc.mjs +11 -0
  8. package/copy-of-vitnode-app/root/.vscode/settings.json +6 -0
  9. package/copy-of-vitnode-app/root/README.md +48 -0
  10. package/copy-of-vitnode-app/root/global.d.ts +9 -0
  11. package/copy-of-vitnode-app/root/src/app/[locale]/(main)/layout.tsx +6 -1
  12. package/copy-of-vitnode-app/root/src/app/[locale]/(main)/page.tsx +7 -15
  13. package/copy-of-vitnode-app/root/src/app/[locale]/admin/(auth)/layout.tsx +8 -5
  14. package/copy-of-vitnode-app/root/src/app/[locale]/layout.tsx +13 -8
  15. package/copy-of-vitnode-app/root/src/app/api/[...route]/route.ts +3 -2
  16. package/copy-of-vitnode-app/root/src/app/global-error.tsx +3 -3
  17. package/copy-of-vitnode-app/root/src/app/{globals.css → global.css} +61 -53
  18. package/copy-of-vitnode-app/root/src/app/layout.tsx +1 -1
  19. package/copy-of-vitnode-app/root/src/middleware.ts +24 -0
  20. package/copy-of-vitnode-app/root/src/vitnode.api.config.ts +9 -0
  21. package/copy-of-vitnode-app/root/src/vitnode.config.ts +32 -0
  22. package/copy-of-vitnode-app/root/tsconfig.json +2 -1
  23. package/dist/src/create/create-package-json.js +74 -0
  24. package/dist/src/create/create-vitnode.js +70 -0
  25. package/dist/src/helpers/get-available-package-managers.js +24 -0
  26. package/dist/src/helpers/get-package-json.js +2 -0
  27. package/dist/src/helpers/init-vitnode.js +15 -0
  28. package/dist/src/helpers/install-dependencies.js +67 -0
  29. package/dist/src/helpers/is-folder-empty.js +49 -0
  30. package/dist/src/helpers/is-online.js +38 -0
  31. package/dist/src/helpers/is-writeable.js +11 -0
  32. package/dist/src/helpers/packages-json.js +1 -0
  33. package/dist/src/helpers/validate-pkg.js +14 -0
  34. package/dist/src/index.js +65 -0
  35. package/dist/src/plugin/index.js +18 -0
  36. package/dist/src/prepare/prepare.js +16 -0
  37. package/dist/src/questions.js +52 -0
  38. package/dist/src/validation.js +40 -0
  39. package/dist/tsconfig.tsbuildinfo +1 -0
  40. package/package.json +9 -9
  41. package/copy-of-vitnode-app/root/src/app/[locale]/admin/not-found.tsx +0 -5
  42. package/copy-of-vitnode-app/root/src/app/not-found.tsx +0 -13
package/README.md CHANGED
@@ -29,6 +29,12 @@ or
29
29
  pnpm create vitnode-app@latest
30
30
  ```
31
31
 
32
+ or
33
+
34
+ ```bash
35
+ bun create vitnode-app@latest
36
+ ```
37
+
32
38
  ## Options
33
39
 
34
40
  | Option | Description |
@@ -0,0 +1,20 @@
1
+ version: '3.8'
2
+
3
+ services:
4
+ database:
5
+ container_name: vitnode_postgres_dev
6
+ image: postgres:17.5-alpine
7
+ restart: unless-stopped
8
+ environment:
9
+ POSTGRES_USER: ${POSTGRES_USER-root}
10
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD-root}
11
+ POSTGRES_DB: ${POSTGRES_NAME-vitnode}
12
+ volumes:
13
+ - ./docker/dev:/var/lib/postgresql/data
14
+ ports:
15
+ - '5432:5432'
16
+ networks:
17
+ - vitnode_dev
18
+
19
+ networks:
20
+ vitnode_dev:
@@ -1,4 +1,4 @@
1
- import vitnodePrettier from "eslint-config-typescript-vitnode/prettierrc";
1
+ import vitnodePrettier from '@vitnode/eslint-config/prettierrc';
2
2
 
3
3
  /**
4
4
  * @see https://prettier.io/docs/en/configuration.html
@@ -1,3 +1,3 @@
1
- import eslintVitNode from 'eslint-config-typescript-vitnode/eslint';
1
+ import eslintVitNode from '@vitnode/eslint-config/eslint';
2
2
 
3
3
  export default [...eslintVitNode];
@@ -0,0 +1,10 @@
1
+ POSTGRES_URL=postgresql://root:root@localhost:5432/vitnode
2
+
3
+ NEXT_PUBLIC_BACKEND_URL=http://localhost:3000
4
+ NEXT_PUBLIC_BACKEND_CLIENT_URL=http://localhost:3000
5
+ NEXT_PUBLIC_FRONTEND_URL=http://localhost:3000
6
+
7
+ # === Docker Database Postgres ===
8
+ POSTGRES_USER=root
9
+ POSTGRES_PASSWORD=root
10
+ POSTGRES_NAME=vitnode
@@ -0,0 +1,28 @@
1
+ # deps
2
+ /node_modules
3
+
4
+ # generated content
5
+ .contentlayer
6
+ .content-collections
7
+ .source
8
+
9
+ # test & build
10
+ /coverage
11
+ /.next/
12
+ /out/
13
+ /build
14
+ *.tsbuildinfo
15
+
16
+ # misc
17
+ .DS_Store
18
+ *.pem
19
+ /.pnp
20
+ .pnp.js
21
+ npm-debug.log*
22
+ yarn-debug.log*
23
+ yarn-error.log*
24
+
25
+ # others
26
+ .env*.local
27
+ .vercel
28
+ next-env.d.ts
@@ -0,0 +1,11 @@
1
+ import vitnodePrettier from '@vitnode/eslint-config/prettierrc';
2
+
3
+ /**
4
+ * @see https://prettier.io/docs/en/configuration.html
5
+ * @type {import("prettier").Config}
6
+ */
7
+ const config = {
8
+ ...vitnodePrettier,
9
+ };
10
+
11
+ export default config;
@@ -0,0 +1,6 @@
1
+ {
2
+ "cSpell.words": ["vitnode"],
3
+ "search.exclude": {
4
+ "**/(plugins)/*": true
5
+ }
6
+ }
@@ -0,0 +1,48 @@
1
+ <p align="center">
2
+ <br>
3
+ <a href="https://vitnode.com/" target="_blank">
4
+ <picture>
5
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/VitNode/vitnode/canary/assets/logo/vitnode_logo_dark.svg">
6
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/VitNode/vitnode/canary/assets/logo/vitnode_logo_light.svg">
7
+ <img alt="VitNode Logo" src="https://raw.githubusercontent.com/VitNode/vitnode/canary/assets/logo/vitnode_logo_light.svg" width="400">
8
+ </picture>
9
+ </a>
10
+ <br>
11
+ <br>
12
+ </p>
13
+
14
+ # VitNode App
15
+
16
+ This is a basic template for a [VitNode](https://vitnode.com/) app.
17
+
18
+ ## Getting Started
19
+
20
+ To get started, run the following commands:
21
+
22
+ ```bash
23
+ pnpm i
24
+ # or
25
+ bun i
26
+ # or
27
+ npm i
28
+ ```
29
+
30
+ Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
31
+
32
+ ## Development
33
+
34
+ To start the development server, you need to create a `.env` file in the root of the project from `.env.example`.
35
+
36
+ In the `development` environment, you can just copy and paste the content of `.env.example` to `.env`.
37
+
38
+ ### Development server
39
+
40
+ To start the development server, run the following command:
41
+
42
+ ```bash
43
+ pnpm dev
44
+ # or
45
+ bun dev
46
+ # or
47
+ npm run dev
48
+ ```
@@ -0,0 +1,9 @@
1
+ /// <reference types="next-intl" />
2
+
3
+ import type core from './src/locales/@vitnode/core/en.json';
4
+
5
+ declare module 'next-intl' {
6
+ interface AppConfig {
7
+ Messages: typeof core;
8
+ }
9
+ }
@@ -1,9 +1,14 @@
1
1
  import { LogoVitNode } from '@vitnode/core/components/logo-vitnode';
2
2
  import { ThemeLayout } from '@vitnode/core/views/layouts/theme/layout';
3
3
 
4
+ import { vitNodeConfig } from '../../../vitnode.config';
5
+
4
6
  export default function Layout({ children }: { children: React.ReactNode }) {
5
7
  return (
6
- <ThemeLayout logo={<LogoVitNode className="w-34" />}>
8
+ <ThemeLayout
9
+ logo={<LogoVitNode className="w-34" />}
10
+ vitNodeConfig={vitNodeConfig}
11
+ >
7
12
  {children}
8
13
  </ThemeLayout>
9
14
  );
@@ -3,16 +3,8 @@ import { buttonVariants } from '@vitnode/core/components/ui/button';
3
3
  import { Link } from '@vitnode/core/lib/navigation';
4
4
  import { cn } from '@vitnode/core/lib/utils';
5
5
  import { ArrowRight, Book, Terminal } from 'lucide-react';
6
- import { getTranslations } from 'next-intl/server';
7
-
8
- export default async function Home({
9
- params,
10
- }: {
11
- params: Promise<{ locale: string }>;
12
- }) {
13
- const { locale } = await params;
14
- const t = await getTranslations({ locale, namespace: 'welcome.home' });
15
6
 
7
+ export default function Page() {
16
8
  return (
17
9
  <main className="container mx-auto flex min-h-[calc(100vh-4rem)] flex-col items-center justify-center gap-16 px-4 py-16">
18
10
  {/* Hero Section */}
@@ -20,11 +12,11 @@ export default async function Home({
20
12
  <LogoVitNode className="w-44" />
21
13
 
22
14
  <div className="space-y-4">
23
- <h1 className="from-foreground to-foreground/70 text-balance bg-gradient-to-br bg-clip-text text-4xl font-bold tracking-tight text-transparent md:text-5xl lg:text-6xl">
24
- {t('title')}
15
+ <h1 className="from-foreground to-foreground/70 bg-gradient-to-br bg-clip-text text-4xl font-bold tracking-tight text-balance text-transparent md:text-5xl lg:text-6xl">
16
+ Start Your Journey!
25
17
  </h1>
26
- <p className="text-muted-foreground mx-auto max-w-2xl text-pretty text-lg">
27
- {t('desc')}
18
+ <p className="text-muted-foreground mx-auto max-w-2xl text-lg text-pretty">
19
+ Dive in. Create or install your first plugin!
28
20
  </p>
29
21
  </div>
30
22
 
@@ -40,7 +32,7 @@ export default async function Home({
40
32
  target="_blank"
41
33
  >
42
34
  <Terminal className="mr-2 h-4 w-4" />
43
- {t('go_to_admin_cp')}
35
+ Go to AdminCP
44
36
  <ArrowRight className="ml-2 h-4 w-4" />
45
37
  </Link>
46
38
 
@@ -56,7 +48,7 @@ export default async function Home({
56
48
  target="_blank"
57
49
  >
58
50
  <Book className="mr-2 h-4 w-4" />
59
- {t('read_our_docs')}
51
+ Read our Docs
60
52
  </Link>
61
53
 
62
54
  <Link
@@ -1,7 +1,10 @@
1
- import { AdminLayout } from '@vitnode/core/views/admin/layouts/admin-layout';
1
+ import {
2
+ AdminLayout,
3
+ type AdminLayoutProps,
4
+ } from '@vitnode/core/views/admin/layouts/admin-layout';
2
5
 
3
- export default function Layout(
4
- props: React.ComponentProps<typeof AdminLayout>,
5
- ) {
6
- return <AdminLayout {...props} />;
6
+ import { vitNodeConfig } from '@/vitnode.config';
7
+
8
+ export default function Layout(props: AdminLayoutProps) {
9
+ return <AdminLayout vitNodeConfig={vitNodeConfig} {...props} />;
7
10
  }
@@ -1,13 +1,14 @@
1
1
  import type { RootLayoutProps } from '@vitnode/core/views/layouts/root-layout';
2
2
  import type { Metadata } from 'next';
3
3
 
4
- import { vitNodeConfig } from '@/vitnode.config';
5
4
  import {
6
5
  generateMetadataRootLayout,
7
6
  RootLayout,
8
7
  } from '@vitnode/core/views/layouts/root-layout';
9
8
  import { Geist, Geist_Mono } from 'next/font/google';
10
9
 
10
+ import { vitNodeConfig } from '@/vitnode.config';
11
+
11
12
  const geistSans = Geist({
12
13
  variable: '--font-geist-sans',
13
14
  subsets: ['latin'],
@@ -22,14 +23,18 @@ export const generateMetadata = (): Metadata =>
22
23
  generateMetadataRootLayout(vitNodeConfig);
23
24
 
24
25
  export const generateStaticParams = () =>
25
- vitNodeConfig.i18n.locales.map(locale => ({ locale }));
26
+ vitNodeConfig.i18n.locales.map(locale => ({ locale: locale.code }));
27
+
28
+ export default async function LocaleLayout(props: RootLayoutProps) {
29
+ const { locale } = await props.params;
26
30
 
27
- export default function LocaleLayout(props: RootLayoutProps) {
28
31
  return (
29
- <RootLayout
30
- className={`${geistSans.variable} ${geistMono.variable} antialiased`}
31
- config={vitNodeConfig}
32
- {...props}
33
- />
32
+ <html lang={locale} suppressHydrationWarning>
33
+ <body
34
+ className={`${geistSans.variable} ${geistMono.variable} antialiased`}
35
+ >
36
+ <RootLayout config={vitNodeConfig} {...props} />
37
+ </body>
38
+ </html>
34
39
  );
35
40
  }
@@ -1,9 +1,10 @@
1
- import { vitNodeApiConfig } from '@/vitnode.api.config';
2
- import { vitNodeConfig } from '@/vitnode.config';
3
1
  import { OpenAPIHono } from '@hono/zod-openapi';
4
2
  import { VitNodeAPI } from '@vitnode/core/api/config';
5
3
  import { handle } from 'hono/vercel';
6
4
 
5
+ import { vitNodeApiConfig } from '@/vitnode.api.config';
6
+ import { vitNodeConfig } from '@/vitnode.config';
7
+
7
8
  const app = new OpenAPIHono().basePath('/api');
8
9
  VitNodeAPI({
9
10
  app,
@@ -1,11 +1,11 @@
1
1
  'use client';
2
2
 
3
- import { vitNodeConfig } from '@/vitnode.config';
4
3
  import { GlobalErrorView } from '@vitnode/core/views/error/global-error-view';
4
+ import { Geist, Geist_Mono } from 'next/font/google';
5
5
 
6
- import './globals.css';
6
+ import './global.css';
7
7
 
8
- import { Geist, Geist_Mono } from 'next/font/google';
8
+ import { vitNodeConfig } from '@/vitnode.config';
9
9
 
10
10
  const geistSans = Geist({
11
11
  variable: '--font-geist-sans',
@@ -1,81 +1,84 @@
1
- @import 'tailwindcss' source('../../src');
1
+ @import 'tailwindcss';
2
2
 
3
3
  @import 'tw-animate-css';
4
4
 
5
5
  @source "../../node_modules/@vitnode/core/dist/src/components";
6
6
  @source "../../node_modules/@vitnode/core/dist/src/views";
7
7
 
8
- @custom-variant dark (&:is(.dark *));
9
-
10
8
  :root:not(.dark) {
11
- --background: oklch(1 0 0);
12
- --foreground: oklch(0.141 0.005 285.823);
9
+ --background: oklch(0.98 0 0);
10
+ --foreground: oklch(0.145 0 0);
13
11
  --card: oklch(1 0 0);
14
- --card-foreground: oklch(0.141 0.005 285.823);
12
+ --card-foreground: oklch(0.145 0 0);
15
13
  --popover: oklch(1 0 0);
16
- --popover-foreground: oklch(0.141 0.005 285.823);
14
+ --popover-foreground: oklch(0.145 0 0);
17
15
  --primary: oklch(0.51 0.16 262.61);
18
16
  --primary-foreground: oklch(0.985 0 0);
19
- --secondary: oklch(0.967 0.001 286.375);
20
- --secondary-foreground: oklch(0.21 0.006 285.885);
21
- --muted: oklch(0.967 0.001 286.375);
22
- --muted-foreground: oklch(0.552 0.016 285.938);
23
- --accent: oklch(0.94 0.005 286); /* Adjusted for better contrast on muted */
24
- --accent-foreground: oklch(0.21 0.006 285.885);
25
- --destructive: oklch(0.577 0.245 27.325);
26
- --border: oklch(
27
- 0.9 0.02 262.61
28
- ); /* Similar hue to dark primary, lighter/desaturated */
29
- --ring: oklch(0.7 0.16 262.61); /* Lighter version of dark primary */
30
- --chart-1: oklch(0.65 0.22 40);
31
- --chart-2: oklch(0.6 0.15 185);
32
- --chart-3: oklch(0.42 0.09 230);
33
- --chart-4: oklch(0.83 0.19 85);
34
- --chart-5: oklch(0.77 0.18 70);
17
+ --secondary: oklch(0.96 0 0);
18
+ --secondary-foreground: oklch(0.205 0 0);
19
+ --muted: oklch(0.97 0 0);
20
+ --muted-foreground: oklch(0.45 0 0);
21
+ --accent: oklch(0.95 0 0);
22
+ --accent-foreground: oklch(0.205 0 0);
23
+ --destructive: oklch(0.6 0.2 24.45);
24
+ --warn: oklch(0.54 0.12 82.58);
25
+ --border: oklch(0.9 0 0);
26
+ --input: oklch(0.9 0 0);
27
+ --ring: oklch(0.7 0.16 262.61);
28
+ --chart-1: oklch(0.646 0.222 41.116);
29
+ --chart-2: oklch(0.6 0.118 184.704);
30
+ --chart-3: oklch(0.398 0.07 227.392);
31
+ --chart-4: oklch(0.828 0.189 84.429);
32
+ --chart-5: oklch(0.769 0.188 70.08);
33
+ --sidebar: var(--card);
34
+ --sidebar-foreground: oklch(0.145 0 0);
35
+ --sidebar-primary: var(--primary);
36
+ --sidebar-primary-foreground: var(--primary-foreground);
37
+ --sidebar-accent: oklch(0.975 0 0);
38
+ --sidebar-accent-foreground: oklch(0.205 0 0);
39
+ --sidebar-border: oklch(0.902 0 0);
40
+ --sidebar-ring: oklch(0.708 0 0);
35
41
  }
36
42
 
37
43
  .dark {
38
- --background: oklch(0.12 0 0);
39
- --foreground: oklch(0.98 0.005 240);
40
- --card: oklch(0.18 0.005 240);
41
- --card-foreground: oklch(0.98 0.005 240);
42
- --popover: oklch(0.18 0.005 240);
43
- --popover-foreground: oklch(0.98 0.005 240);
44
+ --background: oklch(0.1 0 0);
45
+ --foreground: oklch(0.98 0 0);
46
+ --card: oklch(0.18 0 0);
47
+ --card-foreground: oklch(0.98 0 0);
48
+ --popover: oklch(0.18 0 0);
49
+ --popover-foreground: oklch(0.98 0 0);
44
50
  --primary: oklch(0.51 0.16 262.61);
45
- --primary-foreground: oklch(0.99 0.005 240);
51
+ --primary-foreground: oklch(0.98 0 0);
46
52
  --secondary: oklch(0.24 0.01 240);
47
53
  --secondary-foreground: oklch(0.98 0.005 240);
48
- --muted: oklch(0.22 0.01 240); /* Made slightly darker */
49
- --muted-foreground: oklch(0.75 0.005 240);
50
- --accent: oklch(0.28 0.015 240);
51
- --destructive: oklch(0.704 0.191 22.216);
52
- --border: oklch(0.28 0.005 240);
54
+ --muted: oklch(0.22 0 0);
55
+ --muted-foreground: oklch(0.7 0 0);
56
+ --accent: oklch(0.28 0 0);
57
+ --destructive: oklch(0.62 0.2 25.35);
58
+ --warn: oklch(0.76 0.18 81.84);
59
+ --border: oklch(0.28 0 0);
60
+ --input: oklch(0.28 0 0);
53
61
  --ring: oklch(0.51 0.16 262.61);
54
- --chart-1: oklch(0.55 0.24 265);
55
- --chart-2: oklch(0.7 0.17 160);
56
- --chart-3: oklch(0.8 0.18 70);
57
- --chart-4: oklch(0.7 0.26 300);
58
- --chart-5: oklch(0.7 0.24 20);
62
+ --chart-1: oklch(0.488 0.243 264.376);
63
+ --chart-2: oklch(0.696 0.17 162.48);
64
+ --chart-3: oklch(0.769 0.188 70.08);
65
+ --chart-4: oklch(0.627 0.265 303.9);
66
+ --chart-5: oklch(0.645 0.246 16.439);
67
+ --sidebar: var(--card);
68
+ --sidebar-foreground: oklch(0.98 0 0);
69
+ --sidebar-primary: var(--primary);
70
+ --sidebar-primary-foreground: var(--primary-foreground);
71
+ --sidebar-accent: oklch(0.22 0 0);
72
+ --sidebar-accent-foreground: oklch(0.98 0 0);
73
+ --sidebar-border: oklch(0.269 0 0);
74
+ --sidebar-ring: oklch(0.51 0.16 262.61);
59
75
  }
60
76
 
61
77
  :root {
62
78
  --radius: 0.625rem;
63
- --input: var(--border);
64
- --sidebar: var(--muted);
65
- --sidebar-foreground: var(--foreground);
66
- --sidebar-primary: var(--primary);
67
- --sidebar-primary-foreground: var(--primary-foreground);
68
- --sidebar-accent: var(--accent);
69
- --sidebar-accent-foreground: var(--accent-foreground);
70
- --sidebar-border: var(--border);
71
- --sidebar-ring: var(--ring);
72
79
  }
73
80
 
74
81
  @theme inline {
75
- --radius-sm: calc(var(--radius) - 4px);
76
- --radius-md: calc(var(--radius) - 2px);
77
- --radius-lg: var(--radius);
78
- --radius-xl: calc(var(--radius) + 4px);
79
82
  --color-background: var(--background);
80
83
  --color-foreground: var(--foreground);
81
84
  --color-card: var(--card);
@@ -91,6 +94,7 @@
91
94
  --color-accent: var(--accent);
92
95
  --color-accent-foreground: var(--accent-foreground);
93
96
  --color-destructive: var(--destructive);
97
+ --color-warn: var(--warn);
94
98
  --color-border: var(--border);
95
99
  --color-input: var(--input);
96
100
  --color-ring: var(--ring);
@@ -99,6 +103,10 @@
99
103
  --color-chart-3: var(--chart-3);
100
104
  --color-chart-4: var(--chart-4);
101
105
  --color-chart-5: var(--chart-5);
106
+ --radius-sm: calc(var(--radius) - 4px);
107
+ --radius-md: calc(var(--radius) - 2px);
108
+ --radius-lg: var(--radius);
109
+ --radius-xl: calc(var(--radius) + 4px);
102
110
  --color-sidebar: var(--sidebar);
103
111
  --color-sidebar-foreground: var(--sidebar-foreground);
104
112
  --color-sidebar-primary: var(--sidebar-primary);
@@ -1,4 +1,4 @@
1
- import './globals.css';
1
+ import './global.css';
2
2
 
3
3
  export default async function RootLayout({
4
4
  children,
@@ -0,0 +1,24 @@
1
+ import createMiddleware from 'next-intl/middleware';
2
+
3
+ import { vitNodeConfig } from './vitnode.config';
4
+
5
+ export default createMiddleware({
6
+ locales: vitNodeConfig.i18n.locales.map(locale => locale.code),
7
+ defaultLocale: vitNodeConfig.i18n.defaultLocale,
8
+ localePrefix: vitNodeConfig.i18n.localePrefix,
9
+ });
10
+
11
+ export const config = {
12
+ matcher: [
13
+ // Enable a redirect to a matching locale at the root
14
+ '/',
15
+
16
+ // Set a cookie to remember the previous locale for
17
+ // all requests that have a locale prefix
18
+ '/(en)/:path*',
19
+
20
+ // Enable redirects that add missing locales
21
+ // (e.g. `/pathnames` -> `/en/pathnames`)
22
+ '/((?!_next|_vercel|api|.*\\..*).*)',
23
+ ],
24
+ };
@@ -1,5 +1,14 @@
1
1
  import { buildApiConfig } from '@vitnode/core/vitnode.config';
2
+ import { drizzle } from 'drizzle-orm/postgres-js';
3
+
4
+ export const POSTGRES_URL =
5
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
6
+ process.env.POSTGRES_URL || 'postgresql://root:root@localhost:5432/vitnode';
2
7
 
3
8
  export const vitNodeApiConfig = buildApiConfig({
4
9
  plugins: [],
10
+ dbProvider: drizzle({
11
+ connection: POSTGRES_URL,
12
+ casing: 'camelCase',
13
+ }),
5
14
  });
@@ -0,0 +1,32 @@
1
+ import { buildConfig, handleRequestConfig } from '@vitnode/core/vitnode.config';
2
+ import { getRequestConfig } from 'next-intl/server';
3
+
4
+ export const vitNodeConfig = buildConfig({
5
+ metadata: {
6
+ title: 'VitNode',
7
+ shortTitle: 'VitNode',
8
+ },
9
+ plugins: [],
10
+ i18n: {
11
+ locales: [
12
+ {
13
+ code: 'en',
14
+ name: 'English',
15
+ },
16
+ ],
17
+ defaultLocale: 'en',
18
+ },
19
+ theme: {
20
+ defaultTheme: 'light',
21
+ },
22
+ });
23
+
24
+ // This is the request config for the app. It will be used in the app router.
25
+ export default getRequestConfig(
26
+ async ({ requestLocale }) =>
27
+ await handleRequestConfig({
28
+ requestLocale,
29
+ vitNodeConfig,
30
+ pathToMessages: async path => await import(`./locales/${path}`),
31
+ }),
32
+ );
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/tsconfig",
3
- "extends": "eslint-config-typescript-vitnode/tsconfig",
3
+ "extends": "@vitnode/eslint-config/tsconfig",
4
4
  "compilerOptions": {
5
5
  "target": "ESNext",
6
6
  "module": "esnext",
@@ -13,6 +13,7 @@
13
13
  }
14
14
  ],
15
15
  "paths": {
16
+ "@/.source": ["./.source/index.ts"],
16
17
  "@/*": ["./src/*"]
17
18
  }
18
19
  },
@@ -0,0 +1,74 @@
1
+ import { readFile, writeFile } from 'fs/promises';
2
+ import { dirname, join } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import { getAvailablePackageManagers } from '../helpers/get-available-package-managers.js';
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = dirname(__filename);
7
+ export const createPackageJSON = async ({ appName, packageManager, root, eslint, docker, }) => {
8
+ const availablePackageManagers = await getAvailablePackageManagers();
9
+ const pkg = JSON.parse(await readFile(join(__dirname, '..', '..', '..', 'package.json'), 'utf-8'));
10
+ const packageJson = {
11
+ name: appName,
12
+ version: '0.1.0',
13
+ private: true,
14
+ type: 'module',
15
+ scripts: {
16
+ 'db:push': 'vitnode push',
17
+ 'db:migrate': 'vitnode migrate',
18
+ dev: 'vitnode init && next dev --turbopack',
19
+ build: 'next build --turbopack',
20
+ start: 'next start',
21
+ ...(eslint
22
+ ? {
23
+ lint: 'eslint .',
24
+ 'lint:fix': 'eslint . --fix',
25
+ }
26
+ : {}),
27
+ ...(docker
28
+ ? {
29
+ 'docker:dev': `docker compose -f ./docker-compose.yml -p ${appName}-vitnode-dev up -d`,
30
+ }
31
+ : {}),
32
+ 'drizzle-kit': 'drizzle-kit',
33
+ },
34
+ dependencies: {
35
+ '@hono/zod-openapi': '^0.19.8',
36
+ '@hono/zod-validator': '^0.7.0',
37
+ '@hookform/resolvers': '^5.1.1',
38
+ '@react-email/components': '^0.1.1',
39
+ '@vitnode/core': `^${pkg.version}`,
40
+ 'babel-plugin-react-compiler': '19.1.0-rc.2',
41
+ 'drizzle-kit': '^0.31.3',
42
+ 'drizzle-orm': '^0.44.2',
43
+ hono: '^4.8.3',
44
+ 'lucide-react': '^0.523.0',
45
+ next: '^15.3.4',
46
+ 'next-intl': '^4.3.1',
47
+ react: '^19.1.0',
48
+ 'react-dom': '^19.1.0',
49
+ 'react-hook-form': '^7.58.1',
50
+ sonner: '^2.0.5',
51
+ zod: '^3.25.67',
52
+ },
53
+ devDependencies: {
54
+ '@tailwindcss/postcss': '^4.1.11',
55
+ '@types/node': '^24',
56
+ '@types/react': '^19.1',
57
+ '@types/react-dom': '^19.1',
58
+ ...(eslint
59
+ ? {
60
+ eslint: '^9.29.0',
61
+ '@vitnode/eslint-config': `^${pkg.version}`,
62
+ 'prettier-plugin-tailwindcss': '^0.6.12',
63
+ prettier: '^3.6.1',
64
+ }
65
+ : {}),
66
+ 'react-email': '^4.0.17',
67
+ tailwindcss: '^4.1.11',
68
+ 'tw-animate-css': '^1.3.2',
69
+ typescript: '^5.8.3',
70
+ },
71
+ packageManager: `${packageManager}@${availablePackageManagers[packageManager]}`,
72
+ };
73
+ await writeFile(join(root, 'package.json'), JSON.stringify(packageJson, null, 2));
74
+ };