studio.deployment.open. The bundled fused-studio/deployment service owns that command and its dialog. Replace this contribution to control deployment UI without replacing the workspace shell.
Your module can define its own modal, fields, environment choices, buttons, validation, and progress display. It receives the same host context as the default deployment service. Backend authentication, feature gates, command validation, and stale-manifest checks still apply. A new deployment backend or operation requires corresponding server support; changing a button does not add one.
Declare the replacement
studio-pack.yaml
service modules receive null as their mount container. Create a dialog owned by your module, append it to the document, and remove it during cleanup. Register studio.deployment.open; the default shell’s button will invoke your handler. The resolved default deployment service is removed before activation, so it does not register a competing handler.
An isolated frame cannot implement this command because it has no command bridge. This replacement requires explicit trust:
Use the working example
The Harnest checkout includesexamples/studio-packs/team-deployment/. It contains the manifest above and a standalone module with:
- A Team deployment dialog instead of the default modal.
- A native environment selector with
localandstagingchoices. Configure those environments in the project’s deployment manifest before using them. - Review plan, which reads the deployment overview without starting infrastructure.
- Deploy reviewed plan, enabled only after an unblocked review.
- A completion display driven by Studio job state.
assets/deployment.js.
Render the modal with React
Packs are framework-independent. The plain DOM example avoids a build dependency; it is not a requirement. Use React components for your modal, forms, state, and buttons. React’s createRoot API mounts a component tree into one container, androot.unmount() cleans it up.
For a visual slot, Studio passes the container as host. For a deployment service, create one container in the entry adapter, then let React own everything inside it:
src/deployment.jsx
DeploymentDialog is your component: implement focus containment, closing, environment choices, review, and job handling there. Register the command in activate, rather than waiting for a React effect, so it is available when Studio enables shell controls. Components can clean up subscriptions through their effect cleanup functions.
Compile JSX and bundle react, react-dom, and your components into a production browser ES module exporting activate. Point the manifest to the generated assets/deployment.js; do not serve raw JSX, unresolved package imports, or a development server. Declare every generated JavaScript chunk in ui.assets. Put generated CSS in both ui.assets and ui.styles, scoped to your component. Studio does not supply a global React instance. Keep bundle assets within the UI size limits.
Shell commands and state
These commands are supplied by the default shell. A custom shell must implement the commands its deployment contribution uses.
Subscribe to
project to follow selection. Subscribe to jobs for complete job snapshots containing IDs, status, and output. Match your submitted job ID and process its completion once. Subscription and command-registration calls return cleanup functions. Stop handling pending results after cleanup, and invalidate reviews when the selected project or environment changes.
The default deployment service checks selection and server capability before opening, owns an independent dialog, and cleans up its command and subscriptions. It uses the same shell commands to review generated configuration and submit deployment jobs. These interfaces do not add new frame permissions.
Review before applying
Usestudio.request for authenticated requests relative to /api/:
plan, blockers, manifest_revision, recorded deployment state, and history. It reviews saved configuration; it does not deploy. If configuration is missing, use deployment/inspect to discover inputs and deployment/propose to produce a source proposal, as the bundled service does.
Only after the user selects the apply action, check unsaved edits and use the exact project, environment, and revision associated with the review:
Recover and verify
Test missing project selection, disabled deployment, an invalid environment, a valid review, job failure, and project changes while requests are pending. Opening or reviewing the example does not require running containers. Test actual apply only against an authorized deployment target. Use?safe-ui=1 to restore the bundled deployment UI for comparison. Launch with --safe-ui to exclude all external packs, including builder defaults and resources. Two packs claiming fused-studio/deployment fail composition; load order cannot resolve competing replacements.