Documentation

Everything Packly does, in the order it does it. Run every command from your project root: Packly reads packly.ini from the current directory.

1. Install

Packly ships as 5 standalone binaries. Download the one for your platform from the latest release:

PlatformFile
Linux x64packly-linux-amd64
Linux ARM64packly-linux-arm64
macOS Intelpackly-macos-amd64
macOS Apple Siliconpackly-macos-arm64
Windows x64packly-windows-amd64.exe

Linux and macOS: make it executable and put it in your PATH.

$ chmod +x packly-linux-amd64
$ sudo mv packly-linux-amd64 /usr/local/bin/packly
$ packly                # prints the available commands

Windows: rename the file to packly.exe and place it in a folder listed in your PATH.

2. Quick start

Create packly.ini at your project root, or let the first packly install generate a default one, then fill it in:

[build]
source = assets
target = public

[dependencies]
bootstrap = https://github.com/twbs/bootstrap/archive/refs/tags/v5.3.3.zip
confetti  = https://cdn.jsdelivr.net/npm/canvas-confetti@1.9.2/dist/confetti.module.mjs

[sass]
version     = 1.79.2
entrypoints = styles/app.scss

Then run:

$ packly install        # downloads into assets/vendor/
$ packly build          # copies to public/build/ and compiles Sass
$ packly build --watch  # same, then rebuilds on every change

Your files are now in public/build/. See Using the files in HTML to load them in your pages.

3. packly.ini reference

If the file does not exist, the first packly install or packly build creates it with defaults. It has three sections.

[build]

KeyDefaultMeaning
sourceassetsFolder holding your own assets and the vendor/ folder.
targetpublicPublic folder. Packly always writes into <target>/build/.
ignoreemptyComma-separated paths, relative to source, never copied to the build. Example: vendor/bootstrap when you only need its Sass sources.

[dependencies]

One line per dependency. The key is the folder name, the value is one or more comma-separated URLs.

[dependencies]
; single file โ†’ assets/vendor/jquery/jquery.min.js
jquery = https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js
; several files in one folder
leaflet = https://unpkg.com/leaflet@1.9.4/dist/leaflet.js, https://unpkg.com/leaflet@1.9.4/dist/leaflet.css
; ZIP archive โ†’ extracted into assets/vendor/bootstrap/
bootstrap = https://github.com/twbs/bootstrap/archive/refs/tags/v5.3.3.zip
Always put the version in the URL. A URL without a version (unpkg.com/leaflet/dist/leaflet.css) can return a different file tomorrow.

[sass]

KeyDefaultMeaning
version1.79.2 in the generated filedart-sass version to download. Required as soon as you have entrypoints.
entrypointsemptyComma-separated files, relative to source, compiled to CSS. Example: styles/app.scss, styles/admin.scss. Leave empty to skip Sass: nothing is downloaded.
stylecompressedCSS output style: compressed (minified) or expanded (readable, handy in development). Any other value stops Packly with an error.
sourcemapfalseSet to true to write a .css.map file next to each CSS file.

4. packly install

$ packly install
$ packly install --force   # delete and download every dependency again
  1. Creates <source>/vendor/ and a .gitignore inside it that ignores everything.
  2. Processes dependencies in alphabetical order.
  3. For each URL, skips it if it was already installed. Packly keeps a hidden marker file per URL, so changing a URL triggers a new download.
  4. A URL ending in .zip is extracted. If the archive starts with a root folder (like GitHub archives), that folder is removed so files land directly in vendor/<key>/. Folders named docs, site, test, tests, demo, samples and .github are skipped.
  5. Any other URL is saved as a single file, named after the last part of the URL, query string removed.

Archive entries that would write outside the target folder (../) are rejected. Downloads time out after 30 seconds. Any failed download or extraction stops Packly with an error; dependencies already installed stay installed.

5. packly build

$ packly build
  1. Deletes <target>/build/, then recreates it. Never put files there by hand.
  2. Copies every file of source into it, keeping the folder structure, except .scss and .sass files, hidden files and folders, and paths listed in ignore.
  3. Compiles each Sass entrypoint (next section).

6. Sass

On the first build with at least one entrypoint, Packly downloads the official dart-sass release for your OS and architecture into .sass/ at your project root, with a .gitignore. This works on the same 5 platforms as Packly itself.

Each entrypoint is compiled to the same relative path, with a .css extension:

assets/styles/app.scss  โ†’  public/build/styles/app.css

By default the CSS is compressed and no source map is written. For development, switch both in packly.ini:

[sass]
style     = expanded
sourcemap = true   ; also writes public/build/styles/app.css.map

An entrypoint that does not exist only prints a warning. A Sass compilation error stops Packly and shows the dart-sass output.

To change the Sass version, edit version and delete the .sass/ folder.

7. Watch mode

$ packly build --watch

Builds once, then watches every folder of source except vendor/ and ignored paths. After a change, it waits 300 ms for other changes, then runs a full build. New folders are watched automatically. Hidden files and editor backup files (ending in ~) do not trigger a build.

Watch mode stops on build errors. A Sass syntax error, for example, ends the process: fix the file and run packly build --watch again.

Since vendor/ is not watched, run packly install then packly build after changing dependencies.

8. Using the files in HTML

Packly never touches your templates. You reference the files in /build/ yourself:

<link rel="stylesheet" href="/build/styles/app.css">

<script type="importmap">
{
  "imports": {
    "confetti": "/build/vendor/confetti/confetti.module.mjs"
  }
}
</script>

<script type="module" src="/build/js/app.js"></script>

Then import confetti from 'confetti'; works natively in the browser.

9. Git and CI

Commit packly.ini. Packly already ignores vendor/ and .sass/. Add the build output to your own .gitignore:

public/build/

In CI or on deploy, run both commands:

$ packly install
$ packly build