# dsh-theme-synthwave > πŸ“– δΈ­ζ–‡ζ–‡ζ‘£οΌš[README.md](./README.md) A Synthwave theme plugin for the DSH (DeepSeek Harness) Web UI. One package ships both the host half (config reading, media file serving) and the client half (theme tokens, neon glow, background media, font scaling), ready to use after installation. The background supports local image slideshows or video, semi-transparent panels that let the media show through, plus configurable neon glow, blur, and global font scaling. ![showcase](showcase.png) ## ✨ Features - **Neon glow on hover/focus**: adds layered `text-shadow` glow to links, buttons, `role="button"` and other clickable controls, switching colors on hover/focus. - **Semi-transparent panels revealing the background**: adjust the app/sidebar background opacity with `background.baseAlpha` to let the image or video behind show through. - **Background image slideshow**: cycle multiple images sequentially or randomly, with configurable opacity and interval. - **Background video**: supports local video files or `http(s)` URLs, with configurable loop, mute, and `object-fit`. - **Background media / default bubble blur**: `blur` 0–40px, applied only at the render layer without touching the source files. - **Root font scaling `fontScale`**: scales text via the root font size, avoiding CSS `zoom` hit-target and popup-positioning issues in Firefox. - **Light/dark adaptive tokens**: dark mode keeps the synthwave neon look; light mode automatically switches to a light background with dark text to stay readable. - **Config card shortcut**: in the Plugins configuration page, the card offers "Open config file" and "Copy path" buttons to quickly open or copy the current profile's `config.dsh-theme-synthwave.jsonc`. - **Removable media**: the config card can remove a configured video, and remove any single image from the image list; changes are written back to the local config immediately. - **Editing safety**: the config file editor supports a "Cancel" action to discard unsaved changes; if the config fails to parse, the plugin falls back to defaults (without touching the file) and shows a notice in the UI. ## πŸš€ Quick start 1. **Install the plugin** ```bash # Local directory dsh plugin --profile web add link: # Git repository (after publishing to GitHub) dsh plugin --profile web add "git+https://github.com//dsh-theme-synthwave.git" # npm (after publishing) dsh plugin --profile web add @1mlightyears/dsh-theme-synthwave ``` > **Git install note**: a `git+` install fetches the **source** (not built artifacts); DSH/pnpm runs this package's `prepare` script after install to build `lib/` from `src/`. pnpm β‰₯10 refuses to run a git dependency's `prepare` until you allow it: the first `add` fails and `dsh` prints the exact package key to copy into that profile's `pnpm-workspace.yaml`, e.g.: > > ```yaml > allowBuilds: > '@1mlightyears/dsh-theme-synthwave': true > ``` > > Then re-run `add`. Lock the commit (`git+https://…#`) so later pushes cannot silently change what runs. > If your repository is a monorepo and the plugin lives in a subdirectory: ```bash dsh plugin --profile web add "git+https://github.com//.git#subdirectory=path/to/dsh-theme-synthwave" ``` 2. **Create/edit the config** On first page load, the plugin automatically generates `config.dsh-theme-synthwave.jsonc` in the current profile directory (using built-in defaults). You can also create it manually by following [`config.dsh-theme-synthwave.example.jsonc`](./config.dsh-theme-synthwave.example.jsonc). The config file lives in the current profile directory, not the session workspace. 3. **Prepare background assets** Put images or videos in the same directory as `config.dsh-theme-synthwave.jsonc` (absolute paths and `http(s)` URLs also work). > **Current directory**: the base directory that `.` (or any relative path) in `background.video.path` / `background.images.paths` resolves against is the directory containing `config.dsh-theme-synthwave.jsonc` β€” i.e. the current profile directory (usually `$DSH_HOME/profiles//`). It is **not** the session workspace and **not** the plugin package directory. > 4. **Restart and refresh** Restart DSH after the first install, then hard-refresh the page in the browser to see the effect. Afterwards, changing `config.dsh-theme-synthwave.jsonc` only requires a hard refresh. ## βš™οΈ Configuration You can also open or copy the current profile's config file path from the "DeepSeek Harness: 合成泒风格主钘" card in DSH Settings β†’ Plugins β†’ Plugin configuration. ![settings](settings.png) The plugin looks for `config.dsh-theme-synthwave.jsonc` in the current profile directory (usually `$DSH_HOME/profiles//`); if it does not exist, the plugin creates one with built-in defaults. [`config.dsh-theme-synthwave.example.jsonc`](./config.dsh-theme-synthwave.example.jsonc) is a commented reference template you can follow. In the "DeepSeek Harness: 合成泒风格主钘" card you can perform the common operations directly: choose/upload an image or a dynamic background, remove a dynamic background or a single image from the "Current background media" list, apply a media source via URL or bare filename, configure the dynamic background's autoplay policy and cache duration, clear all cached dynamic backgrounds, and edit the config file text ("Save" writes it, "Cancel" discards unsaved changes). If the config file fails to parse, the plugin temporarily applies defaults **without modifying the file**, and shows a notice suggesting you delete it (the plugin will recreate a default) or fix it against the example file. > **Mobile autoplay note**: a dynamic background can be large. To save data, mobile never autoplays by default (`background.video.autoplay` defaults to `never`). Whenever the dynamic background is already cached locally (Cache Storage hit) it will autoplay with no extra data; otherwise the page shows a "Load dynamic background" button (annotated with the file size when known; remote-URL sizes are unknown), which downloads and plays only after a tap. A minimal example without comments: ```jsonc { "textGlow": { "enabled": true, "alpha": 0.6, "hoverAlpha": 0.85, "blurEm": 0.30, "colors": ["#ff2a6d"], "hoverColors": ["#05d9e8"], "suppressHoverFill": true }, "fontScale": 1.15, "background": { "baseAlpha": 0.5, "blur": 2, "defaultEffect": 1, "video": { "path": "background.mp4", "loop": true, "muted": true, "objectFit": "cover", "autoplay": "never", "cacheDays": 30 }, "images": { "paths": ["background.jpg"], "alpha": 0.85, "intervalMs": 60000, "order": "sequential" } } } ``` After changing `config.dsh-theme-synthwave.jsonc`, hard-refresh the page to reload the config; only installing/uninstalling the plugin itself requires a DSH restart. ## πŸ”Œ Service endpoints | Path | Description | | ----------------------------------------- | --------------------------------------------------------------------------------------------------- | | `GET /synthwave-theme-config` | Returns the resolved JSON config (including`configPath`) for the browser half. | | `POST /synthwave-theme-config/open` | Opens the current profile's config file with the OS default handler. | | `POST /synthwave-theme-config/remove` | Removes the dynamic background record, or removes a given image from the image list, and writes the config back. | | `POST /synthwave-theme-config/video-options` | Sets the dynamic background's autoplay policy and cache duration (`cacheDays`). | | `GET /synthwave-theme-media/` | Reads and returns background image/dynamic background bytes (512MB cap, with `Cache-Control` by cache duration). | ## ❓ FAQ - **Background media doesn't show**: make sure `config.dsh-theme-synthwave.jsonc` is in the current profile directory, the media path resolves, and you have hard-refreshed the page. See [`config.dsh-theme-synthwave.example.jsonc`](./config.dsh-theme-synthwave.example.jsonc) for parameter details. - **Video has no sound**: background video is muted by default, which is expected under browser autoplay policy; see the `video.muted` comment in `config.dsh-theme-synthwave.example.jsonc`. - **Dynamic background doesn't autoplay on mobile**: this is intentional to save data (see the "Mobile autoplay note" above). Tap "Load dynamic background" to play it; it will autoplay automatically once cached locally. - **How to clear cached dynamic backgrounds**: click "Clear all cached dynamic backgrounds" under "Dynamic background options" in the config card; it deletes the local browser cache and reports the count and total size released. ## πŸ“ Project structure ``` . β”œβ”€β”€ src/ β”‚ β”œβ”€β”€ host/ β”‚ β”‚ └── index.ts # host half: reads config, serves media and config endpoints β”‚ └── client/ β”‚ β”œβ”€β”€ index.ts # client half: tokens / glow / background / blur / font scaling β”‚ └── OpenConfigCard.ts # plugin config card: open/copy the config file β”œβ”€β”€ lib/ # build output (do not edit by hand) β”‚ β”œβ”€β”€ index.js β”‚ └── client.js β”œβ”€β”€ build/ # vendored DSH client-bundle build preset β”œβ”€β”€ cordis.patch.yml # bundle patch β”œβ”€β”€ tsdown.config.ts # tsdown build entry β”œβ”€β”€ config.dsh-theme-synthwave.example.jsonc # config template └── package.json ``` ## πŸ› οΈ Development ```bash pnpm install # also runs `prepare` to build lib/ pnpm build # tsdown β†’ lib/index.js + lib/client.js ``` Build output goes to `lib/`; do not edit `lib/` by hand before publishing. Note: the host half loads when the DSH process starts, so changing it requires restarting `dsh --profile web`; a browser refresh only reloads the client half. ## πŸ“„ License [Apache-2.0](./LICENSE)