{"id":15046977,"url":"https://github.com/shogunpurple/theme-it","last_synced_at":"2025-10-30T01:35:49.429Z","repository":{"id":87655254,"uuid":"115221869","full_name":"shogunpurple/theme-it","owner":"shogunpurple","description":"A tiny, framework agnostic theming library powered by custom CSS properties (CSS4 Variables) with absolutely zero dependencies.","archived":false,"fork":false,"pushed_at":"2018-07-24T09:40:10.000Z","size":804,"stargazers_count":7,"open_issues_count":3,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-03T04:51:44.083Z","etag":null,"topics":["css","stylesheets","theme"],"latest_commit_sha":null,"homepage":"","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/shogunpurple.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":"2017-12-23T21:06:34.000Z","updated_at":"2023-12-29T18:33:51.000Z","dependencies_parsed_at":"2023-03-13T18:40:49.983Z","dependency_job_id":null,"html_url":"https://github.com/shogunpurple/theme-it","commit_stats":null,"previous_names":["mmckeaveney/theme-it"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/shogunpurple/theme-it","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shogunpurple%2Ftheme-it","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shogunpurple%2Ftheme-it/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shogunpurple%2Ftheme-it/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shogunpurple%2Ftheme-it/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shogunpurple","download_url":"https://codeload.github.com/shogunpurple/theme-it/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shogunpurple%2Ftheme-it/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":281730899,"owners_count":26551804,"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-29T02:00:06.901Z","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":["css","stylesheets","theme"],"created_at":"2024-09-24T20:53:49.823Z","updated_at":"2025-10-30T01:35:49.387Z","avatar_url":"https://github.com/shogunpurple.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# theme-it :wrench: :rainbow:\n[![All Contributors](https://img.shields.io/badge/all_contributors-3-orange.svg?style=flat-square)](#contributors)\n[![npm](https://img.shields.io/npm/v/theme-it.svg)](https://www.npmjs.com/package/theme-it)\n[![license](https://img.shields.io/github/license/mmckeaveney/theme-it.svg)](https://github.com/mmckeaveney/theme-it/blob/master/LICENSE)\n\n\nA small (1.6kb minified + gzipped), blazing fast theming library powered by CSS custom properties (also known as CSS4 Variables) with absolutely zero dependencies.\n\n- [theme-it](#theme-it)\n    - [Rationale](#rationale)\n    - [Installation](#installation)\n    - [Basic Usage](#basic-usage)\n        - [Check if your browser supports CSS custom properties and theme-it](#check-if-your-browser-supports-css-custom-properties-and-theme-it)\n        - [Manage themes and properties using theme-it](#manage-themes-and-properties-using-theme-it)\n        - [Perform a callback when you execute a theme-it operation](#perform-a-callback-when-you-execute-a-theme-it-operation)\n    - [Advanced Usage](#advanced-usage)\n        - [Create a completely new theme at runtime, and apply it](#create-a-completely-new-theme-at-runtime-and-apply-it)\n    - [Examples](#examples)\n    - [API](#api)\n        - [The Themeit object](#the-themeit-object)\n        - [Configuration options](#configuration-options)\n            - [debug](#debug)\n            - [themeClasses](#themeclasses)\n        - [Callbacks](#callbacks)\n            - [onPropertyGet](#onpropertyget)\n            - [onPropertySet](#onpropertyset)\n            - [onPropertyRemove](#onpropertyremove)\n            - [onThemesCreate](#onthemescreate)\n            - [onThemeApply](#onthemeapply)\n            - [onThemeUnapply](#onthemeunapply)\n    - [Command Line Interface](#command-line-interface)\n    - [Development](#development)\n    - [Known Issues](#known-issues)\n    - [Contributors](#contributors)\n\n## Rationale\nVariables are one of the reasons [CSS preprocessors](https://developer.mozilla.org/en-US/docs/Glossary/CSS_preprocessor) ([SASS](http://sass-lang.com/), [LESS](http://lesscss.org/)) exist at all. The limitation here is that preprocessors provide variable functionality at **compile time**. This means you cannot access these variables at runtime when you compile code from your chosen preprocessor into CSS. This poses a problem that many developers solve by bundling a different stylesheet for every theme and switching between them with JavaScript.\n\nNative [CSS custom properties](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables) were introduced to allow you to work with variables directly, change them at runtime with JS and DRY up CSS definitions out of the box. theme-it is a small, fast library that provides a bunch of utilities and abstractions for working with CSS variables at runtime, allowing you to dynamically theme your applications at the root or even component level regardless of framework, and without a CSS preprocessor or any other dependencies at all.\n\n**theme-it** allows you to:\n- Manage CSS Variable themes at runtime (apply and unapply themes)\n- Get and set individual CSS variables at runtime\n- Add callbacks for all theming operations so you can update client state, post to the server and more.\n- Convert your current CSS in JS theme configuration to use CSS variables\n- Genrerate completely new theme CSS using the CLI, or create them in the browser to enable totally custom, user created colour schemes at runtime.\n\n\n## Installation\n**npm**\n```\nnpm i theme-it\n```\n\n**yarn**\n```\nyarn add theme-it\n```\n\n## Basic Usage\nThere are many different ways to use theme-it in your application. The easiest way is to create your own theme classes in your CSS, and manage the classnames using theme-it. theme-it has a class based API, so you need to instantiate the `Themeit` object in order to use it.\n\nThe following is a simple example of a theme you can create in one of your CSS files. Each class contains CSS variables which cascade - meaning any children of the element with that class applied will inherit the theme variables.\n\n```css\n.dark-theme {\n    --primary-color: black;\n    --secondary-color: darkblue;\n    --tertiary-color: darkgreen;\n}\n\n.light-theme {\n    --primary-color: white;\n    --secondary-color: skyblue;\n    --tertiary-color: green;\n}\n```\n\n### Check if your browser supports CSS custom properties and theme-it\n`isSupported()` will return a boolean as to whether or not your browser supports CSS custom properties.\n\n```js\nconst themeit = new Themeit();\n\nif (themeit.isSupported()) {\n    console.log(\"CSS custom properties supported. It's party time\");\n}\n```\n\nCurrent browser support for CSS variables (courtesy of [caniuse](http://caniuse.com)):\n![alt text](./assets/browserSupport.png \"Browser Support for CSS variables\")\n\n\n\n### Manage themes and properties using theme-it\nYou can manage themes as well as individual properties with theme-it. The following example shows you how to do this.\n\nEvery function that manages themes and properties in theme-it follows a convention. The last argument is always a selector, which defaults to `body` for application wide theming. You can however pass your own selector to theme at the component level.\n\nEvery update to a theme or property will trigger a re-render, which will apply your new theme or property instantly. Theme-it will also throw errors if you try to apply themes or remove properties that don't exist.\n\n```js\n// imports the minified production bundle.\n// To import transpiled, non-minified code, import from the lib/ directory.\nimport Themeit from \"theme-it\";\n\nconst themeit = new Themeit({\n    themeClasses: [\"light-theme\", \"dark-theme\"]\n});\n\n// apply a theme\nthemeit.applyTheme(\"dark-theme\");\n\n// get the value of a CSS property\nconst darkThemePrimaryColor = themeit.getProperty(\"primary-color\"); // black\n\n// set the value of a CSS property\nthemeit.setProperty(\"primary-color\", \"purple\");\n\n// remove a CSS property completely\nthemeit.removeProperty(\"primary-color\");\n\n// apply a different theme (this replaces the theme already on the element)\nthemeit.applyTheme(\"light-theme\");\n\n// unapply the theme\nthemeit.unapplyTheme(\"light-theme\");\n\n// apply a theme to a certain element and its children\nthemeit.applyTheme(\"dark-theme\", \".my-cool-element\")\n```\n\n### Perform a callback when you execute a theme-it operation  \ntheme-it allows you to provide optional callbacks when you instantiate the `Themeit` object. This allows you to perform an action when you apply, unapply or create a theme. You can also provide callbacks for getting, setting and removing properties.\n\nThis is especially useful when you want to keep track of the current theme in your client state, or perform a call to the server with the updated theme information.\n\nRefer to the API for the details on each callback and its arguments.\n\n```js\nconst themeit = new Themeit({\n    themeClasses: [\"dark-theme\", \"light-theme\"],\n    onPropertyGet: console.log,\n    onPropertySet: console.log,\n    onPropertyRemove: console.log,\n    onThemesCreate: console.log,\n    onThemeApply: console.log,\n    onThemeUnapply: console.log\n});\n\nthemeit.applyTheme(\"dark-theme\") // onThemeApply will be executed\nthemeit.unapplyTheme(\"dark-theme\") // onThemeUnapply will be executed\nthemeit.setProperty(\"primary-color\", \"red\") // onPropertySet will be executed\nthemeit.getProperty(\"primary-color\") // onPropertyGet will be executed\nthemeit.removeProperty(\"primary-color\") // onPropertyRemove will be executed\nthemeit.createThemes({\n    \"new-theme\": {\n        primaryColor: \"blue\"\n    }\n}); // onThemesCreate will be executed\n```\n\n## Advanced Usage\n\n### Create a completely new theme at runtime, and apply it\nYou can create new themes at runtime with theme-it and apply them. You pass in a theme configuration object similar to what you would use in CSS in JS libraries, which theme-it will transform into valid CSS definitions using CSS variables. These CSS definitions will be injected into the `\u003chead /\u003e` tag of the document. Be aware that refreshing the page means you will lose your theme.\n\nA solution to this is to use the `onThemesCreate` callback to save your theme somewhere so you can use it again.  \n\nNote that when the theme config is parsed, it will flatten the object structure into a CSS class definition, changing the theme names and variables from camel to kebab-case. For example, when you perform the following:\n\n```js\nthemeit.createThemes({\n    coolTheme: {\n        primaryColor: \"blue\"\n    }\n});\n\n```\n\nThe theme object will be transformed into the following and injected into the `head` tag.\n\n```css\n.cool-theme {\n    --primary-color: blue;\n}\n```\n\nYou can also nest properties, and theme-it will flatten them out for you -\n\n```js\nthemeit.createThemes({\n  nestedDarkTheme: {\n    primaryColor: \"black\",\n    secondaryColor: \"papayawhip\",\n    globalBorder: \"2px\",\n    button: {\n      primaryColor: \"blue\"\n    },\n    input: {\n      secondaryColor: \"papayawhip\",\n      radio: {\n        color: \"purple\"\n      },\n      text: {\n        border: \"5px\"\n      }\n    }\n  }\n});\n\n```\n\nThe generated CSS for the above theme will look like this -\n\n```css\n  .nested-dark-theme {\n    --primary-color: black;\n    --secondary-color: papayawhip;\n    --global-border: 2px;\n    --button-primary-color: blue;\n    --input-secondary-color: papayawhip;\n    --input-radio-color: purple;\n    --input-text-border: 5px\n  }\n```\n\nIf you find a theme you like and want to add it to your CSS so you don't have to generate it every time, you can run theme-it with the `debug` flag, which will output the generated CSS to the console when you create a theme. You can then copy this CSS into your own code and add the class name to theme-its `themeClasses` array so you can manage it.\n\nYou can also do this without running theme-it in the browser by using the [Command Line Interface](#command-line-interface).\n\nSome other examples to show how you can create a theme, and apply it after creation -\n\n```js\nconst themeit = new Themeit();\n\n// Create some new themes\nthemeit.createThemes({\n    coolNewTheme: {\n        primaryColor: \"papayawhip\",\n        secondaryColor: \"palevioletred\",\n        tertiaryColor: \"purple\",\n    },\n    otherCoolNewTheme: {\n        primaryColor: \"white\",\n        secondaryColor: \"white\",\n        tertiaryColor: \"white\",\n    }\n});\n\n// apply the first theme\nthemeit.applyTheme(\"cool-new-theme\");\n\n// apply the second theme\nthemeit.applyTheme(\"other-cool-new-theme\");\n\n// Nested theme\nthemeit.createThemes({\n  nestedDarkTheme: {\n    primaryColor: \"black\",\n    secondaryColor: \"papayawhip\",\n    globalBorder: \"2px\",\n    button: {\n      primaryColor: \"blue\"\n    },\n    input: {\n      secondaryColor: \"papayawhip\",\n      radio: {\n        color: \"purple\"\n      },\n      text: {\n        border: \"5px\"\n      }\n    }\n  },\n  nestedLightTheme: {\n    primaryColor: \"gray\",\n    secondaryColor: \"purple\",\n    globalBorder: \"2px\",\n    button: {\n      primaryColor: \"blue\"\n    },\n    input: {\n      secondaryColor: \"papayawhip\",\n      radio: {\n        color: \"purple\"\n      },\n      text: {\n        border: \"5px\"\n      }\n    }\n  }\n})\n\nthemeit.applyTheme(\"nested-light-theme\");\n```\n\n## Examples\nAs a way of show casing the power of Themeit we created some examples in different frameworks.\nThe examples are just a showcase. Themeit doesn't, in any way, depend on the frameworks listed below.\n - [Vue](https://codesandbox.io/s/zz2on366jl?view=preview)\n\n## API\n\n### The Themeit object\nThis is the main object you need to instantiate in order to use themeit. You can do so as follows:\n\n```js\nimport Themeit from \"theme-it\";\n\nconst themeit = new Themeit();\n```\n\n### Configuration options\nThe `Themeit` constructor takes a configuration object. Below are all the available options.\n\n#### debug\n`Boolean`\n\ndefault: `false`\n\nWhen `debug` is true, extra logging and information will be logged to the console when you perform certain theme-it operations. This is useful for development.\n\n```js\nnew Themeit({ debug: true });\n```\n\n\n#### themeClasses\n`Array\u003cString\u003e`\n\ndefault: `[]`\n\nThe list of class names for themes you have already created in your CSS. This is required so theme-it knows which themes already exist, as well as for theme management. Make sure to keep this updated when you create a new theme in your CSS. When creating runtime themes with `createThemes`, theme-it will automatically update this array with the new theme name.\n\n```css\n.cool-theme {\n    --primary-color: yellow;\n}\n```\n\n```js\nnew Themeit({\n    themeClasses: [\"cool-theme\"]\n})\n```\n\n### Callbacks\n\n#### onPropertyGet\nCallback executed after `getProperty` is run.\n\n**Type definition**\n\n`(property: string, value: string, element: DOMNode) =\u003e any`\n\ndefault: `undefined`\n\n**property**: the name of the property you asked for (ie: `\"primary-color\"`)\n\n**value**: the value of the property you asked for (ie: `\"blue\"`)\n\n**element**: the DOM element you accessed the property on.\n\n```js\nnew Themeit({\n    onPropertyGet: (property, value, element) =\u003e console.log(property, value, element)\n}).getProperty(\"primary-color\");\n\n// primary-color, blue, \u003cbody\u003e...\u003c/body\u003e\n```\n\n\n#### onPropertySet\nCallback executed after `setProperty` is run.\n\n**Type definition**\n\n`(property: string, value: string, element: DOMNode) =\u003e any`\n\ndefault: `undefined`\n\n**property**: the name of the property you set (ie: `\"primary-color\"`)\n\n**value**: the value you set  (ie: `\"blue\"`)\n\n**element**: the DOM element you set the property on.\n\n```js\nnew Themeit({\n    onPropertySet: (property, value, element) =\u003e console.log(property, value, element)\n}).setProperty(\"primary-color\", \"red\");\n\n// primary-color, blue, \u003cbody\u003e...\u003c/body\u003e\n```\n\n\n#### onPropertyRemove\nCallback executed after `removeProperty` is run.\n\n**Type definition**\n\n`(property: string, value: string, element: DOMNode) =\u003e any`\n\ndefault: `undefined`\n\n**property**: the name of the property you removed (ie: `\"primary-color\"`)\n\n**value**: the value of the property you removed (ie: `\"blue\"`)\n\n**element**: the DOM element you remove the property from.\n\n```js\nnew Themeit({\n    onPropertyRemove: (property, value, element) =\u003e console.log(property, value, element)\n}).removeProperty(\"primary-color\");\n\n// primary-color, blue, \u003cbody\u003e...\u003c/body\u003e\n```\n\n#### onThemesCreate\nCallback executed after `createThemes` is run.\n\n**Type definition**\n\n`(themeNames: Array\u003cString\u003e, generatedThemeCSS: string) =\u003e any`\n\ndefault: `undefined`\n\n**themeNames**: The kebab-case names of the themes you generated.\n\n**generatedThemeCSS**: The CSS generated by the new theme as a string.\n\n```js\nnew Themeit({\n    onThemesCreate: (themeName, css) =\u003e console.log(themeName, css);\n}).createThemes({\n    myTheme: {\n        primaryColor: \"purple\"\n    }\n});\n\n// [\"my-theme\"]\n`\n.my-theme {\n    --primary-color: purple\n}\n`\n```\n\n#### onThemeApply\nCallback executed after `applyTheme` is run.\n\n**Type definition**\n\n`(themeName: string, element: DOMNode) =\u003e any`\n\ndefault: `undefined`\n\n**themeName**: the name of the theme you applied (ie: `\"some-theme\"`)\n\n**element**: the DOM element you applied the theme to.\n\n```js\nnew Themeit({\n    themeClasses: [\"my-theme\"],\n    onThemeApply: (themeName, element) =\u003e console.log(themeName, element);\n}).applyTheme(\"my-theme\");\n\n// \"my-theme\", \u003cbody\u003e ... \u003c/body\u003e\n```\n\n\n#### onThemeUnapply\nCallback executed after `unapplyTheme` is run.\n\n**Type definition**\n\n`(themeName: string, element: DOMNode) =\u003e any`\n\ndefault: `undefined`\n\n**themeName**: the name of the theme you unapplied (ie: `\"some-theme\"`)\n\n**element**: the DOM element you unapplied the theme from.\n\n```js\nnew Themeit({\n    themeClasses: [\"my-theme\"],\n    onThemeApply: (themeName, element) =\u003e console.log(themeName, element);\n}).unapplyTheme(\"my-theme\");\n\n// \"my-theme\", \u003cbody\u003e ... \u003c/body\u003e\n```\n\n## Command Line Interface\nThe CLI converts a JSON file with your theme configuration into a valid CSS file, which you can then use in your application by adding the classname to the `themeClasses` array. This saves you running theme-it in the browser to do the conversion.\n\ntheme-config.json\n```json\n{\n    \"primaryTheme\": {\n        \"primaryColor\": \"red\"\n    }\n}\n```\n\n```\ntheme-it theme-config.json my-theme.css\n```\n\nmy-theme.css\n```css\n.primary-theme {\n    --primary-color: red\n}\n\n```\n\n## Development\n\nClone the repo and install dependencies with your favourite package manager. The NPM scripts in the `package.json` are below.\n\n* `build:minified` =\u003e builds and minifies the code and outputs a production ready bundle\n* `clean` =\u003e blows away build folders (`lib`, `dist`) for a clean build\n* `dev` =\u003e runs a `parcel` development server with hot reloading for development. Access the development playground at `localhost:1234`  \n* `prepublish` =\u003e runs `prepublish:compile` when executing a `npm publish`\n* `prepublish:compile` =\u003e run `clean`, `transpile` and then `build:minified`\n* `test` =\u003e runs the jest test suite.\n* `test:watch` =\u003e run `test` in `watch` mode, which will re-run when you change files pertaining to your tests.\n* `test:update` =\u003e run `test`, but update outdated jest snapshots  \n* `transpile` =\u003e transpile all files in `src` into the `lib` folder using babel\n* `contributors:add` =\u003e add a contributor to the all-contributorsrc. For example: `npm run contributors:add -- yourusername`. You can then select your contributions.\n* `contributors:generate` =\u003e generate the new allcontributors file before checking in.\n* `contributors:check` =\u003e check that the all-contributorsrc reflects all the people who have actually contributed to the project on github.\n\n## Known Issues\n- theme-it does not currently work with Internet Explorer due to lack of support for CSS variables. See [this issue](https://github.com/mmckeaveney/theme-it/issues/5) if you know how to implement a polyfill for this. I'd love your input!\n## Contributors\n\nThanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)):\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore --\u003e\n| [\u003cimg src=\"https://avatars1.githubusercontent.com/u/11256663?s=400\u0026u=55b64769a088cd1b32efd26238521eb449520f99\u0026v=4\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eMartin McKeaveney\u003c/b\u003e\u003c/sub\u003e](https://github.com/mmckeaveney)\u003cbr /\u003e[💻](https://github.com/mmckeaveney/theme-it/commits?author=mmckeaveney \"Code\") [📖](https://github.com/mmckeaveney/theme-it/commits?author=mmckeaveney \"Documentation\") [💡](#example-mmckeaveney \"Examples\") [🤔](#ideas-mmckeaveney \"Ideas, Planning, \u0026 Feedback\") [⚠️](https://github.com/mmckeaveney/theme-it/commits?author=mmckeaveney \"Tests\") | [\u003cimg src=\"https://avatars1.githubusercontent.com/u/9913651?v=4\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003evictoriasloan\u003c/b\u003e\u003c/sub\u003e](https://github.com/victoriasloan)\u003cbr /\u003e[💻](https://github.com/mmckeaveney/theme-it/commits?author=victoriasloan \"Code\") [💡](#example-victoriasloan \"Examples\") | [\u003cimg src=\"https://avatars1.githubusercontent.com/u/5371454?v=4\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eJohan\u003c/b\u003e\u003c/sub\u003e](https://github.com/johman10)\u003cbr /\u003e[💻](https://github.com/mmckeaveney/theme-it/commits?author=johman10 \"Code\") |\n| :---: | :---: | :---: |\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n\nThis project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshogunpurple%2Ftheme-it","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshogunpurple%2Ftheme-it","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshogunpurple%2Ftheme-it/lists"}