@helloleo/plugins 0.1.19 → 0.1.20-beta.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.
- package/dist/index.js +6 -2
- package/dist/templates/tanstack-start-2026-06-18/components.json +22 -0
- package/dist/templates/tanstack-start-2026-06-18/drizzle.config.ts +20 -0
- package/dist/templates/tanstack-start-2026-06-18/package.json +103 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/accordion.tsx +51 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/alert-dialog.tsx +115 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/alert.tsx +49 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/aspect-ratio.tsx +5 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/avatar.tsx +47 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/badge.tsx +32 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/breadcrumb.tsx +101 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/button.tsx +49 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/calendar.tsx +177 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/card.tsx +55 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/carousel.tsx +240 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/chart.tsx +331 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/checkbox.tsx +26 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/collapsible.tsx +11 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/command.tsx +143 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/context-menu.tsx +187 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/dialog.tsx +104 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/drawer.tsx +98 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/dropdown-menu.tsx +188 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/form.tsx +171 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/hover-card.tsx +27 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/input-otp.tsx +69 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/input.tsx +22 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/label.tsx +21 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/menubar.tsx +229 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/navigation-menu.tsx +120 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/pagination.tsx +98 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/popover.tsx +31 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/progress.tsx +25 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/radio-group.tsx +36 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/resizable.tsx +37 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/scroll-area.tsx +44 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/select.tsx +152 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/separator.tsx +24 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/sheet.tsx +122 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/sidebar.tsx +744 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/skeleton.tsx +7 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/slider.tsx +23 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/sonner.tsx +23 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/switch.tsx +27 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/table.tsx +94 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/tabs.tsx +53 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/textarea.tsx +21 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/toggle-group.tsx +57 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/toggle.tsx +42 -0
- package/dist/templates/tanstack-start-2026-06-18/src/components/ui/tooltip.tsx +32 -0
- package/dist/templates/tanstack-start-2026-06-18/src/db/index.ts +9 -0
- package/dist/templates/tanstack-start-2026-06-18/src/db/schema.ts +18 -0
- package/dist/templates/tanstack-start-2026-06-18/src/global.d.ts +3 -0
- package/dist/templates/tanstack-start-2026-06-18/src/hooks/use-mobile.tsx +19 -0
- package/dist/templates/tanstack-start-2026-06-18/src/lib/proxy.ts +83 -0
- package/dist/templates/tanstack-start-2026-06-18/src/lib/utils.ts +6 -0
- package/dist/templates/tanstack-start-2026-06-18/src/routeTree.gen.ts +59 -0
- package/dist/templates/tanstack-start-2026-06-18/src/router.tsx +33 -0
- package/dist/templates/tanstack-start-2026-06-18/src/routes/__root.tsx +59 -0
- package/dist/templates/tanstack-start-2026-06-18/src/routes/index.tsx +33 -0
- package/dist/templates/tanstack-start-2026-06-18/src/server.ts +31 -0
- package/dist/templates/tanstack-start-2026-06-18/src/styles.css +214 -0
- package/dist/templates/tanstack-start-2026-06-18/tsconfig.json +27 -0
- package/dist/templates/tanstack-start-2026-06-18/vite.config.ts +17 -0
- package/dist/templates/tanstack-start-2026-06-18/wrangler.jsonc +27 -0
- package/package.json +1 -1
- package/src/templates/tanstack-start-2026-06-18/components.json +22 -0
- package/src/templates/tanstack-start-2026-06-18/drizzle.config.ts +20 -0
- package/src/templates/tanstack-start-2026-06-18/package.json +103 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/accordion.tsx +51 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/alert-dialog.tsx +115 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/alert.tsx +49 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/aspect-ratio.tsx +5 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/avatar.tsx +47 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/badge.tsx +32 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/breadcrumb.tsx +101 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/button.tsx +49 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/calendar.tsx +177 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/card.tsx +55 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/carousel.tsx +240 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/chart.tsx +331 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/checkbox.tsx +26 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/collapsible.tsx +11 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/command.tsx +143 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/context-menu.tsx +187 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/dialog.tsx +104 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/drawer.tsx +98 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/dropdown-menu.tsx +188 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/form.tsx +171 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/hover-card.tsx +27 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/input-otp.tsx +69 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/input.tsx +22 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/label.tsx +21 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/menubar.tsx +229 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/navigation-menu.tsx +120 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/pagination.tsx +98 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/popover.tsx +31 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/progress.tsx +25 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/radio-group.tsx +36 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/resizable.tsx +37 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/scroll-area.tsx +44 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/select.tsx +152 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/separator.tsx +24 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/sheet.tsx +122 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/sidebar.tsx +744 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/skeleton.tsx +7 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/slider.tsx +23 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/sonner.tsx +23 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/switch.tsx +27 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/table.tsx +94 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/tabs.tsx +53 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/textarea.tsx +21 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/toggle-group.tsx +57 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/toggle.tsx +42 -0
- package/src/templates/tanstack-start-2026-06-18/src/components/ui/tooltip.tsx +32 -0
- package/src/templates/tanstack-start-2026-06-18/src/db/index.ts +9 -0
- package/src/templates/tanstack-start-2026-06-18/src/db/schema.ts +18 -0
- package/src/templates/tanstack-start-2026-06-18/src/global.d.ts +3 -0
- package/src/templates/tanstack-start-2026-06-18/src/hooks/use-mobile.tsx +19 -0
- package/src/templates/tanstack-start-2026-06-18/src/lib/proxy.ts +83 -0
- package/src/templates/tanstack-start-2026-06-18/src/lib/utils.ts +6 -0
- package/src/templates/tanstack-start-2026-06-18/src/routeTree.gen.ts +59 -0
- package/src/templates/tanstack-start-2026-06-18/src/router.tsx +33 -0
- package/src/templates/tanstack-start-2026-06-18/src/routes/__root.tsx +59 -0
- package/src/templates/tanstack-start-2026-06-18/src/routes/index.tsx +33 -0
- package/src/templates/tanstack-start-2026-06-18/src/server.ts +31 -0
- package/src/templates/tanstack-start-2026-06-18/src/styles.css +214 -0
- package/src/templates/tanstack-start-2026-06-18/tsconfig.json +27 -0
- package/src/templates/tanstack-start-2026-06-18/vite.config.ts +17 -0
- package/src/templates/tanstack-start-2026-06-18/wrangler.jsonc +27 -0
- package/src/tools/scaffold.ts +20 -12
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import {
|
|
2
|
+
HeadContent,
|
|
3
|
+
Outlet,
|
|
4
|
+
Scripts,
|
|
5
|
+
createRootRouteWithContext,
|
|
6
|
+
} from '@tanstack/react-router'
|
|
7
|
+
import type { QueryClient } from '@tanstack/react-query'
|
|
8
|
+
import type { ReactNode } from 'react'
|
|
9
|
+
|
|
10
|
+
// Side-effect order matters: Tailwind needs to be linked into the SSR'd
|
|
11
|
+
// document. Importing the stylesheet as a URL and listing it in `head.links`
|
|
12
|
+
// is the Start-native way (a bare `import './styles.css'` only works client-side).
|
|
13
|
+
import appCss from '../styles.css?url'
|
|
14
|
+
|
|
15
|
+
export const Route = createRootRouteWithContext<{ queryClient: QueryClient }>()({
|
|
16
|
+
head: () => ({
|
|
17
|
+
meta: [
|
|
18
|
+
{ charSet: 'utf-8' },
|
|
19
|
+
{ name: 'viewport', content: 'width=device-width, initial-scale=1.0' },
|
|
20
|
+
{ title: '{{LEO_NAME}}' },
|
|
21
|
+
],
|
|
22
|
+
links: [
|
|
23
|
+
{ rel: 'stylesheet', href: appCss },
|
|
24
|
+
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
|
|
25
|
+
{
|
|
26
|
+
rel: 'preconnect',
|
|
27
|
+
href: 'https://fonts.gstatic.com',
|
|
28
|
+
crossOrigin: 'anonymous',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
rel: 'stylesheet',
|
|
32
|
+
href: 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Space+Grotesk:wght@400;500;600;700&display=swap',
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
}),
|
|
36
|
+
component: RootComponent,
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
function RootComponent() {
|
|
40
|
+
return (
|
|
41
|
+
<RootDocument>
|
|
42
|
+
<Outlet />
|
|
43
|
+
</RootDocument>
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function RootDocument({ children }: Readonly<{ children: ReactNode }>) {
|
|
48
|
+
return (
|
|
49
|
+
<html lang="en">
|
|
50
|
+
<head>
|
|
51
|
+
<HeadContent />
|
|
52
|
+
</head>
|
|
53
|
+
<body>
|
|
54
|
+
{children}
|
|
55
|
+
<Scripts />
|
|
56
|
+
</body>
|
|
57
|
+
</html>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { createFileRoute } from '@tanstack/react-router'
|
|
2
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
3
|
+
|
|
4
|
+
// Server functions run only on the server (dev: node + cf-shim; prod: the
|
|
5
|
+
// worker). This is the seam where you read your bindings — import { db } from
|
|
6
|
+
// '#/db' and query Drizzle, or import { kv, storage } from '@helloleo/runtime'.
|
|
7
|
+
// Keep binding access INSIDE the handler, never at module scope.
|
|
8
|
+
const getMessage = createServerFn({ method: 'GET' }).handler(() => {
|
|
9
|
+
return { message: 'Hello from the server' }
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
export const Route = createFileRoute('/')({
|
|
13
|
+
component: Home,
|
|
14
|
+
loader: () => getMessage(),
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Do not `export default function Home()`. This breaks the default
|
|
19
|
+
* codesplitting by Tanstack Router.
|
|
20
|
+
*/
|
|
21
|
+
function Home() {
|
|
22
|
+
const { message } = Route.useLoaderData()
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<div className="p-8">
|
|
26
|
+
<h1 className="text-4xl font-bold">Welcome to HelloLeo</h1>
|
|
27
|
+
<p className="mt-4 text-lg">{message}</p>
|
|
28
|
+
<p className="mt-2 text-sm text-muted-foreground">
|
|
29
|
+
Edit <code>src/routes/index.tsx</code> to get started.
|
|
30
|
+
</p>
|
|
31
|
+
</div>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Cloudflare Worker entry (wrangler.jsonc `main`). Wraps the TanStack Start
|
|
2
|
+
// server entry so an SSR failure renders a clean 500 instead of a raw stack.
|
|
3
|
+
type ServerEntry = {
|
|
4
|
+
fetch: (request: Request, env: unknown, ctx: unknown) => Promise<Response> | Response
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
let serverEntryPromise: Promise<ServerEntry> | undefined
|
|
8
|
+
|
|
9
|
+
async function getServerEntry(): Promise<ServerEntry> {
|
|
10
|
+
if (!serverEntryPromise) {
|
|
11
|
+
serverEntryPromise = import('@tanstack/react-start/server-entry').then(
|
|
12
|
+
(m) => ((m as { default?: ServerEntry }).default ?? m) as ServerEntry,
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
return serverEntryPromise
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default {
|
|
19
|
+
async fetch(request: Request, env: unknown, ctx: unknown) {
|
|
20
|
+
try {
|
|
21
|
+
const handler = await getServerEntry()
|
|
22
|
+
return await handler.fetch(request, env, ctx)
|
|
23
|
+
} catch (error) {
|
|
24
|
+
console.error(error)
|
|
25
|
+
return new Response('<h1>Something went wrong</h1>', {
|
|
26
|
+
status: 500,
|
|
27
|
+
headers: { 'content-type': 'text/html; charset=utf-8' },
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* HelloLeo Design System -- READ BEFORE STYLING.
|
|
3
|
+
*
|
|
4
|
+
* Design tokens are the single source of truth and power the no-code Design
|
|
5
|
+
* panel (the user edits colors / fonts / radius visually). Conventions:
|
|
6
|
+
* - Raw tokens live in :root (light) and .dark (dark). The @media
|
|
7
|
+
* (prefers-color-scheme: dark) block mirrors .dark so apps follow the OS
|
|
8
|
+
* by default; adding the `dark` class still forces dark explicitly.
|
|
9
|
+
* - @theme inline maps each raw token to a Tailwind utility
|
|
10
|
+
* (bg-background, text-foreground, rounded-lg, ...). Edit the raw token,
|
|
11
|
+
* not the component class. Never hardcode #hex in components.
|
|
12
|
+
* - When you add a color token, add it to :root, .dark, AND the media block,
|
|
13
|
+
* or one theme breaks.
|
|
14
|
+
*
|
|
15
|
+
* UI primitives live in src/components/ui (shadcn/ui) and consume these
|
|
16
|
+
* tokens. One responsibility per file.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
@import "tailwindcss" source(none);
|
|
20
|
+
@source "../src";
|
|
21
|
+
@import "tw-animate-css";
|
|
22
|
+
|
|
23
|
+
@custom-variant dark (&:is(.dark *));
|
|
24
|
+
|
|
25
|
+
@theme inline {
|
|
26
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
27
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
28
|
+
--radius-lg: var(--radius);
|
|
29
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
30
|
+
--color-background: var(--background);
|
|
31
|
+
--color-foreground: var(--foreground);
|
|
32
|
+
--color-card: var(--card);
|
|
33
|
+
--color-card-foreground: var(--card-foreground);
|
|
34
|
+
--color-popover: var(--popover);
|
|
35
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
36
|
+
--color-primary: var(--primary);
|
|
37
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
38
|
+
--color-secondary: var(--secondary);
|
|
39
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
40
|
+
--color-muted: var(--muted);
|
|
41
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
42
|
+
--color-accent: var(--accent);
|
|
43
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
44
|
+
--color-destructive: var(--destructive);
|
|
45
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
|
46
|
+
--color-border: var(--border);
|
|
47
|
+
--color-input: var(--input);
|
|
48
|
+
--color-ring: var(--ring);
|
|
49
|
+
--color-chart-1: var(--chart-1);
|
|
50
|
+
--color-chart-2: var(--chart-2);
|
|
51
|
+
--color-chart-3: var(--chart-3);
|
|
52
|
+
--color-chart-4: var(--chart-4);
|
|
53
|
+
--color-chart-5: var(--chart-5);
|
|
54
|
+
--color-sidebar: var(--sidebar);
|
|
55
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
56
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
57
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
58
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
59
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
60
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
61
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
62
|
+
--font-sans: "Inter", system-ui, sans-serif;
|
|
63
|
+
--font-display: "Space Grotesk", "Inter", sans-serif;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
:root {
|
|
67
|
+
--radius: 0.625rem;
|
|
68
|
+
--background: oklch(1 0 0);
|
|
69
|
+
--foreground: oklch(0.145 0 0);
|
|
70
|
+
--card: oklch(1 0 0);
|
|
71
|
+
--card-foreground: oklch(0.145 0 0);
|
|
72
|
+
--popover: oklch(1 0 0);
|
|
73
|
+
--popover-foreground: oklch(0.145 0 0);
|
|
74
|
+
--primary: oklch(0.205 0 0);
|
|
75
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
76
|
+
--secondary: oklch(0.97 0 0);
|
|
77
|
+
--secondary-foreground: oklch(0.205 0 0);
|
|
78
|
+
--muted: oklch(0.97 0 0);
|
|
79
|
+
--muted-foreground: oklch(0.556 0 0);
|
|
80
|
+
--accent: oklch(0.97 0 0);
|
|
81
|
+
--accent-foreground: oklch(0.205 0 0);
|
|
82
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
83
|
+
--destructive-foreground: oklch(0.985 0 0);
|
|
84
|
+
--border: oklch(0.922 0 0);
|
|
85
|
+
--input: oklch(0.922 0 0);
|
|
86
|
+
--ring: oklch(0.708 0 0);
|
|
87
|
+
--chart-1: oklch(0.646 0.222 41.116);
|
|
88
|
+
--chart-2: oklch(0.6 0.118 184.704);
|
|
89
|
+
--chart-3: oklch(0.398 0.07 227.392);
|
|
90
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
|
91
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
|
92
|
+
--sidebar: oklch(0.985 0 0);
|
|
93
|
+
--sidebar-foreground: oklch(0.145 0 0);
|
|
94
|
+
--sidebar-primary: oklch(0.205 0 0);
|
|
95
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
96
|
+
--sidebar-accent: oklch(0.97 0 0);
|
|
97
|
+
--sidebar-accent-foreground: oklch(0.205 0 0);
|
|
98
|
+
--sidebar-border: oklch(0.922 0 0);
|
|
99
|
+
--sidebar-ring: oklch(0.708 0 0);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* Dark palette -- kept identical in .dark (explicit) and the media block
|
|
103
|
+
* (system default). Edit BOTH when changing a token. */
|
|
104
|
+
.dark {
|
|
105
|
+
--background: oklch(0.145 0 0);
|
|
106
|
+
--foreground: oklch(0.985 0 0);
|
|
107
|
+
--card: oklch(0.205 0 0);
|
|
108
|
+
--card-foreground: oklch(0.985 0 0);
|
|
109
|
+
--popover: oklch(0.205 0 0);
|
|
110
|
+
--popover-foreground: oklch(0.985 0 0);
|
|
111
|
+
--primary: oklch(0.922 0 0);
|
|
112
|
+
--primary-foreground: oklch(0.205 0 0);
|
|
113
|
+
--secondary: oklch(0.269 0 0);
|
|
114
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
115
|
+
--muted: oklch(0.269 0 0);
|
|
116
|
+
--muted-foreground: oklch(0.708 0 0);
|
|
117
|
+
--accent: oklch(0.269 0 0);
|
|
118
|
+
--accent-foreground: oklch(0.985 0 0);
|
|
119
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
120
|
+
--destructive-foreground: oklch(0.985 0 0);
|
|
121
|
+
--border: oklch(1 0 0 / 10%);
|
|
122
|
+
--input: oklch(1 0 0 / 15%);
|
|
123
|
+
--ring: oklch(0.556 0 0);
|
|
124
|
+
--chart-1: oklch(0.488 0.243 264.376);
|
|
125
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
126
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
|
127
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
|
128
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
|
129
|
+
--sidebar: oklch(0.205 0 0);
|
|
130
|
+
--sidebar-foreground: oklch(0.985 0 0);
|
|
131
|
+
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
132
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
133
|
+
--sidebar-accent: oklch(0.269 0 0);
|
|
134
|
+
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
135
|
+
--sidebar-border: oklch(1 0 0 / 10%);
|
|
136
|
+
--sidebar-ring: oklch(0.556 0 0);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
@media (prefers-color-scheme: dark) {
|
|
140
|
+
:root {
|
|
141
|
+
--background: oklch(0.145 0 0);
|
|
142
|
+
--foreground: oklch(0.985 0 0);
|
|
143
|
+
--card: oklch(0.205 0 0);
|
|
144
|
+
--card-foreground: oklch(0.985 0 0);
|
|
145
|
+
--popover: oklch(0.205 0 0);
|
|
146
|
+
--popover-foreground: oklch(0.985 0 0);
|
|
147
|
+
--primary: oklch(0.922 0 0);
|
|
148
|
+
--primary-foreground: oklch(0.205 0 0);
|
|
149
|
+
--secondary: oklch(0.269 0 0);
|
|
150
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
151
|
+
--muted: oklch(0.269 0 0);
|
|
152
|
+
--muted-foreground: oklch(0.708 0 0);
|
|
153
|
+
--accent: oklch(0.269 0 0);
|
|
154
|
+
--accent-foreground: oklch(0.985 0 0);
|
|
155
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
156
|
+
--destructive-foreground: oklch(0.985 0 0);
|
|
157
|
+
--border: oklch(1 0 0 / 10%);
|
|
158
|
+
--input: oklch(1 0 0 / 15%);
|
|
159
|
+
--ring: oklch(0.556 0 0);
|
|
160
|
+
--chart-1: oklch(0.488 0.243 264.376);
|
|
161
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
162
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
|
163
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
|
164
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
|
165
|
+
--sidebar: oklch(0.205 0 0);
|
|
166
|
+
--sidebar-foreground: oklch(0.985 0 0);
|
|
167
|
+
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
168
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
169
|
+
--sidebar-accent: oklch(0.269 0 0);
|
|
170
|
+
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
171
|
+
--sidebar-border: oklch(1 0 0 / 10%);
|
|
172
|
+
--sidebar-ring: oklch(0.556 0 0);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
@layer base {
|
|
177
|
+
* {
|
|
178
|
+
border-color: var(--color-border);
|
|
179
|
+
}
|
|
180
|
+
html,
|
|
181
|
+
body {
|
|
182
|
+
font-family: var(--font-sans);
|
|
183
|
+
}
|
|
184
|
+
body {
|
|
185
|
+
background-color: var(--color-background);
|
|
186
|
+
color: var(--color-foreground);
|
|
187
|
+
min-height: 100vh;
|
|
188
|
+
}
|
|
189
|
+
h1, h2, h3, h4 {
|
|
190
|
+
font-family: var(--font-display);
|
|
191
|
+
letter-spacing: -0.02em;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
@layer utilities {
|
|
196
|
+
.prose-note {
|
|
197
|
+
color: var(--color-foreground);
|
|
198
|
+
}
|
|
199
|
+
.prose-note h1 { font-size: 1.875rem; font-weight: 700; margin: 1.25rem 0 0.75rem; font-family: var(--font-display); }
|
|
200
|
+
.prose-note h2 { font-size: 1.5rem; font-weight: 600; margin: 1rem 0 0.5rem; font-family: var(--font-display); }
|
|
201
|
+
.prose-note h3 { font-size: 1.25rem; font-weight: 600; margin: 0.875rem 0 0.5rem; }
|
|
202
|
+
.prose-note p { margin: 0.5rem 0; line-height: 1.7; }
|
|
203
|
+
.prose-note ul { list-style: disc; padding-left: 1.5rem; margin: 0.5rem 0; }
|
|
204
|
+
.prose-note ol { list-style: decimal; padding-left: 1.5rem; margin: 0.5rem 0; }
|
|
205
|
+
.prose-note li { margin: 0.25rem 0; }
|
|
206
|
+
.prose-note a { color: var(--color-primary); text-decoration: underline; }
|
|
207
|
+
.prose-note code { background: var(--color-muted); padding: 0.125rem 0.375rem; border-radius: 0.25rem; font-size: 0.875em; }
|
|
208
|
+
.prose-note pre { background: var(--color-muted); padding: 1rem; border-radius: 0.5rem; overflow-x: auto; margin: 0.75rem 0; }
|
|
209
|
+
.prose-note pre code { background: transparent; padding: 0; }
|
|
210
|
+
.prose-note blockquote { border-left: 3px solid var(--color-primary); padding-left: 1rem; margin: 0.75rem 0; color: var(--color-muted-foreground); }
|
|
211
|
+
.prose-note hr { border-color: var(--color-border); margin: 1.5rem 0; }
|
|
212
|
+
.prose-note table { border-collapse: collapse; margin: 0.75rem 0; }
|
|
213
|
+
.prose-note th, .prose-note td { border: 1px solid var(--color-border); padding: 0.375rem 0.75rem; }
|
|
214
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"include": ["**/*.ts", "**/*.tsx"],
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "ES2022",
|
|
5
|
+
"jsx": "react-jsx",
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"paths": {
|
|
8
|
+
"#/*": ["./src/*"],
|
|
9
|
+
"@/*": ["./src/*"]
|
|
10
|
+
},
|
|
11
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
12
|
+
"types": ["@cloudflare/workers-types", "vite/client"],
|
|
13
|
+
|
|
14
|
+
/* Bundler mode */
|
|
15
|
+
"moduleResolution": "bundler",
|
|
16
|
+
"allowImportingTsExtensions": true,
|
|
17
|
+
"noEmit": true,
|
|
18
|
+
|
|
19
|
+
/* Linting */
|
|
20
|
+
"skipLibCheck": true,
|
|
21
|
+
"strict": true,
|
|
22
|
+
"noUnusedLocals": true,
|
|
23
|
+
"noUnusedParameters": true,
|
|
24
|
+
"noFallthroughCasesInSwitch": true,
|
|
25
|
+
"noUncheckedSideEffectImports": true
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { defineConfig } from '@helloleo/vite-config'
|
|
2
|
+
|
|
3
|
+
// @helloleo/vite-config owns the whole build/dev/sandbox pipeline: in dev it
|
|
4
|
+
// aliases `cloudflare:workers` -> @helloleo/runtime/cf-shim (libsql .dev.db for
|
|
5
|
+
// D1+KV, local disk for R2) and runs plain Vite SSR; at build it adds
|
|
6
|
+
// @cloudflare/vite-plugin to emit a workerd Worker bound to wrangler.jsonc. It
|
|
7
|
+
// also binds host:true/port:5173 itself (>=0.1.2).
|
|
8
|
+
//
|
|
9
|
+
// The one thing the wrapper doesn't set: HMR over the HelloLeo preview proxy,
|
|
10
|
+
// which terminates HTTPS on :443 — so point the HMR client at wss://…:443.
|
|
11
|
+
export default defineConfig({
|
|
12
|
+
vite: {
|
|
13
|
+
server: {
|
|
14
|
+
hmr: { clientPort: 443, protocol: 'wss' },
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
})
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "node_modules/wrangler/config-schema.json",
|
|
3
|
+
"name": "{{LEO_NAME}}",
|
|
4
|
+
"compatibility_date": "2025-09-02",
|
|
5
|
+
"compatibility_flags": ["nodejs_compat"],
|
|
6
|
+
// @cloudflare/vite-plugin builds the Worker from the TanStack Start server
|
|
7
|
+
// entry; src/server.ts wraps it. These three bindings are the PROD path that
|
|
8
|
+
// the dev cf-shim emulates locally — keep the names DB / KV / BUCKET, that is
|
|
9
|
+
// the contract @helloleo/runtime expects.
|
|
10
|
+
"main": "src/server.ts",
|
|
11
|
+
"observability": { "enabled": true },
|
|
12
|
+
// Provision real resources before deploy (`wrangler d1/kv/r2 create`) and swap
|
|
13
|
+
// the placeholder ids below. In dev none of this matters — the cf-shim backs
|
|
14
|
+
// DB with libsql (.dev.db), KV in libsql, and R2 on the local filesystem.
|
|
15
|
+
"d1_databases": [
|
|
16
|
+
{
|
|
17
|
+
"binding": "DB",
|
|
18
|
+
"database_name": "{{LEO_NAME}}",
|
|
19
|
+
"database_id": "REPLACE_WITH_D1_ID",
|
|
20
|
+
// drizzle-kit generate writes migrations here; `wrangler d1 migrations
|
|
21
|
+
// apply DB --remote` reads this dir to apply them to prod D1.
|
|
22
|
+
"migrations_dir": "drizzle"
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
"kv_namespaces": [{ "binding": "KV", "id": "REPLACE_WITH_KV_ID" }],
|
|
26
|
+
"r2_buckets": [{ "binding": "BUCKET", "bucket_name": "{{LEO_NAME}}" }]
|
|
27
|
+
}
|
package/src/tools/scaffold.ts
CHANGED
|
@@ -8,11 +8,11 @@ import { renderTemplate } from "../template-render.ts";
|
|
|
8
8
|
* Identifier for the scaffold template a project was generated from. It is
|
|
9
9
|
* also the directory name under src/templates/. Written to .leo/project.json
|
|
10
10
|
* so the webapp / leo-core can tell which template (and therefore which
|
|
11
|
-
* conventions: TanStack
|
|
11
|
+
* conventions: TanStack Start file routing + SSR, Tailwind v4, shadcn/ui) a
|
|
12
12
|
* workspace was bootstrapped with. Bump this (and add a new templates/<id>/
|
|
13
13
|
* dir) when the scaffold's shape changes.
|
|
14
14
|
*/
|
|
15
|
-
export const SCAFFOLD_VERSION = "tanstack-
|
|
15
|
+
export const SCAFFOLD_VERSION = "tanstack-start-2026-06-18";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* The project workspace directory is named after the project UUID -- the
|
|
@@ -30,7 +30,7 @@ export interface BaseScaffoldOptions {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
* Write the base scaffold by rendering the TanStack
|
|
33
|
+
* Write the base scaffold by rendering the TanStack Start template into dir,
|
|
34
34
|
* then adding .leo/project.json (template metadata the tool owns, not part of
|
|
35
35
|
* the template tree). Shared between `scaffold` (frontend-only) and
|
|
36
36
|
* `setup_netsuite` (base + OAuth files). Returns the relative paths written.
|
|
@@ -59,17 +59,21 @@ export async function writeBaseScaffold(
|
|
|
59
59
|
|
|
60
60
|
export const scaffold = tool({
|
|
61
61
|
description:
|
|
62
|
-
"Scaffold a new React 19 + Vite + Tailwind CSS v4 + TanStack
|
|
63
|
-
"with shadcn/ui baked in
|
|
64
|
-
"
|
|
65
|
-
"src/
|
|
62
|
+
"Scaffold a new React 19 + Vite + Tailwind CSS v4 + TanStack Start project " +
|
|
63
|
+
"with shadcn/ui baked in, wired to @helloleo/runtime for Cloudflare " +
|
|
64
|
+
"bindings (D1 + KV + R2). Renders the full template: TanStack file-based " +
|
|
65
|
+
"routing + SSR (src/routes/, src/router.tsx), the Cloudflare Worker entry " +
|
|
66
|
+
"(src/server.ts) + wrangler.jsonc (DB/KV/BUCKET bindings), a Drizzle DB " +
|
|
67
|
+
"layer (src/db/schema.ts as the single source of truth, src/db/index.ts " +
|
|
68
|
+
"typed client, drizzle.config.ts), the complete shadcn/ui component set " +
|
|
69
|
+
"under src/components/ui, src/lib/utils.ts (cn helper), src/lib/proxy.ts " +
|
|
66
70
|
"(HelloLeo integration proxy), src/styles.css (shadcn design tokens, " +
|
|
67
71
|
"light+dark), plus package.json, vite.config.ts, tsconfig.json, " +
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
72
|
+
"components.json, .gitignore and the generated src/routeTree.gen.ts. Call " +
|
|
73
|
+
"this FIRST for any new project before adding routes and pages. For " +
|
|
74
|
+
"NetSuite projects (NetSuite MCP in the live list), call `setup_netsuite` " +
|
|
75
|
+
"INSTEAD -- it bundles base scaffold + OAuth wiring in one call. Do not " +
|
|
76
|
+
"call both.",
|
|
73
77
|
args: {
|
|
74
78
|
name: tool.schema
|
|
75
79
|
.string()
|
|
@@ -87,6 +91,10 @@ export const scaffold = tool({
|
|
|
87
91
|
"UI: shadcn/ui components are already in src/components/ui -- import and",
|
|
88
92
|
" use them; do not attempt to re-add via the shadcn CLI.",
|
|
89
93
|
"Design system: edit tokens in src/styles.css (light + dark blocks).",
|
|
94
|
+
"Database: edit src/db/schema.ts (the single source of truth) -- `bun run",
|
|
95
|
+
" db:push` syncs it to the dev DB; the `dev` script does this for you.",
|
|
96
|
+
" Query via `import { db } from '#/db'` inside loaders/server functions.",
|
|
97
|
+
" KV + R2: `import { kv, storage } from '@helloleo/runtime'`.",
|
|
90
98
|
"Data fetching: React Query is wired (QueryClient on the router context +",
|
|
91
99
|
" QueryClientProvider). ALWAYS fetch with @tanstack/react-query --",
|
|
92
100
|
" useQuery / useMutation in components, or a route loader calling",
|