{"id":15512710,"url":"https://github.com/mudbugmedia/critical-path-css-rails","last_synced_at":"2025-10-12T09:31:39.475Z","repository":{"id":48664524,"uuid":"42787921","full_name":"mudbugmedia/critical-path-css-rails","owner":"mudbugmedia","description":"Only load the CSS you need for the initial viewport in Rails!","archived":false,"fork":false,"pushed_at":"2023-02-04T22:46:04.000Z","size":147,"stargazers_count":150,"open_issues_count":6,"forks_count":55,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-09-04T19:26:56.661Z","etag":null,"topics":["asset-pipeline","css-generator","css-path","loadcss-rails","penthouse","rails"],"latest_commit_sha":null,"homepage":null,"language":"Ruby","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/mudbugmedia.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-09-19T20:08:29.000Z","updated_at":"2025-07-22T14:00:53.000Z","dependencies_parsed_at":"2024-06-19T00:00:27.732Z","dependency_job_id":"40098557-0236-4e33-8fbc-bcf21984f468","html_url":"https://github.com/mudbugmedia/critical-path-css-rails","commit_stats":{"total_commits":108,"total_committers":13,"mean_commits":8.307692307692308,"dds":"0.16666666666666663","last_synced_commit":"909dfc53ce1b262741a94b06d600352de5587881"},"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"purl":"pkg:github/mudbugmedia/critical-path-css-rails","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mudbugmedia%2Fcritical-path-css-rails","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mudbugmedia%2Fcritical-path-css-rails/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mudbugmedia%2Fcritical-path-css-rails/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mudbugmedia%2Fcritical-path-css-rails/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mudbugmedia","download_url":"https://codeload.github.com/mudbugmedia/critical-path-css-rails/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mudbugmedia%2Fcritical-path-css-rails/sbom","scorecard":{"id":667138,"data":{"date":"2025-08-11","repo":{"name":"github.com/mudbugmedia/critical-path-css-rails","commit":"909dfc53ce1b262741a94b06d600352de5587881"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.1,"checks":[{"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":"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":"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":"Code-Review","score":1,"reason":"Found 2/12 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":"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":-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":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: containerImage not pinned by hash: docker/ruby/Dockerfile:1: pin your Docker image by updating ruby:2.5.0 to ruby:2.5.0@sha256:cde5649ea901f6b36714b69a0ad8717ddaffa42131343dba30a02b61f3177fca","Warn: downloadThenRun not pinned by hash: docker/ruby/Dockerfile:4","Warn: npmCommand not pinned by hash: docker/ruby/Dockerfile:12","Info:   0 out of   1 containerImage dependencies pinned","Info:   0 out of   1 downloadThenRun dependencies pinned","Info:   0 out of   1 npmCommand dependencies pinned"],"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":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["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":"Vulnerabilities","score":3,"reason":"7 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-vh95-rmgr-6w4m","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","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"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 27 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"}}]},"last_synced_at":"2025-08-21T18:27:56.266Z","repository_id":48664524,"created_at":"2025-08-21T18:27:56.266Z","updated_at":"2025-08-21T18:27:56.266Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278794591,"owners_count":26047013,"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","status":"online","status_checked_at":"2025-10-07T02:00:06.786Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["asset-pipeline","css-generator","css-path","loadcss-rails","penthouse","rails"],"created_at":"2024-10-02T09:53:48.200Z","updated_at":"2025-10-12T09:31:39.161Z","avatar_url":"https://github.com/mudbugmedia.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"# critical-path-css-rails [![Code Climate](https://codeclimate.com/github/mudbugmedia/critical-path-css-rails/badges/gpa.svg)](https://codeclimate.com/github/mudbugmedia/critical-path-css-rails)\n\nOnly load the CSS you need for the initial viewport in Rails!\n\nThis gem gives you the ability to load only the CSS you *need* on an initial page view. This gives you blazin' fast rending as there's no initial network call to grab your application's CSS.\n\nThis gem assumes that you'll load the rest of the CSS asyncronously. At the moment, the suggested way is to use the [loadcss-rails](https://github.com/michael-misshore/loadcss-rails) gem.\n\nThis gem uses [Penthouse](https://github.com/pocketjoso/penthouse) to generate the critical CSS.\n\n## Dependency Requirements for / Upgrading to the Latest Release\n\n### For 1.0.0 or later\nTo maintain the latest version of Penthouse, this gem depends on NodeJS and NVM to be installed on the system.\n\n### For 2.0.0 or later\nThis gem may require additional packages to be installed to run Chrome headless. Per the Penthouse documentation, this may be all you need:\n\n```\nsudo apt-get install libnss3\n```\n\nHowever, more packages may need to be installed depending on your OS distribution which can be found via [this answer](https://github.com/GoogleChrome/puppeteer/issues/404#issuecomment-323555784)\n\n## Installation\n\nAfter reviewing the dependency requirements, add `critical-path-css-rails` to your Gemfile:\n\n```\ngem 'critical-path-css-rails', '~\u003e 3.1.0'\n```\n\nDownload and install by running:\n\n```\nbundle install\n```\n\nRun the generator to install the rake task and configuration file:\n\n```\nrails generate critical_path_css:install\n```\n\nThe generator adds the following files:\n\n* `config/critical_path_css.yml` **Note:** This file supports ERB.\n* `lib/tasks/critical_path_css.rake`\n\n\n## Usage\n\nFirst, you'll need to configue a few things in the YAML file: `config/critical_path_css.yml`\n\n**Note** that `manifest_name`, `css_path`, `css_paths` are all **mutually exclusive**; if using `css_path`, configuration for `manifest_name` AND `css_paths` should be omitted.\n\n* `manifest_name`: If you're using the asset pipeline, add the manifest name.\n* `css_path`: If you're not using the asset pipeline, you'll need to define the path to the application's main CSS. The gem assumes your CSS lives in `RAILS_ROOT/public`. If your main CSS file is in `RAILS_ROOT/public/assets/main.css`, you would set the variable to `/assets/main.css`.\n* `css_paths`: If you have the need to specify multiple CSS source files, you can do so with `css_paths`. When using this option, a separate CSS path must be specified for each route, and they will be matched based on the order specified (the first CSS path will be applied to the first route, the second CSS path to the second route, etc).\n* `routes`: List the routes that you would like to generate the critical CSS for. (i.e. /resources, /resources/show/1, etc.)\n* `base_url`: Add your application's URL for the necessary environments.\n\n\nBefore generating the CSS, ensure that your application is running (viewable from a browser) and the main CSS file exists. Then in a separate tab, run the rake task to generate the critical CSS.\n\nIf you are using the Asset Pipeline, precompiling the assets will generate the critical CSS after the assets are precompiled.\n```\nrake assets:precompile\n```\nElse you can generate the critical CSS manually using the below task:\n```\nrake critical_path_css:generate\n```\n\n\nTo load the generated critical CSS into your layout, in the head tag, insert:\n\n```HTML+ERB\n\u003cstyle\u003e\n    \u003c%= CriticalPathCss.fetch(request.path) %\u003e\n\u003c/style\u003e\n```\n\nA simple example using [loadcss-rails](https://github.com/michael-misshore/loadcss-rails) looks like:\n\n```HTML+ERB\n\u003cstyle\u003e\n  \u003c%= CriticalPathCss.fetch(request.path) %\u003e\n\u003c/style\u003e\n\u003cscript\u003e\n    loadCSS(\"\u003c%= stylesheet_path('application') %\u003e\");\n\u003c/script\u003e\n\u003clink rel=\"preload\" href=\"\u003c%= stylesheet_path('application') %\u003e\" as=\"style\" onload=\"this.onload=null;this.rel='stylesheet'\"\u003e\n\u003cnoscript\u003e\n    \u003clink rel=\"stylesheet\" href=\"\u003c%= stylesheet_path('application') %\u003e\"\u003e\n\u003c/noscript\u003e\n```\n\n### Route-level Control of CSS Generation and Removal\n\nCriticalPathCss exposes some methods to give the user more control over the generation of Critical CSS and managment of the CSS cache:\n\n``` ruby\nCriticalPathCss.generate route         # Generates the critical path CSS for the given route (relative path)\n\nCriticalPathCss.generate_all           # Generates critical CSS for all routes in critical_path_css.yml\n\nCriticalPathCss.clear route            # Removes the CSS for the given route from the cache\n\nCriticalPathCss.clear_matched routes   # Removes the CSS for the matched routes from the cache\n```\n\nNOTE: The `clear_matched` method will not work with Memcached due to the latter's incompatibility with Rails' `delete_matched` method.  We recommend using an alternative cache such as [Redis](https://github.com/redis-store/redis-rails).\n\nIn addition to the `critical_path_css:generate` rake task described above, you also have access to task which clears the CSS cache:\n\n```\nrake critical_path_css:clear_all\n```\nNOTE: The `critical_path_css:clear_all` rake task may need to be customized to suit your particular cache implementation.\n\nCareful use of these methods allows the developer to generate critical path CSS dynamically within the app.  The user should strongly consider using a [background job](http://edgeguides.rubyonrails.org/active_job_basics.html) when generating CSS in order to avoid tying up a rails thread.  The `generate` method will send a GET request to your server which could cause infinite recursion if the developer is not careful.\n\nA user can use these methods to [dynamically generate critical path CSS](https://gist.github.com/taranda/1597e97ccf24c978b59aef9249666c77) without using the `rake critical_path_css:generate` rake task and without hardcoding the application's routes into `config/critical_path_css.yml`.  See [this Gist](https://gist.github.com/taranda/1597e97ccf24c978b59aef9249666c77) for an example of such an implementation.\n\n## Upgrading from a version earlier than 0.3.0\n\nThe latest version of Critcal Path CSS Rails changes the functionality of the `generate` method.  In past versions,\n`generate` would produce CSS for all of the routes listed in `config/critical_path_css.yml`.  This functionality has been replaced by the `generate_all` method, and `generate` will only produce CSS for one route.\n\nDevelopers upgrading from versions prior to 0.3.0 will need to replace `CriticalPathCss:generate` with `CriticalPathCss:generate_all` throughout their codebase.  One file that will need updating is `lib/tasks/critical_path_css.rake`.  Users can upgrade this file automatically by running:\n\n``` prompt\nrails generate critical_path_css:install\n```\n\nAnswer 'Y' when prompted to overwrite `critical_path_css.rake`.  However, overwriting `critical_path_css.yml` is not recommended nor necessary.\n\n\n## Testing / Development\n\nThis gem is to be tested inside of docker/docker-compose. [Combustion](https://github.com/pat/combustion), alongside rspec-rails and capybara, are the primary components for testing. To run the test, you'll need to have [Docker](https://docs.docker.com/engine/installation) installed. Once installed, run the following commands in the gem's root to build, run, and shell into the docker container.\n\n```Bash\n  docker-compose build\n  docker-compose up -d\n  docker exec -it $(cat app_container_name) /bin/bash\n```\n\nOnce shell'd in, run `bundle exec rspec spec` to run the test. The test rails app lives in `spec/internal`, and it can be viewed locally at `http://localhost:9292/`\n\nIf you encounter Chromium errors trying to run the tests, installing [Puppeteer](https://github.com/GoogleChrome/puppeteer) might help.\n\n```Bash\n  npm install puppeteer\n```\n\n\n## Versions\n\nThe critical-path-css-rails gem follows these version guidelines:\n\n```\npatch version bump = updates to critical-path-css-rails and patch-level updates to Penthouse\nminor version bump = minor-level updates to critical-path-css-rails and Penthouse\nmajor version bump = major-level updates to critical-path-css-rails, Penthouse, and updates to Rails which may be backwards-incompatible\n```\n\n## Contributing\n\nFeel free to open an issue ticket if you find something that could be improved.\n\nCopyright Mudbug Media and Michael Misshore, released under the MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmudbugmedia%2Fcritical-path-css-rails","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmudbugmedia%2Fcritical-path-css-rails","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmudbugmedia%2Fcritical-path-css-rails/lists"}