create-bridgething 0.11.0 → 0.12.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.
@@ -1,40 +1,24 @@
1
-
2
1
  ## This project is a launcher
3
2
 
4
- `manifest.json` declares `"role": "launcher"`, which means two things:
5
-
6
- - The daemon hides this bundle from `client.webapp.list`, so a launcher never
7
- lists itself in its own grid.
8
- - The bundle is eligible for the device's **launcher slot**. Holding that slot
9
- makes this the home screen: the boot default, the target of the Mode-button
10
- gesture, and what the back button returns to.
3
+ `manifest.json` declares `"role": "launcher"`. The daemon keeps this bundle out
4
+ of `client.webapp.list`, so the grid you draw excludes itself. Holding the
5
+ device's launcher slot makes it the home screen: the boot default, the target of
6
+ the Mode gesture, and where the Back button returns to.
11
7
 
12
- `bun run push` claims the slot and switches to it, so a push puts you straight
13
- on the home screen. `bun run push --release` hands it back, and the companion
14
- phone app can do the same. The built-in hub stays installed and can never be
15
- uninstalled, so releasing the slot always gets the stock home screen back. That
16
- is the recovery path if a launcher you are building wedges the device.
8
+ `bun run push` claims the slot and switches to it. `bun run push --release` hands
9
+ it back to the built-in hub, the recovery path when a build wedges the device.
17
10
 
18
- ### What a home screen is expected to do
11
+ ### What a home screen covers
19
12
 
20
- Nothing is enforced. The daemon does not require a launcher to implement any
21
- particular surface; if yours does less than the built-in hub, that is a choice,
22
- not an error, and the user can switch back. The built-in hub covers:
13
+ A launcher implements as much or as little as you want. The built-in hub covers:
23
14
 
24
- - the app grid (`client.webapp.list` / `.icon` / `.activate` / `.current`, plus
25
- the `onWebappInstalled` / `onWebappUninstalled` events so the grid stays live)
26
- - bluetooth settings: bonds, adapter alias, discoverable
15
+ - the app grid (`client.webapp.list`, `.icon`, `.activate`, `.current`, plus
16
+ `onWebappInstalled` and `onWebappUninstalled`)
17
+ - bluetooth bonds, adapter alias, discoverable
27
18
  - display brightness
28
19
  - system info and health
29
20
  - power: restart, shut down, factory reset
30
- - OTA progress (`client.system.onOtaProgress` / `.onOtaError`)
31
-
32
- The starter here implements only the grid. Read the built-in hub's source if you
33
- want a reference for the rest; everything it uses is on the public client SDK.
34
-
35
- ### Onboarding is not your problem
21
+ - OTA progress (`client.system.onOtaProgress` and `.onOtaError`)
36
22
 
37
- The first-boot pairing wizard lives in the built-in hub. A phone must already be
38
- paired before anyone can install your launcher, so by the time this runs, the
39
- device is set up. A factory reset clears the launcher slot along with everything
40
- else, which puts the built-in hub and its wizard back.
23
+ The starter here draws the grid. Everything the hub uses is on the public client
24
+ SDK.
@@ -1,9 +1,6 @@
1
1
  import { BridgethingClient, type WebappInfo } from '@bridgething/client';
2
2
  import { useEffect, useMemo, useState } from 'react';
3
-
4
- const wsUrl =
5
- import.meta.env.VITE_BRIDGETHING_URL ??
6
- (typeof window !== 'undefined' ? `ws://${window.location.host}/` : 'ws://127.0.0.1:8891/');
3
+ import { daemonUrl } from './daemon';
7
4
 
8
5
  type Entry = {
9
6
  info: WebappInfo;
@@ -11,7 +8,7 @@ type Entry = {
11
8
  };
12
9
 
13
10
  export default function App() {
14
- const client = useMemo(() => new BridgethingClient({ url: wsUrl }), []);
11
+ const client = useMemo(() => new BridgethingClient({ url: daemonUrl() }), []);
15
12
  const [entries, setEntries] = useState<Entry[] | null>(null);
16
13
  const [error, setError] = useState<string | null>(null);
17
14
  const [activating, setActivating] = useState<string | null>(null);
@@ -1,19 +1,13 @@
1
-
2
1
  ## This project is a system overlay
3
2
 
4
- `manifest.json` declares `"overlay": "overlay.js"`. When this bundle holds the
5
- device's **overlay slot**, the daemon injects that file into every webapp's
6
- document as it loads. The page in `src/` is incidental: it only renders if
7
- someone launches this bundle from the hub.
8
-
9
- `bun run push` claims the slot for you and reloads the kiosk, so the overlay
10
- appears over whatever app is showing. It deliberately does **not** switch to
11
- this bundle's own page - switching away from the app you are testing against is
12
- the opposite of what you want.
3
+ `manifest.json` declares `"overlay": "overlay.js"`. While this bundle holds the
4
+ device's overlay slot, the daemon injects that file into every webapp's document
5
+ as it loads. The page in `src/` renders when someone launches this bundle from
6
+ the hub.
13
7
 
14
- `bun run push --release` hands the slot back to the daemon's built-in overlay.
15
- That is the recovery path when a build of yours misbehaves; the companion phone
16
- app can do the same thing.
8
+ `bun run push` claims the overlay slot and reloads the kiosk, so the overlay
9
+ appears over the webapp that is showing. `bun run push --release` hands the slot
10
+ back to the built-in overlay, the recovery path when a build misbehaves.
17
11
 
18
12
  ### The contract
19
13
 
@@ -23,42 +17,34 @@ The daemon prepends one global before your bundle:
23
17
  window.__bridgethingOverlay = { origin: 'http://127.0.0.1:8891', surfaces: {...} };
24
18
  ```
25
19
 
26
- - **`surfaces`** is the active webapp's declared profile: `notifications`,
27
- `call`, `pairing`, `connection`, `volume`. An app that draws its own volume
28
- indicator declares `volume: false`. **Honor these.** The daemon cannot enforce
29
- it, and ignoring them means the user sees two of everything on apps that draw
30
- their own. If every surface is off, the daemon injects nothing at all.
31
- - **`origin`** is the kiosk origin. Check `location.origin` against it before
32
- mounting so the bundle never runs in a page the daemon did not serve.
20
+ `surfaces` is the active webapp's declared profile, a boolean each for
21
+ `notifications`, `call`, `pairing`, `connection`, `volume`, and `voice`. Render
22
+ only the surfaces set to true; an app that draws its own volume indicator
23
+ declares `volume: false`. When every surface is false the daemon injects nothing.
33
24
 
34
- Everything else comes from `@bridgething/client` over the local websocket, the
35
- same SDK a normal webapp uses.
25
+ `origin` is the kiosk origin. Compare `location.origin` against it before
26
+ mounting. Everything else comes from `@bridgething/client` over the local
27
+ websocket.
36
28
 
37
- ### Constraints that are not style
29
+ ### Output constraints
38
30
 
39
- `overlay.js` must be **one self-contained file** under 512 KiB. It is injected as
40
- a script string into another app's document, so it cannot import a module graph,
41
- fetch assets, or reach a bundler at runtime. `vite.overlay.config.ts` builds it
42
- as a single inlined iife; keep it that way.
31
+ `overlay.js` must be one self-contained file under 512 KiB. The daemon injects it
32
+ as a script string into another app's document, so it carries its own code and
33
+ styles and reaches nothing at runtime. `vite.overlay.config.ts` builds a single
34
+ inlined iife; keep that shape.
43
35
 
44
- That is a constraint on the *output*, not on how you write it. Style
45
- `overlay/main.tsx` with tailwind classes exactly like the rest of the project.
46
- `overlay/style.css` is a real stylesheet; it is imported with vite's `?inline`
47
- so the compiled css lands in the bundle as a string and gets mounted into the
48
- shadow root. Add `@theme` tokens or plain rules there. Because the shadow root
49
- is closed, tailwind is told not to scan the project (`source(none)`) and only
50
- generates what `overlay/main.tsx` uses - if you split the overlay across more
51
- files, add each one with `@source`.
36
+ Style `overlay/main.tsx` with tailwind classes like the rest of the project.
37
+ `overlay/style.css` is imported with vite's `?inline`, so the compiled css mounts
38
+ into the shadow root as a string. Tailwind scans only `overlay/main.tsx`
39
+ (`source(none)`), so add an `@source` line for every file you split across.
52
40
 
53
- The starter encodes four things you should not drop:
41
+ ### Keep these four from the starter
54
42
 
55
- 1. **Origin guard** before mounting.
56
- 2. **`__bridgethingOverlayMounted`** guard, so a double injection is a no-op.
57
- 3. **Closed shadow root**, so your styles and the host app's cannot reach each
58
- other.
59
- 4. **Escape-only, capture-phase key handling**, and only while something is
60
- showing. Your overlay sits on top of every app on the device; swallowing keys
61
- broadly breaks all of them.
43
+ 1. The origin guard before mounting.
44
+ 2. The `__bridgethingOverlayMounted` guard, so a second injection is a no-op.
45
+ 3. The closed shadow root, which keeps your styles and the host app's apart.
46
+ 4. Escape-only key handling on the capture phase, active only while something is
47
+ showing.
62
48
 
63
- You are running inside someone else's page. A crash, a fullscreen paint, or a
64
- greedy key handler takes down every webapp, not just this one.
49
+ You run inside every webapp's page. A crash, a fullscreen paint, or a broad key
50
+ handler takes down all of them.