{"_id":"@pic0/ssg","_rev":"2-c41d1ef932efc008b7835d46ca1164d5","name":"@pic0/ssg","dist-tags":{"latest":"6.0.1"},"versions":{"6.0.0":{"name":"@pic0/ssg","version":"6.0.0","keywords":["static-site-generator","ssg"],"author":{"name":"Wolfram Kriesing"},"license":"agpl-3.0","_id":"@pic0/ssg@6.0.0","maintainers":[{"name":"wolframkriesing","email":"w+npm@kriesing.de"}],"bin":{"picossg":"src/build-cli.js"},"dist":{"shasum":"4fa9d4166c0f4e5b4ffc9e5a69bb14126c58f6b4","tarball":"https://registry.npmjs.org/@pic0/ssg/-/ssg-6.0.0.tgz","fileCount":18,"integrity":"sha512-tTSkUqzzOu30HOp3QdUmnlCPwO1qg2XWmig2yBmm2jCwC7ZOnBTF6z3win1K7yc7fk3MfjATUL9Txk5LT7ntbA==","signatures":[{"sig":"MEUCIQCyQIhYE9CaWYEovTP34JYK3FqmdJMnlmnTkDkxeNaC6QIgCTGg/pW8skSVVD3+d+3IE4mPlWZ2fVWvQ3OTer/9W1I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":92743},"main":"src/build-cli.js","type":"module","gitHead":"ab377789c2a76c93f42af989aa442d17c0065be1","scripts":{"test":"diff -ru test/golden-ref _output > /tmp/diffout; cat /tmp/diffout | diffstat; if [ -s /tmp/diffout ]; then echo ❌ Differences found; else echo ✅ OK; fi","build":"node src/build-cli.js -c test/content -o _output","serve":"http-server _output -p 8899","test:ci":"npm run test:preprocess && npm run build && npm run test && npm run build && npm run test:smoke","testdiffs":"cat /tmp/diffout","build:site":"node src/build-cli.js -c picossg.dev -o _picossg.dev","serve:site":"http-server _picossg.dev -p 8000","test:smoke":"./tools/smoke test/smoke.yaml","test:watch":"nodemon --quiet --legacy-watch --watch _output --watch test/golden-ref --watch src/build.js --ext '*' --exec \"bash -c 'npm test --silent'\"","build:watch":"node --watch-path test/content --watch-path src src/build-cli.js -c test/content -o _output","postinstall":"bash -c 'mkdir -p ./tools && file=smoke-v2.4.0-Linux-x86_64 && [ \"$(uname -s)\" = \"Darwin\" ] && file=smoke-v2.4.0-Darwin-arm64 && curl -sL https://github.com/SamirTalwar/smoke/releases/download/v2.4.0/$file -o ./tools/smoke && chmod +x ./tools/smoke'","build:watch:dev":"node --watch src/build-cli.js -c test/content -o _output","test:preprocess":"node src/build-cli.js -c test/content -o _output -x _config_preprocess_assertions.js","build:site:watch":"nodemon --quiet --legacy-watch --watch picossg.dev --watch CHANGELOG.md --ext '*' --exec \"bash -c 'npm run build:site'\"","test:preprocess:watch":"node --watch src/build-cli.js -c test/content -o _output -x _config_preprocess_assertions.js"},"_npmUser":{"name":"wolframkriesing","email":"w+npm@kriesing.de"},"repository":{"url":"https://codeberg.org/wolframkriesing/picossg.git","type":"git"},"_npmVersion":"10.9.2","description":"The pico static side generator, the simplest one I ever wanted and hopefully 'found'.","directories":{},"_nodeVersion":"23.11.0","dependencies":{"yaml":"^2.8.1","chalk":"^5.5.0","nunjucks":"^3.2.4","markdown-it":"^14.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"nodemon":"^3.1.10","http-server":"^14.1.1"},"_npmOperationalInternal":{"tmp":"tmp/ssg_6.0.0_1754425332794_0.28537247464533855","host":"s3://npm-registry-packages-npm-production"}},"6.0.1":{"name":"@pic0/ssg","publishConfig":{"access":"public"},"description":"The pico static side generator, the simplest one I ever wanted and hopefully 'found'.","version":"6.0.1","main":"src/build-cli.js","type":"module","bin":{"picossg":"src/build-cli.js"},"scripts":{"build":"node src/build-cli.js -c test/content -o _output","start":"http-server _output -p 8899","build:watch":"node --watch-path test/content --watch-path src src/build-cli.js -c test/content -o _output","build:watch:dev":"node --watch src/build-cli.js -c test/content -o _output","build:site":"node src/build-cli.js -c picossg.dev -o _picossg.dev","build:site:watch":"nodemon --quiet --legacy-watch --watch picossg.dev --watch CHANGELOG.md --ext '*' --exec \"bash -c 'npm run build:site'\"","start:site":"http-server _picossg.dev -p 8000","test:preprocess":"node src/build-cli.js -c test/content -o _output -x _config_preprocess_assertions.js","test:preprocess:watch":"node --watch src/build-cli.js -c test/content -o _output -x _config_preprocess_assertions.js","test":"diff -ru test/golden-ref _output > /tmp/diffout; cat /tmp/diffout | diffstat; if [ -s /tmp/diffout ]; then echo ❌ Differences found; else echo ✅ OK; fi","test:watch":"nodemon --quiet --legacy-watch --watch _output --watch test/golden-ref --watch src/build.js --ext '*' --exec \"bash -c 'npm test --silent'\"","test:ci":"npm run test:preprocess && npm run build && npm run test && npm run build && npm run test:smoke","testdiffs":"cat /tmp/diffout","test:smoke":"./tools/smoke test/smoke.yaml","dev:install":"bash -c 'mkdir -p ./tools && if [ \"$(uname -s)\" = \"Darwin\" ]; then file=smoke-v2.4.0-Darwin-arm64; else file=smoke-v2.4.0-Linux-x86_64; fi && curl -sL https://github.com/SamirTalwar/smoke/releases/download/v2.4.0/$file -o ./tools/smoke && chmod +x ./tools/smoke'"},"keywords":["static-site-generator","ssg"],"author":{"name":"Wolfram Kriesing"},"license":"agpl-3.0","repository":{"type":"git","url":"https://codeberg.org/wolframkriesing/picossg.git"},"dependencies":{"chalk":"^5.5.0","markdown-it":"^14.1.0","nunjucks":"^3.2.4","yaml":"^2.8.1"},"devDependencies":{"http-server":"^14.1.1","nodemon":"^3.1.10"},"_id":"@pic0/ssg@6.0.1","gitHead":"ace41c8cb8efa373dcbeb2abd6afac39d4fab70c","_nodeVersion":"23.11.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-taOe+4ZCqo9EDk5gkZWogxlt0/s46bDr1VHbvp/Z5SokLrzA6c//EpuX/fpdwKBkmC8UtHl031MprrQCRPqDnA==","shasum":"19f442ec39b3c52d391abe102f9f2ccd89147e13","tarball":"https://registry.npmjs.org/@pic0/ssg/-/ssg-6.0.1.tgz","fileCount":18,"unpackedSize":95332,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCbh1flvpZgJFHz3AKXeqZ4GhtwUosMM+sB3WlumWdQoAIhAKaygKDscrYnhH4KplthXSp4ZI5j75AKnYOh7eI0g9a6"}]},"_npmUser":{"name":"wolframkriesing","email":"w+npm@kriesing.de"},"directories":{},"maintainers":[{"name":"wolframkriesing","email":"w+npm@kriesing.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ssg_6.0.1_1770890682546_0.7789938394542619"},"_hasShrinkwrap":false}},"time":{"created":"2025-08-05T20:22:12.659Z","modified":"2026-02-12T10:04:42.811Z","6.0.0":"2025-08-05T20:22:12.993Z","6.0.1":"2026-02-12T10:04:42.697Z"},"author":{"name":"Wolfram Kriesing"},"license":"agpl-3.0","keywords":["static-site-generator","ssg"],"repository":{"type":"git","url":"https://codeberg.org/wolframkriesing/picossg.git"},"description":"The pico static side generator, the simplest one I ever wanted and hopefully 'found'.","maintainers":[{"name":"wolframkriesing","email":"w+npm@kriesing.de"}],"readme":"# picossg\n\nThe pico static site generator – the simplest one I ever wanted and hopefully \"found\".\nSee the [picossg.dev](https://picossg.dev) for more information.\n\n## What it does\n\npicossg processes:\n- files from the `content` directory into the `output` directory, processing the files if needed\n- Markdown files (`.md`) using [markdown-it](https://markdown-it.github.io/)\n- Nunjucks templates (`.njk`) using [nunjucks](https://mozilla.github.io/nunjucks/)\n- Combined Nunjucks + Markdown files (`.md.njk`)\n- Static assets (copied as-is)\n\nIt transforms these files into a static website with a 1:1 mapping from source director+file structure to output.\n\n## How to use it\n\n- Make sure to have nodejs installed [see here](https://nodejs.org/en/download/)\n- open a terminal\n- run `npx @pic0/ssg -c content -o output`, this builds all files in the `content` directory into the `output` directory\n- to serve, open another terminal, run `npx http-server output -p 0` (`-p 0` searches for an available port, staring with 8080), open http://localhost:8080 (or the right port) in your browser\n  and the files in `content` are processed and served from `output`\n\n## Getting Started\n\n- create your new site's directory: `mkdir my-site; cd my-site`\n- create the `content` directory: `mkdir content`\n- put the `package.json` in the root of the project\n```json\n{\n  \"name\": \"my-ssg-site\",\n  \"version\": \"1.0.0\",\n  \"scripts\": {\n    \"build\": \"npx @pic0/ssg -c content -o output\",\n    \"start\": \"npx http-server output -p 0\",\n    \"build:watch\": \"npx nodemon --quiet --legacy-watch --watch content --ext '*' --exec \\\"bash -c 'npm run build'\\\"\"\n  }\n}\n```\n- put some `*.html.md` or `*.html.njk` file into the `content` directory, e.g. start with `index.html.md`\n  (you can start with just putting \"Hello World!\" in there, for more [see \"Create a Site\" in the docs](https://picossg.dev/docs/create-site/))\n- run `npm run build:watch` in one terminal to start building the site\n- run `npm start` in another terminal to start the server\n- open http://localhost:8080 in your browser to see the site (the port may be different, see the output of the `npm start` command)\n\nThe `npm run build` script above (the code `npx @pic0/ssg -c content -o output`) will run the remote picossg\npackage (which is published on npmjs.org) and look for files in the `content` directory, process them and put them to the `output` directory.  \nThe `npm run start` (or can also be called as `npm start`) script (the script `npx http-server output -p 0`) \nwill run the remote package `http-server` (also published on npmjs.org) and serve the files from the `output` directory on an available port (mostly 8080)\non your local computer, which you can then see in your browser at http://localhost:8080.  \nThe `npm run build:watch` script uses yet another remote package `nodemon` to watch the `content` directory for changes \nand re-run the build command whenever a file changes, so you don't have to call `npm run build` every time you change a file.\n\n## Examples\n\n- see a [basic example in this repo](examples/1-basic), it contains a simple [index.html.njk](examples/1-basic/content/index.html.njk) file, start reading there\n- a more complex example is the [picossg.dev](https://picossg.dev) site, which is built with picossg of course,\n  and contains a lot of examples, see the [source code in this repo here](https://codeberg.org/wolframkriesing/picossg/src/branch/main/picossg.dev)\n- a bit more complex example is a design implemented for the JSCraftCamp.org site for 2025,\n  find it in the [jscc-site-2025 repo](https://codeberg.org/wolframkriesing/jscc-site-2025) – it uses only picossg to build the site\n- [my blog](https://picostitch.com) runs only on picossg [the source code is here](https://codeberg.org/wolframkriesing/picostitch-com)\n\n## Philosophy\n\nThe core philosophy of picossg is simplicity and predictability:\n\n1. **1:1 file mapping** – Each source file maps directly to an output file with the same path (except for extension changes)\n2. **Minimal magic** – The only \"magic\" is:\n   - Files starting with underscore (`_*`) are excluded from the output\n   - Template files (`.njk`, `.md`) are processed, a `file.html.md.njk` processes nunjucks and markdown and outputs `file.html`, \n     just by working off the extensions from the last one backward. Allows also for `style.css.njk` to be processed and output as `style.css` if desired.\n   - All other files are copied as-is\n3. **Asset handling** – Any assets (CSS, images, etc.) in the source directory are copied to the output, as mentioned in 2. already\n4. **_config.js** – An optional `_config.js` file in the content directory can provide `preprocess()` and `postprocess()` functions, they both receive a map of all files\n   and can be used to preprocess the content before rendering or postprocess the output after rendering.\n\nThere are no complex configuration options, no plugins, no middleware – just a simple, predictable build process.\n\n## How to develop PicoSSG\n\nPicoSSG is developed in JavaScript, using Node.js. It uses Nunjucks for templating and Markdown-it for Markdown processing.\nTo ensure that PicoSSG really still works as with the last commit, there are tests.\nThe tests are on various levels:\n1) the most essential ones are those you find in `test/content` and `test/golden-ref`, they compare the output of the build with the expected output,\n   these tests are run `npm test` and `npm run test:watch` (in watch mode),\n   with `npm run testdiffs` you can see the differences between the output and the expected output in case the tests failed\n2) the second layer is testing the preprocessor, which finds all the files to be processed, see the file [test/content/_config_preprocess_assertions.js]\n   the function `const preprocess()` at the bottom, the test names should explain what is tested. These tests are separate because they\n   run during the build step, see the `npm run test:preprocess` command it just runs the build step with using the config file `_config_preprocess_assertions.js`, which contains our tests.\n   You can run these in watch mode too, which is `npm run test:preprocess:watch`.\n3) the third layer is the smoke tests, which are run with `npm run test:smoke` (there is no watch mode).\n   These I introduced when I started testing the better error messages that are given during the build process, and for that [smoke](https://github.com/SamirTalwar/smoke)\n   is just THE TOOL. Each test runs a build and the test is about comparing the console output of the build with some expected output.\n   See the [test/smoke.yaml] file, which contains the tests, and the [test/njk-errors] directory, which contains the \"broken\" templates that are used to test the error messages.\n\n### Set up\n\nTo develop picossg, clone the repository and install the dependencies:\n\n- `git clone https://codeberg.org/wolframkriesing/picossg.git`\n- `cd picossg`\n- `npm i`\n- `npm run dev:install` which will install tools needed in development, like [smoke](https://github.com/SamirTalwar/smoke), which need to be installed once\n\n### Does it all work?\n\nYou might hate tests, but the least these do here is: tell you if all the things work as expected, on your machine ;) and if it makes sense to even\nstart changing any code. Because if tests fail already the setup might need some love first. (Might also be that the provided setup has a flaw, then report it please.)\nSo I encourage you to run the tests first.\n\n- `npm run test:ci` runs all the tests, just not in watch mode\n- `npm run test:watch` runs the golden-ref tests in watch mode, and re-runs on any content change\n- `test:preprocess:watch` runs the preprocess tests in watch mode, they can NOT run in parallel with the `npm run test:watch` tests,\n  since they are using the same `_output` directory and would overwrite each other, therefore the final `nom run test:ci` command does the \"final\" test before a release\n- `npm run test:smoke` runs the tests that tests the njk error messages\n \nThe `npm test` runs a simple `diff` command, it compares the generated `_output` directory with the expected output in `test/golden-ref`.\n\nSince the default `npm run build:watch` runs multiple times when you change the source code, e.g. `build.js`\nthere is also `build:watch:dev` which only watches the code to be run and NOT the content to be generated.\n\n## Run it via docker\n\n- you can use `docker-compose run --rm --remove-orphans picossg_node node src/build-cli.js -c content -o _output` to run the build\n- to build the content from the directory [picossg.dev](./picossg.dev) into `_picossg.dev` directory you can use `docker-compose run --rm --remove-orphans picossg_node npm run build:site`\n\n## (To be) Listed at\n\n- [ ] https://www.markdownguide.org/tools/\n- [ ] https://www.staticgen.com/\n- ","readmeFilename":"README.md"}