@lumerahq/cli 0.9.3 → 0.10.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/README.md +8 -8
- package/dist/{chunk-V2XXMMEI.js → chunk-WRAZC6SJ.js} +5 -4
- package/dist/index.js +8 -8
- package/dist/{init-LVO3ZMG7.js → init-EDSRR3YM.js} +9 -0
- package/dist/{resources-2IHBFKMX.js → resources-PGBVCS2K.js} +7 -5
- package/dist/{run-4NDI2CN4.js → run-WIRQDYYX.js} +1 -1
- package/package.json +1 -1
- package/templates/default/ARCHITECTURE.md +80 -0
- package/templates/default/CLAUDE.md +13 -13
- package/templates/default/README.md +5 -5
- package/templates/default/biome.json +5 -0
- package/templates/default/package.json.hbs +5 -4
- package/templates/default/platform/collections/example_items.json +1 -3
- package/templates/default/scripts/seed-demo.py +1 -1
- package/templates/default/src/components/Sidebar.tsx +3 -5
- package/templates/default/src/components/StatCard.tsx +2 -8
- package/templates/default/src/lib/queries.ts +1 -1
- package/templates/default/src/main.tsx +4 -10
- package/templates/default/src/routes/__root.tsx +1 -1
- package/templates/default/src/routes/index.tsx +3 -5
- package/templates/default/src/routes/settings.tsx +2 -6
- package/templates/default/src/styles.css +6 -2
- package/templates/default/vite.config.ts +3 -2
package/README.md
CHANGED
|
@@ -19,14 +19,14 @@ lumera logout # Clear stored credentials
|
|
|
19
19
|
lumera whoami # Show current user
|
|
20
20
|
lumera status # Show project info
|
|
21
21
|
|
|
22
|
-
lumera
|
|
23
|
-
lumera app
|
|
24
|
-
lumera app
|
|
22
|
+
lumera dev # Start dev server
|
|
23
|
+
lumera apply app # Deploy frontend
|
|
24
|
+
lumera destroy app # Delete app from Lumera
|
|
25
25
|
|
|
26
|
-
lumera
|
|
27
|
-
lumera
|
|
28
|
-
lumera
|
|
29
|
-
lumera
|
|
26
|
+
lumera plan # Preview infrastructure changes
|
|
27
|
+
lumera apply # Apply collections, automations, hooks
|
|
28
|
+
lumera pull # Pull remote state to local
|
|
29
|
+
lumera destroy # Delete remote resources
|
|
30
30
|
|
|
31
31
|
lumera run <script> # Run Python scripts locally
|
|
32
32
|
```
|
|
@@ -84,7 +84,7 @@ For automated environments, use the `LUMERA_TOKEN` environment variable:
|
|
|
84
84
|
|
|
85
85
|
```bash
|
|
86
86
|
export LUMERA_TOKEN=your_api_token
|
|
87
|
-
lumera app
|
|
87
|
+
lumera apply app
|
|
88
88
|
```
|
|
89
89
|
|
|
90
90
|
The CLI checks for credentials in this order:
|
|
@@ -56,10 +56,11 @@ var ApiClient = class {
|
|
|
56
56
|
}
|
|
57
57
|
// Automations
|
|
58
58
|
async listAutomations(params) {
|
|
59
|
-
|
|
60
|
-
if (params?.external_id)
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
const qs = new URLSearchParams();
|
|
60
|
+
if (params?.external_id) qs.set("external_id", params.external_id);
|
|
61
|
+
if (params?.include_code) qs.set("include_code", "true");
|
|
62
|
+
const query = qs.toString();
|
|
63
|
+
const path = `/api/automations${query ? `?${query}` : ""}`;
|
|
63
64
|
const result = await this.request(path);
|
|
64
65
|
return result.automations || [];
|
|
65
66
|
}
|
package/dist/index.js
CHANGED
|
@@ -92,33 +92,33 @@ async function main() {
|
|
|
92
92
|
switch (command) {
|
|
93
93
|
// Resource commands
|
|
94
94
|
case "plan":
|
|
95
|
-
await import("./resources-
|
|
95
|
+
await import("./resources-PGBVCS2K.js").then((m) => m.plan(args.slice(1)));
|
|
96
96
|
break;
|
|
97
97
|
case "apply":
|
|
98
|
-
await import("./resources-
|
|
98
|
+
await import("./resources-PGBVCS2K.js").then((m) => m.apply(args.slice(1)));
|
|
99
99
|
break;
|
|
100
100
|
case "pull":
|
|
101
|
-
await import("./resources-
|
|
101
|
+
await import("./resources-PGBVCS2K.js").then((m) => m.pull(args.slice(1)));
|
|
102
102
|
break;
|
|
103
103
|
case "destroy":
|
|
104
|
-
await import("./resources-
|
|
104
|
+
await import("./resources-PGBVCS2K.js").then((m) => m.destroy(args.slice(1)));
|
|
105
105
|
break;
|
|
106
106
|
case "list":
|
|
107
|
-
await import("./resources-
|
|
107
|
+
await import("./resources-PGBVCS2K.js").then((m) => m.list(args.slice(1)));
|
|
108
108
|
break;
|
|
109
109
|
case "show":
|
|
110
|
-
await import("./resources-
|
|
110
|
+
await import("./resources-PGBVCS2K.js").then((m) => m.show(args.slice(1)));
|
|
111
111
|
break;
|
|
112
112
|
// Development
|
|
113
113
|
case "dev":
|
|
114
114
|
await import("./dev-BHBF4ECH.js").then((m) => m.dev(args.slice(1)));
|
|
115
115
|
break;
|
|
116
116
|
case "run":
|
|
117
|
-
await import("./run-
|
|
117
|
+
await import("./run-WIRQDYYX.js").then((m) => m.run(args.slice(1)));
|
|
118
118
|
break;
|
|
119
119
|
// Project
|
|
120
120
|
case "init":
|
|
121
|
-
await import("./init-
|
|
121
|
+
await import("./init-EDSRR3YM.js").then((m) => m.init(args.slice(1)));
|
|
122
122
|
break;
|
|
123
123
|
case "status":
|
|
124
124
|
await import("./status-E4IHEUKO.js").then((m) => m.status(args.slice(1)));
|
|
@@ -332,6 +332,15 @@ async function init(args) {
|
|
|
332
332
|
console.log(pc.green(" \u2713"), pc.dim(`${installed} Lumera skills installed`));
|
|
333
333
|
}
|
|
334
334
|
syncClaudeMd(targetDir);
|
|
335
|
+
if (isGitInstalled()) {
|
|
336
|
+
try {
|
|
337
|
+
execSync('git add -A && git commit -m "chore: install lumera skills"', {
|
|
338
|
+
cwd: targetDir,
|
|
339
|
+
stdio: "ignore"
|
|
340
|
+
});
|
|
341
|
+
} catch {
|
|
342
|
+
}
|
|
343
|
+
}
|
|
335
344
|
} catch (err) {
|
|
336
345
|
console.log(pc.yellow(" \u26A0"), pc.dim(`Failed to install skills: ${err}`));
|
|
337
346
|
}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-CDZZ3JYU.js";
|
|
4
4
|
import {
|
|
5
5
|
createApiClient
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-WRAZC6SJ.js";
|
|
7
7
|
import {
|
|
8
8
|
loadEnv
|
|
9
9
|
} from "./chunk-2CR762KB.js";
|
|
@@ -452,7 +452,7 @@ async function planCollections(api, localCollections) {
|
|
|
452
452
|
}
|
|
453
453
|
async function planAutomations(api, localAutomations) {
|
|
454
454
|
const changes = [];
|
|
455
|
-
const remoteAutomations = await api.listAutomations();
|
|
455
|
+
const remoteAutomations = await api.listAutomations({ include_code: true });
|
|
456
456
|
const remoteByExternalId = new Map(remoteAutomations.filter((a) => a.external_id).map((a) => [a.external_id, a]));
|
|
457
457
|
for (const { automation, code } of localAutomations) {
|
|
458
458
|
const remote = remoteByExternalId.get(automation.external_id);
|
|
@@ -526,9 +526,11 @@ async function applyCollections(api, localCollections) {
|
|
|
526
526
|
const hasRelations = localCollections.some((c) => c.fields.some((f) => f.type === "relation"));
|
|
527
527
|
if (hasRelations) {
|
|
528
528
|
for (const local of localCollections) {
|
|
529
|
+
const relationFieldNames = new Set(local.fields.filter((f) => f.type === "relation").map((f) => f.name));
|
|
529
530
|
const withoutRelations = {
|
|
530
531
|
...local,
|
|
531
|
-
fields: local.fields.filter((f) => f.type !== "relation")
|
|
532
|
+
fields: local.fields.filter((f) => f.type !== "relation"),
|
|
533
|
+
indexes: local.indexes?.filter((idx) => !idx.fields.some((f) => relationFieldNames.has(f)))
|
|
532
534
|
};
|
|
533
535
|
const apiFormat = convertCollectionToApiFormat(withoutRelations);
|
|
534
536
|
try {
|
|
@@ -742,7 +744,7 @@ async function pullCollections(api, platformDir, filterName) {
|
|
|
742
744
|
async function pullAutomations(api, platformDir, filterName) {
|
|
743
745
|
const automationsDir = join(platformDir, "automations");
|
|
744
746
|
mkdirSync(automationsDir, { recursive: true });
|
|
745
|
-
const automations = await api.listAutomations();
|
|
747
|
+
const automations = await api.listAutomations({ include_code: true });
|
|
746
748
|
for (const automation of automations) {
|
|
747
749
|
if (!automation.external_id || automation.managed) continue;
|
|
748
750
|
if (filterName && automation.external_id !== filterName && automation.name !== filterName) {
|
|
@@ -847,7 +849,7 @@ async function listResources(api, platformDir, filterType) {
|
|
|
847
849
|
}
|
|
848
850
|
if (!filterType || filterType === "automations") {
|
|
849
851
|
const localAutomations = loadLocalAutomations(platformDir);
|
|
850
|
-
const remoteAutomations = await api.listAutomations();
|
|
852
|
+
const remoteAutomations = await api.listAutomations({ include_code: true });
|
|
851
853
|
const remoteByExternalId = new Map(remoteAutomations.filter((a) => a.external_id && !a.managed).map((a) => [a.external_id, a]));
|
|
852
854
|
const localIds = new Set(localAutomations.map((a) => a.automation.external_id));
|
|
853
855
|
for (const { automation, code } of localAutomations) {
|
package/package.json
CHANGED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# {{projectTitle}} — Architecture
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
{{projectTitle}} is a Lumera embedded app — a React frontend served inside the Lumera platform iframe, backed by collections, hooks, and automations managed through the Lumera CLI.
|
|
6
|
+
|
|
7
|
+
## System Diagram
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
┌─────────────────────────────────────────────────┐
|
|
11
|
+
│ Lumera Platform │
|
|
12
|
+
│ │
|
|
13
|
+
│ ┌───────────┐ postMessage ┌────────────┐ │
|
|
14
|
+
│ │ Host UI │ ◄──────────────► │ App │ │
|
|
15
|
+
│ │ │ (auth, init) │ (iframe) │ │
|
|
16
|
+
│ └─────┬─────┘ └─────┬──────┘ │
|
|
17
|
+
│ │ │ │
|
|
18
|
+
│ │ REST API │ │
|
|
19
|
+
│ ▼ ▼ │
|
|
20
|
+
│ ┌──────────────────────────────────────────┐ │
|
|
21
|
+
│ │ Lumera API │ │
|
|
22
|
+
│ │ - Collections (CRUD, SQL, search) │ │
|
|
23
|
+
│ │ - Automations (run, poll, cancel) │ │
|
|
24
|
+
│ │ - File storage (upload, download) │ │
|
|
25
|
+
│ └──────────────┬───────────────────────────┘ │
|
|
26
|
+
│ │ │
|
|
27
|
+
│ ▼ │
|
|
28
|
+
│ ┌──────────────────────────────────────────┐ │
|
|
29
|
+
│ │ Tenant Database (PocketBase/SQLite) │ │
|
|
30
|
+
│ │ - example_items │ │
|
|
31
|
+
│ │ - (add your collections here) │ │
|
|
32
|
+
│ └──────────────────────────────────────────┘ │
|
|
33
|
+
└─────────────────────────────────────────────────┘
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Frontend (`src/`)
|
|
37
|
+
|
|
38
|
+
React app using TanStack Router (file-based routing) and TanStack Query for data fetching. Embedded in Lumera via iframe with postMessage bridge for authentication.
|
|
39
|
+
|
|
40
|
+
| Directory | Purpose |
|
|
41
|
+
|------------------|--------------------------------------|
|
|
42
|
+
| `src/routes/` | Pages — file names map to URL paths |
|
|
43
|
+
| `src/components/`| Shared React components |
|
|
44
|
+
| `src/lib/` | API helpers, query functions |
|
|
45
|
+
| `src/main.tsx` | App entry — auth bridge, router init |
|
|
46
|
+
|
|
47
|
+
**Key patterns:**
|
|
48
|
+
- Auth context flows from `main.tsx` via `AuthContext`
|
|
49
|
+
- Data fetching uses `pbList`, `pbSql` from `@lumerahq/ui/lib`
|
|
50
|
+
- Styling via Tailwind CSS 4 with theme tokens in `styles.css`
|
|
51
|
+
|
|
52
|
+
## Platform Resources (`platform/`)
|
|
53
|
+
|
|
54
|
+
Declarative definitions deployed via `lumera apply`.
|
|
55
|
+
|
|
56
|
+
| Directory | Purpose |
|
|
57
|
+
|--------------------------|----------------------------------|
|
|
58
|
+
| `platform/collections/` | Collection schemas (JSON) |
|
|
59
|
+
| `platform/automations/` | Background Python scripts |
|
|
60
|
+
| `platform/hooks/` | Server-side JS on collection events |
|
|
61
|
+
|
|
62
|
+
## Scripts (`scripts/`)
|
|
63
|
+
|
|
64
|
+
Local Python scripts run via `lumera run`. Used for seeding data, migrations, and ad-hoc operations. All scripts should be idempotent.
|
|
65
|
+
|
|
66
|
+
## Data Flow
|
|
67
|
+
|
|
68
|
+
1. **User opens app** → Lumera host sends auth payload via postMessage
|
|
69
|
+
2. **App authenticates** → Stores session token in `AuthContext`
|
|
70
|
+
3. **App fetches data** → Calls Lumera API via `@lumerahq/ui/lib` helpers
|
|
71
|
+
4. **Data mutations** → API calls trigger collection hooks if configured
|
|
72
|
+
5. **Background work** → Automations run async via `createRun` / `pollRun`
|
|
73
|
+
|
|
74
|
+
## Collections
|
|
75
|
+
|
|
76
|
+
| Collection | Purpose |
|
|
77
|
+
|------------------|----------------------------|
|
|
78
|
+
| `example_items` | Starter collection (replace with your own) |
|
|
79
|
+
|
|
80
|
+
_Update this table as you add collections._
|
|
@@ -33,9 +33,9 @@ pnpm dev # Start dev server
|
|
|
33
33
|
pnpm deploy # Deploy frontend
|
|
34
34
|
|
|
35
35
|
# All other commands
|
|
36
|
-
pnpm dlx @lumerahq/cli
|
|
37
|
-
pnpm dlx @lumerahq/cli
|
|
38
|
-
pnpm dlx @lumerahq/cli
|
|
36
|
+
pnpm dlx @lumerahq/cli plan
|
|
37
|
+
pnpm dlx @lumerahq/cli apply
|
|
38
|
+
pnpm dlx @lumerahq/cli destroy
|
|
39
39
|
pnpm dlx @lumerahq/cli run scripts/seed-demo.py
|
|
40
40
|
pnpm dlx @lumerahq/cli status
|
|
41
41
|
```
|
|
@@ -50,10 +50,10 @@ lumera login
|
|
|
50
50
|
pnpm dev
|
|
51
51
|
|
|
52
52
|
# With custom port
|
|
53
|
-
lumera
|
|
53
|
+
lumera dev --port 3000
|
|
54
54
|
|
|
55
55
|
# With ngrok tunnel
|
|
56
|
-
lumera
|
|
56
|
+
lumera dev --url https://my-tunnel.ngrok.io
|
|
57
57
|
|
|
58
58
|
# Plain vite (no Lumera registration)
|
|
59
59
|
pnpm dev:vite
|
|
@@ -71,21 +71,21 @@ pnpm lint
|
|
|
71
71
|
# Format code
|
|
72
72
|
pnpm format
|
|
73
73
|
|
|
74
|
-
# Run all checks (lint + typecheck) - use in CI
|
|
74
|
+
# Run all checks (lint + format + typecheck) - use in CI
|
|
75
75
|
pnpm check:ci
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
### Deploying
|
|
79
79
|
|
|
80
80
|
```bash
|
|
81
|
-
# Deploy frontend
|
|
82
|
-
lumera app
|
|
81
|
+
# Deploy frontend
|
|
82
|
+
lumera apply app
|
|
83
83
|
|
|
84
|
-
# Apply
|
|
85
|
-
lumera
|
|
84
|
+
# Apply all resources (collections, automations, hooks, app)
|
|
85
|
+
lumera apply
|
|
86
86
|
|
|
87
|
-
# Preview
|
|
88
|
-
lumera
|
|
87
|
+
# Preview changes first
|
|
88
|
+
lumera plan
|
|
89
89
|
```
|
|
90
90
|
|
|
91
91
|
### Running Scripts
|
|
@@ -129,7 +129,7 @@ EOF
|
|
|
129
129
|
|
|
130
130
|
## Important Rules
|
|
131
131
|
|
|
132
|
-
1. **Authenticate first** - Before running any CLI or SDK commands, ensure the user has run `lumera login
|
|
132
|
+
1. **Authenticate first** - Before running any CLI or SDK commands, ensure the user has run `lumera login`. This stores credentials in `.lumera/credentials.json` which the SDK reads automatically.
|
|
133
133
|
|
|
134
134
|
2. **Source of truth is code** - `platform/` contains all schemas, automations, hooks. Update local code first, then deploy.
|
|
135
135
|
|
|
@@ -23,13 +23,13 @@ Lumera custom embedded app.
|
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
25
|
# Development
|
|
26
|
-
lumera
|
|
27
|
-
lumera
|
|
26
|
+
lumera dev # Start dev server
|
|
27
|
+
lumera dev --port 3000 # Custom port
|
|
28
28
|
|
|
29
29
|
# Deployment
|
|
30
|
-
lumera app
|
|
31
|
-
lumera
|
|
32
|
-
lumera
|
|
30
|
+
lumera apply app # Build and deploy frontend
|
|
31
|
+
lumera apply # Apply all resources
|
|
32
|
+
lumera plan # Preview changes
|
|
33
33
|
|
|
34
34
|
# Scripts
|
|
35
35
|
lumera run scripts/seed-demo.py # Run seed script
|
|
@@ -12,16 +12,16 @@
|
|
|
12
12
|
"name": "{{projectTitle}}"
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
|
-
"dev": "pnpm dlx @lumerahq/cli
|
|
16
|
-
"deploy": "pnpm dlx @lumerahq/cli app
|
|
15
|
+
"dev": "pnpm dlx @lumerahq/cli dev",
|
|
16
|
+
"deploy": "pnpm dlx @lumerahq/cli apply app",
|
|
17
17
|
"dev:vite": "vite",
|
|
18
18
|
"build": "vite build && tsc",
|
|
19
19
|
"preview": "vite preview",
|
|
20
|
-
"typecheck": "tsc --noEmit",
|
|
20
|
+
"typecheck": "tsr generate && tsc --noEmit",
|
|
21
21
|
"lint": "biome lint --write .",
|
|
22
22
|
"format": "biome format --write .",
|
|
23
23
|
"check": "biome check --write .",
|
|
24
|
-
"check:ci": "biome check . && tsc --noEmit"
|
|
24
|
+
"check:ci": "biome check . && tsr generate && tsc --noEmit"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@lumerahq/ui": "^0.5.0",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@biomejs/biome": "^2.0.0",
|
|
39
39
|
"@tailwindcss/vite": "^4.0.6",
|
|
40
|
+
"@tanstack/router-cli": "1.155.0",
|
|
40
41
|
"@types/react": "^19.2.0",
|
|
41
42
|
"@types/react-dom": "^19.2.0",
|
|
42
43
|
"@vitejs/plugin-react": "^5.0.4",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { cn } from '@lumerahq/ui/lib';
|
|
1
2
|
import { Link, useRouterState } from '@tanstack/react-router';
|
|
2
|
-
import {
|
|
3
|
+
import { ChevronLeft, ChevronRight, LayoutDashboard, Settings } from 'lucide-react';
|
|
3
4
|
import { useState } from 'react';
|
|
4
|
-
import { cn } from '@lumerahq/ui/lib';
|
|
5
5
|
|
|
6
6
|
type NavItem = {
|
|
7
7
|
to: string;
|
|
@@ -37,9 +37,7 @@ export function Sidebar() {
|
|
|
37
37
|
<div className="size-8 rounded-lg bg-primary flex items-center justify-center text-primary-foreground font-bold text-sm">
|
|
38
38
|
{{projectInitial}}
|
|
39
39
|
</div>
|
|
40
|
-
{!collapsed &&
|
|
41
|
-
<span className="font-semibold text-sm">{{projectTitle}}</span>
|
|
42
|
-
)}
|
|
40
|
+
{!collapsed && <span className="font-semibold text-sm">{{projectTitle}}</span>}
|
|
43
41
|
</Link>
|
|
44
42
|
</div>
|
|
45
43
|
|
|
@@ -16,15 +16,9 @@ export function StatCard({ title, value, subtitle, icon, className }: StatCardPr
|
|
|
16
16
|
<div className="space-y-1">
|
|
17
17
|
<p className="text-sm font-medium text-muted-foreground">{title}</p>
|
|
18
18
|
<p className="text-2xl font-semibold tracking-tight">{value}</p>
|
|
19
|
-
{subtitle &&
|
|
20
|
-
<p className="text-sm text-muted-foreground">{subtitle}</p>
|
|
21
|
-
)}
|
|
19
|
+
{subtitle && <p className="text-sm text-muted-foreground">{subtitle}</p>}
|
|
22
20
|
</div>
|
|
23
|
-
{icon &&
|
|
24
|
-
<div className="rounded-lg bg-muted p-2.5 text-muted-foreground">
|
|
25
|
-
{icon}
|
|
26
|
-
</div>
|
|
27
|
-
)}
|
|
21
|
+
{icon && <div className="rounded-lg bg-muted p-2.5 text-muted-foreground">{icon}</div>}
|
|
28
22
|
</div>
|
|
29
23
|
</div>
|
|
30
24
|
);
|
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import ReactDOM from 'react-dom/client';
|
|
1
|
+
import { type HostPayload, isEmbedded, onInitMessage, postReadyMessage } from '@lumerahq/ui/lib';
|
|
3
2
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
4
|
-
import {
|
|
3
|
+
import { createHashHistory, createRouter, RouterProvider } from '@tanstack/react-router';
|
|
4
|
+
import { createContext, StrictMode, useEffect, useRef, useState } from 'react';
|
|
5
|
+
import ReactDOM from 'react-dom/client';
|
|
5
6
|
import { Toaster } from 'sonner';
|
|
6
7
|
|
|
7
|
-
import {
|
|
8
|
-
isEmbedded,
|
|
9
|
-
onInitMessage,
|
|
10
|
-
postReadyMessage,
|
|
11
|
-
type HostPayload,
|
|
12
|
-
} from '@lumerahq/ui/lib';
|
|
13
|
-
|
|
14
8
|
import { routeTree } from './routeTree.gen';
|
|
15
9
|
import '@lumerahq/ui/styles.css';
|
|
16
10
|
import './styles.css';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createFileRoute } from '@tanstack/react-router';
|
|
2
|
+
import { Activity, FileText, TrendingUp, Users } from 'lucide-react';
|
|
2
3
|
import { useContext } from 'react';
|
|
3
|
-
import { Users, FileText, Activity, TrendingUp } from 'lucide-react';
|
|
4
|
-
import { AuthContext } from '../main';
|
|
5
4
|
import { StatCard } from '../components/StatCard';
|
|
5
|
+
import { AuthContext } from '../main';
|
|
6
6
|
|
|
7
7
|
export const Route = createFileRoute('/')({
|
|
8
8
|
component: HomePage,
|
|
@@ -16,9 +16,7 @@ function HomePage() {
|
|
|
16
16
|
{/* Header */}
|
|
17
17
|
<div>
|
|
18
18
|
<h1 className="text-2xl font-semibold">Dashboard</h1>
|
|
19
|
-
<p className="text-muted-foreground mt-1">
|
|
20
|
-
Welcome back, {auth?.user?.name ?? 'User'}
|
|
21
|
-
</p>
|
|
19
|
+
<p className="text-muted-foreground mt-1">Welcome back, {auth?.user?.name ?? 'User'}</p>
|
|
22
20
|
</div>
|
|
23
21
|
|
|
24
22
|
{/* Stats Grid */}
|
|
@@ -9,16 +9,12 @@ function SettingsPage() {
|
|
|
9
9
|
<div className="space-y-6">
|
|
10
10
|
<div>
|
|
11
11
|
<h1 className="text-2xl font-semibold">Settings</h1>
|
|
12
|
-
<p className="text-muted-foreground mt-1">
|
|
13
|
-
Manage your application settings
|
|
14
|
-
</p>
|
|
12
|
+
<p className="text-muted-foreground mt-1">Manage your application settings</p>
|
|
15
13
|
</div>
|
|
16
14
|
|
|
17
15
|
<div className="rounded-xl border bg-card p-6">
|
|
18
16
|
<h2 className="font-semibold mb-4">General</h2>
|
|
19
|
-
<p className="text-sm text-muted-foreground">
|
|
20
|
-
Add your settings UI here
|
|
21
|
-
</p>
|
|
17
|
+
<p className="text-sm text-muted-foreground">Add your settings UI here</p>
|
|
22
18
|
</div>
|
|
23
19
|
</div>
|
|
24
20
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { defineConfig } from 'vite';
|
|
2
|
-
import viteReact from '@vitejs/plugin-react';
|
|
3
1
|
import tailwindcss from '@tailwindcss/vite';
|
|
4
2
|
import { tanstackRouter } from '@tanstack/router-plugin/vite';
|
|
3
|
+
import viteReact from '@vitejs/plugin-react';
|
|
4
|
+
import { defineConfig } from 'vite';
|
|
5
5
|
|
|
6
6
|
export default defineConfig({
|
|
7
7
|
base: './', // Use relative paths for S3 hosting at subpaths
|
|
@@ -22,6 +22,7 @@ export default defineConfig({
|
|
|
22
22
|
server: {
|
|
23
23
|
allowedHosts: [
|
|
24
24
|
'mac.lumerahq.com',
|
|
25
|
+
'untunable-del-nonephemerally.ngrok-free.dev',
|
|
25
26
|
],
|
|
26
27
|
},
|
|
27
28
|
});
|