Solel//dev docs

The app frame

Your app's front end runs in a frame inside a window the desktop draws. Knowing what the desktop does for you, and what the frame allows, saves you building it twice.

What the desktop draws

  • The window. The title bar, your app's icon, the window controls, moving, resizing and snapping are the desktop's. Don't draw a title bar or a window of your own.
  • The title is your manifest's name, or what you set with solel.setTitle(), up to 80 characters.
  • The size. People can make a window as small as 360 by 240 pixels, or maximise it on a 4K display. Lay out by the window's own width, with container queries.
  • The ground. Your page fills the window edge to edge. Give it a solid --bg, not glass.
  • A window behind takes its first click to come forward, so that click doesn't reach your page.

On a phone

When the person is on a phone, and your manifest's layouts includes phone, your app opens full screen under an app bar with a back button, and the frame stops above the bottom bar. solel.ready() says which layout is in use, and the layout event says when it changes. An app without phone in its layouts doesn't show on a phone.

Where the page loads from

  • A front end on its own https address loads straight from there, and keeps its own origin.
  • A front end your back end serves loads from /.solel/app/<frame token>/ on Solel's own address, which the core passes to your back end. The token names the app and the person, and lasts 24 hours. solel.ready() gives the path to show.

For a page your back end serves, the frame's address carries the token, so link to your own pages and call your back end with relative addresses, like fetch('api/notes'), and build with a relative base, such as Vite's base: './'. Redirects to a path, like /notes/1, stay inside the frame.

What the page may do

The frame is sandboxed. Your page can run scripts, send forms, open new tabs, download files, show dialogs, write to the clipboard and go full screen.

A page your back end serves runs with an origin of its own, so it can't reach the desktop, its storage or the sign-in. It has no cookies or local storage either: keep what your app needs in its back end. Code that tries them anyway should catch the error.

let saved: string | null = null;
try {
  saved = localStorage.getItem('draft');
} catch {
  // No storage in the frame: ask the back end instead.
}
  • Shortcuts. Keys pressed in your page never reach the desktop, so passes on Ctrl Alt shortcuts, such as Ctrl Alt W to close the window. AltGr is left alone.
  • Opening at a path. A notification's link, solel.openApp(), or a link to your server with ?open=app/<id>/<path>, opens your app at that path. ready() gives it when the app opens, and the open event when it's already running.

How the page and the desktop talk is in How it works.