# Technical Documentation: ankane/chartkick > ℹ️ **Provenance:** Hybrid Fusion: `ankane/chartkick` (README + 3 In-Tree Chapters) · [CodeWiki Reference](https://codewiki.google/github.com/ankane/chartkick) · Recency: Active (< 180 days) ## 1. Project Overview & Quickstart (ankane/chartkick) # Chartkick Create beautiful JavaScript charts with one line of Ruby. No more fighting with charting libraries! [See it in action](https://chartkick.com) :fire: For admin charts and dashboards, check out [Blazer](https://github.com/ankane/blazer/), and for advanced visualizations, check out [Vega](https://github.com/ankane/vega) :two_hearts: A perfect companion to [Groupdate](https://github.com/ankane/groupdate), [Hightop](https://github.com/ankane/hightop), and [ActiveMedian](https://github.com/ankane/active_median) [](https://github.com/ankane/chartkick/actions) ## Quick Start Add this line to your application’s Gemfile: ```ruby gem "chartkick" ``` Then follow the instructions for your JavaScript setup: - [Importmap](#importmap) (Rails default) - [Bun, esbuild, rollup.js, or Webpack](#bun-esbuild-rollupjs-or-webpack) - [Sprockets](#sprockets) This sets up Chartkick with [Chart.js](https://www.chartjs.org/). For other charting libraries and frameworks, see [these instructions](#additional-charting-libraries). ### Importmap In `config/importmap.rb`, add: ```ruby pin "chartkick", to: "chartkick.js" pin "Chart.bundle", to: "Chart.bundle.js" ``` And in `app/javascript/application.js`, add: ```js import "chartkick" import "Chart.bundle" ``` ### Bun, esbuild, rollup.js, or Webpack Run: ```sh bun add chartkick chart.js # or yarn add chartkick chart.js ``` And in `app/javascript/application.js`, add: ```js import "chartkick/chart.js" ``` ### Sprockets In `app/assets/javascripts/application.js`, add: ```js //= require chartkick //= require Chart.bundle ``` ## Charts Line chart ```erb <%= line_chart User.group_by_day(:created_at).count %> ``` Pie chart ```erb <%= pie_chart Goal.group(:name).count %> ``` Column chart ```erb <%= column_chart Task.group_by_hour_of_day(:created_at, format: "%l %P").count %> ``` Bar chart ```erb <%= bar_chart Shirt.group(:size).sum(:price) %> ``` Area chart ```erb <%= area_chart Visit.group_by_minute(:created_at).maximum(:load_time) %> ``` Scatter chart ```erb <%= scatter_chart City.pluck(:size, :population) %> ``` Geo chart - *Google Charts* ```erb <%= geo_chart Medal.group(:country).count %> ``` Timeline - *Google Charts* ```erb <%= timeline [ ["Washington", "1789-04-29", "1797-03-03"], ["Adams", "1797-03-03", "1801-03-03"], ["Jefferson", "1801-03-03", "1809-03-03"] ] %> ``` Multiple series ```erb <%= line_chart [ {name: "Workout", data: {"2026-01-01" => 3, "2026-01-02" => 4}}, {name: "Call parents", data: {"2026-01-01" => 5, "2026-01-02" => 3}} ] %> ``` or ```erb <%= line_chart Feat.group(:goal_id).group_by_week(:created_at).count %> ``` ## Data Data can be a hash, array, or URL. #### Hash ```erb <%= line_chart({"2026-01-01" => 2, "2026-01-02" => 3}) %> ``` #### Array ```erb <%= line_chart [["2026-01-01", 2], ["2026-01-02", 3]] %> ``` #### URL Make your pages load super fast and stop worrying about timeouts. Give each chart its own endpoint. ```erb <%= line_chart completed_tasks_charts_path %> ``` And in your controller, pass the data as JSON. ```ruby class ChartsController < ApplicationController def completed_tasks render json: Task.group_by_day(:completed_at).count end end ``` For multiple series, add `chart_json` at the end. ```ruby render json: Task.group(:goal_id).group_by_day(:completed_at).count.chart_json ``` ## Options Id, width, and height ```erb <%= line_chart data, id: "users-chart", width: "800px", height: "500px" %> ``` Min and max values ```erb <%= line_chart data, min: 1000, max: 5000 %> ``` `min` defaults to 0 for charts with non-negative values. Use `nil` to let the charting library decide. Min and max for x-axis - *Chart.js* ```erb <%= line_chart data, xmin: "2026-01-01", xmax: "2026-02-01" %> ``` Colors ```erb <%= line_chart data, colors: ["#b00", "#666"] %> ``` Stacked columns or bars ```erb <%= column_chart data, stacked: true %> ``` Discrete axis ```erb <%= line_chart data, discrete: true %> ``` Label (for single series) ```erb <%= line_chart data, label: "Value" %> ``` Axis titles ```erb <%= line_chart data, xtitle: "Time", ytitle: "Population" %> ``` Straight lines between points instead of a curve ```erb <%= line_chart data, curve: false %> ``` Hide points ```erb <%= line_chart data, points: false %> ``` Show or hide legend ```erb <%= line_chart data, legend: false %> ``` Specify legend position ```erb <%= line_chart data, legend: "bottom" %> ``` Donut chart ```erb <%= pie_chart data, donut: true %> ``` Prefix, useful for currency - *Chart.js, Highcharts* ```erb <%= line_chart data, prefix: "$" %> ``` Suffix, useful for percentages - *Chart.js, Highcharts* ```erb <%= line_chart data, suffix: "%" %> ``` Set a thousands separator - *Chart.js, Highcharts* ```erb <%= line_chart data, thousands: "," %> ``` Set a decimal separator - *Chart.js, Highcharts* ```erb <%= line_chart data, decimal: "," %> ``` Set significant digits - *Chart.js, Highcharts* ```erb <%= line_chart data, precision: 3 %> ``` Set rounding - *Chart.js, Highcharts* ```erb <%= line_chart data, round: 2 %> ``` Show insignificant zeros, useful for currency - *Chart.js, Highcharts* ```erb <%= line_chart data, round: 2, zeros: true %> ``` Friendly byte sizes - *Chart.js* ```erb <%= line_chart data, bytes: true %> ``` Specify the message when data is loading ```erb <%= line_chart data, loading: "Loading..." %> ``` Specify the message when data is empty ```erb <%= line_chart data, empty: "No data" %> ``` Refresh data from a remote source every `n` seconds ```erb <%= line_chart url, refresh: 60 %> ``` You can pass options directly to the charting library with: ```erb <%= line_chart data, library: {backgroundColor: "#eee"} %> ``` See the documentation for [Chart.js](https://www.chartjs.org/docs/), [Google Charts](https://developers.google.com/chart/interactive/docs/gallery), and [Highcharts](https://api.highcharts.com/highcharts) for more info. For Chart.js plugins, check out [this guide](guides/Chartjs-Plugins.md). To customize datasets in Chart.js, use: ```erb <%= line_chart data, dataset: {borderWidth: 10} %> ``` You can pass this option to individual series as well. ### Global Options To set options for all of your charts, create an initializer `config/initializers/chartkick.rb` with: ```ruby Chartkick.options = { height: "400px", colors: ["#b00", "#666"] } ``` Customize the html ```ruby Chartkick.options[:html] = '%{loading}' ``` You capture the JavaScript in a content block with: ```ruby Chartkick.options[:content_for] = :charts_js ``` Then, in your layout, use: ```erb <%= yield :charts_js %> ``` For Padrino, use `yield_content` instead of `yield`. This is great for including all of your JavaScript at the bottom of the page. ### Multiple Series You can pass a few options with a series: - `name` - `data` - `color` - `dataset` - *Chart.js only* - `points` - *Chart.js only* - `curve` - *Chart.js only* ### Code If you want to use the charting library directly, get the code with: ```erb <%= line_chart data, code: true %> ``` The code will be logged to the JavaScript console. JavaScript functions cannot be logged, so it may not be identical. ### Download Charts *Chart.js only* Give users the ability to download charts. It all happens in the browser - no server-side code needed. ```erb <%= line_chart data, download: true %> ``` Safari will open the image in a new window instead of downloading. Set the filename ```erb <%= line_chart data, download: {filename: "boom"} %> ``` Set the background color ```erb <%= line_chart data, download: {background: "#ffffff"} %> ``` Set title ```erb <%= line_chart data, title: "Awesome chart" %> ``` ## Additional Charting Libraries - [Google Charts](#google-charts) - [Highcharts](#highcharts) ### Google Charts In your layout or views, add: ```erb <%= javascript_include_tag "https://www.gstatic.com/charts/loader.js" %> ``` For Importmap (Rails default), in `config/importmap.rb`, add: ```ruby pin "chartkick", to: "chartkick.js" ``` And in `app/javascript/application.js`, add: ```js import "chartkick" ``` For Bun, esbuild, rollup.js, or Webpack, run: ```sh bun add chartkick # or yarn add chartkick ``` And in `app/javascript/packs/application.js`, add: ```js import "chartkick" ``` For Sprockets, in `app/assets/javascripts/application.js`, add: ```js //= require chartkick ``` To specify a language or Google Maps API key, use: ```js Chartkick.configure({language: "de", mapsApiKey: "..."}) ``` before your charts. ### Highcharts For Importmap (Rails default), run: ```sh bin/importmap pin highcharts --download ``` And in `config/importmap.rb`, add: ```ruby pin "chartkick", to: "chartkick.js" ``` And in `app/javascript/application.js`, add: ```js import "chartkick" import Highcharts from "highcharts" window.Highcharts = Highcharts ``` For Bun, esbuild, rollup.js, or Webpack, run: ```sh bun add chartkick highcharts # or yarn add chartkick highcharts ``` And in `app/javascript/packs/application.js`, add: ```js import "chartkick/highcharts" ``` For Sprockets, download [highcharts.js](https://code.highcharts.com/highcharts.js) into `vendor/assets/javascripts` (or use `yarn add highcharts`), and in `app/assets/javascripts/application.js`, add: ```js //= require chartkick //= require highcharts ``` ### Multiple Libraries If more than one charting library is loaded, choose between them with: ```erb <%= line_chart data, adapter: "google" %> ``` ## Sinatra and Padrino Download [chartkick.js](https://raw.githubusercontent.com/ankane/chartkick/master/vendor/assets/javascripts/chartkick.js) and include it manually. ```html ``` Then include the charting library. Chart.js - download [Chart.js](https://unpkg.com/chart.js@4/dist/chart.umd.js) and the [date-fns adapter bundle](https://unpkg.com/chartjs-adapter-date-fns@3/dist/chartjs-adapter-date-fns.bundle.js) ```html ``` Google Charts ```html ``` Highcharts - download [highcharts.js](https://code.highcharts.com/highcharts.js) ```html ``` ## JavaScript API Access a chart with: ```javascript var chart = Chartkick.charts["chart-id"] ``` Get the underlying chart object with: ```javascript chart.getChartObject() ``` You can also use: ```javascript chart.getElement() chart.getData() chart.getOptions() chart.getAdapter() ``` Update the data with: ```javascript chart.updateData(newData) ``` You can also specify new options: ```javascript chart.setOptions(newOptions) // or chart.updateData(newData, newOptions) ``` Refresh the data from a remote source: ```javascript chart.refreshData() ``` Redraw the chart with: ```javascript chart.redraw() ``` Destroy the chart with: ```javascript chart.destroy() ``` Loop over charts with: ```javascript Chartkick.eachChart(function (chart) { // do something }) ``` ## Content Security Policy (CSP) Check out [how to configure CSP](https://github.com/ankane/chartkick/blob/master/guides/Content-Security-Policy.md) ## Tutorials - [Charts with Chartkick and Groupdate](https://gorails.com/episodes/charts-with-chartkick-and-groupdate) - [Creando gráficos en Ruby on Rails con Chartkick y Chart.js](https://www.youtube.com/watch?v=W92AlkwQn3M) - [Make Easy Graphs and Charts on Rails with Chartkick](https://www.sitepoint.com/make-easy-graphs-and-charts-on-rails-with-chartkick/) - [Practical Graphs on Rails: Chartkick in Practice](https://www.sitepoint.com/graphs-on-rails-chartkick-in-practice/) ## History View the [changelog](https://github.com/ankane/chartkick/blob/master/CHANGELOG.md) ## Contributing Everyone is encouraged to help improve this project. Here are a few ways you can help: - [Report bugs](https://github.com/ankane/chartkick/issues) - Fix bugs and [submit pull requests](https://github.com/ankane/chartkick/pulls) - Write, clarify, or fix documentation - Suggest or add new features To get started with development: ```sh git clone https://github.com/ankane/chartkick.git cd chartkick bundle install bundle exec rake test ``` ## 2. In-Tree Documentation Chapters (ankane/chartkick) ## File: README.md # Chartkick Create beautiful JavaScript charts with one line of Ruby. No more fighting with charting libraries! [See it in action](https://chartkick.com) :fire: For admin charts and dashboards, check out [Blazer](https://github.com/ankane/blazer/), and for advanced visualizations, check out [Vega](https://github.com/ankane/vega) :two_hearts: A perfect companion to [Groupdate](https://github.com/ankane/groupdate), [Hightop](https://github.com/ankane/hightop), and [ActiveMedian](https://github.com/ankane/active_median) [](https://github.com/ankane/chartkick/actions) ## Quick Start Add this line to your application’s Gemfile: ```ruby gem "chartkick" ``` Then follow the instructions for your JavaScript setup: - [Importmap](#importmap) (Rails default) - [Bun, esbuild, rollup.js, or Webpack](#bun-esbuild-rollupjs-or-webpack) - [Sprockets](#sprockets) This sets up Chartkick with [Chart.js](https://www.chartjs.org/). For other charting libraries and frameworks, see [these instructions](#additional-charting-libraries). ### Importmap In `config/importmap.rb`, add: ```ruby pin "chartkick", to: "chartkick.js" pin "Chart.bundle", to: "Chart.bundle.js" ``` And in `app/javascript/application.js`, add: ```js import "chartkick" import "Chart.bundle" ``` ### Bun, esbuild, rollup.js, or Webpack Run: ```sh bun add chartkick chart.js # or yarn add chartkick chart.js ``` And in `app/javascript/application.js`, add: ```js import "chartkick/chart.js" ``` ### Sprockets In `app/assets/javascripts/application.js`, add: ```js //= require chartkick //= require Chart.bundle ``` ## Charts Line chart ```erb <%= line_chart User.group_by_day(:created_at).count %> ``` Pie chart ```erb <%= pie_chart Goal.group(:name).count %> ``` Column chart ```erb <%= column_chart Task.group_by_hour_of_day(:created_at, format: "%l %P").count %> ``` Bar chart ```erb <%= bar_chart Shirt.group(:size).sum(:price) %> ``` Area chart ```erb <%= area_chart Visit.group_by_minute(:created_at).maximum(:load_time) %> ``` Scatter chart ```erb <%= scatter_chart City.pluck(:size, :population) %> ``` Geo chart - *Google Charts* ```erb <%= geo_chart Medal.group(:country).count %> ``` Timeline - *Google Charts* ```erb <%= timeline [ ["Washington", "1789-04-29", "1797-03-03"], ["Adams", "1797-03-03", "1801-03-03"], ["Jefferson", "1801-03-03", "1809-03-03"] ] %> ``` Multiple series ```erb <%= line_chart [ {name: "Workout", data: {"2026-01-01" => 3, "2026-01-02" => 4}}, {name: "Call parents", data: {"2026-01-01" => 5, "2026-01-02" => 3}} ] %> ``` or ```erb <%= line_chart Feat.group(:goal_id).group_by_week(:created_at).count %> ``` ## Data Data can be a hash, array, or URL. #### Hash ```erb <%= line_chart({"2026-01-01" => 2, "2026-01-02" => 3}) %> ``` #### Array ```erb <%= line_chart [["2026-01-01", 2], ["2026-01-02", 3]] %> ``` #### URL Make your pages load super fast and stop worrying about timeouts. Give each chart its own endpoint. ```erb <%= line_chart completed_tasks_charts_path %> ``` And in your controller, pass the data as JSON. ```ruby class ChartsController < ApplicationController def completed_tasks render json: Task.group_by_day(:completed_at).count end end ``` For multiple series, add `chart_json` at the end. ```ruby render json: Task.group(:goal_id).group_by_day(:completed_at).count.chart_json ``` ## Options Id, width, and height ```erb <%= line_chart data, id: "users-chart", width: "800px", height: "500px" %> ``` Min and max values ```erb <%= line_chart data, min: 1000, max: 5000 %> ``` `min` defaults to 0 for charts with non-negative values. Use `nil` to let the charting library decide. Min and max for x-axis - *Chart.js* ```erb <%= line_chart data, xmin: "2026-01-01", xmax: "2026-02-01" %> ``` Colors ```erb <%= line_chart data, colors: ["#b00", "#666"] %> ``` Stacked columns or bars ```erb <%= column_chart data, stacked: true %> ``` Discrete axis ```erb <%= line_chart data, discrete: true %> ``` Label (for single series) ```erb <%= line_chart data, label: "Value" %> ``` Axis titles ```erb <%= line_chart data, xtitle: "Time", ytitle: "Population" %> ``` Straight lines between points instead of a curve ```erb <%= line_chart data, curve: false %> ``` Hide points ```erb <%= line_chart data, points: false %> ``` Show or hide legend ```erb <%= line_chart data, legend: false %> ``` Specify legend position ```erb <%= line_chart data, legend: "bottom" %> ``` Donut chart ```erb <%= pie_chart data, donut: true %> ``` Prefix, useful for currency - *Chart.js, Highcharts* ```erb <%= line_chart data, prefix: "$" %> ``` Suffix, useful for percentages - *Chart.js, Highcharts* ```erb <%= line_chart data, suffix: "%" %> ``` Set a thousands separator - *Chart.js, Highcharts* ```erb <%= line_chart data, thousands: "," %> ``` Set a decimal separator - *Chart.js, Highcharts* ```erb <%= line_chart data, decimal: "," %> ``` Set significant digits - *Chart.js, Highcharts* ```erb <%= line_chart data, precision: 3 %> ``` Set rounding - *Chart.js, Highcharts* ```erb <%= line_chart data, round: 2 %> ``` Show insignificant zeros, useful for currency - *Chart.js, Highcharts* ```erb <%= line_chart data, round: 2, zeros: true %> ``` Friendly byte sizes - *Chart.js* ```erb <%= line_chart data, bytes: true %> ``` Specify the message when data is loading ```erb <%= line_chart data, loading: "Loading..." %> ``` Specify the message when data is empty ```erb <%= line_chart data, empty: "No data" %> ``` Refresh data from a remote source every `n` seconds ```erb <%= line_chart url, refresh: 60 %> ``` You can pass options directly to the charting library with: ```erb <%= line_chart data, library: {backgroundColor: "#eee"} %> ``` See the documentation for [Chart.js](https://www.chartjs.org/docs/), [Google Charts](https://developers.google.com/chart/interactive/docs/gallery), and [Highcharts](https://api.highcharts.com/highcharts) for more info. For Chart.js plugins, check out [this guide](guides/Chartjs-Plugins.md). To customize datasets in Chart.js, use: ```erb <%= line_chart data, dataset: {borderWidth: 10} %> ``` You can pass this option to individual series as well. ### Global Options To set options for all of your charts, create an initializer `config/initializers/chartkick.rb` with: ```ruby Chartkick.options = { height: "400px", colors: ["#b00", "#666"] } ``` Customize the html ```ruby Chartkick.options[:html] = '%{loading}' ``` You capture the JavaScript in a content block with: ```ruby Chartkick.options[:content_for] = :charts_js ``` Then, in your layout, use: ```erb <%= yield :charts_js %> ``` For Padrino, use `yield_content` instead of `yield`. This is great for including all of your JavaScript at the bottom of the page. ### Multiple Series You can pass a few options with a series: - `name` - `data` - `color` - `dataset` - *Chart.js only* - `points` - *Chart.js only* - `curve` - *Chart.js only* ### Code If you want to use the charting library directly, get the code with: ```erb <%= line_chart data, code: true %> ``` The code will be logged to the JavaScript console. JavaScript functions cannot be logged, so it may not be identical. ### Download Charts *Chart.js only* Give users the ability to download charts. It all happens in the browser - no server-side code needed. ```erb <%= line_chart data, download: true %> ``` Safari will open the image in a new window instead of downloading. Set the filename ```erb <%= line_chart data, download: {filename: "boom"} %> ``` Set the background color ```erb <%= line_chart data, download: {background: "#ffffff"} %> ``` Set title ```erb <%= line_chart data, title: "Awesome chart" %> ``` ## Additional Charting Libraries - [Google Charts](#google-charts) - [Highcharts](#highcharts) ### Google Charts In your layout or views, add: ```erb <%= javascript_include_tag "https://www.gstatic.com/charts/loader.js" %> ``` For Importmap (Rails default), in `config/importmap.rb`, add: ```ruby pin "chartkick", to: "chartkick.js" ``` And in `app/javascript/application.js`, add: ```js import "chartkick" ``` For Bun, esbuild, rollup.js, or Webpack, run: ```sh bun add chartkick # or yarn add chartkick ``` And in `app/javascript/packs/application.js`, add: ```js import "chartkick" ``` For Sprockets, in `app/assets/javascripts/application.js`, add: ```js //= require chartkick ``` To specify a language or Google Maps API key, use: ```js Chartkick.configure({language: "de", mapsApiKey: "..."}) ``` before your charts. ### Highcharts For Importmap (Rails default), run: ```sh bin/importmap pin highcharts --download ``` And in `config/importmap.rb`, add: ```ruby pin "chartkick", to: "chartkick.js" ``` And in `app/javascript/application.js`, add: ```js import "chartkick" import Highcharts from "highcharts" window.Highcharts = Highcharts ``` For Bun, esbuild, rollup.js, or Webpack, run: ```sh bun add chartkick highcharts # or yarn add chartkick highcharts ``` And in `app/javascript/packs/application.js`, add: ```js import "chartkick/highcharts" ``` For Sprockets, download [highcharts.js](https://code.highcharts.com/highcharts.js) into `vendor/assets/javascripts` (or use `yarn add highcharts`), and in `app/assets/javascripts/application.js`, add: ```js //= require chartkick //= require highcharts ``` ### Multiple Libraries If more than one charting library is loaded, choose between them with: ```erb <%= line_chart data, adapter: "google" %> ``` ## Sinatra and Padrino Download [chartkick.js](https://raw.githubusercontent.com/ankane/chartkick/master/vendor/assets/javascripts/chartkick.js) and include it manually. ```html ``` Then include the charting library. Chart.js - download [Chart.js](https://unpkg.com/chart.js@4/dist/chart.umd.js) and the [date-fns adapter bundle](https://unpkg.com/chartjs-adapter-date-fns@3/dist/chartjs-adapter-date-fns.bundle.js) ```html ``` Google Charts ```html ``` Highcharts - download [highcharts.js](https://code.highcharts.com/highcharts.js) ```html ``` ## JavaScript API Access a chart with: ```javascript var chart = Chartkick.charts["chart-id"] ``` Get the underlying chart object with: ```javascript chart.getChartObject() ``` You can also use: ```javascript chart.getElement() chart.getData() chart.getOptions() chart.getAdapter() ``` Update the data with: ```javascript chart.updateData(newData) ``` You can also specify new options: ```javascript chart.setOptions(newOptions) // or chart.updateData(newData, newOptions) ``` Refresh the data from a remote source: ```javascript chart.refreshData() ``` Redraw the chart with: ```javascript chart.redraw() ``` Destroy the chart with: ```javascript chart.destroy() ``` Loop over charts with: ```javascript Chartkick.eachChart(function (chart) { // do something }) ``` ## Content Security Policy (CSP) Check out [how to configure CSP](https://github.com/ankane/chartkick/blob/master/guides/Content-Security-Policy.md) ## Tutorials - [Charts with Chartkick and Groupdate](https://gorails.com/episodes/charts-with-chartkick-and-groupdate) - [Creando gráficos en Ruby on Rails con Chartkick y Chart.js](https://www.youtube.com/watch?v=W92AlkwQn3M) - [Make Easy Graphs and Charts on Rails with Chartkick](https://www.sitepoint.com/make-easy-graphs-and-charts-on-rails-with-chartkick/) - [Practical Graphs on Rails: Chartkick in Practice](https://www.sitepoint.com/graphs-on-rails-chartkick-in-practice/) ## History View the [changelog](https://github.com/ankane/chartkick/blob/master/CHANGELOG.md) ## Contributing Everyone is encouraged to help improve this project. Here are a few ways you can help: - [Report bugs](https://github.com/ankane/chartkick/issues) - Fix bugs and [submit pull requests](https://github.com/ankane/chartkick/pulls) - Write, clarify, or fix documentation - Suggest or add new features To get started with development: ```sh git clone https://github.com/ankane/chartkick.git cd chartkick bundle install bundle exec rake test ``` --- ## File: guides/Chartjs-Plugins.md # Chart.js Plugins Chartkick works with Chart.js global plugins. Here’s how to add the [annotation](https://www.chartjs.org/chartjs-plugin-annotation/latest/) plugin. For Importmaps, download the [UMD version](https://unpkg.com/chartjs-plugin-annotation@3/dist/chartjs-plugin-annotation.cjs) to `vendor/javascript`, change the extension from `.cjs` to `.js`, pin it in `config/importmap.rb`, and use: ```javascript import "chartjs-plugin-annotation" ``` For Bun, esbuild, rollup.js, and Webpack, install the NPM package and use: ```javascript import { Chart } from "chart.js" import annotationPlugin from "chartjs-plugin-annotation" Chart.register(annotationPlugin) ``` For Sprockets, download the [UMD version](https://unpkg.com/chartjs-plugin-annotation@3/dist/chartjs-plugin-annotation.cjs) to `vendor/assets/javascripts`, change the extension from `.cjs` to `.js`, and use: ```javascript //= require chartjs-plugin-annotation ``` Then use the `library` option to apply it to charts: ```erb <%= line_chart data, library: {plugins: {annotation: {annotations: {line1: {type: "line", yMin: 2, yMax: 2}}}}} %> ``` --- ## File: guides/Content-Security-Policy.md # Content Security Policy (CSP) Chartkick tries to make CSP as easy as possible. Currently, `unsafe-inline` styles must be enabled for charts to work. There are open issues to resolve this with some of the charting libraries. - [Chart.js](https://github.com/chartjs/Chart.js/issues/5208) - [Highcharts](https://github.com/highcharts/highcharts/issues/6173) Google Charts also requires `unsafe-eval` and as well as styles and scripts from the `https://www.gstatic.com` domain. ## Rails 5.2+ Rails 5.2+ has built-in support for CSP. Configure CSP and enable automatic nonce generation in `config/initializers/content_security_policy.rb` with: ```ruby Rails.application.config.content_security_policy do |policy| policy.script_src :self policy.style_src :self end Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } ``` Enable unsafe inline styles on actions that have charts ```ruby class ChartsController < ApplicationController content_security_policy only: :index do |policy| policy.style_src :self, :unsafe_inline end end ``` ## Secure Headers Configure CSP in `config/initializers/secure_headers.rb` with: ```ruby SecureHeaders::Configuration.default do |config| config.csp = { default_src: %w('none'), script_src: %w('self'), style_src: %w('self') } end SecureHeaders::Configuration.named_append(:charts) do |request| {style_src: %w('unsafe-inline')} end ``` Enable unsafe inline styles on actions that have charts ```ruby class ChartsController < ApplicationController def index use_content_security_policy_named_append(:charts) end end ``` --- METRICS --- - Files Extracted: 4 - Estimated Token Budget: ~6906 tokens - Recency Window: Active (< 180 days) - Canonical Reference: https://codewiki.google/github.com/ankane/chartkick