create-better-t-stack 1.12.4 → 1.13.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 (39) hide show
  1. package/README.md +1 -2
  2. package/dist/index.js +73 -73
  3. package/package.json +1 -1
  4. package/template/base/apps/server/_gitignore +17 -2
  5. package/template/base/apps/web-base/_gitignore +39 -13
  6. package/template/base/apps/web-base/src/index.css +1 -1
  7. package/template/base/apps/web-next/next-env.d.ts +5 -0
  8. package/template/base/apps/web-next/next.config.ts +7 -0
  9. package/template/base/apps/web-next/package.json +41 -0
  10. package/template/base/apps/web-next/postcss.config.mjs +5 -0
  11. package/template/base/apps/web-next/src/app/favicon.ico +0 -0
  12. package/template/base/apps/web-next/src/app/layout.tsx +41 -0
  13. package/template/base/apps/web-next/src/app/page.tsx +83 -0
  14. package/template/base/apps/web-next/src/components/header.tsx +30 -0
  15. package/template/base/apps/web-next/src/components/mode-toggle.tsx +39 -0
  16. package/template/base/apps/web-next/src/components/providers.tsx +25 -0
  17. package/template/base/apps/web-next/src/components/theme-provider.tsx +11 -0
  18. package/template/base/apps/web-next/src/utils/trpc.ts +33 -0
  19. package/template/base/apps/web-next/tsconfig.json +28 -0
  20. package/template/with-auth/apps/server/src/lib/with-next-context.ts +14 -0
  21. package/template/with-auth/apps/server/src/with-next-app/api/auth/[...all]/route.ts +4 -0
  22. package/template/with-auth/apps/web-next/src/app/dashboard/page.tsx +31 -0
  23. package/template/with-auth/apps/web-next/src/app/login/page.tsx +16 -0
  24. package/template/with-auth/apps/web-next/src/components/header.tsx +33 -0
  25. package/template/with-auth/apps/web-next/src/components/sign-in-form.tsx +135 -0
  26. package/template/with-auth/apps/web-next/src/components/sign-up-form.tsx +160 -0
  27. package/template/with-auth/apps/web-next/src/components/theme-provider.tsx +11 -0
  28. package/template/with-auth/apps/web-next/src/components/user-menu.tsx +60 -0
  29. package/template/with-auth/apps/web-next/src/lib/auth-client.ts +5 -0
  30. package/template/with-auth/apps/web-next/src/utils/trpc.ts +39 -0
  31. package/template/with-next/apps/server/next-env.d.ts +5 -0
  32. package/template/with-next/apps/server/next.config.ts +7 -0
  33. package/template/with-next/apps/server/package.json +20 -0
  34. package/template/with-next/apps/server/src/app/api/trpc/[trpc]/route.ts +14 -0
  35. package/template/with-next/apps/server/src/app/route.ts +5 -0
  36. package/template/with-next/apps/server/src/lib/context.ts +9 -0
  37. package/template/with-next/apps/server/src/middleware.ts +19 -0
  38. package/template/with-next/apps/server/tsconfig.json +27 -0
  39. package/template/base/apps/web-tanstack-start/src/index.css +0 -135
@@ -0,0 +1,135 @@
1
+ import { authClient } from "@/lib/auth-client";
2
+ import { useForm } from "@tanstack/react-form";
3
+ import { toast } from "sonner";
4
+ import { z } from "zod";
5
+ import Loader from "./loader";
6
+ import { Button } from "./ui/button";
7
+ import { Input } from "./ui/input";
8
+ import { Label } from "./ui/label";
9
+ import { useRouter } from "next/navigation";
10
+
11
+ export default function SignInForm({
12
+ onSwitchToSignUp,
13
+ }: {
14
+ onSwitchToSignUp: () => void;
15
+ }) {
16
+ const router = useRouter()
17
+ const { isPending } = authClient.useSession();
18
+
19
+ const form = useForm({
20
+ defaultValues: {
21
+ email: "",
22
+ password: "",
23
+ },
24
+ onSubmit: async ({ value }) => {
25
+ await authClient.signIn.email(
26
+ {
27
+ email: value.email,
28
+ password: value.password,
29
+ },
30
+ {
31
+ onSuccess: () => {
32
+ router.push("/dashboard")
33
+ toast.success("Sign in successful");
34
+ },
35
+ onError: (error) => {
36
+ toast.error(error.error.message);
37
+ },
38
+ },
39
+ );
40
+ },
41
+ validators: {
42
+ onSubmit: z.object({
43
+ email: z.string().email("Invalid email address"),
44
+ password: z.string().min(6, "Password must be at least 6 characters"),
45
+ }),
46
+ },
47
+ });
48
+
49
+ if (isPending) {
50
+ return <Loader />;
51
+ }
52
+
53
+ return (
54
+ <div className="mx-auto w-full mt-10 max-w-md p-6">
55
+ <h1 className="mb-6 text-center text-3xl font-bold">Welcome Back</h1>
56
+
57
+ <form
58
+ onSubmit={(e) => {
59
+ e.preventDefault();
60
+ e.stopPropagation();
61
+ void form.handleSubmit();
62
+ }}
63
+ className="space-y-4"
64
+ >
65
+ <div>
66
+ <form.Field name="email">
67
+ {(field) => (
68
+ <div className="space-y-2">
69
+ <Label htmlFor={field.name}>Email</Label>
70
+ <Input
71
+ id={field.name}
72
+ name={field.name}
73
+ type="email"
74
+ value={field.state.value}
75
+ onBlur={field.handleBlur}
76
+ onChange={(e) => field.handleChange(e.target.value)}
77
+ />
78
+ {field.state.meta.errors.map((error) => (
79
+ <p key={error?.message} className="text-red-500">
80
+ {error?.message}
81
+ </p>
82
+ ))}
83
+ </div>
84
+ )}
85
+ </form.Field>
86
+ </div>
87
+
88
+ <div>
89
+ <form.Field name="password">
90
+ {(field) => (
91
+ <div className="space-y-2">
92
+ <Label htmlFor={field.name}>Password</Label>
93
+ <Input
94
+ id={field.name}
95
+ name={field.name}
96
+ type="password"
97
+ value={field.state.value}
98
+ onBlur={field.handleBlur}
99
+ onChange={(e) => field.handleChange(e.target.value)}
100
+ />
101
+ {field.state.meta.errors.map((error) => (
102
+ <p key={error?.message} className="text-red-500">
103
+ {error?.message}
104
+ </p>
105
+ ))}
106
+ </div>
107
+ )}
108
+ </form.Field>
109
+ </div>
110
+
111
+ <form.Subscribe>
112
+ {(state) => (
113
+ <Button
114
+ type="submit"
115
+ className="w-full"
116
+ disabled={!state.canSubmit || state.isSubmitting}
117
+ >
118
+ {state.isSubmitting ? "Submitting..." : "Sign In"}
119
+ </Button>
120
+ )}
121
+ </form.Subscribe>
122
+ </form>
123
+
124
+ <div className="mt-4 text-center">
125
+ <Button
126
+ variant="link"
127
+ onClick={onSwitchToSignUp}
128
+ className="text-indigo-600 hover:text-indigo-800"
129
+ >
130
+ Need an account? Sign Up
131
+ </Button>
132
+ </div>
133
+ </div>
134
+ );
135
+ }
@@ -0,0 +1,160 @@
1
+ import { authClient } from "@/lib/auth-client";
2
+ import { useForm } from "@tanstack/react-form";
3
+ import { toast } from "sonner";
4
+ import { z } from "zod";
5
+ import Loader from "./loader";
6
+ import { Button } from "./ui/button";
7
+ import { Input } from "./ui/input";
8
+ import { Label } from "./ui/label";
9
+ import { useRouter } from "next/navigation";
10
+
11
+ export default function SignUpForm({
12
+ onSwitchToSignIn,
13
+ }: {
14
+ onSwitchToSignIn: () => void;
15
+ }) {
16
+ const router = useRouter();
17
+ const { isPending } = authClient.useSession();
18
+
19
+ const form = useForm({
20
+ defaultValues: {
21
+ email: "",
22
+ password: "",
23
+ name: "",
24
+ },
25
+ onSubmit: async ({ value }) => {
26
+ await authClient.signUp.email(
27
+ {
28
+ email: value.email,
29
+ password: value.password,
30
+ name: value.name,
31
+ },
32
+ {
33
+ onSuccess: () => {
34
+ router.push("/dashboard");
35
+ toast.success("Sign up successful");
36
+ },
37
+ onError: (error) => {
38
+ toast.error(error.error.message);
39
+ },
40
+ },
41
+ );
42
+ },
43
+ validators: {
44
+ onSubmit: z.object({
45
+ name: z.string().min(2, "Name must be at least 2 characters"),
46
+ email: z.string().email("Invalid email address"),
47
+ password: z.string().min(6, "Password must be at least 6 characters"),
48
+ }),
49
+ },
50
+ });
51
+
52
+ if (isPending) {
53
+ return <Loader />;
54
+ }
55
+
56
+ return (
57
+ <div className="mx-auto w-full mt-10 max-w-md p-6">
58
+ <h1 className="mb-6 text-center text-3xl font-bold">Create Account</h1>
59
+
60
+ <form
61
+ onSubmit={(e) => {
62
+ e.preventDefault();
63
+ e.stopPropagation();
64
+ void form.handleSubmit();
65
+ }}
66
+ className="space-y-4"
67
+ >
68
+ <div>
69
+ <form.Field name="name">
70
+ {(field) => (
71
+ <div className="space-y-2">
72
+ <Label htmlFor={field.name}>Name</Label>
73
+ <Input
74
+ id={field.name}
75
+ name={field.name}
76
+ value={field.state.value}
77
+ onBlur={field.handleBlur}
78
+ onChange={(e) => field.handleChange(e.target.value)}
79
+ />
80
+ {field.state.meta.errors.map((error) => (
81
+ <p key={error?.message} className="text-red-500">
82
+ {error?.message}
83
+ </p>
84
+ ))}
85
+ </div>
86
+ )}
87
+ </form.Field>
88
+ </div>
89
+
90
+ <div>
91
+ <form.Field name="email">
92
+ {(field) => (
93
+ <div className="space-y-2">
94
+ <Label htmlFor={field.name}>Email</Label>
95
+ <Input
96
+ id={field.name}
97
+ name={field.name}
98
+ type="email"
99
+ value={field.state.value}
100
+ onBlur={field.handleBlur}
101
+ onChange={(e) => field.handleChange(e.target.value)}
102
+ />
103
+ {field.state.meta.errors.map((error) => (
104
+ <p key={error?.message} className="text-red-500">
105
+ {error?.message}
106
+ </p>
107
+ ))}
108
+ </div>
109
+ )}
110
+ </form.Field>
111
+ </div>
112
+
113
+ <div>
114
+ <form.Field name="password">
115
+ {(field) => (
116
+ <div className="space-y-2">
117
+ <Label htmlFor={field.name}>Password</Label>
118
+ <Input
119
+ id={field.name}
120
+ name={field.name}
121
+ type="password"
122
+ value={field.state.value}
123
+ onBlur={field.handleBlur}
124
+ onChange={(e) => field.handleChange(e.target.value)}
125
+ />
126
+ {field.state.meta.errors.map((error) => (
127
+ <p key={error?.message} className="text-red-500">
128
+ {error?.message}
129
+ </p>
130
+ ))}
131
+ </div>
132
+ )}
133
+ </form.Field>
134
+ </div>
135
+
136
+ <form.Subscribe>
137
+ {(state) => (
138
+ <Button
139
+ type="submit"
140
+ className="w-full"
141
+ disabled={!state.canSubmit || state.isSubmitting}
142
+ >
143
+ {state.isSubmitting ? "Submitting..." : "Sign Up"}
144
+ </Button>
145
+ )}
146
+ </form.Subscribe>
147
+ </form>
148
+
149
+ <div className="mt-4 text-center">
150
+ <Button
151
+ variant="link"
152
+ onClick={onSwitchToSignIn}
153
+ className="text-indigo-600 hover:text-indigo-800"
154
+ >
155
+ Already have an account? Sign In
156
+ </Button>
157
+ </div>
158
+ </div>
159
+ );
160
+ }
@@ -0,0 +1,11 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { ThemeProvider as NextThemesProvider } from "next-themes"
5
+
6
+ export function ThemeProvider({
7
+ children,
8
+ ...props
9
+ }: React.ComponentProps<typeof NextThemesProvider>) {
10
+ return <NextThemesProvider {...props}>{children}</NextThemesProvider>
11
+ }
@@ -0,0 +1,60 @@
1
+ import {
2
+ DropdownMenu,
3
+ DropdownMenuContent,
4
+ DropdownMenuItem,
5
+ DropdownMenuLabel,
6
+ DropdownMenuSeparator,
7
+ DropdownMenuTrigger,
8
+ } from "@/components/ui/dropdown-menu";
9
+ import { authClient } from "@/lib/auth-client";
10
+ import { Button } from "./ui/button";
11
+ import { Skeleton } from "./ui/skeleton";
12
+ import { useRouter } from "next/navigation";
13
+ import Link from "next/link";
14
+
15
+ export default function UserMenu() {
16
+ const router = useRouter();
17
+ const { data: session, isPending } = authClient.useSession();
18
+
19
+ if (isPending) {
20
+ return <Skeleton className="h-9 w-24" />;
21
+ }
22
+
23
+ if (!session) {
24
+ return (
25
+ <Button variant="outline" asChild>
26
+ <Link href="/login">Sign In</Link>
27
+ </Button>
28
+ );
29
+ }
30
+
31
+ return (
32
+ <DropdownMenu>
33
+ <DropdownMenuTrigger asChild>
34
+ <Button variant="outline">{session.user.name}</Button>
35
+ </DropdownMenuTrigger>
36
+ <DropdownMenuContent className="bg-card">
37
+ <DropdownMenuLabel>My Account</DropdownMenuLabel>
38
+ <DropdownMenuSeparator />
39
+ <DropdownMenuItem>{session.user.email}</DropdownMenuItem>
40
+ <DropdownMenuItem asChild>
41
+ <Button
42
+ variant="destructive"
43
+ className="w-full"
44
+ onClick={() => {
45
+ authClient.signOut({
46
+ fetchOptions: {
47
+ onSuccess: () => {
48
+ router.push("/");
49
+ },
50
+ },
51
+ });
52
+ }}
53
+ >
54
+ Sign Out
55
+ </Button>
56
+ </DropdownMenuItem>
57
+ </DropdownMenuContent>
58
+ </DropdownMenu>
59
+ );
60
+ }
@@ -0,0 +1,5 @@
1
+ import { createAuthClient } from "better-auth/react";
2
+
3
+ export const authClient = createAuthClient({
4
+ baseURL: process.env.NEXT_PUBLIC_SERVER_URL,
5
+ });
@@ -0,0 +1,39 @@
1
+ import { QueryCache, QueryClient } from '@tanstack/react-query';
2
+ import { createTRPCClient, httpBatchLink } from '@trpc/client';
3
+ import { createTRPCOptionsProxy } from '@trpc/tanstack-react-query';
4
+ import type { AppRouter } from '../../../server/src/routers';
5
+ import { toast } from 'sonner';
6
+
7
+ export const queryClient = new QueryClient({
8
+ queryCache: new QueryCache({
9
+ onError: (error) => {
10
+ toast.error(error.message, {
11
+ action: {
12
+ label: "retry",
13
+ onClick: () => {
14
+ queryClient.invalidateQueries();
15
+ },
16
+ },
17
+ });
18
+ },
19
+ }),
20
+ });
21
+
22
+ const trpcClient = createTRPCClient<AppRouter>({
23
+ links: [
24
+ httpBatchLink({
25
+ url: `${process.env.NEXT_PUBLIC_SERVER_URL}/api/trpc`,
26
+ fetch(url, options) {
27
+ return fetch(url, {
28
+ ...options,
29
+ credentials: "include",
30
+ });
31
+ },
32
+ }),
33
+ ],
34
+ })
35
+
36
+ export const trpc = createTRPCOptionsProxy<AppRouter>({
37
+ client: trpcClient,
38
+ queryClient,
39
+ });
@@ -0,0 +1,5 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+
4
+ // NOTE: This file should not be edited
5
+ // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
@@ -0,0 +1,7 @@
1
+ import type { NextConfig } from "next";
2
+
3
+ const nextConfig: NextConfig = {
4
+ /* config options here */
5
+ };
6
+
7
+ export default nextConfig;
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "server",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "dev": "next dev --turbopack",
7
+ "build": "next build",
8
+ "start": "next start"
9
+ },
10
+ "dependencies": {
11
+ "@trpc/client": "^11.1.0",
12
+ "@trpc/server": "^11.1.0",
13
+ "next": "15.3.0"
14
+ },
15
+ "devDependencies": {
16
+ "@types/node": "^20",
17
+ "@types/react": "^19",
18
+ "typescript": "^5"
19
+ }
20
+ }
@@ -0,0 +1,14 @@
1
+ import { fetchRequestHandler } from '@trpc/server/adapters/fetch';
2
+ import { appRouter } from '@/routers';
3
+ import { createContext } from '@/lib/context';
4
+ import { NextRequest } from 'next/server';
5
+
6
+ function handler(req: NextRequest) {
7
+ return fetchRequestHandler({
8
+ endpoint: '/api/trpc',
9
+ req,
10
+ router: appRouter,
11
+ createContext: () => createContext(req)
12
+ });
13
+ }
14
+ export { handler as GET, handler as POST };
@@ -0,0 +1,5 @@
1
+ import { NextResponse } from "next/server";
2
+
3
+ export async function GET() {
4
+ return NextResponse.json({ message: "OK" });
5
+ }
@@ -0,0 +1,9 @@
1
+ import type { NextRequest } from "next/server";
2
+
3
+ export async function createContext(req: NextRequest) {
4
+ return {
5
+ session: null,
6
+ };
7
+ }
8
+
9
+ export type Context = Awaited<ReturnType<typeof createContext>>;
@@ -0,0 +1,19 @@
1
+ import { NextResponse } from "next/server";
2
+
3
+ export function middleware() {
4
+ const res = NextResponse.next()
5
+
6
+ res.headers.append('Access-Control-Allow-Credentials', "true")
7
+ res.headers.append('Access-Control-Allow-Origin', process.env.CORS_ORIGIN || "")
8
+ res.headers.append('Access-Control-Allow-Methods', 'GET,POST,OPTIONS')
9
+ res.headers.append(
10
+ 'Access-Control-Allow-Headers',
11
+ 'Content-Type, Authorization'
12
+ )
13
+
14
+ return res
15
+ }
16
+
17
+ export const config = {
18
+ matcher: '/api/:path*',
19
+ }
@@ -0,0 +1,27 @@
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": "preserve",
15
+ "incremental": true,
16
+ "plugins": [
17
+ {
18
+ "name": "next"
19
+ }
20
+ ],
21
+ "paths": {
22
+ "@/*": ["./src/*"]
23
+ }
24
+ },
25
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
26
+ "exclude": ["node_modules"]
27
+ }
@@ -1,135 +0,0 @@
1
- @import "tailwindcss";
2
- @import "tw-animate-css";
3
-
4
- @custom-variant dark (&:where(.dark, .dark *));
5
-
6
- @theme {
7
- --font-sans:
8
- "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",
9
- "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
10
- }
11
-
12
- html,
13
- body {
14
- @apply bg-white dark:bg-gray-950;
15
-
16
- @media (prefers-color-scheme: dark) {
17
- color-scheme: dark;
18
- }
19
- }
20
-
21
- :root {
22
- --radius: 0.625rem;
23
- --background: oklch(1 0 0);
24
- --foreground: oklch(0.145 0 0);
25
- --card: oklch(1 0 0);
26
- --card-foreground: oklch(0.145 0 0);
27
- --popover: oklch(1 0 0);
28
- --popover-foreground: oklch(0.145 0 0);
29
- --primary: oklch(0.205 0 0);
30
- --primary-foreground: oklch(0.985 0 0);
31
- --secondary: oklch(0.97 0 0);
32
- --secondary-foreground: oklch(0.205 0 0);
33
- --muted: oklch(0.97 0 0);
34
- --muted-foreground: oklch(0.556 0 0);
35
- --accent: oklch(0.97 0 0);
36
- --accent-foreground: oklch(0.205 0 0);
37
- --destructive: oklch(0.577 0.245 27.325);
38
- --border: oklch(0.922 0 0);
39
- --input: oklch(0.922 0 0);
40
- --ring: oklch(0.708 0 0);
41
- --chart-1: oklch(0.646 0.222 41.116);
42
- --chart-2: oklch(0.6 0.118 184.704);
43
- --chart-3: oklch(0.398 0.07 227.392);
44
- --chart-4: oklch(0.828 0.189 84.429);
45
- --chart-5: oklch(0.769 0.188 70.08);
46
- --sidebar: oklch(0.985 0 0);
47
- --sidebar-foreground: oklch(0.145 0 0);
48
- --sidebar-primary: oklch(0.205 0 0);
49
- --sidebar-primary-foreground: oklch(0.985 0 0);
50
- --sidebar-accent: oklch(0.97 0 0);
51
- --sidebar-accent-foreground: oklch(0.205 0 0);
52
- --sidebar-border: oklch(0.922 0 0);
53
- --sidebar-ring: oklch(0.708 0 0);
54
- }
55
-
56
- .dark {
57
- --background: oklch(0.145 0 0);
58
- --foreground: oklch(0.985 0 0);
59
- --card: oklch(0.205 0 0);
60
- --card-foreground: oklch(0.985 0 0);
61
- --popover: oklch(0.205 0 0);
62
- --popover-foreground: oklch(0.985 0 0);
63
- --primary: oklch(0.922 0 0);
64
- --primary-foreground: oklch(0.205 0 0);
65
- --secondary: oklch(0.269 0 0);
66
- --secondary-foreground: oklch(0.985 0 0);
67
- --muted: oklch(0.269 0 0);
68
- --muted-foreground: oklch(0.708 0 0);
69
- --accent: oklch(0.269 0 0);
70
- --accent-foreground: oklch(0.985 0 0);
71
- --destructive: oklch(0.704 0.191 22.216);
72
- --border: oklch(1 0 0 / 10%);
73
- --input: oklch(1 0 0 / 15%);
74
- --ring: oklch(0.556 0 0);
75
- --chart-1: oklch(0.488 0.243 264.376);
76
- --chart-2: oklch(0.696 0.17 162.48);
77
- --chart-3: oklch(0.769 0.188 70.08);
78
- --chart-4: oklch(0.627 0.265 303.9);
79
- --chart-5: oklch(0.645 0.246 16.439);
80
- --sidebar: oklch(0.205 0 0);
81
- --sidebar-foreground: oklch(0.985 0 0);
82
- --sidebar-primary: oklch(0.488 0.243 264.376);
83
- --sidebar-primary-foreground: oklch(0.985 0 0);
84
- --sidebar-accent: oklch(0.269 0 0);
85
- --sidebar-accent-foreground: oklch(0.985 0 0);
86
- --sidebar-border: oklch(1 0 0 / 10%);
87
- --sidebar-ring: oklch(0.556 0 0);
88
- }
89
-
90
- @theme inline {
91
- --radius-sm: calc(var(--radius) - 4px);
92
- --radius-md: calc(var(--radius) - 2px);
93
- --radius-lg: var(--radius);
94
- --radius-xl: calc(var(--radius) + 4px);
95
- --color-background: var(--background);
96
- --color-foreground: var(--foreground);
97
- --color-card: var(--card);
98
- --color-card-foreground: var(--card-foreground);
99
- --color-popover: var(--popover);
100
- --color-popover-foreground: var(--popover-foreground);
101
- --color-primary: var(--primary);
102
- --color-primary-foreground: var(--primary-foreground);
103
- --color-secondary: var(--secondary);
104
- --color-secondary-foreground: var(--secondary-foreground);
105
- --color-muted: var(--muted);
106
- --color-muted-foreground: var(--muted-foreground);
107
- --color-accent: var(--accent);
108
- --color-accent-foreground: var(--accent-foreground);
109
- --color-destructive: var(--destructive);
110
- --color-border: var(--border);
111
- --color-input: var(--input);
112
- --color-ring: var(--ring);
113
- --color-chart-1: var(--chart-1);
114
- --color-chart-2: var(--chart-2);
115
- --color-chart-3: var(--chart-3);
116
- --color-chart-4: var(--chart-4);
117
- --color-chart-5: var(--chart-5);
118
- --color-sidebar: var(--sidebar);
119
- --color-sidebar-foreground: var(--sidebar-foreground);
120
- --color-sidebar-primary: var(--sidebar-primary);
121
- --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
122
- --color-sidebar-accent: var(--sidebar-accent);
123
- --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
124
- --color-sidebar-border: var(--sidebar-border);
125
- --color-sidebar-ring: var(--sidebar-ring);
126
- }
127
-
128
- @layer base {
129
- * {
130
- @apply border-border outline-ring/50;
131
- }
132
- body {
133
- @apply bg-background text-foreground;
134
- }
135
- }