One command, three subcommands, four flags. It exists because Deck has no build step
and most of the people it is for are not running one — they want the files in a folder
and a tag to paste. npx runs it without installing anything.
That is a working page. Open it and every component in Deck is available to it, with
no config file and nothing to compile. If you are using npm properly you can also
npm install @echodial/deck and point your bundler at
@echodial/deck/css — the CLI is for the other case.
Running it with no arguments, or with a subcommand it does not recognise, prints the
usage summary and exits cleanly. Piping the output into head or
less is handled: the broken pipe is treated as the end of the output
rather than as a crash.
Commands
npx @echodial/deck init [dir]
Copies Deck's built assets out of the package and into your project, then prints the tags to paste into your layout. This is the whole install for anyone not using npm as a build tool, which is most of the people Deck is for.
Default argument
assets/deck, relative to the current directory.
What it does
Creates the target directory, including any parents.
Skips a file that is already there, and says how many it skipped. Pass --force to overwrite.
Counts a file that is not in dist/ as missing rather than failing, and tells you to run the build.
Prints the exact <link> and <script> tags for what it copied.
Worth knowing
The snippet it prints strips a leading public_html/, public/, web/, htdocs/, httpdocs/, www/, wwwroot/, dist/ or static/ from the path, because the folder on disk is not the folder in the URL. If your document root is named something else, the printed path will have that segment in it and you will need to take it out yourself.
Writes a complete starter HTML page: a skip link, a sticky navbar with a working theme toggle, a hero, a card grid, a form field, a live brand-hue slider and a toast button. It is a page that already does something rather than an empty shell.
Default argument
index.html, in the current directory.
What it does
Refuses to overwrite an existing file, and says so. Pass --force to replace it.
Creates any parent directories the path needs.
Assumes the assets are at /assets/deck/. Run init first, or edit the two paths at the top.
Includes an @layer app.pages block, so the first CSS you write is already in the right place to beat Deck without !important.
Worth knowing
The page it writes is a demonstration, not a template to build a product on top of unchanged — it has an inline oninput and an inline onclick in it, which are fine for showing what a line of code does and are not how you should write an application.
Lists what is actually in the installed package's dist/, with each file's size. Useful for deciding what to copy, and for confirming a build produced what you expected.
Default argument
Nothing to pass.
What it does
Reads the package's own dist/, not your project.
Sizes are the raw bytes on disk, not compressed — the number your server sends is smaller.
Directories are listed with a trailing slash and not recursed into.
Worth knowing
An empty or short listing means the package was installed without a build. Published releases ship dist/; a git clone does not, and needs npm run build first.
Flags are position-independent — anywhere after the subcommand is fine — and unknown
ones are ignored rather than rejected.
Command line flags
Flag
Applies to
What it does
--min
init
Copy deck.min.css instead of deck.css, and print the minified name in the snippet. The readable build is easier to learn from; the minified one is what you deploy.
--bundle
init
Copy one combined deck.bundle.min.js instead of the three separate scripts. One request instead of three, at the cost of sending the adapter code to pages that do not use it.
--css-only
init
Skip the scripts entirely. Everything HTML and CSS can carry on their own still works — the dialog-based overlays, <details> accordions, tabs, forms, the whole layout.
--force
init, starter
Overwrite files that already exist. Without it both commands leave what is there alone.
What init copies
The set depends on the flags. deck-icons.svg is always included, because
the icon component is useless without it and the script resolves the sprite against
its own location — so as long as the two land in the same folder, nothing needs
configuring.
To load the sprite from somewhere else — a CDN, or a hashed asset path — put
data-deck-icons on the script tag. init prints that line as
a reminder every time it runs.
A PHP project does not need the Node CLI at all. composer require
echodial/deck installs the package, and composer deck-publish
copies the same files into your public directory — once your own
composer.json wires the publisher in, because Composer never runs a
dependency's scripts. The wiring is on the PHP helper
page.
Scripts in the package itself
These are for working on Deck rather than with it, and they run in a clone of
the repository rather than through npx.
npm scripts in the Deck repository
Script
What it does
npm run build
Concatenates src/*.css into dist/, minifies, bundles the scripts, and writes the size report. Needed after a clone, because dist/ is not in git.
npm run demo
Builds, then publishes the result into public_html/assets/ so the demo and these docs are running against the current source.
npm start
Serves public_html/ on port 4321 with PHP's built-in server.
npm run clean
Removes dist/.
node tools/docs/extract.mjs
Regenerates dist/api.json — every class, token, layer and source line — which is what every table on this site is built from.
node tools/docs/verify.mjs
Fails the build if a page claims a class that does not exist, uses one that does not exist, or if a new class was added with no documentation and no backlog entry.
When it does not do what you expected
It says files are "not built". The installed package has no
dist/. That is normal in a git clone — run npm run build
in the package. A release from npm always ships it.
It says everything was already there. That is the skip behaviour,
not a failure. Add --force to overwrite.
The page loads but has no styling. The path in the printed snippet
is a URL, and it assumed a standard document root name. Check that the
href actually resolves from the browser.
Icons are empty boxes.deck-icons.svg is not beside
deck.js. Either put it there or set
data-deck-icons on the script tag.
Nothing interactive works. The scripts were skipped —
--css-only, or the tags were not pasted in. Everything that needs
script is listed at the end of the
JavaScript reference.