PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 0.8.7
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v0.8.7
1.1.10 1.1.9 1.1.8 1.1.7 1.1.6 1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.1 1.0.0 0.9.8 0.9.7 0.9.6 0.9.4 0.9.5 0.9.3 0.9.2 0.9.1 0.9.0 0.8.9 0.8.8 0.8.7 All 34 releases
desktop-mode / README.md

README.md in OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin 0.8.7, at README.md

251 lines 18.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 # WP Desktop Mode
2
3 A WordPress plugin that reimagines `/wp-admin` as a desktop operating system. Admin screens open as draggable, resizable, minimizable **windows** on a **desktop**, with a left-edge **dock** built from the admin menu. Purely opt-in per user — the classic admin stays untouched for everyone else, and deactivating the plugin restores vanilla Core exactly.
4
5 Zero Core patches. Every feature is wired through public WordPress hooks.
6
7 [](https://wordpress.org/plugins/desktop-mode/![Active Installs](https://img.shields.io/wordpress/plugin/installs/desktop-mode?logo=wordpress&logoColor=%23fff&label=Active%20Installs&labelColor=%2323282D&color=%2323282D)](https://wordpress.org/plugins/desktop-mode/](https://wordpress.org/plugins/desktop-mode/) [](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/WordPress/desktop-mode/refs/heads/trunk/.wordpress-org/blueprints/blueprint.json![Playground Demo Link](https://img.shields.io/wordpress/plugin/v/desktop-mode?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjQ2IDI2IDUxIDUyIiBmaWxsPSJ3aGl0ZSI%2BPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik01My43MTE3IDQ1LjQ4MzlDNTIuNjY1IDQ2LjkyNzcgNTIuMTEyNyA0OC43MDE3IDUyLjAyMzkgNTAuNjUxM0M1Mi4wMDk2IDUwLjk2NjcgNTIuMDA3MyA1MS4yODY2IDUyLjAxNzEgNTEuNjEwNUM1Mi4xNDk0IDU1Ljk5NjUgNTQuNDgxMyA2MS4xMDUxIDU4LjY4NzkgNjUuMzExOEM2NS4xMjU4IDcxLjc0OTYgNzMuNjc2MSA3My43OTY2IDc4LjUxNiA3MC4yODgxQzc2LjQ4MDIgNjkuODA4NCA3NC40MjA2IDY5LjA2MDcgNzIuMzkyNiA2OC4wNjMzQzcxLjg3MiA2OC4wNDA1IDcxLjMxMTkgNjcuOTcyNiA3MC43MTE2IDY3Ljg1MjZDNjkuNjg1MiA2Ny42NDczIDY4LjU5OTggNjcuMjk0OSA2Ny40OTQxIDY2Ljc5MzZDNjcuNDk0MSA2Ni43OTM1IDY3LjQ5NCA2Ni43OTMzIDY3LjQ5NCA2Ni43OTMxQzY1LjQ3MTkgNjUuODc2NSA2My4zODE4IDY0LjQ2MjIgNjEuNDU5NiA2Mi41NEM1OS41Mzc2IDYwLjYxOCA1OC4xMjM0IDU4LjUyODEgNTcuMjA2OCA1Ni41MDYzQzU3LjIwNjcgNTYuNTA2MiA1Ny4yMDY2IDU2LjUwNjIgNTcuMjA2NSA1Ni41MDYyQzU2LjcwNTMgNTUuNDAwNCA1Ni4zNTI4IDU0LjMxNSA1Ni4xNDc1IDUzLjI4ODRDNTYuMDI3NSA1Mi42ODgzIDU1Ljk1OTYgNTIuMTI4MyA1NS45MzY4IDUxLjYwNzhDNTQuOTM5MyA0OS41Nzk3IDU0LjE5MTQgNDcuNTE5OSA1My43MTE3IDQ1LjQ4MzlaTTQ5LjY3OTUgNTcuNjkwNkM0OS44MjYgNTcuNTQ0MSA0OS45Nzk3IDU3LjQwNzQgNTAuMTQwMSA1Ny4yODA1QzUwLjYxMTcgNTguNjU3IDUxLjIzNCA2MC4wMzAzIDUxLjk5NjggNjEuMzczNEM1MS44OTQyIDYxLjgyNiA1MS44NzI2IDYyLjQ0NiA1Mi4wMzg4IDYzLjI3NzFDNTIuMzY4NyA2NC45MjY5IDUzLjM5NzYgNjYuOTUyMiA1NS4yMjI5IDY4Ljc3NzVDNTcuMDQ4MiA3MC42MDI4IDU5LjA3MzUgNzEuNjMxNiA2MC43MjMyIDcxLjk2MTZDNjEuNTU0NiA3Mi4xMjc5IDYyLjE3NDcgNzIuMTA2MSA2Mi42MjczIDcyLjAwMzVDNjMuOTcwNCA3Mi43NjYyIDY1LjM0MzcgNzMuMzg4NCA2Ni43MjAxIDczLjg1OTlDNjYuNTkzMSA3NC4wMjA0IDY2LjQ1NjQgNzQuMTc0MyA2Ni4zMDk3IDc0LjMyMDlDNjMuMjQ4MiA3Ny4zODI1IDU3LjA0MzUgNzYuMTQxNSA1Mi40NTEyIDcxLjU0OTJDNDcuODU4OSA2Ni45NTY5IDQ2LjYxNzkgNjAuNzUyMiA0OS42Nzk1IDU3LjY5MDZaTTY0LjkyMzkgNTkuMDc1OEM3NC4xMDg2IDY4LjI2MDUgODYuNTE4IDcwLjc0MjQgOTIuNjQxMSA2NC42MTkzQzk0Ljg1NSA2Mi40MDUzIDk1Ljk0MzkgNTkuMzY5NiA5NS45OTc5IDU1Ljk2MTZDOTYuMDkzMSA0OS45NDQxIDkyLjk2MTMgNDIuNzY2MSA4Ny4wOTc2IDM2LjkwMjRDNzcuOTEzIDI3LjcxNzcgNjUuNTAzNiAyNS4yMzU5IDU5LjM4MDUgMzEuMzU5QzU3LjE2MzYgMzMuNTc1OCA1Ni4wNzQ3IDM2LjYxNjcgNTYuMDIzNSA0MC4wMzAzQzU1LjkzMzIgNDYuMDQ1IDU5LjA2NDcgNTMuMjE2NiA2NC45MjM5IDU5LjA3NThaTTc3Ljg1ODYgNjAuNzA1NkM3OC4wMjkyIDYxLjU1ODQgNzguMDk0NCA2Mi4zMzAxIDc4LjA3NDcgNjMuMDIyNEM3NC42MjU1IDYxLjgyMTggNzAuOTcwMiA1OS41Nzg5IDY3LjY5NTYgNTYuMzA0NEM2NC40MjExIDUzLjAyOTggNjIuMTc4MiA0OS4zNzQ1IDYwLjk3NzYgNDUuOTI1NEM2MS42NyA0NS45MDU2IDYyLjQ0MTcgNDUuOTcwOSA2My4yOTQ1IDQ2LjE0MTVDNjYuMTk4MSA0Ni43MjIyIDY5LjU3MzEgNDguNDgwMiA3Mi41NDY1IDUxLjQ1MzZDNzUuNTE5OCA1NC40MjcgNzcuMjc3OSA1Ny44MDE5IDc3Ljg1ODYgNjAuNzA1NlpNNjIuMTUyMiAzNC4xMzA3QzYwLjQ5MjcgMzUuNzkwMiA1OS42MDcyIDM4LjQ4OTUgNjAuMDUzMyA0Mi4wNjA4QzY0Ljc0ODMgNDEuNjA0NCA3MC42MDA1IDQzLjk2NDIgNzUuMzE4MiA0OC42ODE5QzgwLjAzNTkgNTMuMzk5NiA4Mi4zOTU3IDU5LjI1MTcgODEuOTM5MiA2My45NDY4Qzg1LjUxMDYgNjQuMzkyOCA4OC4yMDk4IDYzLjUwNzMgODkuODY5MyA2MS44NDc4QzkxLjcxNTggNjAuMDAxMyA5Mi42MDQgNTYuODY3NyA5MS43NjYxIDUyLjY3NzdDOTAuOTM0NSA0OC41MjAxIDg4LjQ0NzQgNDMuNzk1NSA4NC4zMjU5IDM5LjY3NDFDODAuMjA0NSAzNS41NTI2IDc1LjQ3OTkgMzMuMDY1NSA3MS4zMjIzIDMyLjIzMzlDNjcuMTMyMyAzMS4zOTU5IDYzLjk5ODcgMzIuMjg0MiA2Mi4xNTIyIDM0LjEzMDdaIi8%2BPC9zdmc%2B&logoColor=%23fff&label=Playground%20Demo&labelColor=%233858e9&color=%233858e9)](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/WordPress/desktop-mode/refs/heads/trunk/.wordpress-org/blueprints/blueprint.json](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/WordPress/desktop-mode/refs/heads/trunk/.wordpress-org/blueprints/blueprint.json) [](https://wp.com/open?deep_link=add-site%3Fblueprint_url%3Dhttps%253A%252F%252Fraw.githubusercontent.com%252FWordPress%252Fdesktop-mode%252Frefs%252Fheads%252Ftrunk%252F.wordpress-org%252Fblueprints%252Fblueprint.json![Studio Demo Link](https://img.shields.io/wordpress/plugin/v/desktop-mode?logo=wordpress&logoColor=%23fff&label=Open%20in%20WordPress%20Studio&labelColor=%2323282D&color=%2323282D)](https://wp.com/open?deep_link=add-site%3Fblueprint_url%3Dhttps%253A%252F%252Fraw.githubusercontent.com%252FWordPress%252Fdesktop-mode%252Frefs%252Fheads%252Ftrunk%252F.wordpress-org%252Fblueprints%252Fblueprint.json](https://wp.com/open?deep_link=add-site%3Fblueprint_url%3Dhttps%253A%252F%252Fraw.githubusercontent.com%252FWordPress%252Fdesktop-mode%252Frefs%252Fheads%252Ftrunk%252F.wordpress-org%252Fblueprints%252Fblueprint.json)
8
9 ## Demo
10
11 <video src="https://github.com/user-attachments/assets/590aacc2-e9d7-4213-889e-b91e060e1bd8" controls width="720"></video>
12
13 ---
14
15 ## Contents
16
17 - [](#demoDemo](#demo](#demo)
18 - [](#current-stateCurrent State](#current-state](#current-state)
19 - [](#still-aheadStill ahead](#still-ahead](#still-ahead)
20 - [](#repository-layoutRepository layout](#repository-layout](#repository-layout)
21 - [](#how-to-run-itHow to run it](#how-to-run-it](#how-to-run-it)
22 - [](#quick-installQuick install](#quick-install](#quick-install)
23 - [](#development-setupDevelopment setup](#development-setup](#development-setup)
24 - [](#requirementsRequirements](#requirements](#requirements)
25 - [](#for-plugin-authorsFor plugin authors](#for-plugin-authors](#for-plugin-authors)
26 - [](#licenseLicense](#license](#license)
27
28 ---
29
30 ## Current State
31
32 - **Per-user opt-in**
33 Admin-bar toggle sets the `desktop_mode_mode` user meta. A dedicated `/desktop-mode/` portal URL auto-enables desktop mode for first-time visitors (gated by `desktop_mode_portal_auto_enable`) and the `admin_init` redirect sends opted-in users from `/wp-admin/` to the portal (`desktop_mode_admin_redirect_to_portal`).
34
35 - **Desktop shell**
36 Fixed-viewport desktop that overlays `/wp-admin`: wallpaper area, unified dock (placement picked in OS Settings — left / right / bottom, default bottom), right-column widget layer, and full windowing system. `desktop_mode_mode_init`, `desktop_mode_shell_before` / `_after`, and the `desktop_mode_shell_config` filter are the main extension points.
37
38 - **Window system — iframe + native**
39 Iframe windows load admin pages with `?wp_desktop=1` (chromeless mode). Native windows render directly in the parent DOM via `desktop_mode_register_window()` / `wp.desktop.registerWindow()` — multi-tab native windows are supported through `desktop_mode_register_window_tab()`. Both types share drag, resize, minimize, maximize, close, fullscreen, and detach-to-new-tab.
40
41 - **Dock**
42 One unified rail hosting every admin menu — core and plugin alike — plus shell-level system tiles. Placement (left / right / bottom) is the user's OS Settings preference. Core menus are ordered before plugin menus; per-item hiding via `desktop_mode_dock_placement` (`'hidden'`). Per-item multi-window support via `desktop_mode_dock_item_multi`. Letter-badge icon fallback for plugins without icon art.
43
44 - **Virtual desktops (“Spaces”)**
45 Multiple desktops per user, each with its own window set. Overview grid (zoom-out view) surfaces the Spaces switcher, thumbnails, and create/close controls.
46
47 - **Arrange & snap**
48 Admin-bar Arrange menu: Cascade, Tile, Overview, Snap to grid. Plugins contribute custom entries via `desktop_mode_arrange_menu_items` and react to clicks via `desktop-mode.arrange.custom-action`. Tile grid dimensions and snap cell size are both filterable.
49
50 - **Wallpaper registry**
51 Server- and client-side registration (`desktop_mode_register_wallpaper()` / `wp.desktop.registerWallpaper()`). CSS presets + canvas (WebGL/2D) wallpapers with collision-aware surface data (`wp.desktop.getWallpaperSurfaces()`) for snow/rain/physics effects. In-panel `renderEditor` callback for custom controls, shared vendor-module loader (`pixijs` pre-registered).
52
53 - **Widgets**
54 Right-column floating cards, optionally draggable / resizable outside the column. `desktop_mode_register_widget()` / `wp.desktop.registerWidget()`. Built-in clock. User placement persists per-user in `localStorage`.
55
56 - **Desktop icons**
57 Wallpaper-layer shortcuts via `desktop_mode_register_icon()` — targets a registered native window or an admin URL.
58
59 - **AI Assistant + slash commands**
60 Cmd+K palette backed by an OpenAI agentic loop (search_posts, search_pages, search_comments tools). Admin-configured API key + model picker. Auto-analysis on `save_post` / term / comment save with per-entity prompt filters. `wp.desktop.registerCommand()` adds slash commands with autocomplete (`suggest()`), confirm dialogs (`ctx.confirm()`), and full lifecycle hooks (`before-run` / `after-run` / `error`). Built-in `/open [window]` is extensible via `desktop-mode.open-command.items`.
61
62 - **Palette registry**
63 Cmd+K cycles through all registered palettes (`wp.desktop.registerPalette()`) — the AI assistant is palette 0 by default; additional plugin overlays share the shortcut.
64
65 - **Cross-frame drag bridge**
66 Media-library attachments drag across iframe boundaries via coordinated postMessage. Site-wide toggle through the Extended Options REST endpoint.
67
68 - **Toast notifications**
69 Shell-level toasts rendered via the `<wpd-toast>` component. Plugins register their own tone/icon via the `desktop_mode_toast_types` filter. Iframe pages raise a toast through the `desktop-mode-notification` bridge message — it survives the iframe's own lifecycle.
70
71 - **OS Settings**
72 Native-window settings panel: wallpaper picker (with HD-only media filter), accent color swatches + custom gradient editor, dock size slider, AI platform config, and per-user default-on-startup window. Persisted via `/desktop-mode/v1/os-settings`.
73
74 - **Session persistence**
75 Full window stack (including desktops, focus, state) is debounce-saved to `/desktop-mode/v1/session` and restored without layout flicker. Viewport-shrink clamping keeps off-screen windows reachable.
76
77 - **postMessage bridge**
78 Typed messages for title changes, navigation (same-origin validated), focus, color-scheme sync, screen-meta panels (Screen Options / Help), external-link capture, iframe-ready handshake, and observability (`iframe-error`, `iframe-network`).
79
80 - **UI component library**
81 ~25 `<wpd-*>` web components (`wpd-button`, `wpd-menu`, `wpd-panel`, `wpd-range-field`, `wpd-swatch`, `wpd-toast`, `wpd-tabs`, …) available to plugin authors — rendered server-side via `desktop_mode_component()` or imported in TS.
82
83 - **i18n**
84 Full gettext coverage across PHP and TypeScript; Spanish translation shipped. Strings go through `wp.i18n` (`__`, `_x`, `_n`, `sprintf`) directly — no shell-specific re-export.
85
86 - **Component registration API**
87 Stable `desktop_mode_register_*` functions for windows, widgets, wallpapers, icons, and window tabs. All return `true` / `WP_Error` with documented error codes.
88
89 - **Public hook API**
90 Comprehensive PHP and JS hook surface — dock items, placement, multi-window, native-window lifecycle, widget lifecycle, wallpaper lifecycle + surfaces, window lifecycle, iframe observability, arrange actions, virtual-desktop transitions, palette registration, command lifecycle, batch close, AI prompt + model + post-type filters, accents, toast types, default wallpaper. See [](./docs/hooks-reference.md`docs/hooks-reference.md`](./docs/hooks-reference.md](./docs/hooks-reference.md) and [](./docs/javascript-reference.md`docs/javascript-reference.md`](./docs/javascript-reference.md](./docs/javascript-reference.md).
91
92 ---
93
94 ## Still ahead
95
96 - **Mobile (phone OS)** — purpose-built home-screen grid, full-screen apps, app switcher, gesture nav, bottom tab bar.
97 - **Tablet hybrid** — split view, slide-over, horizontal dock. `wp.desktop.mode = 'desktop' | 'tablet' | 'mobile'` surface.
98 - **Cross-window drag & drop (the North Star)** — extend the current drag bridge to Media → Gutenberg block insertion, with pluggable mime-type negotiation.
99 - **Polish** — color-scheme-aware variables across all shell surfaces, View Transitions API animations, full a11y audit (ARIA, focus traps, keyboard nav).
100 - **…and a whole lot more hooks, filters, and actions** — every new surface lands with its own extension points, so this list keeps growing.
101
102 See [](./docs/architecture.md`docs/architecture.md`](./docs/architecture.md](./docs/architecture.md) for how the pieces fit together and [](./docs/hooks-reference.md`docs/hooks-reference.md`](./docs/hooks-reference.md](./docs/hooks-reference.md) for the hook surface (current and planned).
103
104 See [](./docs/architecture.md`docs/architecture.md`](./docs/architecture.md](./docs/architecture.md) for how the pieces fit together and [](./docs/hooks-reference.md`docs/hooks-reference.md`](./docs/hooks-reference.md](./docs/hooks-reference.md) for the hook surface (current and planned).
105
106 ---
107
108 ## Repository layout
109
110 ```
111 .
112 ├── desktop-mode.php # bootstrap: header, constants, require_once of includes/
113 ├── includes/ # PHP subsystems
114 │ ├── helpers.php admin-bar.php ajax.php
115 │ ├── assets.php render.php portal.php
116 │ ├── session.php default-window.php components.php
117 │ ├── os-settings.php extended-options.php
118 │ ├── accents.php wallpapers.php toast-types.php
119 │ ├── media-query.php
120 │ └── ai-copilot/ # AI assistant (OpenAI client, analysis, search, jobs)
121 ├── assets/ # compiled CSS + JS (Vite output; tracked in git)
122 │ ├── css/ desktop.css, windows.css, dock.css, chromeless.css, variables.css
123 │ └── js/ desktop.js, desktop.min.js, chromeless bridge, media-library enhancements
124 ├── src/ # TypeScript source — compiled by Vite
125 │ ├── desktop.ts / dock.ts / hooks.ts / commands.ts / palette-registry.ts
126 │ ├── ai-assistant.ts / drag-bridge.ts / toast.ts / desktop-icons.ts
127 │ ├── native-windows.ts / built-in-commands.ts / public-api.ts / types.ts
128 │ ├── window/ # Window class — DOM, pointer, tabs, iframe bridge
129 │ ├── window-manager/ # stack, desktops, arrange, snap, overview
130 │ ├── wallpapers/ # registry, layer, surfaces, server sync, vendor loader
131 │ ├── widgets/ # registry, layer, frame, picker, storage
132 │ ├── settings/ # OS Settings panel sections
133 │ ├── ui/ # <wpd-*> web components
134 │ ├── modules/ # vendor-script lazy-loader
135 │ └── plugins/ # built-in demos (animated-logo-wallpaper)
136 ├── docs/ # developer-facing docs (source of truth for plugin authors)
137 ├── tests/ # PHPUnit + Vitest
138 ├── languages/ # .po / .mo (es shipped)
139 ├── bin/ # package-zip helpers
140 ├── package.json # devDeps (vite, typescript, vitest)
141 ├── vite.config.js # Vite lib-mode: src/desktop.ts → assets/js/desktop[.min].js (IIFE)
142 ├── vitest.config.ts
143 └── tsconfig.json
144 ```
145
146 ---
147
148 ## How to run it
149
150 ### Quick install
151
152 Just want to try it? Grab the pre-built zip and upload it to any WordPress — [](https://developer.wordpress.com/studio/Studio by WordPress.com](https://developer.wordpress.com/studio/](https://developer.wordpress.com/studio/), [](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-env/`wp-env`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-env/](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-env/), or a hosted site. No Node, no build step.
153
154 1. Download [](https://github.com/WordPress/desktop-mode/releases/latest/download/desktop-mode.zip`desktop-mode.zip`](https://github.com/WordPress/desktop-mode/releases/latest/download/desktop-mode.zip](https://github.com/WordPress/desktop-mode/releases/latest/download/desktop-mode.zip) from the latest release (or pick a specific version from the [](https://github.com/WordPress/desktop-mode/releasesreleases page](https://github.com/WordPress/desktop-mode/releases](https://github.com/WordPress/desktop-mode/releases)).
155 2. In WP Admin: **Plugins → Add New → Upload Plugin**, choose the zip, and activate.
156 3. Click the **desktop** icon in the admin bar's top-right corner. The admin reloads inside the desktop shell. Click the same icon again to return to classic admin.
157
158 ### Development setup
159
160 For hacking on the plugin: clone the repo, run the build in watch mode, and load it into a local WordPress via symlink so every save is one browser refresh away.
161
162 #### 1. Install dependencies
163
164 ```bash
165 npm install
166 ```
167
168 #### 2. Build the TypeScript bundle
169
170 The plugin uses **[](https://vitejs.dev/Vite](https://vitejs.dev/](https://vitejs.dev/)** in library mode. esbuild handles transpile and minify, so builds finish in ~70 ms per bundle.
171
172 **Full build** — produces every bundle (`npm run build:desktop`, `:iframe-bridge`, `:recycle-bin`, `:posts-window`):
173
174 ```bash
175 npm run build
176 ```
177
178 Writes:
179
180 - `assets/js/desktop.js` / `.min.js` — main shell bundle (loaded based on `SCRIPT_DEBUG`).
181 - `assets/js/iframe-bridge.js` / `.min.js` — opt-in bridge that gives any same-origin iframe access to `wp.desktop.iframe.*`.
182 - `assets/js/recycle-bin.js` / `.min.js` — Recycle Bin native window.
183 - `assets/js/posts-window.js` / `.min.js` — Native Posts window (the `<wpd-table>` replacement for the `edit.php` iframe; opt-in per user via OS Settings → Features).
184
185 **Development watch** — auto-recompiles the unminified bundle on save:
186
187 ```bash
188 npm run dev
189 ```
190
191 Leave it running in a separate terminal; refresh the browser after each save. Set `define( 'SCRIPT_DEBUG', true )` in `wp-config.php` so WordPress picks up the unminified bundle during development.
192
193 #### 3. Load into a local WordPress
194
195 You need a running WordPress to load the plugin into. Pick whichever is easier.
196
197 ##### Studio, wp-env, or a hosted WP
198
199 Run `npm run package` to build a zip from `HEAD` (with correct 0644 / 0755 permissions), then follow the [](#quick-installQuick install](#quick-install](#quick-install) steps 2–3 to upload and activate it. Re-package and re-upload after each change.
200
201 > If you changed source, run `npm run build` before `npm run package` — the Vite output is gitignored, and `bin/package.sh` splices the built files into the zip from your working tree.
202
203 ##### Clone `wordpress-develop` and symlink
204
205 Gives you the full dev loop: `npm run dev` rebuilds on save, a browser refresh picks it up.
206
207 ```bash
208 # clone Core's Docker-based dev host alongside this repo
209 git clone https://github.com/WordPress/wordpress-develop.git
210 cd wordpress-develop
211 npm install
212
213 # symlink this plugin into the WP plugins directory
214 ln -s "$(pwd)/../alcazaba-plugin" src/wp-content/plugins/desktop-mode
215
216 # boot + install WordPress
217 npm run env:start # nginx + PHP + MySQL in Docker
218 npm run env:install # installs WordPress
219 ```
220
221 Site: **http://localhost:8889**
222 Admin: **http://localhost:8889/wp-admin/**
223 Credentials: `admin` / `password`
224
225 Stop the environment with `npm run env:stop` (from the `wordpress-develop` directory). Activate the plugin per [](#quick-installQuick install](#quick-install](#quick-install) steps 2–3.
226
227 ---
228
229 ## Requirements
230
231 - WordPress **6.0+**
232 - PHP **7.4+**
233
234 ## For plugin authors
235
236 **This plugin is built to be extended.** Every significant behavior is hookable — drop an icon on the desktop, add a dock item, gate desktop mode by role, react to window events, or register a native window, all from your own plugin with zero patches here.
237
238 **See [](./docs/README.md`docs/`](./docs/README.md](./docs/README.md) — the developer documentation index.**
239
240 Quick links:
241
242 - [](./docs/getting-started.mdGetting Started](./docs/getting-started.md](./docs/getting-started.md) — the five-minute tour for plugin authors.
243 - [](./docs/architecture.mdArchitecture](./docs/architecture.md](./docs/architecture.md) — how the pieces fit together.
244 - [](./docs/hooks-reference.mdHooks Reference](./docs/hooks-reference.md](./docs/hooks-reference.md) — every action and filter we fire, with signatures and examples.
245 - [](./docs/javascript-reference.mdJavaScript Reference](./docs/javascript-reference.md](./docs/javascript-reference.md) — CustomEvents, `window.wp.desktop` API, and the iframe `postMessage` bridge.
246 - [](./docs/examples/Examples](./docs/examples/](./docs/examples/) — copy-paste recipes.
247
248 ## License
249
250 GPLv2 or later. See [](LICENSELICENSE](LICENSE](LICENSE).
251