Build a Drel App
A Drel app is not a proprietary format: standard browsers must always be able to load it. Start with the smallest level that solves your problem and add the next one only when you need it.
npx skills add dyyz1993/Drel --skill drel-app-development
Your app and the push service are independent
Your app is a web page. It deploys to any static host (Cloudflare Pages, Vercel, Netlify, Nginx) and needs no push backend of its own. A push service only delivers a wake-up — a URL or an appId + route — and is never required for the app to work.
Level 1 — An ordinary web page
Zero barrier to entry. Open the URL in Drel, tap a push notification that opens it, or save it as a favorite tile. Two simple adaptations make it feel native:
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
body {
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
}
Support prefers-color-scheme for automatic dark mode, and read query parameters straight from window.location.search.
Level 2 — An app in the App Center
Add a standard Web App Manifest for a custom name, an icon and a standalone launch experience, then have an operator gateway sign a parent manifest.
{
"schemaVersion": "1",
"appId": "com.example.orders",
"name": "Order Assistant",
"startURL": "https://app.example.com/app/index.html",
"allowedOrigins": ["https://app.example.com"],
"capabilities": [],
"routes": ["/app/index.html", "/app/orders/*"],
"cache": { "strategy": "networkOnly", "version": "1", "persistent": false }
}
The routes array decides where a push can land. A push carrying appId and route opens that exact screen.
curl https://api.drel.app/push -H 'content-type: application/json' -d '{
"deviceKey": "YOUR_KEY",
"title": "New order",
"appId": "com.example.orders",
"route": "/app/orders/1024"
}'
How a manifest becomes trusted
A manifest is not trusted because it says so. It is trusted because it verifies against a public key the user confirmed.
Which fields are standard, and which are Drel's
Two different objects are involved, and mixing them up is the most common mistake.
| Object | Standard? | Who signs it | Purpose |
|---|---|---|---|
manifest.webmanifest |
W3C standard | Nobody — you publish it | Name, icons, start URL, scope, display mode. Any browser and PWA host can read it. |
| Parent gateway manifest | Drel | The gateway, with Ed25519 | App identity, allowed origins, routes, native action declarations, offline binding. |
Standard Web App Manifest fields you can rely on
idW3C
name, short_nameW3C
name is absent, Drel falls back to the page title or a user-chosen label.iconsW3C
start_urlW3C
scopeW3C
displayW3C
standalone. It is a hint, not a command — Drel keeps its back, exit, and security controls.theme_color, background_colorW3C
shortcuts, screenshots, orientationW3C
Fields Drel adds
appIdDrel
allowedOriginsDrel
scheme://host:port — never as a wildcard domain.routesDrel
capabilities_v2Drel
cacheDrel
networkOnly or manifest, plus the version, persistence, and resource manifest binding.webManifestDrel
signatureDrel
One Drel-only extension inside the standard manifest
drel_offlineDrel
Because the block is prefixed and handled separately, the same file still works as an ordinary PWA manifest in any other browser or host.
Level 3 — Strong offline package
A Web App Manifest alone does not make an app durable offline. Reliable offline launch requires a verified package and a user-initiated install.
Publish three files:
| File | Role |
|---|---|
package.json | Resource manifest: every file with its path, size, SHA-256 and MIME type. |
manifest.webmanifest | Standard manifest plus a drel_offline block pointing at the resource manifest and its digest. |
| Signed parent manifest | The POST /api/v1/html-apps body that the gateway signs with Ed25519. |
Include every static asset — a missing chunk means a white screen offline. Keep API calls on the network, and label cached data honestly instead of faking it as live.
Hard limits: resource manifest ≤1MiB, ≤2000 files, ≤50MiB per file, ≤250MiB total.
Level 4 — Native actions
Declare each action in the signed manifest and call it behind a fallback. Read the Bridge API reference for the complete contract.
Ship checklist
- Works in a plain browser without the Bridge.
- Safe-area insets are respected and dark mode is readable.
start_urlandscopecarry no query string.- Every static asset is in the package with a valid hash.
- Offline shows an honest fallback, not fake live data.
- A push with
appId + routelands on the intended screen. - No secret appears in
start_url, a screenshot, or a log.
Live examples
Every level has a running fixture: strong offline, offline plus live data, declared actions and the reusable template.