{"id":14155147,"url":"https://github.com/foundation/panini","last_synced_at":"2026-02-14T16:01:12.732Z","repository":{"id":27783511,"uuid":"31272277","full_name":"foundation/panini","owner":"foundation","description":"A super simple flat file generator.","archived":false,"fork":false,"pushed_at":"2025-11-15T09:18:54.000Z","size":536,"stargazers_count":595,"open_issues_count":43,"forks_count":103,"subscribers_count":30,"default_branch":"develop","last_synced_at":"2025-11-15T11:26:36.535Z","etag":null,"topics":["data","flat-file","gulp","handlebars","handlebars-helpers","handlebars-partials","hbs","html","javascript","json","panini","partials","yaml"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/foundation.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-02-24T17:31:10.000Z","updated_at":"2025-11-10T14:13:04.000Z","dependencies_parsed_at":"2024-11-14T18:45:10.865Z","dependency_job_id":null,"html_url":"https://github.com/foundation/panini","commit_stats":{"total_commits":140,"total_committers":33,"mean_commits":4.242424242424242,"dds":0.5071428571428571,"last_synced_commit":"72bab29994ab7422a17ff41d6b3103d65bb0856d"},"previous_names":["zurb/panini"],"tags_count":20,"template":false,"template_full_name":null,"purl":"pkg:github/foundation/panini","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foundation%2Fpanini","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foundation%2Fpanini/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foundation%2Fpanini/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foundation%2Fpanini/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/foundation","download_url":"https://codeload.github.com/foundation/panini/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foundation%2Fpanini/sbom","scorecard":{"id":407859,"data":{"date":"2025-08-11","repo":{"name":"github.com/foundation/panini","commit":"72bab29994ab7422a17ff41d6b3103d65bb0856d"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.8,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":1,"reason":"Found 3/21 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Warn: project license file does not contain an FSF or OSI license."],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'develop'","Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 12 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"15 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-w573-4hg7-7wgq","Warn: Project is vulnerable to: GHSA-4gmj-3p3h-gm8h","Warn: Project is vulnerable to: GHSA-vfrc-7r7c-w9mx","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-5v2h-r2cx-5xgj","Warn: Project is vulnerable to: GHSA-rrrm-qjm4-v8hf","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-qrpm-p2h7-hrv2","Warn: Project is vulnerable to: GHSA-mwcw-c2x4-8c55","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-18T21:50:55.033Z","repository_id":27783511,"created_at":"2025-08-18T21:50:55.033Z","updated_at":"2025-08-18T21:50:55.033Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29448912,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-14T15:52:44.973Z","status":"ssl_error","status_checked_at":"2026-02-14T15:52:11.208Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["data","flat-file","gulp","handlebars","handlebars-helpers","handlebars-partials","hbs","html","javascript","json","panini","partials","yaml"],"created_at":"2024-08-17T08:02:15.521Z","updated_at":"2026-02-14T16:01:12.562Z","avatar_url":"https://github.com/foundation.png","language":"JavaScript","readme":"# Panini\n\n[![Build Status](https://travis-ci.org/foundation/panini.svg?branch=master)](https://travis-ci.org/foundation/panini) [![npm version](https://badge.fury.io/js/panini.svg)](https://badge.fury.io/js/panini) [![Dependency Status](https://david-dm.org/foundation/panini.svg)](https://david-dm.org/foundation/panini)\n\nA super simple flat file generator for use with Gulp. It compiles a series of HTML **pages** using a common **layout**. These pages can also include HTML **partials**, external Handlebars **helpers**, or external **data** as JSON or YAML.\n\nPanini isn't a full-fledged static site generator\u0026mdash;rather, it solves the very specific problem of assembling flat files from common elements, using a templating language.\n\n## Installation\n\n```bash\nnpm install panini --save-dev\n```\n\n## Usage\n\nFeed Panini a stream of HTML files, and get a delicious flattened site out the other end.\n\n```js\nvar gulp = require('gulp');\nvar panini = require('panini');\n\ngulp.task('default', function() {\n  gulp.src('pages/**/*.html')\n    .pipe(panini({\n      root: 'pages/',\n      layouts: 'layouts/',\n      partials: 'partials/',\n      helpers: 'helpers/',\n      data: 'data/'\n    }))\n    .pipe(gulp.dest('build'));\n});\n```\n\nNote that Panini loads layouts, partials, helpers, and data files once on first run. Whenever these files change, call `panini.refresh()` to get it up to date. You can easily do this inside a call to `gulp.watch()`:\n\n```js\ngulp.watch(['./src/{layouts,partials,helpers,data}/**/*'], [panini.refresh]);\n```\n\n## Options\n\n### `root`\n\n**Type:** `String`\n\nPath to the root folder all pages live in. This option does not pull in the files themselves for processing\u0026mdash;that's what `gulp.src()` is for. This setting tells Panini what the common root of your site's pages is.\n\n### `layouts`\n\n**Type:** `String`\n\nPath to a folder containing layouts. Layout files can have the extension `.html`, `.hbs`, or `.handlebars`. One layout must be named `default`. To use a layout other than the default on a specific page, override it in the Front Matter on that page.\n\n```html\n---\nlayout: post\n---\n\n\u003c!-- Uses layouts/post.html as the template --\u003e\n```\n\nAll layouts have a special Handlebars partial called `body` which contains the contents of the page.\n\n```html\n\u003c!-- Header up here --\u003e\n{{\u003e body}}\n\u003c!-- Footer down here --\u003e\n```\n\n### `pageLayouts`\n\n**Type:** `Object`\n\nA list of presets for page layouts, grouped by folder. This allows you to automatically set all pages within a certain folder to have the same layout.\n\n```js\npanini({\n  root: 'src/pages/',\n  layouts: 'src/layouts/',\n  pageLayouts: {\n    // All pages inside src/pages/blog will use the blog.html layout\n    'blog': 'blog'\n  }\n})\n```\n\n### `partials`\n\n**Type:** `String`\n\nPath to a folder containing HTML partials. Partial files can have the extension `.html`, `.hbs`, or `.handlebars`. Each will be registered as a Handlebars partial which can be accessed using the name of the file. (The path to the file doesn't matter\u0026mdash;only the name of the file itself is used.)\n\n```html\n\u003c!-- Renders partials/header.html --\u003e\n{{\u003e header}}\n```\n\n### `helpers`\n\n**Type:** `String`\n\nPath to a folder containing Handlebars helpers. Handlebars helpers are `.js` files which export a function via `module.exports`. The name used to register the helper is the same as the name of the file.\n\nFor example, a file named `markdown.js` that exports this function would add a Handlebars helper called `{{markdown}}`.\n\n```js\nvar marked = require('marked');\n\nmodule.exports = function(text) {\n  return marked(text);\n}\n```\n\n### `data`\n\n**Type:** `String`\n\nPath to a folder containing external data, which will be passed in to every page. Data can be formatted as JSON (`.json`) or YAML (`.yml`). Within a template, the data is stored within a variable with the same name as the file it came from.\n\nFor example, a file named `contact.json` with key/value pairs such as the following:\n\n```js\n{\n    \"name\": \"John Doe\",\n    \"email\": \"john.doe@gmail.com\",\n    \"phone\": \"555-1212\"\n}\n```\n\nCould be used to output the value of John Doe within a template using the Handlebars syntax of `{{contact.name}}`.\n\nData can also be a `.js` file with a `module.exports`. The data returned by the export function will be used.\n\nData can also be inserted into the page itself with a Front Matter template at the top of the file.\n\nLastly, the reserved `page` variable is added to every page template as it renders. It contains the name of the page being rendered, without the extension.\n\n## CLI\n\nYou can also use panini via the CLI.\n\n```\nUsage: panini --layouts=[layoutdir] --root=[rootdir] --output=[destdir] [other options] 'pagesglob'\n\nOptions:\n  --layouts  (required) path to a folder containing layouts\n  --root     (required) path to the root folder all pages live in\n  --output     (required) path to the folder compiled pages should get sent to\n  --partials            path to root folder for partials\n  --helpers             path to folder for additional helpers\n  --data                path to folder for additional data\n\nthe argument pagesglob should be a glob describing what pages you want to apply panini to.\n\nExample: panini --root=src/pages --layouts=src/layouts --partials=src/partials --data=src/data --output=dist 'src/pages/**/*.html'\n```\n\n## Local Development\n\n```bash\ngit clone https://github.com/foundation/panini\ncd panini\nnpm install\n```\n\nUse `npm test` to run tests.\n","funding_links":[],"categories":["yaml"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffoundation%2Fpanini","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffoundation%2Fpanini","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffoundation%2Fpanini/lists"}