{"id":13879771,"url":"https://github.com/hanami/assets","last_synced_at":"2025-07-16T15:32:57.543Z","repository":{"id":16983928,"uuid":"19746778","full_name":"hanami/assets","owner":"hanami","description":"Assets management for Ruby web applications","archived":false,"fork":false,"pushed_at":"2025-03-09T01:00:15.000Z","size":1042,"stargazers_count":47,"open_issues_count":1,"forks_count":41,"subscribers_count":16,"default_branch":"main","last_synced_at":"2025-07-07T15:23:50.771Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://hanamirb.org","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"porterhau5/xkeyscan","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hanami.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","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,"zenodo":null},"funding":{"github":"hanami"}},"created_at":"2014-05-13T16:28:38.000Z","updated_at":"2025-03-09T01:00:18.000Z","dependencies_parsed_at":"2024-02-21T13:28:38.627Z","dependency_job_id":"268726db-5684-4a16-97a9-3b557fbfc493","html_url":"https://github.com/hanami/assets","commit_stats":{"total_commits":362,"total_committers":36,"mean_commits":"10.055555555555555","dds":"0.33977900552486184","last_synced_commit":"b492e5dffe7176348ecfa2314c943df5bdb32c44"},"previous_names":[],"tags_count":36,"template":false,"template_full_name":null,"purl":"pkg:github/hanami/assets","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hanami%2Fassets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hanami%2Fassets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hanami%2Fassets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hanami%2Fassets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hanami","download_url":"https://codeload.github.com/hanami/assets/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hanami%2Fassets/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264924377,"owners_count":23683915,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-08-06T08:02:32.416Z","updated_at":"2025-07-16T15:32:57.309Z","avatar_url":"https://github.com/hanami.png","language":"Ruby","funding_links":["https://github.com/sponsors/hanami"],"categories":["Ruby"],"sub_categories":[],"readme":"# Hanami::Assets\n\nAssets management for Ruby web projects\n\n## Status\n\n[![Gem Version](https://badge.fury.io/rb/hanami-assets.svg)](https://badge.fury.io/rb/hanami-assets)\n[![CI](https://github.com/hanami/assets/actions/workflows/ci.yml/badge.svg)](https://github.com/hanami/assets/actions?query=workflow%3Aci+branch%3Amain)\n[![Test Coverage](https://codecov.io/gh/hanami/assets/branch/main/graph/badge.svg)](https://codecov.io/gh/hanami/assets)\n[![Depfu](https://badges.depfu.com/badges/4b37347bd74042ff96477495cc16531d/overview.svg)](https://depfu.com/github/hanami/assets?project=Bundler)\n\n## Contact\n\n* Home page: http://hanamirb.org\n* Community: http://hanamirb.org/community\n* Guides: https://guides.hanamirb.org\n* Mailing List: http://hanamirb.org/mailing-list\n* API Doc: http://rubydoc.info/gems/hanami-assets\n* Forum: https://discourse.hanamirb.org\n* Chat: http://chat.hanamirb.org\n\n\n## Installation\n\n__Hanami::Assets__ supports Ruby (MRI) 3.1+\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem \"hanami-assets\"\n```\n\nAnd then execute:\n\n```shell\n$ bundle\n```\n\nOr install it yourself as:\n\n```shell\n$ gem install hanami-assets\n```\n\n## Usage\n\n### Command Line (CLI)\n\nDuring development run `bundle exec hanami server`.\nYour app will start the assets management.\n\n### Helpers\n\nHanami Assets provides asset-specific helpers to be used in templates.\nThey resolve one or multiple sources into corresponding HTML tags.\nThose sources can be either a name of a local asset or an absolute URL.\n\nGiven the following template:\n\n```erb\n\u003c!doctype HTML\u003e\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003ctitle\u003eAssets example\u003c/title\u003e\n    \u003c%= stylesheet_tag \"reset\", \"app\" %\u003e\n  \u003c/head\u003e\n\n  \u003cbody\u003e\n  \u003c!-- ... --\u003e\n  \u003c%= javascript_tag \"app\" %\u003e\n  \u003c%= javascript_tag \"https://cdn.somethirdparty.script/foo.js\", async: true %\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\nIt will output this markup:\n\n```html\n\u003c!doctype HTML\u003e\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003ctitle\u003eAssets example\u003c/title\u003e\n    \u003clink href=\"/assets/reset.css\" type=\"text/css\" rel=\"stylesheet\"\u003e\n    \u003clink href=\"/assets/app.css\" type=\"text/css\" rel=\"stylesheet\"\u003e\n  \u003c/head\u003e\n\n  \u003cbody\u003e\n  \u003c!-- ... --\u003e\n  \u003cscript src=\"/assets/app.js\" type=\"text/javascript\"\u003e\u003c/script\u003e\n  \u003cscript src=\"https://cdn.somethirdparty.script/foo.js\" type=\"text/javascript\" async\u003e\u003c/script\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n### Available Helpers\n\nThe `hanami` gem ships with the following helpers for assets:\n\n  * `asset_url`\n  * `javascript_tag`\n  * `stylesheet_tag`\n  * `favicon_tag`\n  * `image_tag`\n  * `video_tag`\n  * `audio_tag`\n  * `path_tag`\n\n## App Structure\n\nHanami applications are generated via `hanami new` CLI command.\n\nAmong other directories, it generates a specific structure for assets:\n\n```shell\n$ tree app/assets\n├── images\n│   └── favicon.ico\n├── js\n│   └── app.ts\n└── css\n    └── app.css\n```\n\n#### Entry Points\n\nEntry Points are the JavaScript files or modules that serve as the starting points of your application.\nThey define the scope of your bundling process and determine which parts of your code will be included in the final output.\nBy understanding the dependencies of your entry points, Hanami Assets can create efficient and optimized bundles for your JavaScript or TypeScript applications.\n\nWhen Hanami Assets encounters an import or require statement for an asset, it process the asset file to the output directory.\nThis process includes any kind of asset: other JavaScript files, stylesheets, images **referenced from the Entry Point**.\n\nThe default entry points are:\n\n  * `app/assets/js/app.ts`\n  * `slices/[slice-name]/assets/js/app.ts`\n\nYou can specify custom Entry Points, by adding an `app.{js,ts,mjs,mts,tsx,jsx}` file into the assets directory of the app or a slice.\n\nAn example is: `app/assets/js/login/app.ts` to define a new Entry Point for a Login page where you want to have a more lightweight bundle.\n\n#### Static Assets\n\nExcept for `js` and `css` directories, all the other directories are considered **static**.\nTheir files will be copied as they are to the destination directory.\n\nIf you have a custom directory `app/assets/fonts`, all the fonts are copied to the destination direcotry.\n\n#### Destination Directory\n\nThe destination directory is `public/assets`.\n\n### Deployment\n\nTo process the assets during deployment run `bundle exec hanami assets compile`.\n\nThe destination directory will contain the processed assets with an hashed name.\n\n#### Fingerprint Mode\n\nAsset fingerprinting is a technique that involves adding a unique identifier to the filenames of static assets to ensure cache-busting.\nBy doing so, you can safely cache and deliver updated versions of assets to client browsers, avoiding the use of outdated cached versions and ensuring a consistent and up-to-date user experience.\n\nDuring the deployment process, Hanami Assets appends to the file name a unique hash.\n\nExample: `app/assets/js/app.ts` -\u003e `public/assets/app-QECGTTYG.js`\n\nIt creates a `/public/assets.json` to map the original asset name to the fingerprint name.\n\nThe simple usage of the `js` helper, will be automatically mapped for you:\n\n```erb\n\u003c%= assets.js \"app\" %\u003e\n```\n\n```html\n\u003cscript src=\"/assets/app-QECGTTYG.js\" type=\"text/javascript\"\u003e\u003c/script\u003e\n```\n\n#### Subresource Integrity (SRI) Mode\n\nSubresource Integrity (SRI) is a security mechanism that allows browsers to verify the integrity of external resources by comparing their content against a cryptographic hash. It helps protect against unauthorized modifications to external scripts and enhances the security and trustworthiness of web applications.\n\n```ruby\nmodule MyApp\n  class App \u003c Hanami::App\n    config.assets.subresource_integrity = [\"sha-384\"]\n  end\nend\n```\n\nOnce turned on, it will look at `/public/assets.json`, and helpers such as `javascript` will include an `integrity` and `crossorigin` attribute.\n\n```erb\n\u003c%= assets.js \"app\" %\u003e\n```\n\n```html\n\u003cscript src=\"/assets/app-QECGTTYG.js\" type=\"text/javascript\" integrity=\"sha384-d9ndh67iVrvaACuWjEDJDJlThKvAOdILG011RxYJt1dQynvf4JXNORcUiZ9nO7lP\" crossorigin=\"anonymous\"\u003e\u003c/script\u003e\n```\n\n#### Content Delivery Network (CDN) Mode\n\nA Content Delivery Network (CDN) is a globally distributed network of servers strategically located in multiple geographical locations.\nCDNs are designed to improve the performance, availability, and scalability of websites and web applications by reducing latency and efficiently delivering content to end users.\n\nA Hanami project can serve assets via a Content Delivery Network (CDN).\n\n```ruby\nmodule MyApp\n  class App \u003c Hanami::App\n    config.assets.base_url = \"https://123.cloudfront.net\"\n  end\nend\n```\n\nFrom now on, helpers will return the absolute URL for the asset, hosted on the CDN specified.\n\n```erb\n\u003c%= javascript 'application' %\u003e\n```\n\n```html\n\u003cscript src=\"https://123.cloudfront.net/assets/application-d1829dc353b734e3adc24855693b70f9.js\" type=\"text/javascript\"\u003e\u003c/script\u003e\n```\n\n```erb\n\u003c%= assets.js \"app\" %\u003e\n```\n\n```html\n\u003cscript src=\"https://123.cloudfront.net/assets/app-QECGTTYG.js\" type=\"text/javascript\"\u003e\u003c/script\u003e\n```\n\nNOTE: We suggest to use SRI mode when using CDN.\n\n## Development\n\nInstall:\n\n  * Node\n  * NPM\n\n```bash\n$ npm install\n$ bundle exec rake test\n```\n\n## Versioning\n\n__Hanami::Assets__ uses [Semantic Versioning 2.0.0](http://semver.org)\n\n## Contributing\n\n1. Fork it (https://github.com/hanami/assets/fork)\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create new Pull Request\n\n## Copyright\n\nCopyright © 2014–2024 Hanami Team – Released under MIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhanami%2Fassets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhanami%2Fassets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhanami%2Fassets/lists"}