{"id":15771801,"url":"https://github.com/gvjacob/temples","last_synced_at":"2026-01-19T22:31:51.127Z","repository":{"id":40769008,"uuid":"262468301","full_name":"gvjacob/temples","owner":"gvjacob","description":"Automatically generate code from predefined templates. No boilerplate.","archived":false,"fork":false,"pushed_at":"2023-01-07T04:41:49.000Z","size":546,"stargazers_count":1,"open_issues_count":12,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-27T14:47:11.336Z","etag":null,"topics":["boilerplate","cli","command-line","console","generate","handlebars","node","prompt","template","temple","yaml"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/temples","language":"TypeScript","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/gvjacob.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}},"created_at":"2020-05-09T02:03:57.000Z","updated_at":"2021-02-22T18:36:34.000Z","dependencies_parsed_at":"2023-02-06T12:01:26.209Z","dependency_job_id":null,"html_url":"https://github.com/gvjacob/temples","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/gvjacob/temples","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gvjacob%2Ftemples","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gvjacob%2Ftemples/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gvjacob%2Ftemples/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gvjacob%2Ftemples/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gvjacob","download_url":"https://codeload.github.com/gvjacob/temples/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gvjacob%2Ftemples/sbom","scorecard":{"id":450630,"data":{"date":"2025-08-11","repo":{"name":"github.com/gvjacob/temples","commit":"6e663e88e22a3043a525810199d1147f57b7781f"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.5,"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":"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":"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":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","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":"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":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"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":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"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":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v2.1.0 not signed: https://api.github.com/repos/gvjacob/temples/releases/38442359","Warn: release artifact v2.1.0 does not have provenance: https://api.github.com/repos/gvjacob/temples/releases/38442359"],"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 'main'"],"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":"Vulnerabilities","score":0,"reason":"28 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-w573-4hg7-7wgq","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-ww39-953v-wcq6","Warn: Project is vulnerable to: GHSA-765h-qjxv-5f44","Warn: Project is vulnerable to: GHSA-f2jv-r9rf-7988","Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj","Warn: Project is vulnerable to: GHSA-896r-f27r-55mw","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-29mw-wpgm-hmr9","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-jgrx-mgxx-jf9v","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-j8xg-fqg3-53r7","Warn: Project is vulnerable to: GHSA-6fc8-4gx4-v693","Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q"],"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-19T08:07:24.809Z","repository_id":40769008,"created_at":"2025-08-19T08:07:24.810Z","updated_at":"2025-08-19T08:07:24.810Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28587241,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-19T20:45:59.482Z","status":"ssl_error","status_checked_at":"2026-01-19T20:45:41.500Z","response_time":67,"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":["boilerplate","cli","command-line","console","generate","handlebars","node","prompt","template","temple","yaml"],"created_at":"2024-10-04T15:05:14.982Z","updated_at":"2026-01-19T22:31:51.103Z","avatar_url":"https://github.com/gvjacob.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eTemples\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\n\u003cbr /\u003e\n🕍\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cb\u003eAutomatically generate code from predefined templates. No boilerplate.\u003c/b\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\nBoilerplate coding is tedious. Temples automates the process by giving you the ability to define \u003ca href=\"https://handlebarsjs.com/\"\u003eHandlebars\u003c/a\u003e templates, target paths, and the CLI commands to automatically generate the code. You can \u003cb\u003ecreate new files\u003c/b\u003e or \u003cb\u003einsert into existing ones\u003c/b\u003e.\n\u003c/p\u003e\n\n\u003cbr /\u003e\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://user-images.githubusercontent.com/23367882/108562618-22f14a00-72ce-11eb-8e2f-1a3f0893db95.gif\" width=\"80%\"/\u003e\n\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\u003csub\u003eExample of Temples CLI\u003c/sub\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cb\u003eFeedback and stars welcomed! :)\u003c/b\u003e\n\u003c/p\u003e\n\u003cbr /\u003e\n\n# Getting Started\n\n- [Installation](#installation)\n- [Usage](#usage)\n- [Configuration](#configuration)\n- [Handlebars Helpers](#handlebars-helpers)\n- [Customizing Handlebars](#customizing-handlebars)\n- [Caveats](#caveats)\n- [Example](#example)\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n# Installation\n\n```bash\n# Install globally\nnpm install [-g] temples\n\n# Or, in your project\nnpm install --save-dev temples\n```\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n# Usage\n\n\u003e Temples reads from a `.temples.yaml` configuration file. Refer to [Configuration](#configuration) below to create your own configuration file before running temples.\n\nYou can run temples by specifying the generator command and props, or invoke a CLI step by step interface where you can input these parameters.\n\n```bash\n# Invoke CLI interface\ntemples\n\n# Or, directly specify generator and value for each prop\ntemples [generator] --[prop]=[value] ...\n\n# Read more in the manual\ntemples -h\n```\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n# Configuration\n\n### generators\n\n\u003e Required. Temples will throw error if undefined.\n\nIn your `.temples.yaml` file, specify the `generators` object. This lists all available generators and what each does, either creating new files or inserting code into existing files.\n\n```yaml\n# .temples.yaml\n\ngenerators:\n  # Give your command a name\n  [command]:\n    # Documentation for this command will\n    # be shown during CLI interface\n    doc: ...\n\n    files: ...\n    inserts: ...\n```\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n### files\n\nGenerate new files given a target path, and an optional template path. If template is given, temples will use the contents of that template, compile it with given props, and output to target path.\n\n```yaml\n# .temples.yaml\n\ngenerators:\n  new-component:\n    files:\n      # Use `component.hbs` and create `index.js`\n      - template: component.hbs\n        target: index.js\n\n      # Create empty file at `index.js`\n      - target: index.js\n\n      # Compile with `name` and create\n      # file at `[component_name]/index.js`\n      - target: '{{ name }}/index.js'\n```\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n### inserts\n\nInsert code into targeted files. Temples uses user defined regex to find tags in targeted files and replace them with the parsed content. File comments are the best ways to do this:\n\n```js\n/* components/index.js */\n\n// temples(import {{ name }} from './{{ name }}';)\nimport Button from './Button';\n```\n\n```yaml\n# .temples.yaml\n\n# File extension to ECMAScript regex pattern\n#\n# The first regex capture group is the\n# template for the insert\nregex:\n  js: '\\/\\/ temples\\((.+)\\)'\n\ngenerators:\n  new-component:\n    inserts:\n      # Insert into `components/index.js`\n      - target: components/index.js\n\n      # Insert into `components/[component_name]/index.js`\n      - target: 'components/{{ name }}/index.js'\n```\n\nHere's a great [playground tool](https://regex101.com/) for finding the right regex pattern.\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n### base\n\nSpecify the base paths for templates, files, or inserts. `base` can be specified and overridden in the root configuration file or the generator command's configuration.\n\n```yaml\n# .temples.yaml\n\n# Find templates, files, and inserts\n# under `dir/`\nbase: dir\n\ngenerators:\n  new-component:\n    # Override to be `dir/subdir/`\n    base: dir/subdir\n\n    # Find templates in `dir/templates`\n    # Target files and inserts in `dir/targets`\n    base:\n      templates: dir/templates\n      target: dir/targets\n\n    # Find templates in `dir/templates`\n    # Target files in `dir/targets/files`\n    # Target inserts in `dir/targets/inserts`\n    base:\n      templates: dir/templates\n      target:\n        files: dir/targets/files\n        inserts: dir/targets/inserts\n```\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n### default\n\nDefault prop values if not provided in CLI.\n\n\u003e If there is no default provided and user doesn't specify value, Handlebars compiles undefined props to empty string.\n\n```yaml\n# .temples.yaml\n\ndefault:\n  name: 'NewComponent'\n\ngenerators:\n  new-component:\n    # Override default in root level\n    default:\n      name: 'NewestComponent'\n    ...\n```\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n### props\n\nSpecify props that should be prompted for in the CLI interface. It's not optimal for temples to search through all props available in templates. You can specify which props to prompt for with this key.\n\n```yaml\n# .temples.yaml\n\ngenerators:\n  new-component:\n    # Ask user for `name` and `directory`\n    props: [name, directory]\n\n    # In YAML, this is the same\n    props:\n    - name\n    - directory\n\n    # Provide documentation for each prop\n    # during CLI interface\n    props:\n    - name: name\n      doc: Name of component\n    - name: directory\n      doc: Directory to place component in\n```\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n### position\n\nPosition to insert output to. This is relative to the regex tag in the target file. Default position is `below`. The most specific position will be used.\n\n```yaml\n# .temples.yaml\n\nposition: above | below | right | left\n\ngenerators:\n  new-component:\n    position: above | below | right | left\n\n    inserts:\n      - target: components/index.js\n        position: above | below | right | left\n```\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n# Handlebars Helpers\n\nTemples uses Handlebars templating engine, and temples has some built-in [helpers](https://handlebarsjs.com/api-reference/helpers.html#helpers).\n\n### camel-case\n\nConvert into camelCase.\n\n```hbs\n{{ camel name }}\n\n# Input: { name: \"BigButton\" }\nbigButton\n```\n\n### kebab-case\n\nConvert into kebab-case\n\n```hbs\n{{ kebab-case name }}\n\n# Input: { name: \"bigButton\" }\nbig-button\n```\n\n### snake-case\n\nConvert into snake_case\n\n```hbs\n{{ snake-case name }}\n\n# Input: { name: \"big-button\" }\nbig_button\n```\n\n### upper-case\n\nConvert into UPPER CASE\n\n```hbs\n{{ upper-case name }}\n\n# Input: { name: \"big-button\" }\nBIG BUTTON\n```\n\n### lower-case\n\nConvert into lower case\n\n```hbs\n{{ lower-case name }}\n\n# Input: { name: \"big-button\" }\nbig button\n```\n\n### title-case\n\nConvert into TitleCase\n\n```hbs\n{{ title-case name }}\n\n# Input: { name: \"big_button\" }\nBigButton\n```\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n# Customizing Handlebars\n\nThe built-in helpers might not be enough for your use case. You can customize the Handlebars instance temples uses by specifying a path to a JavaScript file that configures Handlebars.\n\n#### Runtime Options\n\nUse the given handlebars instance to change its settings. See the [Handlebars runtime documentation](https://handlebarsjs.com/api-reference/runtime.html).\n\n#### Compile Options\n\nReturn an object to customize the compile options for Handlebars. See the [Handlebars compile options](https://handlebarsjs.com/api-reference/compilation.html#handlebars-compile-template-options).\n\n```yaml\n# .temples.yaml\n\nhandlebars: configureHandlebars.js\n```\n\n```js\n// configureHandlebars.js\n\nmodule.exports = (handlebars) =\u003e {\n  handlebars.registerHelper('replace', (v) =\u003e {\n    return v.replace(' ', '-');\n  });\n\n  return {\n    noEscape: false,\n  };\n};\n```\n\n\u003cbr/\u003e\n\u003cbr/\u003e\n\n# Caveats\n\n### Naming Conflicts\n\nIf a variable conflicts with a helper name (e.g. `{{ title }}`), Handlebars will treat it as a helper instead of a variable. You can namespace the variable with `this` or `./` to avoid naming conflicts.\n\n```hbs\n{{ this.title }}\n```\n\n### Escaping Handlebars Syntax\n\nSometimes you need Handlebars to ignore parsing a prop. For example, if you're generating a file from a twig template, Handlebars might parse `{{ example }}` unintentionally.\n\nYou can leave it as it is by escaping:\n\n```hbs\n\\{{ example }}\n```\n\n\u003cbr/\u003e\n\u003cbr/\u003e\n\n# Example\n\nCheck out a documented example [here](https://github.com/gvjacob/temples/tree/main/docs).\n\n\u003cbr/\u003e\n\u003cbr/\u003e\n\n# License\n\nCopyright © 2020 - Present, [Gino Jacob](https://ginojacob.com). MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgvjacob%2Ftemples","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgvjacob%2Ftemples","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgvjacob%2Ftemples/lists"}