Files and sandboxing
Most serious applications need two kinds of file access:
- bundled resources that ship with the app,
- mutable user data created at runtime.
Oro Runtime supports both, but you should treat the filesystem sandbox as a feature, not an obstacle.
1) Start with a dedicated app-data directory#
Create a directory for mutable data inside your working tree or chosen output location:
import * as fs from 'oro:fs/promises'
await fs.mkdir('./data', { recursive: true })
await fs.writeFile('./data/state.json', JSON.stringify({ notes: [] }, null, 2), 'utf8')
Use ordinary JSON for early iterations. Move to SQLite once the model is stable.
2) Read and write structured files#
import * as fs from 'oro:fs/promises'
async function loadState() {
try {
const text = await fs.readFile('./data/state.json', 'utf8')
return JSON.parse(text)
} catch {
return { notes: [] }
}
}
async function saveState(state) {
await fs.writeFile('./data/state.json', JSON.stringify(state, null, 2), 'utf8')
}
This is enough for preferences, cached drafts, import history, and lightweight app state.
3) Keep the sandbox enabled by default#
The sandbox exists to prevent accidental or unsafe file access:
[filesystem]
sandbox_enabled = true
no_follow_symlinks = true
Keep both on unless you have a concrete reason not to. They make your app’s file behavior easier to reason about.
4) Use native pickers for external files#
When users need to import or inspect files outside your app’s controlled data directory, use a picker:
import application from 'oro:application'
import * as fs from 'oro:fs/promises'
const currentWindow = await application.getCurrentWindow()
const [path] = await currentWindow.showOpenFilePicker({ multiple: false })
if (path) {
const text = await fs.readFile(path, 'utf8')
console.log(text)
}
That keeps explicit user intent in the loop.
5) Bundle only what the app needs#
Your bundle inputs should stay separate from mutable user data:
"./dist/index.html" = "index.html"
"./dist/main.js" = "main.js"
"./assets/icon.png" = "assets/icon.png"
Do not write back into the bundled resource tree at runtime. Treat it as read-only application content.
6) A practical rule of thumb#
- Bundle: HTML, CSS, JS, icons, offline shell assets.
- Runtime data: user notes, caches, imported files, session state.
- Secure storage: secrets such as refresh tokens or encryption keys.
Keeping those boundaries clean makes packaging, updates, and debugging simpler.
Next#
Source repository · Edit this page · View Markdown