Deploy from the command line
If you only want a dashboard, installing Orb or Field from the Marketplace needs no terminal. This page is the other way in: for a deploy you script or run from CI, a Home Assistant that manages its resources in YAML, a dashboard you write yourself, or the same steps you’ll take later with a skin of your own. Pick one way per skin; each registers its own copy.
You don’t need to clone or build anything. Each skin’s package ships its resource, the one file Home Assistant loads:
orb-dashboard.js in @dashhaus/orb, field-dashboard.js in @dashhaus/field. A small command-line tool copies it
into Home Assistant, then creates the skin’s own dashboard, which follows the skin as it updates, and any dashboard of
your own: the skin’s card with your cards and rows. After that you change layouts in Home Assistant itself.
CI runs these steps on every change: it packs the release, installs the skins’ packages and @dashhaus/deploy into an
empty folder, writes each skin’s config and deploys it into a simulated Home Assistant.
What you need
Section titled “What you need”- Home Assistant with an admin user.
- Node.js 22 or newer on the computer you deploy from.
- A way to copy a file into Home Assistant’s
/config/wwwfolder: the Terminal & SSH add-on with your public key in itsauthorized_keys, the Samba add-on’s share mounted on your computer, or a Docker volume.
Deploy
Section titled “Deploy”-
Make a folder for your dashboards and install the skins you want and the deploy tool:
Terminal window mkdir my-dashboards && cd my-dashboardsnpm init -ynpm install @dashhaus/orb @dashhaus/field @dashhaus/deploy -
Create a
.envfile in that folder with three settings:.env HA_URL=http://homeassistant.local:8123HA_TOKEN=your-long-lived-access-tokenHA_WWW=root@homeassistant.local:/config/wwwSetting What it is For example HA_URLthe address you open Home Assistant at http://homeassistant.local:8123HA_TOKENan admin's token: Profile → Security → Long-lived access tokens <long-lived access token>HA_WWWHome Assistant's /config/www: user@host:/path over SSH, or a mounted folder root@homeassistant.local:/config/wwwHA_SSH_PORT(optional)only when SSH isn't on port 22 22222HA_WWWis an SSH address like the one above, or a local folder such as/Volumes/config/www. Only the deploy tool usesHA_TOKEN; it never goes into a file it uploads. Keep.envout of version control. -
Create
dashboard.config.mjsnext to it. It names the files to upload and the dashboards to create:dashboard.config.mjs import { resourceFile as field } from "@dashhaus/field/resource";import { resourceFile as orb } from "@dashhaus/orb/resource";/** @type {import("@dashhaus/deploy/config").DeployConfig} */export default {pageTitle: "Home",// Each skin's resource, the file its package ships; leave out the one you don't use.files: [orb, field],dashboards: [// Each skin's own dashboard, on its strategy: it follows the skin as it updates.{ path: "home-orb", title: "Home (Orb)", icon: "mdi:home-variant", strategy: { type: "custom:orb-dashboard" } },{ path: "home-field", title: "Home (Field)", icon: "mdi:knob", strategy: { type: "custom:field-dashboard" } },// A dashboard of your own: a skin's card with your cards and rows, created once and then yours to edit.{path: "my-home",title: "My home",icon: "mdi:floor-plan",card: {type: "custom:dashhaus-orb",title: "Home",rows: [{ title: "Living room", columns: 2, cards: ["light.living_room", "climate.living_room"] },{ title: "Outside", cards: ["weather.home"] },],},},],};A dashboard with a
strategyis the skin’s own: it stores only the strategy, so it lays your house out again each time it opens and follows the skin as it updates. A dashboard with acardis yours: the skin’s card with yourcardsorrows, created once and then edited in Home Assistant. Eachpathneeds a hyphen; Home Assistant requires one. Keep only the skin you want if you don’t need both. The@typecomment lets your editor check the file against@dashhaus/deploy/config; the tool doesn’t need it. -
Deploy:
Terminal window npx dashhaus-deploy --skip-buildThe tool copies each file into
www/, registers it as a dashboard resource, and creates each dashboard the first time.--skip-buildtells it to use the files as installed, since there’s nothing to build. Every step ends in ✓; the last one,Checking that Home Assistant serves it, fetches the file back from Home Assistant, so a wrongHA_WWWshows up here instead of as a blank dashboard.npx dashhaus-deploy --helpprints the options, a config to start from and the.envkeys:Option What it does --config <file>the config to read (default: dashboard.config.mjs in this folder) --skip-buildupload the files as they are; a skin package's file has nothing to build --helpthis text -
Reload any Home Assistant tab that was already open, then pick Home (Orb), Home (Field) or My home in the sidebar.
Home Assistant reads its list of resources when a tab opens. Until you reload, an open tab shows the new dashboard in the sidebar but says “Configuration error” instead of drawing it.
Change the layout
Section titled “Change the layout”A new dashboard lays out every supported entity by area. To choose your own cards, rows and order, open the dashboard and go to ⋮ → Edit dashboard, then the card’s pencil and Show code editor. The preview redraws as you type, and mistakes are listed all together with where they are and what you probably meant:
The card's config has 2 problems:• rows[1].cards[0] (sensor.bedroom_temperature): unknown key "humdity" — did you mean "humidity"?• rows[2].cards[3]: scene.movie_night: scene.* entities have no card yetTo put a skin’s card on another dashboard, add Orb or Field from the card picker. It starts from the generated layout for your house. Put it in a Panel view so it gets the full width.
Lay it out in YAML has both skins’ keys, pages and the bottom nav.
Update
Section titled “Update”Update the packages and run the same command again:
npm update @dashhaus/orb @dashhaus/field @dashhaus/deploynpx dashhaus-deploy --skip-buildRedeploying replaces each file and leaves your dashboards alone, so layouts you edited in Home Assistant are kept. Open tabs pick up the new version when they reload.