Skip to content

v2.0.0

Choose a tag to compare

@stamat stamat released this 31 Jul 19:43
· 57 commits to main since this release

Poops 2.0 has no new features. It is the release where the core loop β€” watch,
build, reload β€” stops carrying old dependencies and old spellings, and where the
compat shims that survived the whole 1.x line finally go.

Changed

  • Poops now requires Node.js 22 or newer. Node 20 reached end of life in
    April 2026, and the dependencies the dev loop is built on β€” the file watcher,
    esbuild β€” assume a modern runtime anyway. CI tests on Node 22 and 24, on both
    Ubuntu and Windows.

  • Live reload is now served by Poops itself, on the server port. The
    livereload package is gone, and with it a second port, an old websocket
    stack, and the snippet you had to paste into your templates.

    "livereload": true alongside "serve" is all it takes. Poops answers
    /__poops_reload as a server-sent events stream and appends a small client
    script to each HTML page it serves β€” appends it to the response, so nothing
    lands in your build output. Behaviour is unchanged otherwise: one reload per
    save once the build settles, CSS-only builds swap stylesheets in place
    instead of reloading, and the browser reconnects by itself after a restart.

    Migrating: delete the livereload.js snippet from your templates (a leftover
    one is harmless β€” it will 404 quietly), and drop livereload.port,
    livereload.exclude, livereload.extraExts and livereload.exts from your
    config. The last three had already stopped doing anything when the reload
    server stopped watching files in 1.5.1.

  • The file watcher moved from chokidar 3 to chokidar 5. Two majors of
    watcher fixes, and one fewer legacy dependency tree under node_modules.
    Nothing in your config changes: watch has always been a list of directories,
    never globs, so chokidar 4 dropping glob support costs nothing here. Watch
    mode behaves as before β€” one rebuild per save, CSS still hot-swaps, deletions
    still remove their output.

  • esbuild moved from 0.25 to 0.28, and the default target from es2019 to
    es2020.
    esbuild is pre-1.0, so its minor bumps shift output by design;
    absorbing that is what a major of ours is for. Expect small differences in
    your bundles β€” the CommonJS interop helper is more careful around a throwing
    module, and Symbol.for calls are annotated as side-effect free, which makes
    minified output slightly smaller.

    The new default target is the visible half: optional chaining (?.) and
    nullish coalescing (??) are ES2020, and compiling them down for browsers
    that have shipped them since 2020 only made bundles bigger. Entries that set
    their own target are untouched.

  • timeDateFormat is now dateFormat. It sets the default format for the
    date filter; the old name said the same thing twice. Deprecated and still
    read through 2.x, gone in 3.0.

    Engines see the rename too: registerFilters({ timeDateFormat, markupOut })
    is now registerFilters({ dateFormat, markupOut }). This is a hard rename β€”
    it lands before the engine interface becomes public API in this same release,
    so a custom engine must update its parameter name for 2.0.

  • output is now out in the markup sub-features. llms, nav, feed,
    searchIndex, sitemap and robots name their output file with out, the
    same word every entry in the config already uses:

    { "nav": { "out": "nav.json", "root": "docs" } }

    output is deprecated but still honoured through 2.x, warning once per
    feature, and stops working in 3.0. The string shorthand ("nav": "nav.json")
    is unaffected.

  • Markup settings belong under markup.options. markup now has the shape
    every other entry has β€” in, out, and everything else in options:

    {
      "markup": {
        "in": "src/markup",
        "out": "dist",
        "options": {
          "engine": "nunjucks",
          "site": { "title": "My Site" },
          "searchIndex": "search-index.json"
        }
      }
    }

    1.x read engine, site, data, includePaths, timeDateFormat,
    collections, searchIndex, sitemap, llms, robots, feed, nav,
    baseURL and autoescape at the markup. level as well. That placement is
    deprecated but still honoured through 2.x β€” each stray key logs a warning
    naming its new home β€” and stops working in 3.0. Where both are set, options
    wins.

Added

  • The markup engine interface is public API as of 2.0. markup.options.engine
    has always accepted any importable module, and
    poops-shopify ships a production
    engine against it β€” but nothing said the interface was stable, so a rename in
    a patch release could have broken it silently. It is documented in
    the engine API reference, semver applies to it from here on,
    and a contract test asserts both builtin engines still expose the shape β€” a
    failing test is a breaking change caught before it ships.

  • serve.base defaults to the markup out directory. Nearly every config
    set it to the path it had just built into. Set it only when the server should
    serve somewhere else; an explicit value still wins, and a project with no
    markup still serves the working directory.

Removed

  • The ssg config key. It has been an alias for reactor since the rename,
    and it was the last compatibility shim in the codebase. A config still using
    it now gets told what to call it instead:

    [info] Config key "ssg" is renamed to "reactor" in 2.0 β€” ignored.
    

Internal

  • Dependency bumps. book-of-spells 1.3 β†’ 1.4 and a postcss patch, both
    routine. Dev-only: neostandard 0.12 β†’ 0.13, and sulphuris 2 β†’ 4 for the
    example site's styles. ESLint stays on 9 β€” neostandard 0.13 still declares a
    peer of eslint@^9, so 10 has to wait for it.

Fixed

  • "Edit this page on GitHub" links work for collection items on Windows. A
    collection item's filePath kept native separators while a regular page's was
    posix, so on Windows the link for a post came out as
    …/edit/main/src/posts\hello.md. Both are posix now.

  • The image cache is read correctly across platforms. Its lookups all key on
    posix paths, so a cache written on Windows β€” committed next to the images it
    describes, or built in CI β€” matched nothing and galleries came up empty. Keys
    and variant paths are normalized on read. The output-directory containment
    check also no longer accepts a sibling directory whose name merely starts with
    the output dir's (dist-old for dist).

  • A style edit hot-swaps the stylesheet the page actually links. With
    minify on, the reload chain was told about site.css while the page linked
    site.min.css β€” no stylesheet matched, so every style edit reloaded the whole
    page instead of swapping the CSS. Both spellings are now reported (and with
    justMinified, only the minified one, since the other is deleted).

Full Changelog: v1.9.8...v2.0.0