Files
EZPPLauncher/THEME_API_V2.md
T
HorizonCode c02b26e8ae feat: polish theme tooling, diagnostics and launcher workflows
Expand the theme editor with multi-select, snapping, context menus, draft
recovery and export validation; add theme backups and trust prompts. Add
in-app diagnostics and rotating log bundle viewing, hardware-accelerated
theme video playback on macOS, and refresh the settings, setup wizard and
theme gallery layouts.
2026-10-29 15:41:33 +01:00

441 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# EZPPLauncher Theme API 2.0
API 2.0 is a declarative theme format. Instead of shipping a JavaScript bundle that
mounts its own UI, a theme describes its background, effects, audio, fonts and
freeform layers in `theme.json`. The launcher renders it, and the built-in advanced
editor can create and edit these themes without writing code.
API 1.0 themes continue to work unchanged. Pick the API that fits the theme:
| | API 1.0 | API 2.0 |
| ----------------------- | ------------------------------------------------- | ---------------------------------------------- |
| Rendering | Svelte bundle (`entry`) | Launcher-rendered |
| Files | `theme.json`, `bundle.js`, `style.css`, `assets/` | `theme.json`, `assets/` |
| Created with | `create-ezpplauncher-theme` | Launcher editor or `create-ezpplauncher-theme` |
| Scripts / arbitrary DOM | Yes | No (data only, optional CSS) |
| Cross-platform | Depends on the bundle | Yes |
---
## Package layout
A packaged `.ezpplauncher-theme` file is a zip with this structure:
```
theme.json
assets/
background.webm
layer.png
music.mp3
font.woff2
preview.png # optional thumbnail
```
An installed theme lives in:
```
# Windows
C:\Users\<user>\.ezpplauncher\themes\<folder>\
# macOS / Linux
~/.ezpplauncher/themes/<folder>/
```
---
## `theme.json`
```json
{
"name": "Midnight",
"version": "1.0.0",
"apiVersion": "2.0",
"author": "Your Name",
"description": "A dark gradient with drifting stars.",
"preview": "preview.png",
"background": {
"type": "gradient",
"from": "#181825",
"to": "#3b1d4f",
"angle": 135,
"opacity": 1
},
"overlay": {
"color": "#000000",
"opacity": 0.2,
"vignette": 0.35
},
"effects": {
"type": "stars",
"density": 40,
"speed": 1,
"color": "#ffd6f2"
},
"typography": {
"body": "Sora Variable",
"heading": "Bebas Neue"
},
"fonts": [
{
"family": "My Display Font",
"src": "display.woff2",
"weight": "400",
"style": "normal"
}
],
"elements": [
{
"id": "tagline",
"type": "text",
"text": "MIDNIGHT",
"x": 640,
"y": 84,
"width": 300,
"height": 72,
"fontFamily": "Bebas Neue",
"fontSize": 46,
"fontWeight": 400,
"color": "#ffffff",
"align": "right",
"verticalAlign": "center",
"letterSpacing": 2
}
],
"audio": {
"src": "music.mp3",
"loop": true
},
"accentColor": "#ff006e",
"css": ""
}
```
### Metadata
| Field | Type | Required | Notes |
| ------------- | ------ | -------- | --------------------------------------------------- |
| `name` | string | yes | Display name; also used for the install folder |
| `version` | string | yes | Semver, used for update checks |
| `apiVersion` | string | yes | Must start with `2` (use `"2.0"`) |
| `author` | string | yes | Shown in the theme manager |
| `description` | string | no | Shown on the theme card |
| `nsfw` | bool | no | Marks the theme as adult content (`18+` badge) |
| `preview` | string | no | Card thumbnail; the editor generates `preview.png` |
| `accentColor` | string | no | Hex color used for focus rings and active UI states |
| `css` | string | no | Extra CSS injected while the theme is active |
### Background
`background.type` selects the layer:
```json
{ "type": "color", "color": "#181825", "opacity": 1 }
```
```json
{ "type": "gradient", "from": "#181825", "to": "#3b1d4f", "angle": 135, "opacity": 1 }
```
```json
{ "type": "image", "src": "background.png", "fit": "cover", "opacity": 1, "blur": 0 }
```
```json
{
"type": "video",
"src": "background.webm",
"fit": "cover",
"opacity": 1,
"blur": 0,
"muted": true
}
```
- `src` is relative to the theme's `assets/` folder.
- `fit` is `cover` (default) or `contain`.
- `opacity` is clamped to `0`–`1`, `blur` to `0`–`40` pixels.
- Background videos autoplay and loop. They are muted by default; set `muted` to `false`
to play their audio.
- Prefer **WebM** for video backgrounds and video layers. It is supported by the
launcher and keeps theme packages much smaller than MP4. MP4, MOV and M4V also
work.
### Overlay
```json
{ "color": "#000000", "opacity": 0.2, "vignette": 0.35 }
```
`opacity` controls the flat dim layer and `vignette` darkens the edges. Both are
clamped to `0`–`1`.
### Effects
```json
{ "type": "stars", "density": 40, "speed": 1, "color": "#ffd6f2" }
```
Supported types: `none`, `stars`, `snow`, `petals`, `bubbles`.
- `density` is clamped to `0`–`120` particles.
- `speed` is clamped to `0.2`–`3`.
- Effects are disabled when the user turns on **Reduce animations**.
### Audio
```json
{ "src": "music.mp3", "loop": true }
```
`src` is relative to `assets/`. Music uses the launcher's volume control and is
silent in the theme editor preview.
### Typography
`typography.body` changes the font used by the launcher UI. `typography.heading`
changes headings such as the launcher title.
```json
"typography": {
"body": "Montserrat Variable",
"heading": "Playfair Display Variable"
}
```
These families ship with the launcher through `@fontsource` and can be used
without adding any files:
| Family | Style |
| --------------------------- | ------- |
| `Sora Variable` | Sans |
| `Montserrat Variable` | Sans |
| `Bebas Neue` | Display |
| `Playfair Display Variable` | Serif |
| `Space Mono` | Mono |
| `JetBrains Mono Variable` | Mono |
Custom fonts can be packaged with the theme. The launcher generates the
`@font-face` rules from `fonts`:
```json
"fonts": [
{ "family": "My Display Font", "src": "display.woff2", "weight": "400", "style": "normal" }
]
```
- `src` is relative to `assets/`.
- Supported formats: WOFF2 (recommended), WOFF, TTF and OTF.
- `weight` defaults to `400`; `style` defaults to `normal`.
- Use the `family` value in `typography` and in text layers.
The editor's **Fonts** tab browses the full Fontsource catalog (2,000+ families)
and downloads the selected family, weight, style and subset as a WOFF2 into the
theme's `assets/` folder. It adds the matching `fonts` entry automatically, so
saved and exported themes stay self-contained.
### Freeform layers
`elements` are rendered above the launcher UI, but only on the **Home** screen.
The launcher canvas is a fixed **1000 × 650** coordinate space. Elements can extend
the home screen with text, images, videos and shapes, and they are
pointer-transparent in the running launcher so they never block buttons.
The order of the `elements` array controls stacking: the last element is drawn on
top. Themes can contain up to 100 layers.
Every layer supports:
| Field | Type | Notes |
| ---------- | ------- | ------------------------------------------------ |
| `id` | string | Unique within the theme |
| `name` | string? | Optional editor label; does not affect rendering |
| `type` | string | `text`, `image`, `video` or `shape` |
| `x`, `y` | number | Position in the 1000 × 650 stage |
| `width` | number | 24–1000 |
| `height` | number | 24–650 |
| `rotation` | number | Degrees, `-360`–`360` |
| `opacity` | number | `0`–`1` |
| `hidden` | boolean | Keep the layer in the file but do not render it |
| `locked` | boolean | Prevent moving/resizing the layer in the editor |
#### Text
```json
{
"id": "greeting",
"type": "text",
"text": "Welcome back!",
"x": 360,
"y": 220,
"width": 420,
"height": 90,
"fontFamily": "Bebas Neue",
"fontSize": 42,
"fontWeight": 600,
"color": "#ffffff",
"align": "center",
"verticalAlign": "center",
"lineHeight": 1.2,
"letterSpacing": 0
}
```
`align` is `left`, `center` or `right`; `verticalAlign` is `top`, `center` or
`bottom`. Font size is clamped to `6`–`240`.
#### Image and video
```json
{
"id": "logo",
"type": "image",
"src": "logo.png",
"x": 700,
"y": 420,
"width": 220,
"height": 140,
"fit": "contain",
"radius": 18,
"opacity": 1
}
```
```json
{
"id": "ambient",
"type": "video",
"src": "ambient.webm",
"x": 0,
"y": 0,
"width": 1000,
"height": 650,
"fit": "cover",
"opacity": 0.35
}
```
Video layers autoplay and loop. They are muted by default; set `muted` to `false` to
play their audio. WebM is recommended for size. Use an `opacity` below `1` if the video
should blend into the launcher UI.
#### Shape
```json
{
"id": "glow",
"type": "shape",
"shape": "ellipse",
"x": 680,
"y": 60,
"width": 260,
"height": 260,
"fill": "#ff006e",
"opacity": 0.18,
"borderWidth": 0,
"borderColor": "#ffffff"
}
```
`shape` is `rectangle`, `ellipse` or `line`. `radius` rounds rectangle corners.
`borderWidth` is clamped to `0`–`40`.
### Custom CSS
The `css` field is appended while the theme is active. Theme authors can use it for
small tweaks, but it is not required. Example:
```css
:root {
--radius: 1rem;
}
```
---
## Using the advanced editor
1. Open **Themes** in the launcher.
2. Select **Create theme**, or the pencil button on an installed API 2.0 theme.
3. The editor opens in its **own resizable window**, not a modal. The center is a
full launcher home canvas at 1000 × 650.
4. Use the left toolbar to add text, image, video and shape layers. Drag layers on
the canvas, resize with the corner handles, or edit exact values in the right
inspector. Shift/Cmd-click a layer or drag a marquee over empty canvas to
select several layers. Multi-selections can be dragged together and aligned
or distributed from the right panel. Layers snap to canvas edges, the canvas
center, and other layers while dragging; hold Alt to disable snapping.
Right-click a layer for quick duplicate, ordering, hide/lock and delete
actions, or right-click empty canvas to add a new layer.
5. The layer list supports double-click rename, hide/show, lock/unlock and
drag-to-reorder. Hidden layers remain in the package, while locked layers
cannot be moved or resized on the canvas.
6. Use the **Theme** tab for metadata, background, effects, typography and custom
CSS. Open the **Fonts** tab to search and download from every Fontsource
family, or import WOFF2, WOFF, TTF and OTF files. Downloaded fonts are copied
into the theme's `assets/` folder when you save.
7. Select **Save theme** to write `theme.json` and copy new assets into
`~/.ezpplauncher/themes`. A fresh `assets/preview.png` thumbnail is rendered
from the theme and the launcher applies the saved theme immediately. Unsaved
edits are autosaved as a local draft and offered for recovery after a crash.
8. Select **Export** to create a shareable `.ezpplauncher-theme` package. A theme
check runs first and reports missing assets, oversized media, missing fonts
and unused imports. Export saves and refreshes the preview, then reports the
final package size.
Keyboard shortcuts:
- `Cmd/Ctrl+Z` undoes the last change.
- `Cmd/Ctrl+Shift+Z` or `Ctrl+Y` redoes it.
- `Cmd/Ctrl+S` saves.
- `Cmd/Ctrl+D` duplicates the selected layer or multi-selection.
- `Cmd/Ctrl+A` selects every visible layer.
- Shift/Cmd-click toggles a layer in the current selection.
- Arrow keys nudge the selected layer(s) by 1 px; hold Shift for 10 px.
- `Delete` removes the selected layer(s).
- Hold Alt while dragging to skip snapping.
- `Esc` clears the selection or closes an open editor dialog.
---
## Creating API 2.0 themes with the CLI
The `create-ezpplauncher-theme` CLI includes a **declarative (API 2.0)** template:
```bash
npx git+https://git.ez-pp.farm/EZPPFarm/create-ezpplauncher-theme.git my-theme
```
Choose `declarative (API 2.0)`, edit `theme.json`, add files to `assets/`, then run:
```bash
npm run build
```
This produces `dist/my_theme.ezpplauncher-theme`. The template also includes
`preview.html` for a standalone browser preview:
```bash
npx serve .
```
---
## Compatibility and limits
- API 2.0 packages must include `theme.json`; `entry` and `style` are not used.
- Asset paths are resolved inside `assets/`; path traversal is rejected by the
import commands.
- Exports include only `assets/` files referenced by `theme.json` (background,
audio, fonts, layers and preview). Orphaned files left in the folder are
omitted, which keeps packages small. API 1.0 themes are exported whole because
their bundles can load files dynamically.
- The editor writes `preview.png` whenever you save or export. The generated
thumbnail renders the background, effects, launcher UI, theme fonts and
freeform layers; custom CSS is not applied to the thumbnail.
- The theme editor only writes inside `~/.ezpplauncher/themes`.
- API 1.0 themes are still loaded through their existing `mountTheme` bundle API.
- API 2.0 themes cannot run JavaScript. Use custom CSS for small visual tweaks, or
use API 1.0 when a theme needs a fully custom UI.
- Freeform layers are decorative, home-screen-only and pointer-transparent; they
cannot add interactive controls.