@lumerahq/cli 0.19.3-dev.0 → 0.19.3

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 +5 -3
  2. package/dist/chunk-H357NP7T.js +77 -0
  3. package/dist/{chunk-GKI2HQJC.js → chunk-JKXLKK5I.js} +14 -1
  4. package/dist/chunk-P5HFNAVN.js +280 -0
  5. package/dist/{chunk-53NOF33P.js → chunk-SU26C4GL.js} +9 -49
  6. package/dist/{deps-ULTIIDYK.js → deps-EC3VRNN7.js} +4 -2
  7. package/dist/{dev-5JMHMS4U.js → dev-R43VQCZD.js} +9 -2
  8. package/dist/index.js +13 -13
  9. package/dist/{init-37XOMJLU.js → init-TDIQAOG4.js} +29 -9
  10. package/dist/{register-JJUMS4FI.js → register-JFJADKAJ.js} +1 -1
  11. package/dist/{resources-4IUZYKGX.js → resources-OP7EECKZ.js} +20 -92
  12. package/dist/{run-5ZOSPBGO.js → run-EJP5WCQU.js} +1 -1
  13. package/dist/{templates-M3RDNDDY.js → templates-LNUOTNLN.js} +2 -3
  14. package/package.json +1 -1
  15. package/templates/default/.agents/skills/.gitkeep +0 -0
  16. package/templates/default/AGENTS.md +151 -0
  17. package/templates/default/README.md +18 -0
  18. package/templates/default/_gitignore +14 -0
  19. package/templates/default/architecture.md +29 -0
  20. package/templates/default/biome.json +38 -0
  21. package/templates/default/components.json +21 -0
  22. package/templates/default/icon.svg +29 -0
  23. package/templates/default/index.html +16 -0
  24. package/templates/default/package.json +53 -0
  25. package/templates/default/platform/automations/.gitkeep +0 -0
  26. package/templates/default/platform/collections/.gitkeep +0 -0
  27. package/templates/default/platform/hooks/.gitkeep +0 -0
  28. package/templates/default/pyproject.toml +14 -0
  29. package/templates/default/scripts/.gitkeep +0 -0
  30. package/templates/default/src/components/layout.tsx +11 -0
  31. package/templates/default/src/lib/auth.ts +9 -0
  32. package/templates/default/src/lib/queries.ts +17 -0
  33. package/templates/default/src/lib/utils.ts +6 -0
  34. package/templates/default/src/main.tsx +130 -0
  35. package/templates/default/src/routes/__root.tsx +10 -0
  36. package/templates/default/src/routes/index.tsx +87 -0
  37. package/templates/default/src/styles.css +128 -0
  38. package/templates/default/template.json +7 -0
  39. package/templates/default/tsconfig.json +22 -0
  40. package/templates/default/vite.config.ts +28 -0
  41. package/dist/chunk-OQW5E7UT.js +0 -159
  42. package/dist/chunk-XDTWVFPE.js +0 -120
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "{{projectName}}",
3
+ "private": true,
4
+ "type": "module",
5
+ "pnpm": {
6
+ "overrides": {
7
+ "@tanstack/router-core": "1.155.0"
8
+ }
9
+ },
10
+ "lumera": {
11
+ "version": 1,
12
+ "name": "{{projectTitle}}"
13
+ },
14
+ "scripts": {
15
+ "dev": "pnpm dlx @lumerahq/cli dev",
16
+ "deploy": "pnpm dlx @lumerahq/cli apply app",
17
+ "dev:vite": "vite",
18
+ "build": "vite build && tsc",
19
+ "preview": "vite preview",
20
+ "typecheck": "tsr generate && tsc --noEmit",
21
+ "lint": "biome lint --write .",
22
+ "format": "biome format --write .",
23
+ "check": "biome check --write .",
24
+ "check:ci": "biome check . && tsr generate && tsc --noEmit"
25
+ },
26
+ "dependencies": {
27
+ "@lumerahq/ui": "^0.7.6",
28
+ "@tanstack/react-query": "^5.90.11",
29
+ "@tanstack/react-router": "1.155.0",
30
+ "@tanstack/router-plugin": "1.155.0",
31
+ "class-variance-authority": "^0.7.1",
32
+ "clsx": "^2.1.1",
33
+ "lucide-react": "^1.7.0",
34
+ "radix-ui": "^1.4.3",
35
+ "shadcn": "^4.1.2",
36
+ "tailwind-merge": "^3.4.0",
37
+ "tw-animate-css": "^1.4.0",
38
+ "react": "^19.2.0",
39
+ "react-dom": "^19.2.0",
40
+ "sonner": "^2.0.7",
41
+ "tailwindcss": "^4.2.2"
42
+ },
43
+ "devDependencies": {
44
+ "@biomejs/biome": "^2.4.10",
45
+ "@tailwindcss/vite": "^4.2.2",
46
+ "@tanstack/router-cli": "1.155.0",
47
+ "@types/react": "^19.2.14",
48
+ "@types/react-dom": "^19.2.3",
49
+ "@vitejs/plugin-react": "^6.0.1",
50
+ "typescript": "^6.0.2",
51
+ "vite": "^8.0.3"
52
+ }
53
+ }
File without changes
@@ -0,0 +1,14 @@
1
+ [project]
2
+ name = "{{projectName}}"
3
+ version = "0.1.0"
4
+ description = "{{projectTitle}} - Lumera custom app"
5
+ requires-python = ">=3.11"
6
+ dependencies = [
7
+ "lumera",
8
+ ]
9
+
10
+ [project.optional-dependencies]
11
+ dev = [
12
+ "ruff",
13
+ "pytest",
14
+ ]
File without changes
@@ -0,0 +1,11 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ export function AppLayout({ children }: { children: ReactNode }) {
4
+ return (
5
+ <div className="min-h-screen bg-background overflow-hidden">
6
+ <main className="overflow-auto scroll-smooth">
7
+ <div className="p-8 max-w-5xl mx-auto">{children}</div>
8
+ </main>
9
+ </div>
10
+ );
11
+ }
@@ -0,0 +1,9 @@
1
+ import { createContext } from 'react';
2
+
3
+ export type AuthContextValue = {
4
+ company?: { id: string; name?: string; apiName?: string };
5
+ user?: { id: string; name: string; email: string; role?: string };
6
+ sessionToken?: string;
7
+ };
8
+
9
+ export const AuthContext = createContext<AuthContextValue | null>(null);
@@ -0,0 +1,17 @@
1
+ // import { type PbRecord, pbList, pbSql } from '@lumerahq/ui/lib';
2
+
3
+ // Add your collection types and query functions here.
4
+ //
5
+ // Example:
6
+ //
7
+ // export type Order = PbRecord & {
8
+ // title: string;
9
+ // amount: number;
10
+ // status: string;
11
+ // };
12
+ //
13
+ // export async function listOrders(page = 1) {
14
+ // return pbList<Order>('orders', { page, perPage: 20, sort: '-created' });
15
+ // }
16
+ //
17
+ // Use bare collection names — namespacing is handled automatically.
@@ -0,0 +1,6 @@
1
+ import { type ClassValue, clsx } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+ }
@@ -0,0 +1,130 @@
1
+ import { type HostPayload, isEmbedded, onInitMessage, postReadyMessage } from '@lumerahq/ui/lib';
2
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
3
+ import { createHashHistory, createRouter, RouterProvider } from '@tanstack/react-router';
4
+ import { StrictMode, useEffect, useRef, useState } from 'react';
5
+ import ReactDOM from 'react-dom/client';
6
+ import { Toaster } from 'sonner';
7
+
8
+ import { AuthContext, type AuthContextValue } from './lib/auth';
9
+ import { routeTree } from './routeTree.gen';
10
+ import './styles.css';
11
+
12
+ const queryClient = new QueryClient({
13
+ defaultOptions: {
14
+ queries: { staleTime: 30_000, retry: 1 },
15
+ },
16
+ });
17
+
18
+ const hashHistory = createHashHistory();
19
+
20
+ const router = createRouter({
21
+ routeTree,
22
+ history: hashHistory,
23
+ context: {},
24
+ defaultPreload: 'intent',
25
+ scrollRestoration: true,
26
+ });
27
+
28
+ declare module '@tanstack/react-router' {
29
+ interface Register {
30
+ router: typeof router;
31
+ }
32
+ }
33
+
34
+ const ROUTE_STORAGE_KEY = '{{projectName}}-route';
35
+
36
+ function RouteRestorer() {
37
+ const isFirstLoad = useRef(true);
38
+
39
+ useEffect(() => {
40
+ if (isFirstLoad.current) {
41
+ isFirstLoad.current = false;
42
+ const savedRoute = localStorage.getItem(ROUTE_STORAGE_KEY);
43
+ if (savedRoute && savedRoute !== '/' && router.state.location.pathname === '/') {
44
+ router.navigate({ to: savedRoute });
45
+ }
46
+ }
47
+
48
+ return router.subscribe('onResolved', ({ toLocation }) => {
49
+ localStorage.setItem(ROUTE_STORAGE_KEY, toLocation.href);
50
+ });
51
+ }, []);
52
+
53
+ return null;
54
+ }
55
+
56
+ const App = () => {
57
+ const [hostContext, setHostContext] = useState<AuthContextValue | null>(null);
58
+ const [status, setStatus] = useState<'pending' | 'ready' | 'denied'>('pending');
59
+
60
+ useEffect(() => {
61
+ if (typeof window === 'undefined') return;
62
+
63
+ const standaloneDevMode =
64
+ import.meta.env.DEV && !isEmbedded() && !!import.meta.env.VITE_DEV_API_BASE_URL;
65
+
66
+ if (!isEmbedded() && !standaloneDevMode) {
67
+ setStatus('denied');
68
+ return;
69
+ }
70
+
71
+ const cleanup = onInitMessage((payload?: HostPayload) => {
72
+ setHostContext({
73
+ company: payload?.company,
74
+ user: payload?.user,
75
+ sessionToken: payload?.session?.token,
76
+ });
77
+ setStatus('ready');
78
+ });
79
+
80
+ postReadyMessage();
81
+ return cleanup;
82
+ }, []);
83
+
84
+ if (status === 'pending') {
85
+ return (
86
+ <main className="flex min-h-screen items-center justify-center bg-background">
87
+ <div className="flex flex-col items-center gap-4">
88
+ <div className="size-10 rounded-xl bg-gradient-to-br from-[var(--accent-gradient-from)] to-[var(--accent-gradient-to)] flex items-center justify-center text-white font-semibold text-lg shadow-sm animate-pulse">
89
+ L
90
+ </div>
91
+ <p className="text-sm text-muted-foreground">Loading...</p>
92
+ </div>
93
+ </main>
94
+ );
95
+ }
96
+
97
+ if (status === 'denied' || !hostContext) {
98
+ return (
99
+ <main className="flex min-h-screen items-center justify-center bg-background">
100
+ <div className="text-center space-y-3">
101
+ <div className="inline-flex size-12 rounded-xl bg-muted items-center justify-center mb-2">
102
+ <span className="text-2xl font-semibold text-muted-foreground">403</span>
103
+ </div>
104
+ <p className="text-sm text-muted-foreground">
105
+ Access denied, this app can only be accessed from within Lumera.
106
+ </p>
107
+ </div>
108
+ </main>
109
+ );
110
+ }
111
+
112
+ return (
113
+ <AuthContext.Provider value={hostContext}>
114
+ <QueryClientProvider client={queryClient}>
115
+ <RouterProvider router={router} />
116
+ <RouteRestorer />
117
+ <Toaster position="top-right" richColors />
118
+ </QueryClientProvider>
119
+ </AuthContext.Provider>
120
+ );
121
+ };
122
+
123
+ const rootElement = document.getElementById('app');
124
+ if (rootElement && !rootElement.innerHTML) {
125
+ ReactDOM.createRoot(rootElement).render(
126
+ <StrictMode>
127
+ <App />
128
+ </StrictMode>,
129
+ );
130
+ }
@@ -0,0 +1,10 @@
1
+ import { createRootRoute, Outlet } from '@tanstack/react-router';
2
+ import { AppLayout } from '../components/layout';
3
+
4
+ export const Route = createRootRoute({
5
+ component: () => (
6
+ <AppLayout>
7
+ <Outlet />
8
+ </AppLayout>
9
+ ),
10
+ });
@@ -0,0 +1,87 @@
1
+ import { createFileRoute } from '@tanstack/react-router';
2
+ import { useContext } from 'react';
3
+ import { MessageSquare, LayoutGrid, Bot, Workflow } from 'lucide-react';
4
+ import { AuthContext } from '../lib/auth';
5
+
6
+ export const Route = createFileRoute('/')({
7
+ component: HomePage,
8
+ });
9
+
10
+ function HomePage() {
11
+ const auth = useContext(AuthContext);
12
+
13
+ return (
14
+ <div className="space-y-10">
15
+ {/* Header */}
16
+ <div>
17
+ <h1 className="text-2xl font-semibold tracking-tight">Welcome{auth?.user?.name ? `, ${auth.user.name}` : ''}</h1>
18
+ <p className="text-muted-foreground mt-2 text-[0.95rem] leading-relaxed">Your app is ready. Use Studio to start building.</p>
19
+ </div>
20
+
21
+ {/* Getting Started */}
22
+ <div className="rounded-xl bg-card p-6 shadow-[0_1px_3px_0_oklch(0_0_0/0.04),0_1px_2px_-1px_oklch(0_0_0/0.04)] border border-border/60 hover:shadow-[0_4px_12px_-2px_oklch(0_0_0/0.06)] transition-shadow duration-300">
23
+ <div className="flex items-start gap-4">
24
+ <div className="rounded-xl bg-gradient-to-br from-primary/10 to-primary/5 p-3 ring-1 ring-primary/10">
25
+ <MessageSquare className="size-6 text-primary" />
26
+ </div>
27
+ <div className="space-y-2">
28
+ <h2 className="font-semibold text-lg tracking-tight">Build with Studio</h2>
29
+ <p className="text-muted-foreground text-sm leading-relaxed">
30
+ Switch to the <strong>Chat</strong> tab and tell the agent what you want to build.
31
+ It will set up your data, write the logic, and build your UI — all from a conversation.
32
+ </p>
33
+ </div>
34
+ </div>
35
+ </div>
36
+
37
+ {/* Example prompts */}
38
+ <div>
39
+ <h2 className="text-sm font-semibold uppercase tracking-wider text-muted-foreground mb-4">Try asking the agent</h2>
40
+ <div className="flex flex-wrap gap-2">
41
+ {[
42
+ 'Build an invoice processing app with approval workflows',
43
+ 'Track vendor payments and flag overdue invoices',
44
+ 'Create a month-end close checklist with task assignments',
45
+ 'Set up an AP inbox that triages emails with AI',
46
+ 'Build an expense tracker with categories and a dashboard',
47
+ ].map((prompt) => (
48
+ <span
49
+ key={prompt}
50
+ className="inline-flex items-center px-3.5 py-2 rounded-lg text-sm bg-card border border-border/60 text-muted-foreground shadow-[0_1px_2px_0_oklch(0_0_0/0.03)] hover:border-primary/30 hover:text-foreground transition-all duration-200 cursor-default"
51
+ >
52
+ {prompt}
53
+ </span>
54
+ ))}
55
+ </div>
56
+ </div>
57
+
58
+ {/* What you can build */}
59
+ <div>
60
+ <h2 className="text-sm font-semibold uppercase tracking-wider text-muted-foreground mb-5">What you can build</h2>
61
+ <div className="grid gap-4 md:grid-cols-3">
62
+ <div className="group rounded-xl bg-card p-5 space-y-3 shadow-[0_1px_2px_0_oklch(0_0_0/0.03)] border border-border/60 hover:shadow-[0_4px_12px_-2px_oklch(0_0_0/0.06)] hover:border-border transition-all duration-300">
63
+ <LayoutGrid className="size-5 text-primary transition-colors duration-300" />
64
+ <h3 className="font-medium text-sm tracking-tight">Internal apps</h3>
65
+ <p className="text-xs text-muted-foreground leading-relaxed">
66
+ Back-office tools for your team — dashboards, approval queues, and operational workflows.
67
+ </p>
68
+ </div>
69
+ <div className="group rounded-xl bg-card p-5 space-y-3 shadow-[0_1px_2px_0_oklch(0_0_0/0.03)] border border-border/60 hover:shadow-[0_4px_12px_-2px_oklch(0_0_0/0.06)] hover:border-border transition-all duration-300">
70
+ <Bot className="size-5 text-primary transition-colors duration-300" />
71
+ <h3 className="font-medium text-sm tracking-tight">Agent-powered workflows</h3>
72
+ <p className="text-xs text-muted-foreground leading-relaxed">
73
+ AI agents that extract data, run reviews, draft outputs, and route exceptions — humans stay in the loop.
74
+ </p>
75
+ </div>
76
+ <div className="group rounded-xl bg-card p-5 space-y-3 shadow-[0_1px_2px_0_oklch(0_0_0/0.03)] border border-border/60 hover:shadow-[0_4px_12px_-2px_oklch(0_0_0/0.06)] hover:border-border transition-all duration-300">
77
+ <Workflow className="size-5 text-primary transition-colors duration-300" />
78
+ <h3 className="font-medium text-sm tracking-tight">Automations</h3>
79
+ <p className="text-xs text-muted-foreground leading-relaxed">
80
+ Connect to your systems, process inbound emails, and trigger actions automatically — with a full audit trail.
81
+ </p>
82
+ </div>
83
+ </div>
84
+ </div>
85
+ </div>
86
+ );
87
+ }
@@ -0,0 +1,128 @@
1
+ @import "tailwindcss";
2
+ @import "tw-animate-css";
3
+ @import "shadcn/tailwind.css";
4
+
5
+ @custom-variant dark (&:is(.dark *));
6
+
7
+ body {
8
+ @apply m-0;
9
+ font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
10
+ font-feature-settings: "cv11", "ss01";
11
+ -webkit-font-smoothing: antialiased;
12
+ -moz-osx-font-smoothing: grayscale;
13
+ }
14
+
15
+ /* Lumera brand theme + full shadcn variable set */
16
+
17
+ :root {
18
+ --radius: 0.75rem;
19
+
20
+ /* Warm off-white background */
21
+ --background: oklch(0.985 0.002 60);
22
+ /* Near-black foreground with warm undertone */
23
+ --foreground: oklch(0.16 0.01 60);
24
+ /* Cards: true white */
25
+ --card: oklch(1 0 0);
26
+ --card-foreground: oklch(0.16 0.01 60);
27
+ --popover: oklch(1 0 0);
28
+ --popover-foreground: oklch(0.16 0.01 60);
29
+ /* Lumera coral-orange primary */
30
+ --primary: oklch(0.62 0.17 35);
31
+ --primary-foreground: oklch(0.995 0 0);
32
+ /* Secondary */
33
+ --secondary: oklch(0.955 0.005 60);
34
+ --secondary-foreground: oklch(0.16 0.01 60);
35
+ /* Warm stone muted tones */
36
+ --muted: oklch(0.955 0.005 60);
37
+ --muted-foreground: oklch(0.50 0.01 60);
38
+ /* Accent — lighter orange tint */
39
+ --accent: oklch(0.95 0.03 50);
40
+ --accent-foreground: oklch(0.35 0.12 35);
41
+ /* Destructive */
42
+ --destructive: oklch(0.55 0.2 25);
43
+ --destructive-foreground: oklch(0.995 0 0);
44
+ /* Warm border */
45
+ --border: oklch(0.91 0.005 60);
46
+ --input: oklch(0.91 0.005 60);
47
+ --ring: oklch(0.62 0.17 35);
48
+ /* Charts */
49
+ --chart-1: oklch(0.646 0.222 41.116);
50
+ --chart-2: oklch(0.6 0.118 184.704);
51
+ --chart-3: oklch(0.398 0.07 227.392);
52
+ --chart-4: oklch(0.828 0.189 84.429);
53
+ --chart-5: oklch(0.769 0.188 70.08);
54
+ /* Sidebar */
55
+ --sidebar: oklch(0.985 0.002 60);
56
+ --sidebar-foreground: oklch(0.16 0.01 60);
57
+ --sidebar-primary: oklch(0.62 0.17 35);
58
+ --sidebar-primary-foreground: oklch(0.995 0 0);
59
+ --sidebar-accent: oklch(0.95 0.03 50);
60
+ --sidebar-accent-foreground: oklch(0.35 0.12 35);
61
+ --sidebar-border: oklch(0.91 0.005 60);
62
+ --sidebar-ring: oklch(0.62 0.17 35);
63
+
64
+ /* Semantic status colors */
65
+ --success: oklch(0.55 0.14 145);
66
+ --success-foreground: oklch(0.995 0 0);
67
+ --warning: oklch(0.75 0.15 70);
68
+ --warning-foreground: oklch(0.25 0.05 60);
69
+
70
+ /* Accent gradient for logo mark */
71
+ --accent-gradient-from: oklch(0.62 0.17 35);
72
+ --accent-gradient-to: oklch(0.58 0.19 25);
73
+ }
74
+
75
+ @theme inline {
76
+ --color-background: var(--background);
77
+ --color-foreground: var(--foreground);
78
+ --color-card: var(--card);
79
+ --color-card-foreground: var(--card-foreground);
80
+ --color-popover: var(--popover);
81
+ --color-popover-foreground: var(--popover-foreground);
82
+ --color-primary: var(--primary);
83
+ --color-primary-foreground: var(--primary-foreground);
84
+ --color-secondary: var(--secondary);
85
+ --color-secondary-foreground: var(--secondary-foreground);
86
+ --color-muted: var(--muted);
87
+ --color-muted-foreground: var(--muted-foreground);
88
+ --color-accent: var(--accent);
89
+ --color-accent-foreground: var(--accent-foreground);
90
+ --color-destructive: var(--destructive);
91
+ --color-destructive-foreground: var(--destructive-foreground);
92
+ --color-border: var(--border);
93
+ --color-input: var(--input);
94
+ --color-ring: var(--ring);
95
+ --color-chart-1: var(--chart-1);
96
+ --color-chart-2: var(--chart-2);
97
+ --color-chart-3: var(--chart-3);
98
+ --color-chart-4: var(--chart-4);
99
+ --color-chart-5: var(--chart-5);
100
+ --color-sidebar: var(--sidebar);
101
+ --color-sidebar-foreground: var(--sidebar-foreground);
102
+ --color-sidebar-primary: var(--sidebar-primary);
103
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
104
+ --color-sidebar-accent: var(--sidebar-accent);
105
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
106
+ --color-sidebar-border: var(--sidebar-border);
107
+ --color-sidebar-ring: var(--sidebar-ring);
108
+ --color-success: var(--success);
109
+ --color-success-foreground: var(--success-foreground);
110
+ --color-warning: var(--warning);
111
+ --color-warning-foreground: var(--warning-foreground);
112
+ --radius-sm: calc(var(--radius) * 0.6);
113
+ --radius-md: calc(var(--radius) * 0.8);
114
+ --radius-lg: var(--radius);
115
+ --radius-xl: calc(var(--radius) * 1.4);
116
+ --radius-2xl: calc(var(--radius) * 1.8);
117
+ --radius-3xl: calc(var(--radius) * 2.2);
118
+ --radius-4xl: calc(var(--radius) * 2.6);
119
+ }
120
+
121
+ @layer base {
122
+ * {
123
+ @apply border-border outline-ring/50;
124
+ }
125
+ body {
126
+ @apply bg-background text-foreground;
127
+ }
128
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "default",
3
+ "title": "Blank Starter",
4
+ "description": "A minimal blank canvas with React frontend and Lumera platform scaffolding. No pre-built collections or agents — start from scratch.",
5
+ "category": "General",
6
+ "version": "1.1.0"
7
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "include": ["**/*.ts", "**/*.tsx"],
3
+ "compilerOptions": {
4
+ "target": "ES2022",
5
+ "jsx": "react-jsx",
6
+ "module": "ESNext",
7
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
8
+ "types": ["vite/client"],
9
+ "moduleResolution": "bundler",
10
+ "allowImportingTsExtensions": true,
11
+ "verbatimModuleSyntax": true,
12
+ "noEmit": true,
13
+ "skipLibCheck": true,
14
+ "strict": true,
15
+ "noUnusedLocals": true,
16
+ "noUnusedParameters": true,
17
+ "noFallthroughCasesInSwitch": true,
18
+ "paths": {
19
+ "@/*": ["./src/*"]
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,28 @@
1
+ import tailwindcss from '@tailwindcss/vite';
2
+ import { tanstackRouter } from '@tanstack/router-plugin/vite';
3
+ import viteReact from '@vitejs/plugin-react';
4
+ import { defineConfig } from 'vite';
5
+
6
+ export default defineConfig({
7
+ base: './', // Use relative paths for S3 hosting at subpaths
8
+ plugins: [
9
+ tanstackRouter({
10
+ target: 'react',
11
+ autoCodeSplitting: true,
12
+ }),
13
+ viteReact(),
14
+ tailwindcss(),
15
+ ],
16
+ resolve: {
17
+ alias: {
18
+ '@': new URL('./src', import.meta.url).pathname,
19
+ },
20
+ dedupe: ['react', 'react-dom'],
21
+ },
22
+ server: {
23
+ allowedHosts: [
24
+ 'mac.lumerahq.com',
25
+ 'untunable-del-nonephemerally.ngrok-free.dev',
26
+ ],
27
+ },
28
+ });