{"id":42830383,"url":"https://github.com/wide/forge","last_synced_at":"2026-02-25T10:15:58.878Z","repository":{"id":42369302,"uuid":"267885176","full_name":"wide/forge","owner":"wide","description":"Zero-based configuration builder for frontend integration projects.","archived":false,"fork":false,"pushed_at":"2022-11-16T10:36:26.000Z","size":49,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":7,"default_branch":"main","last_synced_at":"2026-01-31T01:31:14.620Z","etag":null,"topics":["modulus"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wide.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-05-29T14:58:47.000Z","updated_at":"2021-10-27T14:18:25.000Z","dependencies_parsed_at":"2023-01-21T11:09:41.549Z","dependency_job_id":null,"html_url":"https://github.com/wide/forge","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/wide/forge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wide%2Fforge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wide%2Fforge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wide%2Fforge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wide%2Fforge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wide","download_url":"https://codeload.github.com/wide/forge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wide%2Fforge/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29817592,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-25T05:36:42.804Z","status":"ssl_error","status_checked_at":"2026-02-25T05:36:31.934Z","response_time":61,"last_error":"SSL_read: 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":["modulus"],"created_at":"2026-01-30T11:26:57.689Z","updated_at":"2026-02-25T10:15:58.865Z","avatar_url":"https://github.com/wide.png","language":"JavaScript","readme":"# Forge\r\n\r\nZero-based configuration builder for frontend integration project, made for those you want:\r\n- a builder made for static website, working out-of-the-box with no config needed\r\n- control over the source, the compilation and the destination, unlike Webpack\r\n- extendable low-level vanilla tasks instead of the Gulp stream-thing\r\n- preconfigured well-known libs such as `sass`, `babel`, `parcel` or `twig`\r\n- no black magic\r\n\r\n\r\n## Install\r\n\r\n```\r\nnpm install @wide/forge --save-dev\r\n```\r\n\r\n\r\n## Usage\r\n\r\n- [Commands](#commands)\r\n- [Minimal folder structure](#minimal-folder-structure)\r\n- [HTML / TWIG](#html--twig)\r\n- [CSS / SASS](#css--sass)\r\n- [JS / ESNEXT](#js--esnext)\r\n- [SVG Sprite](#svg-sprite)\r\n- [Favicons](#favicons)\r\n- [Other assets](#other-assets)\r\n- [Advanced usage](#advanced-usage)\r\n\r\n\r\n## Commands\r\n\r\n**Global commands**\r\n- start server and watch changes: `forge serve --open`\r\n- build project for production: `forge build --production`\r\n\r\n**Specific commands**\r\n- clear dist folder: `forge nuke`\r\n- compile specific assets: `forge compile sass js`\r\n- copy static assets to dist: `forge copy`\r\n\r\n\r\n## Minimal folder structure\r\n\r\n**Forge** needs a specific folder structure in order to work without configuration:\r\n```\r\nsrc/\r\n  assets/\r\n    icons/*.svg\r\n    scss/*.scss\r\n    js/*.js\r\n  *.twig\r\n```\r\n\r\nwill be compiled into:\r\n```\r\ndist/\r\n  assets/\r\n    sprite.svg\r\n    *.css\r\n    *.js\r\n  *.html\r\n```\r\n\r\n\r\n## HTML / TWIG\r\n\r\n- source files: `/src/**.twig`\r\n- destination: `/dist/**.html`\r\n- compiled using [`twig`](https://www.npmjs.com/package/twig)\r\n\r\n### Path config\r\n\r\nTo changethe path config config, create/edit the `.forgerc.js` file at the root of your project:\r\n```js\r\nmodule.exports = {\r\n\r\n  // override twig path config\r\n  twig: {\r\n\r\n    // files to watch in /src, will trigger the compilation when changed\r\n    observe: '**/*.{twig,html}', // watch src/index.twig and src/foo/bar.twig\r\n\r\n    // in src/, files to compile, should be pages only\r\n    entries: [\r\n      '**.twig',      // build all twig into html (root = pages)\r\n    ],\r\n\r\n    // do not compile twig file in layouts/ nor components/\r\n    exclude: [\r\n      'layouts/**.twig',\r\n      'components/**.twig'\r\n    ],\r\n\r\n    // in dist/, subfolder to generate HTML files into\r\n    // ex: pages -\u003e  dist/pages/index.html\r\n    output: '', // no subfolder -\u003e dist/index.html\r\n\r\n    // if true, build all file at dist level only\r\n    // ex: src/foo/bar.twig -\u003e dist/bar.twig (foo subfolder is ignored)\r\n    flatten: false,\r\n\r\n    // commands to execute around the compilation\r\n    hooks: {\r\n\r\n      // run before the compilation, can be a string \"npm run something\"\r\n      // or a function receiving the current target and the compiled files\r\n      before(target, compiled) {},\r\n\r\n      // run after the compilation, can be a string \"npm run something\"\r\n      // or a function receiving the current target and the compiled files\r\n      after(target, compiled) {}\r\n    }\r\n  }\r\n}\r\n```\r\n\r\n### Twig config\r\n\r\nTo edit the config of `twig` itself, create a `.twigrc.js` file at the root of your project, it accepts the following props:\r\n```js\r\nmodule.exports = {\r\n\r\n  // alias of path, see https://github.com/twigjs/twig.js/wiki#namespaces\r\n  namespace: {\r\n    'foo': 'src/foo' // {% include 'foo::index.twig' %} =\u003e {% include '/src/foo/index.twig' %}\r\n  },\r\n\r\n  // global data injected in all templates\r\n  data: {\r\n    foo: 'bar' // {{ foo }}\r\n  },\r\n\r\n  // custom functions, see https://github.com/twigjs/twig.js/wiki/Extending-twig.js\r\n  functions: {\r\n    foo() {} // {% foo() %}\r\n  },\r\n\r\n  // custom filters, see https://github.com/twigjs/twig.js/wiki/Extending-twig.js\r\n  filters: {\r\n    foo() {} // {% myvar | foo %}\r\n  },\r\n\r\n  // post-process middlewares\r\n  postprocess: {\r\n    beautify: true, // built-in post-process\r\n    foo(html) {     // custom post-process\r\n      return doSomething(html)\r\n    }\r\n  }\r\n}\r\n```\r\n\r\nNotes:\r\n- `postprocess`: **Forge** comes with a set of post-process to enhance the quality of the generated HTML:\r\n  - `beautify`: use [`js-beautify`](https://www.npmjs.com/package/js-beautify) to format the whole page, accepts these values:\r\n    - `false` disable the post-process\r\n    - `true` enable the post-process (default)\r\n    - `{}` enable and pass custom config\r\n\r\n\r\n## CSS / SASS\r\n\r\n- source files: `/src/assets/**/*.{sass,scss}`\r\n- destination: `/dist/assets/*.css` and `/dist/assets/*.css.map`\r\n- compiled using [`sass`](https://www.npmjs.com/package/sass)\r\n\r\n### Path config\r\n\r\nTo change the path config, create a `.forgerc.js` file at the root of your project with a `sass` prop:\r\n```js\r\nmodule.exports = {\r\n  sass: {\r\n\r\n    // files to watch in /src, will trigger the compilation when changed\r\n    observe: '**/*.{scss,sass}',\r\n\r\n    // in src/, files to compile, must be root level only\r\n    entries: [\r\n      'assets/{scss,sass}/*.{scss,sass}'\r\n    ],\r\n\r\n    // in dist/, subfolder to generate CSS files into\r\n    output: 'assets/', // -\u003e dist/assets/main.css\r\n\r\n    // if true, build all file at dist level only\r\n    // ex: src/assets/foo/bar.scss -\u003e dist/assets/bar.css (foo subfolder is ignored)\r\n    flatten: false,\r\n\r\n    // commands to execute around the compilation\r\n    hooks: {\r\n\r\n      // run before the compilation, can be a string \"npm run something\"\r\n      // or a function receiving the current target and the compiled files\r\n      before(target, compiled) {},\r\n\r\n      // run after the compilation, can be a string \"npm run something\"\r\n      // or a function receiving the current target and the compiled files\r\n      after(target, compiled) {}\r\n    }\r\n  }\r\n}\r\n```\r\n\r\n### SASS config\r\n\r\nTo edit the config of `sass` itself, create a `.sassrc.js` file at the root of your project, it accepts the following props:\r\n```js\r\nmodule.exports = {\r\n\r\n  // path to look-up\r\n  includePaths: [],\r\n\r\n  // enable of disable minification, see https://github.com/sass/node-sass#outputstyle\r\n  outputStyle,\r\n\r\n  // post-process middlewares\r\n  postprocess: {\r\n    autoprefixer: false, // built-in post-process\r\n    foo(css) {           // custom post-process\r\n      return doSomething(css)\r\n    }\r\n  },\r\n\r\n  // ... and all others props described here:\r\n  // https://github.com/sass/node-sass#options\r\n}\r\n```\r\n\r\nNotes:\r\n- `includePaths` includes `node_modules/` by default\r\n- `outputStyle` is `compressed` on `PRODUCTION` by default\r\n- `postprocess`: **Forge** comes with a set of post-process to enhance the quality of the generated CSS\r\n  - `autoprefixer`: use [`autoprefixer`](https://www.npmjs.com/package/autoprefixer) to add browser-specific prefixes:\r\n    - `false` disable the post-process\r\n    - `true` enable the post-process (default)\r\n    - `{}` enable and pass custom config, see [official doc](https://www.npmjs.com/package/autoprefixer#options)\r\n\r\n\r\n## JS / ESNEXT\r\n\r\n- source files: `/src/assets/**/*.js`\r\n- destination: `/dist/assets/*.js` and `/dist/assets/*.js.map`\r\n- compiled using [`parcel`](https://github.com/parcel-bundler/parcel)\r\n\r\n### Path config\r\n\r\nTo change the path config, create a `.forgerc.js` file at the root of your project with a `js` prop:\r\n```js\r\nmodule.exports = {\r\n  js: {\r\n\r\n    // files to watch in /src, will trigger the compilation when changed\r\n    observe: '**/*.js',\r\n\r\n    // in src/, files to compile\r\n    entries: [\r\n      'assets/js/*.js', // build all root level files\r\n    ],\r\n\r\n    // exclude polyfills from compilation\r\n    exclude: [\r\n      'assets/js/polyfills/**.js'\r\n    ]\r\n\r\n    // in dist/, subfolder to generate JS files into\r\n    output: 'assets/', // -\u003e dist/assets/main.js\r\n\r\n    // if true, build all file at dist level only\r\n    // ex: src/assets/foo/bar.js -\u003e dist/assets/bar.js (foo subfolder is ignored)\r\n    flatten: false,\r\n\r\n    // commands to execute around the compilation\r\n    hooks: {\r\n\r\n      // run before the compilation, can be a string \"npm run something\"\r\n      // or a function receiving the current target and the compiled files\r\n      before(target, compiled) {},\r\n\r\n      // run after the compilation, can be a string \"npm run something\"\r\n      // or a function receiving the current target and the compiled files\r\n      after(target, compiled) {}\r\n    }\r\n  }\r\n}\r\n```\r\n\r\n### Parcel config\r\n\r\nTo edit the config of `parcel` itself, create a `.parcelrc.js` file at the root of your project:\r\n```js\r\nmodule.exports = {\r\n  // all props described here:\r\n  // https://parceljs.org/api.html\r\n}\r\n```\r\n\r\nNotes:\r\n- `outDir` and `outFile` are reserved, do not change\r\n- `watch`, `cache`, `contentHash` and `autoinstall` must remain `false`\r\n- `minify` is `true` on `PRODUCTION` by default\r\n- this file is for advanced users, don't mess up :D\r\n\r\n### Babel config\r\n\r\nParcel is using `babel` to transpile ES standards, to edit the config of `babel`, create a `.babelrc.js` file at the root of your project:\r\n```js\r\nmodule.exports = {\r\n  // all props described here:\r\n  // https://babeljs.io/docs/en/6.26.3/babelrc\r\n}\r\n```\r\n\r\n\r\n## SVG Sprite\r\n\r\n- source files: `/src/assets/icons/*.svg`\r\n- destination: `/dist/assets/sprite.svg`\r\n- compiled using [`svg-sprite`](https://www.npmjs.com/package/svg-sprite)\r\n\r\n### Path config\r\n\r\nTo change the path config, create a `.forgerc.js` file at the root of your project with a `svg` prop:\r\n```js\r\nmodule.exports = {\r\n  svg: {\r\n\r\n    // in /src, files to watch, will trigger the compilation when changed\r\n    observe: '**/*.svg',\r\n\r\n    // in src/, files to compile, must be root level only\r\n    entries: [\r\n      'assets/icons/*.svg'\r\n    ],\r\n\r\n    // in dist/, subfolder to generate the sprite file into\r\n    output: 'assets/',\r\n\r\n    // commands to execute around the compilation\r\n    hooks: {\r\n\r\n      // run before the compilation, can be a string \"npm run something\"\r\n      // or a function receiving the current target and the compiled files\r\n      before(target, compiled) {},\r\n\r\n      // run after the compilation, can be a string \"npm run something\"\r\n      // or a function receiving the current target and the compiled files\r\n      after(target, compiled) {}\r\n    }\r\n  }\r\n}\r\n```\r\n\r\n### SVG-Sprite config\r\n\r\nTo edit the config of `svg-sprite` itself, create a `.svgrc.js` file at the root of your project:\r\n```js\r\nmodule.exports = {\r\n  // all props described here:\r\n  // https://www.npmjs.com/package/svg-sprite#configuration-basics\r\n}\r\n```\r\n\r\nNotes:\r\n- `dest` is reserved, do not change\r\n- `mode.symbol.sprite` is `sprite.svg` by default\r\n- `mode.exemple` is `false` on `PRODUCTION` by default\r\n\r\n\r\n## Favicons\r\n\r\n- source files: `/src/assets/favicon.png`\r\n- destination: `/dist/assets/favicons`\r\n- compiled using [`favicons`](https://www.npmjs.com/package/favicons)\r\n\r\n### Path config\r\n\r\nTo change the path config, create a `.forgerc.js` file at the root of your project with a `favicons` prop:\r\n```js\r\nmodule.exports = {\r\n  favicons: {\r\n\r\n    // in /src, files to watch, will trigger the compilation when changed\r\n    observe: 'assets/favicon.png',\r\n\r\n    // in src/, file to compile, must be root level only\r\n    entries: 'assets/favicons.png',\r\n\r\n    // in dist/, subfolder to generate the sprite file into\r\n    output: 'assets/favicons/',\r\n\r\n    // commands to execute around the compilation\r\n    hooks: {\r\n\r\n      // run before the compilation, can be a string \"npm run something\"\r\n      // or a function receiving the current target and the compiled files\r\n      before(target, compiled) {},\r\n\r\n      // run after the compilation, can be a string \"npm run something\"\r\n      // or a function receiving the current target and the compiled files\r\n      after(target, compiled) {}\r\n    }\r\n  }\r\n}\r\n```\r\n\r\n### Favicons config\r\n\r\nTo edit the config of `favicons` itself, create a `.faviconsrc.js` file at the root of your project:\r\n```js\r\nmodule.exports = {\r\n  // all props described here:\r\n  // https://github.com/itgalaxy/favicons#usage\r\n}\r\n```\r\n\r\n\r\n## Other assets\r\n\r\nFor all others assets (images, documents...), **Forge** simply copy them into the `dist/` folder.\r\n\r\n- source files: `/src/assets/**`\r\n- destination: `/dist/assets/**`\r\n\r\n### Path config\r\n\r\nTo change the path config, create a `.forgerc.js` file at the root of your project with a `copy` prop:\r\n```js\r\nmodule.exports = {\r\n  copy: {\r\n\r\n    // in src/, files to copy\r\n    entries: [\r\n      'assets/**'\r\n    ],\r\n\r\n    // ignore to-be-compiled assets\r\n    exclude: [\r\n      'assets/icons/**',\r\n      'assets/scss/**',\r\n      'assets/js/**'\r\n    ]\r\n  }\r\n}\r\n```\r\n\r\n\r\n## Advanced usage\r\n\r\n### Add a compiler\r\n\r\nTo add a new asset compiler, like Handlebars, follow this exemple:\r\n```js\r\n.forgerc.js\r\n{\r\n\r\n  // add a new hbs compiler\r\n  compilers: {\r\n    \r\n    /**\r\n     * Compile handlebars templates\r\n     * @param {Object} ctx\r\n     * @param {Array}  ctx.files to compile into HTML\r\n     * @param {String} ctx.base relative path from wildcard (ex: templates/pages/**.hbs -\u003e templates/pages/foo/bar.hbs -\u003e foo/)\r\n     * @param {String} ctx.dest folder (output + hbs.output -\u003e dist/) \r\n     * @return {Array\u003cObject\u003e} the list of generated files with their octal size [{ filename, size }]\r\n     */\r\n    hbs({ files, base, dest }) {\r\n      return [{\r\n        filename: 'compiled-file.html',\r\n        size: 1024\r\n      }]\r\n    }\r\n\r\n  },\r\n\r\n  // rewrite targets to replace twig with hbs\r\n  targets: ['hbs', 'scss', 'js', 'svg'],\r\n\r\n  // define hbs target config\r\n  hbs: {\r\n    observe: '**/*.{hbs,html}',\r\n    entries: [\r\n      '**.hbs'\r\n    ],\r\n    exclude: [\r\n      'layouts/**.hbs',\r\n      'components/**.hbs'\r\n    ],\r\n    output: ''\r\n  }\r\n}\r\n```\r\n\r\n### Add a command\r\n\r\nTo add a command not related to compilation, follow this exemple:\r\n```js\r\n.forgerc.js\r\n{\r\n  commands: {\r\n    sayhello(argv) {\r\n      console.log('Hello', ...argv._)\r\n    }\r\n  }\r\n}\r\n```\r\n\r\nThen the command is available using:\r\n```bash\r\nforge sayhello you # Hello you\r\n```\r\n\r\n\r\n## Authors\r\n\r\n- **Aymeric Assier** - [github.com/myeti](https://github.com/myeti)\r\n- **Julien Martins Da Costa** - [github.com/jdacosta](https://github.com/jdacosta)\r\n\r\n\r\n## License\r\n\r\nThis project is licensed under the MIT License - see the [licence](licence) file for details","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwide%2Fforge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwide%2Fforge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwide%2Fforge/lists"}