@bardioc/create-bardioc-app 0.5.6 → 0.6.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 +1 -1
- package/package.json +1 -1
- package/templates/_base/README.md +1 -1
- package/templates/_base/public/app-manifest.json +1 -2
- package/templates/angular/.env.example +4 -1
- package/templates/angular/package.json +2 -2
- package/templates/angular/scripts/dev-env.mjs +62 -0
- package/templates/angular/scripts/dev.mjs +56 -0
- package/templates/angular/scripts/sync-runtime-env.mjs +2 -28
- package/templates/angular/src/app/app.component.ts +44 -26
- package/templates/angular/src/app/bardioc.token.ts +2 -2
- package/templates/angular/src/main.ts +6 -8
- package/templates/angular/src/styles.css +4 -0
- package/templates/nextjs/.env.example +4 -1
- package/templates/nextjs/app/page.tsx +18 -15
- package/templates/nextjs/next.config.ts +1 -1
- package/templates/nextjs/package.json +3 -3
- package/templates/nextjs/scripts/dev-env.mjs +62 -0
- package/templates/nextjs/scripts/dev.mjs +56 -0
- package/templates/preact/.env.example +3 -0
- package/templates/preact/package.json +2 -2
- package/templates/preact/src/App.tsx +10 -10
- package/templates/preact/src/main.tsx +3 -3
- package/templates/preact/vite.config.ts +4 -1
- package/templates/solid/.env.example +3 -0
- package/templates/solid/package.json +2 -2
- package/templates/solid/src/App.tsx +10 -10
- package/templates/solid/src/bardioc-sdk.tsx +11 -23
- package/templates/solid/src/main.tsx +5 -3
- package/templates/solid/vite.config.ts +4 -1
- package/templates/svelte/.env.example +3 -0
- package/templates/svelte/package.json +2 -2
- package/templates/svelte/src/App.svelte +12 -12
- package/templates/svelte/src/main.ts +5 -5
- package/templates/svelte/vite.config.ts +4 -1
- package/templates/vite/.env.example +3 -0
- package/templates/vite/CLAUDE.md +34 -7
- package/templates/vite/package.json +3 -3
- package/templates/vite/public/app-manifest.json +0 -1
- package/templates/vite/src/auth/onboarding.tsx +7 -5
- package/templates/vite/src/climate/conditions-chart.tsx +2 -2
- package/templates/vite/src/climate/overview-view.tsx +1 -1
- package/templates/vite/src/climate/stations-view.tsx +3 -10
- package/templates/vite/src/climate/use-climate.ts +8 -8
- package/templates/vite/src/events/live-events-view.tsx +8 -10
- package/templates/vite/src/graph/explorer-view.tsx +7 -14
- package/templates/vite/src/graph/requests.ts +16 -19
- package/templates/vite/src/locales/de.json +7 -8
- package/templates/vite/src/locales/en.json +45 -46
- package/templates/vite/src/main.tsx +3 -3
- package/templates/vite/src/profile/profile-view.tsx +5 -12
- package/templates/vite/src/profile/use-profile.ts +3 -3
- package/templates/vite/src/shell/about-dialog.tsx +5 -11
- package/templates/vite/src/shell/app-shell.tsx +63 -22
- package/templates/vite/src/shell/header.tsx +24 -24
- package/templates/vite/vite.config.ts +4 -1
- package/templates/vue/.env.example +3 -0
- package/templates/vue/package.json +2 -2
- package/templates/vue/src/App.vue +12 -12
- package/templates/vue/src/bardioc-sdk.ts +6 -15
- package/templates/vue/src/main.ts +5 -4
- package/templates/vue/vite.config.ts +4 -1
- package/templates/angular/scripts/dev-auth-proxy.mjs +0 -17
- package/templates/angular/src/app/bardioc-bridge.ts +0 -5
- package/templates/nextjs/scripts/dev-auth-proxy.mjs +0 -17
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { createDevAuthProxyHandler } from '@bardioc/app-sdk/dev-proxy';
|
|
4
|
+
import { spawn } from 'node:child_process';
|
|
5
|
+
import { createServer } from 'node:http';
|
|
6
|
+
import { dirname, resolve } from 'node:path';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import { PROXY_PORT_OFFSET, readDevAuthEnv, resolveAppPort } from './dev-env.mjs';
|
|
9
|
+
|
|
10
|
+
const PROXY_HOST = '127.0.0.1';
|
|
11
|
+
|
|
12
|
+
const projectDir = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
13
|
+
const port = resolveAppPort(projectDir);
|
|
14
|
+
|
|
15
|
+
// `next dev` cannot host the SDK Vite plugin, so the proxy runs beside it.
|
|
16
|
+
const proxy = await startProxy(port + PROXY_PORT_OFFSET);
|
|
17
|
+
|
|
18
|
+
// One command string: shell:true resolves the .cmd shim on Windows, and passing an args array
|
|
19
|
+
// alongside it is deprecated (DEP0190).
|
|
20
|
+
const server = spawn(`next dev --port ${port}`, { stdio: 'inherit', shell: true });
|
|
21
|
+
|
|
22
|
+
for (const signal of ['SIGINT', 'SIGTERM']) {
|
|
23
|
+
process.on(signal, () => server.kill(signal));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Exit only once the dev server has, carrying its exit code.
|
|
27
|
+
server.on('exit', (code, signal) => {
|
|
28
|
+
proxy?.close();
|
|
29
|
+
process.exit(signal ? 1 : (code ?? 0));
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Built from the SDK handler rather than startDevAuthProxy, whose own SIGINT handler exits the
|
|
33
|
+
// process before the dev server has shut down. Without DEV_SECRET / API_BASE_URL the dev server
|
|
34
|
+
// runs alone, matching how the SDK Vite plugin disables itself.
|
|
35
|
+
async function startProxy(proxyPort) {
|
|
36
|
+
const env = readDevAuthEnv(projectDir);
|
|
37
|
+
if (!env) {
|
|
38
|
+
console.warn(
|
|
39
|
+
'[bardioc-dev-auth] DEV_SECRET and API_BASE_URL are required for dev auth — proxy disabled'
|
|
40
|
+
);
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const handler = createDevAuthProxyHandler({ ...env, allowOrigin: '*' });
|
|
45
|
+
const proxyServer = createServer((req, res) => void handler(req, res));
|
|
46
|
+
|
|
47
|
+
await new Promise((resolveListen, rejectListen) => {
|
|
48
|
+
proxyServer.once('error', rejectListen);
|
|
49
|
+
proxyServer.listen(proxyPort, PROXY_HOST, resolveListen);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
console.log(
|
|
53
|
+
`[bardioc-dev-auth] proxying /rest/* → ${env.apiBaseUrl} on http://${PROXY_HOST}:${proxyPort}/rest`
|
|
54
|
+
);
|
|
55
|
+
return proxyServer;
|
|
56
|
+
}
|
|
@@ -7,3 +7,6 @@ DEV_SECRET=
|
|
|
7
7
|
|
|
8
8
|
# Base URL of the Bardioc BFF / backend-for-frontend (e.g. https://your-host).
|
|
9
9
|
API_BASE_URL=
|
|
10
|
+
|
|
11
|
+
# By default, the app will start on port {{PORT}}. Feel free to uncomment the following variable and change it to match your local setup preferences.
|
|
12
|
+
#LOCALHOST_PORT={{PORT}}
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
"release:publish": "changeset publish"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@bardioc/app-sdk": "^0.
|
|
21
|
+
"@bardioc/app-sdk": "^1.0.0",
|
|
22
22
|
"preact": "^10.26.7"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@bardioc/configs": "
|
|
25
|
+
"@bardioc/configs": "0.2.1",
|
|
26
26
|
"@changesets/cli": "^2.31.0",
|
|
27
27
|
"@preact/preset-vite": "^2.10.6",
|
|
28
28
|
"@tailwindcss/vite": "^4.3.0",
|
|
@@ -9,7 +9,7 @@ type ResultState =
|
|
|
9
9
|
| { status: 'error'; request: string; message: string };
|
|
10
10
|
|
|
11
11
|
function SdkDemo() {
|
|
12
|
-
const
|
|
12
|
+
const bardioc = useSdk();
|
|
13
13
|
const notify = useNotify();
|
|
14
14
|
const [result, setResult] = useState<ResultState>({ status: 'idle' });
|
|
15
15
|
const [running, setRunning] = useState(false);
|
|
@@ -18,17 +18,17 @@ function SdkDemo() {
|
|
|
18
18
|
if (running) return;
|
|
19
19
|
setRunning(true);
|
|
20
20
|
|
|
21
|
-
const request = '
|
|
21
|
+
const request = 'os.profile.get()';
|
|
22
22
|
setResult({ status: 'loading', request });
|
|
23
23
|
|
|
24
24
|
const startTime = Date.now();
|
|
25
|
-
notify('Getting user profile', 'info');
|
|
25
|
+
notify('Getting user profile…', 'info');
|
|
26
26
|
|
|
27
27
|
try {
|
|
28
|
-
const data = await
|
|
28
|
+
const data = await bardioc.os.profile.get();
|
|
29
29
|
|
|
30
30
|
const duration = Date.now() - startTime;
|
|
31
|
-
notify(`Profile loaded (${duration}ms)
|
|
31
|
+
notify(`Profile loaded (${duration}ms).`, 'success');
|
|
32
32
|
setResult({ status: 'success', request, data });
|
|
33
33
|
} catch (err) {
|
|
34
34
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -40,10 +40,10 @@ function SdkDemo() {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
function handleNotify() {
|
|
43
|
-
notify('Hello from {{DISPLAY_NAME}}', 'info');
|
|
43
|
+
notify('Hello from {{DISPLAY_NAME}}.', 'info');
|
|
44
44
|
setResult({
|
|
45
45
|
status: 'success',
|
|
46
|
-
request: '
|
|
46
|
+
request: 'ui.notify',
|
|
47
47
|
data: { ok: true, message: 'Notification sent to OS' },
|
|
48
48
|
});
|
|
49
49
|
}
|
|
@@ -99,7 +99,7 @@ function SdkDemo() {
|
|
|
99
99
|
<div className="text-muted-foreground border-border border-b pb-2 font-mono text-xs">
|
|
100
100
|
{result.request}
|
|
101
101
|
</div>
|
|
102
|
-
<div className="text-destructive
|
|
102
|
+
<div className="text-destructive whitespace-pre-wrap break-all">{result.message}</div>
|
|
103
103
|
</div>
|
|
104
104
|
)}
|
|
105
105
|
{result.status === 'success' && (
|
|
@@ -121,14 +121,14 @@ export function App() {
|
|
|
121
121
|
const showSdkDemo = isInsideIframe() || isDevStandalone();
|
|
122
122
|
|
|
123
123
|
return (
|
|
124
|
-
<div className="bg-background text-foreground min-h-screen">
|
|
124
|
+
<div className="bg-background text-foreground @container/app min-h-screen">
|
|
125
125
|
{showSdkDemo ? (
|
|
126
126
|
<SdkDemo />
|
|
127
127
|
) : (
|
|
128
128
|
<div className="mx-auto flex min-h-screen w-full max-w-3xl flex-col gap-4 p-4">
|
|
129
129
|
<h1 className="m-0 text-2xl font-semibold">Hello Bardioc App</h1>
|
|
130
130
|
<p className="text-muted-foreground m-0 max-w-2xl text-xs leading-5">
|
|
131
|
-
Open this app inside Bardioc
|
|
131
|
+
Open this app inside Bardioc to use transport requests and send host notifications.
|
|
132
132
|
</p>
|
|
133
133
|
<div className="border-border bg-muted/20 rounded-xl border p-3 text-xs leading-5">
|
|
134
134
|
Outside the host iframe this page is only a local preview shell.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { installDevHost, isDevStandalone, isInsideIframe } from '@bardioc/app-sdk/dev';
|
|
2
2
|
import { AppSdkProvider } from '@bardioc/app-sdk/react';
|
|
3
3
|
import { render } from 'preact';
|
|
4
4
|
import { App } from './App';
|
|
@@ -15,12 +15,12 @@ const devStandalone = isDevStandalone();
|
|
|
15
15
|
const useSdkProvider = insideIframe || devStandalone;
|
|
16
16
|
|
|
17
17
|
if (devStandalone) {
|
|
18
|
-
|
|
18
|
+
installDevHost({ appId: APP_NAME });
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
render(
|
|
22
22
|
useSdkProvider ? (
|
|
23
|
-
<AppSdkProvider
|
|
23
|
+
<AppSdkProvider>
|
|
24
24
|
<App />
|
|
25
25
|
</AppSdkProvider>
|
|
26
26
|
) : (
|
|
@@ -3,9 +3,12 @@ import preact from '@preact/preset-vite';
|
|
|
3
3
|
import tailwindcss from '@tailwindcss/vite';
|
|
4
4
|
import { defineConfig, loadEnv } from 'vite';
|
|
5
5
|
|
|
6
|
+
const DEFAULT_PORT = {{PORT}};
|
|
7
|
+
|
|
6
8
|
export default defineConfig(({ mode }) => {
|
|
7
9
|
const env = loadEnv(mode, __dirname, '');
|
|
8
10
|
const appName = env.VITE_APP_NAME?.trim();
|
|
11
|
+
const port = Number(env.LOCALHOST_PORT) || DEFAULT_PORT;
|
|
9
12
|
|
|
10
13
|
if (!appName) {
|
|
11
14
|
throw new Error('Missing VITE_APP_NAME for Vite config');
|
|
@@ -15,7 +18,7 @@ export default defineConfig(({ mode }) => {
|
|
|
15
18
|
plugins: [
|
|
16
19
|
bardiocDevAuth({ appName }),
|
|
17
20
|
preact(),
|
|
18
|
-
bardiocApp({ appName, port
|
|
21
|
+
bardiocApp({ appName, port }),
|
|
19
22
|
tailwindcss(),
|
|
20
23
|
],
|
|
21
24
|
};
|
|
@@ -7,3 +7,6 @@ DEV_SECRET=
|
|
|
7
7
|
|
|
8
8
|
# Base URL of the Bardioc BFF / backend-for-frontend (e.g. https://your-host).
|
|
9
9
|
API_BASE_URL=
|
|
10
|
+
|
|
11
|
+
# By default, the app will start on port {{PORT}}. Feel free to uncomment the following variable and change it to match your local setup preferences.
|
|
12
|
+
#LOCALHOST_PORT={{PORT}}
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
"release:publish": "changeset publish"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@bardioc/app-sdk": "^0.
|
|
21
|
+
"@bardioc/app-sdk": "^1.0.0",
|
|
22
22
|
"solid-js": "^1.9.7"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@bardioc/configs": "
|
|
25
|
+
"@bardioc/configs": "0.2.1",
|
|
26
26
|
"@changesets/cli": "^2.31.0",
|
|
27
27
|
"@tailwindcss/vite": "^4.3.0",
|
|
28
28
|
"@types/node": "^22.19.19",
|
|
@@ -9,7 +9,7 @@ type ResultState =
|
|
|
9
9
|
| { status: 'error'; request: string; message: string };
|
|
10
10
|
|
|
11
11
|
function SdkDemo() {
|
|
12
|
-
const
|
|
12
|
+
const bardioc = useSdk();
|
|
13
13
|
const notify = useNotify();
|
|
14
14
|
const [result, setResult] = createSignal<ResultState>({ status: 'idle' });
|
|
15
15
|
const [running, setRunning] = createSignal(false);
|
|
@@ -18,17 +18,17 @@ function SdkDemo() {
|
|
|
18
18
|
if (running()) return;
|
|
19
19
|
setRunning(true);
|
|
20
20
|
|
|
21
|
-
const request = '
|
|
21
|
+
const request = 'os.profile.get()';
|
|
22
22
|
setResult({ status: 'loading', request });
|
|
23
23
|
|
|
24
24
|
const startTime = Date.now();
|
|
25
|
-
notify('Getting user profile', 'info');
|
|
25
|
+
notify('Getting user profile…', 'info');
|
|
26
26
|
|
|
27
27
|
try {
|
|
28
|
-
const data = await
|
|
28
|
+
const data = await bardioc.os.profile.get();
|
|
29
29
|
|
|
30
30
|
const duration = Date.now() - startTime;
|
|
31
|
-
notify(`Profile loaded (${duration}ms)
|
|
31
|
+
notify(`Profile loaded (${duration}ms).`, 'success');
|
|
32
32
|
setResult({ status: 'success', request, data });
|
|
33
33
|
} catch (err) {
|
|
34
34
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -40,10 +40,10 @@ function SdkDemo() {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
function handleNotify() {
|
|
43
|
-
notify('Hello from {{DISPLAY_NAME}}', 'info');
|
|
43
|
+
notify('Hello from {{DISPLAY_NAME}}.', 'info');
|
|
44
44
|
setResult({
|
|
45
45
|
status: 'success',
|
|
46
|
-
request: '
|
|
46
|
+
request: 'ui.notify',
|
|
47
47
|
data: { ok: true, message: 'Notification sent to OS' },
|
|
48
48
|
});
|
|
49
49
|
}
|
|
@@ -106,7 +106,7 @@ function SdkDemo() {
|
|
|
106
106
|
<div class="text-muted-foreground border-border border-b pb-2 font-mono text-xs">
|
|
107
107
|
{r.request}
|
|
108
108
|
</div>
|
|
109
|
-
<div class="text-destructive
|
|
109
|
+
<div class="text-destructive whitespace-pre-wrap break-all">{r.message}</div>
|
|
110
110
|
</div>
|
|
111
111
|
);
|
|
112
112
|
}
|
|
@@ -132,14 +132,14 @@ export function App() {
|
|
|
132
132
|
const showSdkDemo = isInsideIframe() || isDevStandalone();
|
|
133
133
|
|
|
134
134
|
return (
|
|
135
|
-
<div class="bg-background text-foreground min-h-screen">
|
|
135
|
+
<div class="bg-background text-foreground @container/app min-h-screen">
|
|
136
136
|
{showSdkDemo ? (
|
|
137
137
|
<SdkDemo />
|
|
138
138
|
) : (
|
|
139
139
|
<div class="mx-auto flex min-h-screen w-full max-w-3xl flex-col gap-4 p-4">
|
|
140
140
|
<h1 class="m-0 text-2xl font-semibold">Hello Bardioc App</h1>
|
|
141
141
|
<p class="text-muted-foreground m-0 max-w-2xl text-xs leading-5">
|
|
142
|
-
Open this app inside Bardioc
|
|
142
|
+
Open this app inside Bardioc to use transport requests and send host notifications.
|
|
143
143
|
</p>
|
|
144
144
|
<div class="border-border bg-muted/20 rounded-xl border p-3 text-xs leading-5">
|
|
145
145
|
Outside the host iframe this page is only a local preview shell.
|
|
@@ -1,33 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createContext,
|
|
1
|
+
import type { Bardioc, NotifyLevel } from '@bardioc/app-sdk';
|
|
2
|
+
import { createContext, useContext, type JSX } from 'solid-js';
|
|
3
3
|
|
|
4
|
-
const BardiocContext = createContext<
|
|
4
|
+
const BardiocContext = createContext<Bardioc>();
|
|
5
5
|
|
|
6
|
-
export function AppSdkProvider(props: {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
onMount(() => {
|
|
10
|
-
void bridge.connect();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
onCleanup(() => {
|
|
14
|
-
bridge.destroy();
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
return <BardiocContext.Provider value={bridge}>{props.children}</BardiocContext.Provider>;
|
|
6
|
+
export function AppSdkProvider(props: { bardioc: Bardioc; children: JSX.Element }) {
|
|
7
|
+
return <BardiocContext.Provider value={props.bardioc}>{props.children}</BardiocContext.Provider>;
|
|
18
8
|
}
|
|
19
9
|
|
|
20
|
-
export function useSdk():
|
|
21
|
-
const
|
|
22
|
-
if (!
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
return bridge;
|
|
10
|
+
export function useSdk(): Bardioc {
|
|
11
|
+
const bardioc = useContext(BardiocContext);
|
|
12
|
+
if (!bardioc) throw new Error('useSdk() must be used inside AppSdkProvider');
|
|
13
|
+
return bardioc;
|
|
26
14
|
}
|
|
27
15
|
|
|
28
16
|
export function useNotify() {
|
|
29
|
-
const
|
|
17
|
+
const { ui } = useSdk();
|
|
30
18
|
return (message: string, level?: NotifyLevel) => {
|
|
31
|
-
|
|
19
|
+
ui.notify(message, level).catch(console.error);
|
|
32
20
|
};
|
|
33
21
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { connect } from '@bardioc/app-sdk';
|
|
2
|
+
import { installDevHost, isDevStandalone, isInsideIframe } from '@bardioc/app-sdk/dev';
|
|
2
3
|
import { render } from 'solid-js/web';
|
|
3
4
|
import { App } from './App';
|
|
4
5
|
import { AppSdkProvider } from './bardioc-sdk';
|
|
@@ -15,15 +16,16 @@ const devStandalone = isDevStandalone();
|
|
|
15
16
|
const useSdkProvider = insideIframe || devStandalone;
|
|
16
17
|
|
|
17
18
|
if (devStandalone) {
|
|
18
|
-
|
|
19
|
+
installDevHost({ appId: APP_NAME });
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
const root = document.getElementById('root')!;
|
|
22
23
|
|
|
23
24
|
if (useSdkProvider) {
|
|
25
|
+
const bardioc = await connect();
|
|
24
26
|
render(
|
|
25
27
|
() => (
|
|
26
|
-
<AppSdkProvider
|
|
28
|
+
<AppSdkProvider bardioc={bardioc}>
|
|
27
29
|
<App />
|
|
28
30
|
</AppSdkProvider>
|
|
29
31
|
),
|
|
@@ -3,9 +3,12 @@ import tailwindcss from '@tailwindcss/vite';
|
|
|
3
3
|
import { defineConfig, loadEnv } from 'vite';
|
|
4
4
|
import solid from 'vite-plugin-solid';
|
|
5
5
|
|
|
6
|
+
const DEFAULT_PORT = {{PORT}};
|
|
7
|
+
|
|
6
8
|
export default defineConfig(({ mode }) => {
|
|
7
9
|
const env = loadEnv(mode, __dirname, '');
|
|
8
10
|
const appName = env.VITE_APP_NAME?.trim();
|
|
11
|
+
const port = Number(env.LOCALHOST_PORT) || DEFAULT_PORT;
|
|
9
12
|
|
|
10
13
|
if (!appName) {
|
|
11
14
|
throw new Error('Missing VITE_APP_NAME for Vite config');
|
|
@@ -15,7 +18,7 @@ export default defineConfig(({ mode }) => {
|
|
|
15
18
|
plugins: [
|
|
16
19
|
bardiocDevAuth({ appName }),
|
|
17
20
|
solid(),
|
|
18
|
-
bardiocApp({ appName, port
|
|
21
|
+
bardiocApp({ appName, port }),
|
|
19
22
|
tailwindcss(),
|
|
20
23
|
],
|
|
21
24
|
};
|
|
@@ -7,3 +7,6 @@ DEV_SECRET=
|
|
|
7
7
|
|
|
8
8
|
# Base URL of the Bardioc BFF / backend-for-frontend (e.g. https://your-host).
|
|
9
9
|
API_BASE_URL=
|
|
10
|
+
|
|
11
|
+
# By default, the app will start on port {{PORT}}. Feel free to uncomment the following variable and change it to match your local setup preferences.
|
|
12
|
+
#LOCALHOST_PORT={{PORT}}
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
"release:publish": "changeset publish"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@bardioc/app-sdk": "^0.
|
|
21
|
+
"@bardioc/app-sdk": "^1.0.0",
|
|
22
22
|
"svelte": "^5.33.14"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@bardioc/configs": "
|
|
25
|
+
"@bardioc/configs": "0.2.1",
|
|
26
26
|
"@changesets/cli": "^2.31.0",
|
|
27
27
|
"@sveltejs/vite-plugin-svelte": "^7.2.0",
|
|
28
28
|
"@tailwindcss/vite": "^4.3.0",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type {
|
|
2
|
+
import type { Bardioc, NotifyLevel } from '@bardioc/app-sdk';
|
|
3
3
|
import { isDevStandalone, isInsideIframe } from '@bardioc/app-sdk/dev';
|
|
4
4
|
import { type Snippet } from 'svelte';
|
|
5
5
|
import './index.css';
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
| { status: 'success'; request: string; data: unknown }
|
|
11
11
|
| { status: 'error'; request: string; message: string };
|
|
12
12
|
|
|
13
|
-
let {
|
|
13
|
+
let { bardioc = null, children }: { bardioc?: Bardioc | null; children?: Snippet } = $props();
|
|
14
14
|
|
|
15
15
|
const showSdkDemo = isInsideIframe() || isDevStandalone();
|
|
16
16
|
|
|
@@ -18,24 +18,24 @@
|
|
|
18
18
|
let running = $state(false);
|
|
19
19
|
|
|
20
20
|
function notify(message: string, level?: NotifyLevel) {
|
|
21
|
-
|
|
21
|
+
bardioc?.ui.notify(message, level).catch(console.error);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
async function runGetProfile() {
|
|
25
|
-
if (running || !
|
|
25
|
+
if (running || !bardioc) return;
|
|
26
26
|
running = true;
|
|
27
27
|
|
|
28
|
-
const request = '
|
|
28
|
+
const request = 'os.profile.get()';
|
|
29
29
|
result = { status: 'loading', request };
|
|
30
30
|
|
|
31
31
|
const startTime = Date.now();
|
|
32
|
-
notify('Getting user profile', 'info');
|
|
32
|
+
notify('Getting user profile…', 'info');
|
|
33
33
|
|
|
34
34
|
try {
|
|
35
|
-
const data = await
|
|
35
|
+
const data = await bardioc.os.profile.get();
|
|
36
36
|
|
|
37
37
|
const duration = Date.now() - startTime;
|
|
38
|
-
notify(`Profile loaded (${duration}ms)
|
|
38
|
+
notify(`Profile loaded (${duration}ms).`, 'success');
|
|
39
39
|
result = { status: 'success', request, data };
|
|
40
40
|
} catch (err) {
|
|
41
41
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
function handleNotify() {
|
|
50
|
-
notify('Hello from {{DISPLAY_NAME}}', 'info');
|
|
50
|
+
notify('Hello from {{DISPLAY_NAME}}.', 'info');
|
|
51
51
|
result = {
|
|
52
52
|
status: 'success',
|
|
53
|
-
request: '
|
|
53
|
+
request: 'ui.notify',
|
|
54
54
|
data: { ok: true, message: 'Notification sent to OS' },
|
|
55
55
|
};
|
|
56
56
|
}
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
}
|
|
61
61
|
</script>
|
|
62
62
|
|
|
63
|
-
<div class="bg-background text-foreground min-h-screen">
|
|
63
|
+
<div class="bg-background text-foreground @container/app min-h-screen">
|
|
64
64
|
{#if showSdkDemo}
|
|
65
65
|
<div class="mx-auto flex min-h-screen w-full max-w-3xl flex-col gap-3 p-4">
|
|
66
66
|
<div class="flex flex-col gap-1">
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
<div class="mx-auto flex min-h-screen w-full max-w-3xl flex-col gap-4 p-4">
|
|
126
126
|
<h1 class="m-0 text-2xl font-semibold">Hello Bardioc App</h1>
|
|
127
127
|
<p class="text-muted-foreground m-0 max-w-2xl text-xs leading-5">
|
|
128
|
-
Open this app inside Bardioc
|
|
128
|
+
Open this app inside Bardioc to use transport requests and send host notifications.
|
|
129
129
|
</p>
|
|
130
130
|
<div class="border-border bg-muted/20 rounded-xl border p-3 text-xs leading-5">
|
|
131
131
|
Outside the host iframe this page is only a local preview shell.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { connect } from '@bardioc/app-sdk';
|
|
2
|
+
import { installDevHost, isDevStandalone, isInsideIframe } from '@bardioc/app-sdk/dev';
|
|
3
3
|
import { mount } from 'svelte';
|
|
4
4
|
import App from './App.svelte';
|
|
5
5
|
import './index.css';
|
|
@@ -15,12 +15,12 @@ const devStandalone = isDevStandalone();
|
|
|
15
15
|
const useSdkProvider = insideIframe || devStandalone;
|
|
16
16
|
|
|
17
17
|
if (devStandalone) {
|
|
18
|
-
|
|
18
|
+
installDevHost({ appId: APP_NAME });
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
const
|
|
21
|
+
const bardioc = useSdkProvider ? await connect() : null;
|
|
22
22
|
|
|
23
23
|
mount(App, {
|
|
24
24
|
target: document.getElementById('app')!,
|
|
25
|
-
props: {
|
|
25
|
+
props: { bardioc },
|
|
26
26
|
});
|
|
@@ -3,9 +3,12 @@ import { svelte } from '@sveltejs/vite-plugin-svelte';
|
|
|
3
3
|
import tailwindcss from '@tailwindcss/vite';
|
|
4
4
|
import { defineConfig, loadEnv } from 'vite';
|
|
5
5
|
|
|
6
|
+
const DEFAULT_PORT = {{PORT}};
|
|
7
|
+
|
|
6
8
|
export default defineConfig(({ mode }) => {
|
|
7
9
|
const env = loadEnv(mode, __dirname, '');
|
|
8
10
|
const appName = env.VITE_APP_NAME?.trim();
|
|
11
|
+
const port = Number(env.LOCALHOST_PORT) || DEFAULT_PORT;
|
|
9
12
|
|
|
10
13
|
if (!appName) {
|
|
11
14
|
throw new Error('Missing VITE_APP_NAME for Vite config');
|
|
@@ -15,7 +18,7 @@ export default defineConfig(({ mode }) => {
|
|
|
15
18
|
plugins: [
|
|
16
19
|
bardiocDevAuth({ appName }),
|
|
17
20
|
svelte(),
|
|
18
|
-
bardiocApp({ appName, port
|
|
21
|
+
bardiocApp({ appName, port }),
|
|
19
22
|
tailwindcss(),
|
|
20
23
|
],
|
|
21
24
|
};
|
|
@@ -7,3 +7,6 @@ DEV_SECRET=
|
|
|
7
7
|
|
|
8
8
|
# Base URL of the Bardioc BFF / backend-for-frontend (e.g. https://your-host).
|
|
9
9
|
API_BASE_URL=
|
|
10
|
+
|
|
11
|
+
# By default, the app will start on port {{PORT}}. Feel free to uncomment the following variable and change it to match your local setup preferences.
|
|
12
|
+
#LOCALHOST_PORT={{PORT}}
|
package/templates/vite/CLAUDE.md
CHANGED
|
@@ -35,9 +35,9 @@ src/
|
|
|
35
35
|
auth/
|
|
36
36
|
onboarding.tsx # Empty full-page screen with the DEV_SECRET dev-auth steps
|
|
37
37
|
shell/
|
|
38
|
-
app-shell.tsx # Sidebar + view routing + Toaster + OS top-menu
|
|
38
|
+
app-shell.tsx # Sidebar + Page + view routing + Toaster + OS top-menu (useCommandMenu)
|
|
39
39
|
about-dialog.tsx # "About" Dialog — reads public/app-manifest.json at runtime (manifest example)
|
|
40
|
-
header.tsx # location combobox + language switcher + sync
|
|
40
|
+
header.tsx # Page actions: location combobox + language switcher + sync
|
|
41
41
|
climate/
|
|
42
42
|
types.ts # Station/ClimateState + METRICS config (icon, unit, color)
|
|
43
43
|
climate-data.ts # demo-data generator (replace with your real source)
|
|
@@ -87,9 +87,10 @@ live SDK data comes only when the app is opened inside the host, or when `DEV_SE
|
|
|
87
87
|
|
|
88
88
|
## UI — `@bardioc/ui`
|
|
89
89
|
|
|
90
|
-
Tailwind v4 + the Bardioc design system. **
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
Tailwind v4 + the Bardioc design system. **Before writing any UI, read
|
|
91
|
+
`node_modules/@bardioc/ui/docs/INDEX.md`** — component choice, design tokens, layout and spacing
|
|
92
|
+
patterns, and copy rules ship with the installed package, so they match its version. Theme is wired
|
|
93
|
+
in `src/index.css`:
|
|
93
94
|
|
|
94
95
|
```css
|
|
95
96
|
@import 'tailwindcss';
|
|
@@ -113,6 +114,7 @@ import {
|
|
|
113
114
|
Empty,
|
|
114
115
|
FilterDropdown,
|
|
115
116
|
Kbd,
|
|
117
|
+
Page,
|
|
116
118
|
SidebarBasic,
|
|
117
119
|
SidebarContainedProvider,
|
|
118
120
|
SortableColumnHeader,
|
|
@@ -126,10 +128,33 @@ import type { ChartConfig } from '@bardioc/ui/shadcn/chart';
|
|
|
126
128
|
import type { TReactTable } from '@bardioc/ui/types'; // TReactTable.ColumnDef<Row>
|
|
127
129
|
```
|
|
128
130
|
|
|
129
|
-
|
|
130
|
-
sidebar uses `SidebarBasic` inside a `SidebarContainedProvider` (the contained variant for
|
|
131
|
+
The sidebar uses `SidebarBasic` inside a `SidebarContainedProvider` (the contained variant for
|
|
131
132
|
OS windows); the language switcher is `ConnectedLanguageSwitcher useI18n={useI18n}`.
|
|
132
133
|
|
|
134
|
+
### Layout — the container contract
|
|
135
|
+
|
|
136
|
+
The app root opens `@container/app`; `Page` opens its own `@container/page` inside it. Keep both:
|
|
137
|
+
sizing that should follow the whole app reads `@container/app`, and anything inside the page column
|
|
138
|
+
— the page header included — reads `@container/page`, so it responds to the column rather than the
|
|
139
|
+
window.
|
|
140
|
+
|
|
141
|
+
`Page` is the scrolling column, a **sibling of the sidebar** — it owns the header, the scroller and
|
|
142
|
+
the padding that lines them up. Don't compose a header and a `ScrollArea` by hand, and don't wrap
|
|
143
|
+
the sidebar in it:
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
<div className="bg-background text-foreground @container/app flex h-full min-h-0">
|
|
147
|
+
<SidebarBasic … />
|
|
148
|
+
<Page title={pageTitle} actions={<Header />} actionsClassName="gap-2" sticky className="min-w-0">
|
|
149
|
+
<ViewContent view={view} />
|
|
150
|
+
</Page>
|
|
151
|
+
</div>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Collapse your own `actions` against the same container (e.g. `@3xl/page:hidden`) so both sides agree
|
|
155
|
+
on what "wide enough" means. `sticky` keeps the header at the top while the body scrolls under it,
|
|
156
|
+
compacting once it does; drop it if you want the header to scroll away instead.
|
|
157
|
+
|
|
133
158
|
---
|
|
134
159
|
|
|
135
160
|
## i18n — `@bardioc/i18n-core`
|
|
@@ -150,6 +175,8 @@ t('overview.updated', { fallback: 'Updated {time}', params: { time } });
|
|
|
150
175
|
- Always pass a `fallback` so a missing key degrades gracefully.
|
|
151
176
|
- `@bardioc/ui` component strings ship with the `@bardioc/ui` package itself — the app only
|
|
152
177
|
carries its own `en/de.json`.
|
|
178
|
+
- Copy style (Title Case labels, sentence-case messages, American English):
|
|
179
|
+
`node_modules/@bardioc/ui/docs/copy.md`.
|
|
153
180
|
|
|
154
181
|
---
|
|
155
182
|
|
|
@@ -18,15 +18,15 @@
|
|
|
18
18
|
"release:publish": "changeset publish"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@bardioc/app-sdk": "^0.
|
|
21
|
+
"@bardioc/app-sdk": "^1.0.0",
|
|
22
22
|
"@bardioc/i18n-core": "^0.1.1",
|
|
23
|
-
"@bardioc/ui": "^0.
|
|
23
|
+
"@bardioc/ui": "^0.7.29",
|
|
24
24
|
"lucide-react": "^0.544.0",
|
|
25
25
|
"react": "19.2.6",
|
|
26
26
|
"react-dom": "19.2.6"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@bardioc/configs": "
|
|
29
|
+
"@bardioc/configs": "0.2.1",
|
|
30
30
|
"@changesets/cli": "^2.31.0",
|
|
31
31
|
"@tailwindcss/vite": "^4.3.0",
|
|
32
32
|
"@types/node": "^22.19.19",
|