{"id":18656585,"url":"https://github.com/zendesk/copenhagen_theme","last_synced_at":"2026-04-02T19:09:42.823Z","repository":{"id":38953271,"uuid":"93491339","full_name":"zendesk/copenhagen_theme","owner":"zendesk","description":"The default theme for Zendesk Guide","archived":false,"fork":false,"pushed_at":"2026-03-26T12:38:27.000Z","size":19981,"stargazers_count":119,"open_issues_count":13,"forks_count":455,"subscribers_count":310,"default_branch":"master","last_synced_at":"2026-03-26T12:57:33.225Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zendesk.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2017-06-06T07:52:12.000Z","updated_at":"2026-03-26T12:38:30.000Z","dependencies_parsed_at":"2023-09-22T21:01:26.386Z","dependency_job_id":"695ad41d-e485-45a0-8565-efd3224d47db","html_url":"https://github.com/zendesk/copenhagen_theme","commit_stats":null,"previous_names":[],"tags_count":224,"template":false,"template_full_name":null,"purl":"pkg:github/zendesk/copenhagen_theme","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zendesk%2Fcopenhagen_theme","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zendesk%2Fcopenhagen_theme/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zendesk%2Fcopenhagen_theme/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zendesk%2Fcopenhagen_theme/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zendesk","download_url":"https://codeload.github.com/zendesk/copenhagen_theme/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zendesk%2Fcopenhagen_theme/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31314021,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T12:59:32.332Z","status":"ssl_error","status_checked_at":"2026-04-02T12:54:48.875Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: 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":[],"created_at":"2024-11-07T07:24:10.852Z","updated_at":"2026-04-02T19:09:42.773Z","avatar_url":"https://github.com/zendesk.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Copenhagen Theme by Zendesk\n\nThe Copenhagen theme is the default Zendesk Guide theme. It is designed to be responsive and accessible.\nLearn more about customizing Zendesk Guide [here](https://support.zendesk.com/hc/en-us/sections/206670747).\n\nThe Copenhagen theme for Help Center consists of:\n- [Manifest file](#manifest-file)\n- [Set of templates](#templates)\n- [Stylesheet and JavaScript files](#stylesheet-and-javascript)\n- [Assets folder](#assets).\n\n## How to use\nThis is the latest version of the Copenhagen theme available for Guide. It is possible to use this repository as a starting point to build your own custom theme. You can fork this repository as you see fit.\nYou can use your favorite IDE to develop themes and preview your changes locally in a web browser using [ZCLI](https://github.com/zendesk/zcli/). For details, read the [zcli themes](https://github.com/zendesk/zcli/blob/master/docs/themes.md) documentation.\n\n## Customizing your theme\nOnce you have forked this repository you can feel free to edit templates, CSS, JavaScript and manage assets.\n\n### Manifest file\nThe manifest allows you to define a group of settings for your theme that can then be changed via the UI in Theming Center.\nYou can read more about the manifest file [here](https://support.zendesk.com/hc/en-us/articles/115012547687).\n\n### Settings folder\nIf you have a variable of type `file`, you need to provide a default file for that variable in the `/settings` folder. This file will be used on the settings panel by default and users can upload a different file if they like.\nEx.\nIf you would like to have a variable for the background image of a section, the variable in your manifest file would look something like this:\n\n```js\n{\n  ...\n  \"settings\": [{\n    \"label\": \"Images\",\n    \"variables\": [{\n      \"identifier\": \"background_image\",\n      \"type\": \"file\",\n      \"description\": \"Background image for X section\",\n      \"label\": \"Background image\",\n    }]\n  }]\n}\n\n```\n\nAnd this would look for a file inside the settings folder named: `background_image`\n\n### Adding assets\nYou can add assets to the asset folder and use them in your CSS, JavaScript and templates.\nYou can read more about assets [here](https://support.zendesk.com/hc/en-us/articles/115012399428)\n\n## Publishing your theme\nAfter you have customized your theme you can download the repository as a `zip` file and import it into Theming Center.\n\nYou can follow the documentation for importing [here](https://support.zendesk.com/hc/en-us/articles/115012794168).\n\nYou can also import directly from GitHub - learn more [here](https://support.zendesk.com/hc/en-us/articles/4408832476698-Setting-up-the-GitHub-integration-with-your-Guide-theme).\n\n## Templates\nThe theme includes all the templates that are used for a Help Center that has *all* the features available.\nList of templates in the theme:\n* Article page\n* Category page\n* Community post list page\n* Community post page\n* Community topic list page\n* Community topic page\n* Contributions page\n* Document head\n* Error page\n* Footer\n* Header\n* Home page\n* New community post page\n* New request page\n* Requests page\n* Search results page\n* Section page\n* Subscriptions page\n* User profile page\n* Service list page (optional, service catalog specific)\n* Service page (optional, service catalog specific)\n* Approval request list page (optional, approvals specific)\n* Approval request page (optional, approvals specific)\n\nYou can add up to 10 optional templates for:\n * Article page\n * Category page\n * Section page\n\nYou do this by creating files under the folders `templates/article_pages`, `templates/category_pages` or `templates/section_pages`.\nLearn more [here](https://support.zendesk.com/hc/en-us/articles/360001948367).\n\n## Stylesheet and JavaScript\n\nWe use Rollup to compile the JS and CSS files that are used in the theme - `style.css` and `script.js`. Do not edit these directly as they'll be regenerated during release.\n\nTo get started:\n\n```console\n$ yarn install\n$ yarn start\n```\n\nThis will compile all the source code in `src` and `styles` and watch for changes. It will also start `preview`.\n\nNotes:\n\n- We intentionally do not use babel when compiling `script.js` so we can get a clean bundle output. Make sure to only use widely supported ecmascript features (ES2015).\n- Do not edit `style.css`, `script.js` and the files inside the `assets` folder directly. They are regenerated during release.\n- Preview requires login so make sure to first run `yarn zcli login -i` if you haven't done that before.\n\n## Assets\nThe Copenhagen theme comes with a few JavaScript assets, but you can add other assets to your theme by placing them in the `assets` folder.\n\n# React components\n\nFrom version 4.0.0, the Copenhagen theme uses some React components to render parts of the UI. These components are located in the `src/modules` folder and are built using the [Zendesk Garden](https://garden.zendesk.com/) component library.\n\nThese components are bundled as native [JavaScript modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) as part of the Rollup build process, and they are emitted as JS files in the `assets` folder. Since assets are renamed when a theme is installed, the modules needs to be imported using the [asset helper](https://developer.zendesk.com/api-reference/help_center/help-center-templates/helpers/#asset-helper). \n\nTo make the process of importing the modules easier, we added a Rollup plugin that generates an [import map](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) that maps the module name to the asset URL. This import map is then injected into the `document_head.hbs` template during the build.\n\nFor example, if you defined a module named `my-module` in the `src/modules/my-module` folder, you can add it to the `rollup.config.mjs` file like this:\n\n```js\nexport default defineConfig([\n  // ...\n  // Configuration for bundling modules in the src/modules directory\n  {\n    // ...\n    input: {\n      \"my-module\": \"src/modules/my-module/index.js\",\n    },\n    // ...\n  }\n]);\n```\n\nRollup will generate a file named `my-module-bundle.js` in the `assets` folder and this import map will be added to the `document_head.hbs` template:\n\n```html\n\u003cscript type=\"importmap\"\u003e\n{\n  \"imports\": {\n    \"my-module\": \"{{asset 'my-module-bundle.js'}}\",\n  }\n}\n\u003c/script\u003e\n```\n\nYou can then import the module in your templates like this:\n\n```hbs\n\u003cscript type=\"module\"\u003e\n  import { something } from \"my-module\";\n\n  // ...\n\u003c/script\u003e\n```\n\n## Internationalization\n\nI18n is implemented in the React components using the [react-i18next](https://react.i18next.com/) library. We use a flat JSON file and we use `.` as a separator for plurals, which is different from the default `_` and it is configured during initialization.\n\nWe also added some tools to be able to integrate the library with the internal translation system used at Zendesk. If you are building a custom theme and you want to provide your own translations you can refer to the library documentation to setup the loading of your translations.\n\n### Integration with the Zendesk translation system\n\n#### Adding translations strings\n\nTranslation strings are added directly in the source code, usually using the `useTranslation` hook, passing the key and the default English value:\n\n```ts\nimport { useTranslation } from 'react-i18next';\n\nfunction MyComponent() {\n  const { t } = useTranslation();\n\n  return \u003cdiv\u003e{t(\"my-key\", \"My default value\")}\u003c/div\u003e\n}\n```\n\nProviding the default English value in the code makes it possible to use it as a fallback value when strings are not yet translated and to extract the strings from the source code to the translations YAML file.\n\n#### Plurals \nWhen using [plurals](https://www.i18next.com/translation-function/plurals), you need to provide default values for the `zero`, `one`, `two`, `few`, `many` and `other` forms, as some languages have specific forms for all of these. These forms should be provided in the translations YAML file, such as [this one](./src/modules/shared/translations/en-us.yml). This can be done manually or by running the extract script after adding the string in the code (check [String extraction](#string-extraction) for more details).\n\nTo use the plural forms in the code, you need to provide at least a default value for `one` and a generic value for the other plural forms. It is also possible to pass a default value for `zero`, if you want it to be different from the generic value. This can be done by passing the default values in the [options](https://www.i18next.com/translation-function/essentials#overview-options) of the `t` function.\n\n```ts\nt(\"my-key\", \"{{count}} items\", {\n  \"defaultValue.zero\": \"No items\",\n  \"defaultValue.one\": \"{{count}} item\",\n  count: ...\n})\n```\n\n#### String extraction\n\nThe `bin/extract-strings.mjs` script can be used to extract translation strings from the source code and put them in the YAML file that is picked up by our internal translation system.\n\nTo extract the strings for all the modules, run:\n\n```bash\nyarn i18n:extract\n```\n\nTo extract the strings for a specific module, run:\n\n```bash\nyarn i18n:extract --module=module-name\n```\n\nYou can also pass the `--mark-obsolete` flag to mark removed strings as obsolete:\n\n```bash\nyarn i18n:extract --mark-obsolete\n```\n\nIf you are adding a new module, you need first to create the initial `src/modules/[MODULE]/translations/en-us.yml` file with the header containing the title and package name:\n\n```yaml\ntitle: \"My Module\"\npackages:\n  - \"package-name\"\n```\n\nThe script wraps the `i18next-parser` tool and converts its output to the YAML format used internally. It is possible to use a similar approach in a custom theme, either using the standard `i18next-parser` output as the source for translations or implementing a custom transformer.\n\n#### Updating translation files\n\nYou can run `yarn i18n:update-translations` to download the latest translations files for all the modules. The script downloads all the locale files for each module, fetching the package name from the `src/modules/[MODULE]/translations/en-us.yml` file, and saves them in the `src/modules/[MODULE]/translations/locales` folder. As for the extraction script, you can pass the `--module` flag to update translations for a specific module.\n\nAll files are then bundled by the build process in a single `[MODULE]-translations-bundle.js` file.\n\n# Accessibility testing\n\nWe use a custom node script that runs [lighthouse](https://github.com/GoogleChrome/lighthouse) for automated accessibility testing.\n\nThere are two ways of running the script:\n- **Development mode** - it runs the accessibility audits on the local theme preview, on a specific account. It requires `zcli themes:preview` to be running;\n- **CI mode** - it runs the accessibility audits on the live theme of a specific account.\n\nDepending on the scope of testing, some manual testing might be needed in addition to the above.\nTools like [axe DevTools](https://www.deque.com/axe/devtools/), screen readers e.g. [VoiceOver](https://www.apple.com/voiceover/info/guide/_1121.html), [contrast checkers](https://webaim.org/resources/contrastchecker/) etc. can assist such testing.\n\n## Development mode\n\nTo run the accessibility audits while changing the theme:\n\n1. Start compiling and previewing changes like you normally would:\n\n```console\n$ yarn install\n$ yarn start\n```\n\n2. Create a `.a11yrc.json` file in the root folder (see [example](.a11yrc.json.example));\n   1. Specify the account/subdomain to preview the theme making sure it matches the active `zcli` profile\n   2. Fill `username` and `password` with the credentials of an admin user;\n   3. Specify which `urls` to test (if left empty, the script will test all urls);\n\n3. In a separate console, run the accessibility audits in development mode:\n\n```console\nyarn test-a11y -d\n```\n\nA11y audits will then run on the preview started in step `1`.\n\n## CI mode\n\nTo run the accessibility audits on the live theme of a specific account, one must:\n\n1. Install node modules:\n\n```console\nyarn install\n```\n\n2. Set `end_user_email`, `end_user_password`, `subdomain` and `urls` as environment variables and run the accessibility audits in CI mode i.e.:\n\n```console\nend_user_email=\u003cEMAIL\u003e \\\nend_user_password=\u003cPASSWORD\u003e \\\nsubdomain=\u003cSUBDOMAIN\u003e \\\nurls=\"\n    https://\u003cSUBDOMAIN\u003e.zendesk.com/hc/en-us/\n    https://\u003cSUBDOMAIN\u003e.zendesk.com/hc/en-us/requests/new\n    https://\u003cSUBDOMAIN\u003e.zendesk.com/hc/en-us/requests\" \\\nyarn test-a11y\n```\n\n## Ignore list\n\nIf there is a known accessibility issue that should be ignored or can't be fixed right away, one may add a new entry to the ignore list in the [script's configuration object](bin/lighthouse/config.js). This will turn the accessibility issue into a warning instead of erroring.\n\nThe entry should include:\n- the audit id;\n- a `path` as a url pattern string;\n- a `selector` as a string.\n\nFor example:\n\n```js\n  custom: {\n    ignore: {\n      tabindex: [\n        {\n          path: \"*\",\n          selector: \"body \u003e a.skip-navigation\",\n        },\n      ],\n      aria-allowed-attr: [\n        {\n          path: \"/hc/:locale/profiles/:id\",\n          selector: \"body \u003e div.profile-info\"\n        }\n      ]\n    },\n  },\n```\n\nIn this example, errors for the audit `tabindex` with the selector `body \u003e a.skip-navigation` will be reported as warnings in all pages (`*`). The same will happen for the audit `aria-allowed-attr` with the selector `body \u003e div.profile-info`, but only for the user profile page `/hc/:locale/profiles/:id`.\n\nPlease keep in mind that this should only be used when strictly necessarity. Accessibility should be a focus and a priority when making changes to the theme.\n\n# Contributing\nPull requests are welcome on GitHub at https://github.com/zendesk/copenhagen_theme. Please mention @zendesk/vikings when creating a pull request.\n\nWe use [conventional commits](https://conventionalcommits.org/) to improve readability of the project history and to automate the release process. The commit message should therefore respect the following format:\n\n```\n\u003ctype\u003e[optional scope]: \u003cdescription\u003e\n\n[optional body]\n\n[optional footer(s)]\n\n```\n\n- type: describes the category of the change. See [supported types](#commit-types).\n- scope: (optional) describes what is affected by the change\n- subject: a small description of the change\n- body: (optional) additional contextual information about the change\n- footer: (optional) adds external links, issue references and other meta-information\n\ni.e.:\n\n```\nchore: automate release\nfix(styles): fix button padding\nfeat(script): add auto focus to fields with errors\n```\n\nWe use [`husky`](https://github.com/typicode/husky) and [`commitlint`](https://github.com/conventional-changelog/commitlint) to validate messages when commiting.\n\nWe use [Github actions](https://github.com/features/actions) together with [`semantic-release`](https://github.com/semantic-release/semantic-release) to release a new version of the theme once a PR gets merged. On each merge, `semantic-release` analyses the commit messages and infers a semantic version bump. It then creates a git tag, updates the manifest version and generates the corresponding [changelog](CHANGELOG.md).\n\n## Commit types\n\nThe list bellow describes the supported commit types and their effect in the release and changelog.\n\n| Type     | Description                                                                                            | Release | Changelog                |\n|----------|--------------------------------------------------------------------------------------------------------|---------|--------------------------|\n| build    | Changes that affect the build system or external dependencies                                          | -       | -                        |\n| chore    | Other changes that don't modify the source code                                                        | -       | -                        |\n| ci       | Changes to our CI configuration files and scripts                                                      | -       | -                        |\n| docs     | Documentation only changes                                                                             | -       | -                        |\n| feat     | A new feature                                                                                          | minor   | Features                 |\n| fix      | A bug fix                                                                                              | patch   | Bug Fixes                |\n| perf     | A code change that improves performance                                                                | patch   | Performance Improvements |\n| refactor | A code change that neither fixes a bug nor adds a feature                                              | -       | -                        |\n| revert   | Reverts a previous commit                                                                              | patch   | Reverts                  |\n| style    | Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) | -       | -                        |\n| test     | Adding missing tests or correcting existing tests                                                      | -       | -                        |\n\n## Breaking changes\n\nCommits that add a breaking change should include `BREAKING CHANGE` in the body or footer of the commit message.\n\ni.e.:\n\n```\nfeat: update theme to use theming api v2\n\nBREAKING CHANGE: theme is now relying on functionality that is exclusive to the theming api v2\n```\n\nThis will then generate a major release and add a `BREAKING CHANGES` section in the [changelog](CHANGELOG.md).\n\n# Bug reports\nBug reports must be submitted through Zendesk's standard support channels: https://www.zendesk.com/contact/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzendesk%2Fcopenhagen_theme","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzendesk%2Fcopenhagen_theme","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzendesk%2Fcopenhagen_theme/lists"}