Anthirayas25 downloadsHost live HTML, CSS and JavaScript apps from your vault in a sandbox, with a validated bridge to your notes.
Run small apps made of plain HTML, CSS and JavaScript that live in your vault. Each app runs in a sandbox with no network access, and reaches your notes only through a bridge that checks every request.
Other plugins show an HTML file. This one lets an HTML app work with your notes (read them, list them, edit front matter, react to changes) while you stay in control of exactly what it may touch.
From the community list (once accepted): Settings, Community plugins, Browse, search for "HTML Playground", install and enable.
Manually: download main.js, manifest.json and styles.css from the latest release into <vault>/.obsidian/plugins/html-playground/, then enable the plugin.
With BRAT: add jrayas/obsidian-html-playground.
Turn on Settings, Files and links, Automatically update internal links. Apps that move or rename notes rely on it. If it is off, moving a note that other notes link to is refused, so links cannot silently break.
examples/hello-app into your vault as Apps/Hello (the default apps folder is Apps).```html-playground
Apps/Hello
height: 300
greeting: Hello from my note
```
The first line is the app folder. Extra name: value lines are parameters the app can read. A line above the block such as App: Hello is a plain-text fallback for when the plugin is off.
| Command | What it does |
|---|---|
| Open app | Choose an app (any folder under your apps folder with a manifest.json) and open it in a tab |
| Reload current app | Reload the active app |
| Open app in the active note's folder | Open the app next to the current note |
| Show snapshots | Browse and restore the copies kept before apps changed notes |
| Open bridge log | See every write apps made, and every one they tried and were refused |
An app is a folder with an index.html, any CSS, JavaScript, images and fonts it needs (bundled locally), and a manifest.json:
{
"name": "Calculator",
"version": "1.0.0",
"entry": "index.html",
"permissions": ["files.read", "frontmatter.read", "files.edit"],
"readScopes": ["Notes", "Data"],
"writeScopes": ["Notes/Calculations"]
}
permissions: exact operation names. Anything not listed returns DENIED.readScopes: folders the app may read (omit for the whole vault, minus your exclusions). Its own folder is always readable.writeScopes: folders the app may write. Required for any write unless you approve the app as trusted.In the app:
await bridge.ready;
const { content } = await bridge.call("files.read", { path: "Notes/Pump sizing.md" });
await bridge.call("frontmatter.update", { path: "Notes/Pump sizing.md", set: { reviewed: true } });
bridge.on("theme", (t) => { /* t.mode is "light" or "dark" */ });
Use the theme variables (var(--background-primary), var(--text-normal), var(--interactive-accent) and so on) so the app follows light, dark and community themes. Keep apps light and touch-friendly: the plugin works on mobile.
Reference: bridge API, path rule, safeguards.
| Setting | Meaning |
|---|---|
| Apps folder | Where Open app looks for manifest.json files |
| Strict paths | Turns off the ./ shortcut for an app's own files |
| Excluded paths | What apps can never see. Built-in defaults (.obsidian, .git, .trash, any hidden folder or file, and your vault's configuration folder even if you renamed it) cannot be removed. Add your own folders, files or patterns |
| Allowed network domains | Global allow-list. A domain must also be in the app's manifest. Empty by default |
| Asset mode | Auto, blob URLs or inline data |
| Snapshots per file, size cap, age limit | How much is kept (defaults 20, 50 MB, 30 days) |
| Write log entries | How many writes the log remembers (default 5,000) |
| Trusted apps | Apps you approved as trusted on this device, with Revoke |
Exclusions hide things from apps only. They do not hide anything in Obsidian itself. An excluded path looks exactly like a missing one to an app.
sandbox="allow-scripts" only (never same-origin) under a Content Security Policy that blocks all network access by default.manifest.json, so it cannot rewrite itself.Details: security.md.
gh attestation verify main.js --repo jrayas/obsidian-html-playground.Works on desktop and mobile (isDesktopOnly is false). Tested on macOS desktop and an Android emulator. Needs Obsidian 1.13.4 or later.
npm ci
npm run build # typecheck, then bundle to main.js
npm test
npm run lint # the same checks Obsidian's community plugin scanner runs
Copy or symlink the folder to <vault>/.obsidian/plugins/html-playground/ to try a build.