App Template (Served Mockups) — Delivery Notes
Delivery summary for turning the business-theme mockups into a standalone, served app template. For the decision record read ADR-0016. This note says what changed and how it was proven.
Status
Implemented; static verification complete, in-app opener verified manually.
| Piece | State |
|---|---|
New repo tranquil-app-template (git init, app/, automations/) | ✅ done |
Move main-view.html + properties.html + mockup.css + fonts/ into app/ | ✅ done |
deno.json — deno task dev serves app/ via npm:browser-sync (no package.json) | ✅ done |
automations/open-app.js — opens both URLs into center + right dock, sets data-theme once | ✅ done + manually verified |
Remove mockup machinery from tranquil-automations (mockups/, lib/mockups.js, lib/mockup-controls.js, config, auto-open, isMockupUrl) | ✅ done |
Add tranquil-app-template to tranquil-dev.code-workspace | ✅ done |
| ADR-0016 | ✅ written |
| Dev server serve + inject + watch, verified | ✅ passed |
Business Themes & Mockups doc update to the served model | ⬜ follow-up |
What & why
The two pages were file:// fixtures inside tranquil-automations (mockups/),
auto-opened at startup and shipped in every automations release. They’re really the seed
for building Tranquil apps, so they moved to their own repo where they’re developed and
served on their own. See ADR-0016 for the
decision and options.
The new repo
tranquil-app-template/
deno.json # deno task dev → npm:browser-sync serving app/ on :3000
deno.lock # the only committed lockfile (no package.json)
.gitignore # .DS_Store, node_modules/
README.md
app/ # served web root
main-view.html # → center pane
properties.html # → right dock
mockup.css
fonts/ # Inter + IBM Plex Mono woff2
automations/
open-app.js # tranquil-automations script; opens both panes Serving. One task, no Node toolchain:
{
"tasks": {
"dev": "deno run -A npm:browser-sync@^3.0.0 start --server app --port 3000 --files "app/**/*" --no-open --no-notify"
}
} Opening. open-app.js runs in Tranquil’s renderer sandbox (the atom global is
injected by runScript in tranquil-automations/lib/tranquil-automations.js), so it needs
no puppeteer / remote-debugging port — it just calls atom.workspace.open with the same location/allowedLocations/defaultLocation/hideURLBar opts the old host loader used,
then sets data-theme once from the active UI theme.
Removal from tranquil-automations
All coupling was in lib/. Deleted mockups/, lib/mockups.js, lib/mockup-controls.js;
then surgically stripped tranquil-automations.js (both requires, the showBusinessMockups config, mockupControls.activate(), and the addTrustedRoot/watchTheme/openMockups block) and pane-controls-capability.js (the isMockupUrl import + its predicate clause).
The one non-obvious trap.
pane-controls-capability.jsimportedisMockupUrlfrom the deletedmockups.js. Deleting the files without also removing thatrequireleaves aMODULE_NOT_FOUNDat module load, which crashes activation and silently drops all automations commands. The import and its!isMockupUrl(urlOf(item)) &&clause had to be removed together. With the clause gone,registerDefaultRemoteControlsmatches “has a webview and is not trusted” — which now also gives the servedhttp://localhost:3000pages their default URL-bar toggle for free.
Verified grep shows zero dangling references, and all edited files parse under babel.
browser-sync under Deno — the two gotchas
The
hoistednode-modules linker needsnodeModulesDir: "manual", which in turn needs apackage.json+deno install. First attempt set"nodeModulesLinker": "hoisted"and Deno refused to start:error: The hoisted node_modules linker requires --node-modules-dir=manual.Since this repo is deliberately
package.json-free, the fix is to omit both keys and let Deno run browser-sync straight from its global npm cache. (The www-tranquil hoisted+manual setup only applies when you keep apackage.json, as SvelteKit does.)browser-sync only injects its live-reload
<script>when the request’sAcceptheader includestext/html. A barecurlreturns the un-injected page even though/browser-sync/browser-sync-client.jsserves200— this looked like a broken injection but isn’t: real browsers and Tranquil webviews always sendAccept: text/html. Confirm withcurl -H 'Accept: text/html'(content-length grows).
A benign Ignored build scripts for packages: npm:fsevents warning prints on startup;
chokidar falls back and file-watching still works.
How it was verified
Dev server (headless). Started deno task dev and probed with curl:
| request | result |
|---|---|
main-view.html / properties.html / mockup.css / both fonts | 200, exact byte sizes |
main-view.html with Accept: text/html | reload snippet injected (15826 → 16373 bytes) |
touch app/mockup.css | server logs File event [change] : app/mockup.css |
Opener (in-app, manual). First run threw “The WebView must be attached to the DOM and
the dom-ready event emitted before this method can be called.” — the immediate executeJavaScript fired before the webview was dom-ready. Fixed by guarding the immediate apply() in a try/catch (the same swallow-and-retry the old mockups.js used) and
letting the did-stop-loading listener re-apply. After the fix the user confirmed both
panes open and theme correctly. This matches the known webview timing behaviour from the RPC
work.
Follow-up
- Update the Business Themes & Mockups doc: it still
describes the pages as tranquil-automations
file://fixtures. Repoint it at the servedtranquil-app-templatemodel.