mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
Make the web app installable (#1144)
* feat(app): make web app installable * fix: restore CI for import and shortcut tests
This commit is contained in:
@@ -187,6 +187,20 @@ Point Playwright MCP at the running Expo web target. Under `npm run dev` (macOS/
|
||||
|
||||
Do NOT use browser history (back/forward). Always navigate by clicking UI elements or using `browser_navigate` with the full URL — the app uses client-side routing and browser history breaks state.
|
||||
|
||||
## App web deploys
|
||||
|
||||
`packages/app` exports a single-page Expo web app and deploys the `dist/`
|
||||
directory to Cloudflare Pages with `npm run deploy:web --workspace=@getpaseo/app`.
|
||||
|
||||
PWA install metadata lives in `packages/app/public/manifest.json` and is linked
|
||||
from `packages/app/public/index.html`. Keep the install icons in `public/` so
|
||||
Cloudflare serves them from stable root URLs after `expo export`.
|
||||
|
||||
Do not add service-worker caching casually. Paseo is a live control surface for
|
||||
agents, and an aggressive service worker can strand installed users on stale web
|
||||
code. If offline behavior becomes a product requirement, add it deliberately
|
||||
with an update strategy and test the installed-app upgrade path.
|
||||
|
||||
## Expo troubleshooting
|
||||
|
||||
```bash
|
||||
|
||||
BIN
packages/app/public/apple-touch-icon.png
Normal file
BIN
packages/app/public/apple-touch-icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.2 KiB |
@@ -4,10 +4,16 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="robots" content="noindex,nofollow" />
|
||||
<meta name="theme-color" content="#181B1A" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-title" content="Paseo" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover"
|
||||
/>
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
||||
<title>%WEB_TITLE%</title>
|
||||
<!-- The `react-native-web` recommended style reset: https://necolas.github.io/react-native-web/docs/setup/#root-element -->
|
||||
<style id="expo-reset">
|
||||
|
||||
27
packages/app/public/manifest.json
Normal file
27
packages/app/public/manifest.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"id": "/",
|
||||
"name": "Paseo",
|
||||
"short_name": "Paseo",
|
||||
"description": "Monitor and control local AI coding agents from anywhere.",
|
||||
"start_url": "/",
|
||||
"scope": "/",
|
||||
"display": "standalone",
|
||||
"orientation": "portrait",
|
||||
"theme_color": "#181B1A",
|
||||
"background_color": "#181B1A",
|
||||
"categories": ["developer", "productivity", "utilities"],
|
||||
"icons": [
|
||||
{
|
||||
"src": "/pwa-icon-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"src": "/pwa-icon-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
packages/app/public/pwa-icon-192.png
Normal file
BIN
packages/app/public/pwa-icon-192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.0 KiB |
BIN
packages/app/public/pwa-icon-512.png
Normal file
BIN
packages/app/public/pwa-icon-512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
@@ -1,4 +1,4 @@
|
||||
import { useMemo, type ReactElement } from "react";
|
||||
import React, { useMemo, type ReactElement } from "react";
|
||||
import { Text, View, type StyleProp, type TextStyle, type ViewStyle } from "react-native";
|
||||
import { StyleSheet } from "react-native-unistyles";
|
||||
import { formatShortcut, type ShortcutKey } from "@/utils/format-shortcut";
|
||||
|
||||
@@ -128,6 +128,7 @@ test("listImportableProviderSessions filters, sorts, limits, and projects import
|
||||
cwd,
|
||||
title: "Already stored",
|
||||
lastActivityAt: "2026-04-30T12:04:00.000Z",
|
||||
firstPrompt: "stored prompt",
|
||||
}),
|
||||
makeDescriptor({
|
||||
sessionId: "older-session",
|
||||
@@ -167,6 +168,7 @@ test("listImportableProviderSessions filters, sorts, limits, and projects import
|
||||
cwd,
|
||||
title: "Already live",
|
||||
lastActivityAt: "2026-04-30T12:01:00.000Z",
|
||||
firstPrompt: "live prompt",
|
||||
}),
|
||||
];
|
||||
const listImportablePersistedAgents = vi.fn(async () => descriptors);
|
||||
|
||||
@@ -1917,6 +1917,7 @@ test("fetch_recent_provider_sessions_request lists importable provider sessions
|
||||
cwd: "/tmp/recent",
|
||||
title: "Already stored",
|
||||
lastActivityAt: "2026-04-30T12:04:00.000Z",
|
||||
firstPrompt: "stored prompt",
|
||||
}),
|
||||
makePersistedProviderSession({
|
||||
provider: "claude",
|
||||
@@ -1967,6 +1968,7 @@ test("fetch_recent_provider_sessions_request lists importable provider sessions
|
||||
cwd: "/tmp/recent",
|
||||
title: "Already live",
|
||||
lastActivityAt: "2026-04-30T12:01:00.000Z",
|
||||
firstPrompt: "live prompt",
|
||||
}),
|
||||
];
|
||||
// The real AgentManager filters by providerFilter at the fan-out level
|
||||
@@ -2096,6 +2098,7 @@ test("fetch_recent_provider_sessions_request reports filteredAlreadyImportedCoun
|
||||
cwd: "/tmp/recent",
|
||||
title: "Already live",
|
||||
lastActivityAt: "2026-04-30T12:01:00.000Z",
|
||||
firstPrompt: "live prompt",
|
||||
}),
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user