npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@city-of-helsinki/react-helsinki-headless-cms

v3.1.0

Published

React components for displaying Headless CMS content according to guidelines set by HDS

Readme

React Helsinki Headless CMS

React UI component library to visualize Headless CMS data using Helsinki Design System.

Introduction

React Helsinki Headless CMS is a highly customized component library based on HDS. It is designed for City of Helsinki web applications using preconfigured WordPress Headless CMS environments. This library provides a set of unified visual components for Pages, Articles, and Article Archives.

NPM Version License

It provides:

  1. Unified designs for pages, layouts, and custom components across multiple applications.
  2. Ability to pass app-specific configurations, such as translations and themes.
  3. A set of components for visually presenting data from WordPress content modules and features.
  4. A set of utilities, type and constants required for components implementation.
  5. Support for required Apollo providers, such as linked events and venue search.

Note: This library does not inject the Helsinki Grotesk font for you; you must add it yourself.

Note: This library uses HDS design tokens through the SCSS interface so that mismatched design token versions do not lead to unexpected results.

The known clients that are using this library

  • The city of Helsinki Events: https://tapahtumat.hel.fi | https://github.com/City-of-Helsinki/events-helsinki-monorepo
  • The city of Helsinki Hobbies: https://harrastukset.hel.fi | https://github.com/City-of-Helsinki/events-helsinki-monorepo
  • The city of Helsinki Sports: https://liikunta.hel.fi | https://github.com/City-of-Helsinki/events-helsinki-monorepo
  • The city of Helsinki Kultus: https://kultus.fi | https://github.com/City-of-Helsinki/palvelutarjotin-ui
  • The city of Helsinki Culture Kids: https://kummilapset.hel.fi/ | https://github.com/City-of-Helsinki/kukkuu-ui

Installation

pnpm add @city-of-helsinki/react-helsinki-headless-cms

Development

NOTE: The library is for general use and should not be developed for a single application environment only! Check the known clients

When to develop

The general requirements for new Component development:

  1. The new Component must be connected to an instance of the WordPress Headless CMS.
  2. The Wordpress Headless CMS environment has new Component compatible architecture, features and data structure (component library is heavily dependent on the GraphQL schemas).
  3. The new Component is not presented in HDS or HDS cannot fully fulfill the specifications.
  4. The new Component exists in HDS backlog, however, still it is not released by HDS team. In that case, HCRC new Component can be implemented and later must be replaced with HDS component when one is available.
  5. New Component can be reused across multiple applications.

Available scripts

| Name | Purpose | Useful Options | | ----------------------- | -------------------------------------------------------------------------------------------------------- | ----------------------------- | | pnpm dev | Starts storybook environment that can be used for developing components. | | | pnpm typecheck | Runs the ts type check in the project components. | | | pnpm lint | Lints the application to be according to quality standards (eslint) and formatting standards (prettier). | --fix: fix fixable problems | | pnpm test | Runs tests with Vitest. | --watch: enable watch mode | | pnpm test-storybook | Runs Storybook tests using test-storybook (Storybook test runner / Playwright). | | | pnpm build | Builds application with rollup. | | | pnpm docker:dev | Runs the application with docker with Development target environment. | | | pnpm docker:prod | Runs the application with docker with Production target environment. | | | pnpm docker:down | Shuts down the docker environment. | | | pnpm generate:graphql | Generates / updates GraphQL schema for the project. | |

NOTE: To manually publish a new version to the NPM, you will need the credentials that can be found from the City of Helsinki Culture and Leisure's Vault-service.

Development environments

You can use docker local environment for development:

docker compose up --build when using Docker

podman compose up --build when using Podman

Alternatively, the local environment can be used:

pnpm dev

Module structure

This library consists of three modules.

  • Core module that includes data naive components.
  • Apollo module that wraps core module components with logic that is able to fetch data with the help of an ApolloClient instance.
  • Nextjs module that provides utilities when working with Nextjs and Apollo.

Husky Git Hooks

This project uses Husky to manage Git hooks. Husky is configured to run specific scripts before committing changes to ensure code quality and consistency.

Pre-commit Hook

The pre-commit hook is configured to run the following commands:

pnpm exec doctoc . -u
pnpm exec lint-staged --relative
  • pnpm exec doctoc . -u: This command updates the table of contents in your markdown files.
  • pnpm exec lint-staged --relative: This command runs linting on staged files to ensure they meet the project's coding standards. The lint-staged configuration can be found from package.json.
    • Using --relative flag to reduce command line length, as the combined length of all the absolute paths for a large commit can get quite long

NOTE: doctoc and husky does not work seamlessly together, since the doctoc does update the TOCs of the markdown files, but does not reject the pre-commit hook execution, and only leaves the refactored files as unstaged in Git.

Commit-msg Hook

The commit-msg hook is configured to run the following command:

npx --no-install commitlint --edit "$1"
  • npx --no-install commitlint --edit "$1": This command uses Commitlint to lint commit messages based on the project's commit message conventions. This repo follows the Conventional Commits.

CI

Checks

  • Tests pass
  • Lint pass
  • Build completes
  • Type check pass

CD

On additions to main, a canary version gets published to npm.

On a new release, a new version is released to npm.

Storybook

Storybook is a frontend workshop for building UI components and pages in isolation https://storybook.js.org/. The Storybook can be used to develop and to test the components, but also to document the components and their features.

The project is using the Storybook 10.

NOTE: Storybook version 10 may require the playwright-chromium installation.

The pnpm dev command will start storybook in port 6006. When you make changes in src, they'll be automatically updated to storybook.

Apollo

This can handle data queries for you if you are using a supported library to fetch your data.

By importing data dependent components from @city-of-helsinki/react-helsinki-headless-cms/apollo, this library will request the data for you.

Note: An Apollo client linked to a graphql endpoint with a supported schema (headless CMS) must be provided in the apolloClient field of the config object.

Simplified example

import { Page } from '@city-of-helsinki/react-helsinki-headless-cms/apollo';
import { Navigation } from '@city-of-helsinki/react-helsinki-headless-cms/apollo';

<ConfigProvider
  config={{
    // ...
    apolloClient: client, // A client for the CMS
    eventsApolloClient: client, // A client to connect a events datasource (the LinkedEvents)
    venuesApolloClient: 'disabled', // A client to connect a venue datasource (the Servicemap / "TPREK")
    // ...
  }}
>
  <Page
    uri="/en/url"
    navigation={<Navigation menuName="Name of menu in headless CMS" />}
  />
</ConfigProvider>;

NextJS

We provide utilities for fetching headless data for NextJs in @city-of-helsinki/react-helsinki-headless-cms/nextjs. These can be used when generating static pages.

Build

This project uses rollup for its final bundle.

NOTE: Check the known issues!!

Use as a application dependency

NOTE: After any changes done to the React Helsinki Headless CMS -library, remember to build again!

Folder-based links

The easiest way to test the React Helsinki Headless CMS -library is to install it as a dependency of an application by using a local relative path:

  • https://docs.npmjs.com/cli/v9/configuring-npm/package-json#local-paths
  • https://pnpm.io/cli/add#install-from-local-file-system (pnpm supports the same file: protocol)

The steps to use the local relative path as a dependency:

  1. Build the React Helsinki Headless CMS -library with pnpm build. You should now have a /dist -folder that contains the built library package.
  2. Add the /dist-directory as a dependency. Remember to use the right relative local path:
{
  "dependencies": {
    "@city-of-helsinki/react-helsinki-headless-cms": "file:../react-helsinki-headless-cms/dist"
  }
}

Tarball-based links

When file: points to a .tgz file, pnpm will transparently let you require files from within the archive. For the node_modules linker, it means that the archive will be unpacked into the generated node_modules folder.

You can create a tarball by first building the package and then calling pack

  1. pnpm build
  2. pnpm pack

The steps to use the local tarball as a dependency:

{
  "dependencies": {
    "@city-of-helsinki/react-helsinki-headless-cms": "file:../react-helsinki-headless-cms-v2.1.0.tgz"
  }
}

Testing

With new features introduced in Storybook version 7, this library is configured with @storybook/addon-a11y Axe Accessibility Plugin.

The test could be run from the Storybook UI (Accessibility tab of the Story) or using the script.

Testing in IDE terminal

pnpm test-storybook

After executing the script, you will get the Axe Accessibility testing report in the terminal window. The number of tests are dynamic per component and decided by Axe plugin logic.

Usage

App.tsx

// ...
import {
  Page,
  PageContent,
  ConfigProvider,
  defaultConfig,
} from "@city-of-helsinki/react-helsinki-headless-cms";

function App() {
  const page = ...;

  return (
    <ConfigProvider config={defaultConfig}>
      <Page
        navigation={
          <Navigation
            languages={...}
            menu={...}
            onTitleClick={() => ...}
            getUrlForLanguage={(language, currentLanguage) => new URL(...)
            }
          />
        }
        content={<PageContent page={page} breadcrumbs={[...]} />}
        footer={...}
      />
    </ConfigProvider>
  );
}

Releases and changelogs

The application uses automatic semantic versions and is released using Release Please.

Release Please is a GitHub Action that automates releases for you. It will create a GitHub release and a GitHub Pull Request with a changelog based on conventional commits.

Each time you merge a "normal" pull request, the release-please-action will create or update a "Release PR" with the changelog and the version bump related to the changes (they're named like release-please--branches--master--components--react-helsinki-headless-cms).

To create a new release, merge the release PR. This creates a new release with notes and a new tag. The release workflow then builds and publishes the package to npm.

When merging release PRs, make sure to use the "Rebase and merge" (or "Squash and merge") option, so that Github doesn't create a merge commit. All the commits must follow the conventional commits format. This is important, because the release-please-action does not work correctly with merge commits (there's an open issue you can track: Chronological commit sorting means that merged PRs can be ignored ).

See Release Please Implementation Design for more details.

And all docs are available here: release-please docs.

Conventional Commits

Use Conventional Commits to ensure that the changelogs are generated correctly.

Releasable units

Release please goes through commits and tries to find "releasable units" using commit messages as guidance - it will then add these units to their respective release PR's and figures out the version number from the types: fix for patch, feat for minor, feat! for major. None of the other types will be included in the changelog. So, you can use for example chore or refactor to do work that does not need to be included in the changelog and won't bump the version.

Configuration

The release-please workflow is located in the release-please.yml file.

The configuration for release-please is located in the release-please-config.json file. See all the options here: release-please docs.

The manifest file is located in the release-please-manifest.json file.

When adding a new app, add it to both the release-please-config.json and release-please-manifest.json file with the current version of the app. After this, release-please will keep track of versions with release-please-manifest.json.

Troubleshooting release-please

If you were expecting a new release PR to be created or old one to be updated, but nothing happened, there's probably one of the older release PR's in pending state or action didn't run.

  1. Check if the release action ran for the last merge to main. If it didn't, run the action manually with a label.
  2. Check if there's any open release PR. If there is, the work is now included on this one (this is the normal scenario).
  3. If you do not see any open release PR related to the work, check if any of the closed PR's are labeled with autorelease: pending - ie. someone might have closed a release PR manually. Change the closed PR's label to autorelease: tagged. Then go and re-run the last merge workflow to trigger the release action - a new release PR should now appear.
  4. Finally check the output of the release action. Sometimes the bot can't parse the commit message and there is a notification about this in the action log. If this happens, it won't include the work in the commit either. You can fix this by changing the commit message to follow the Conventional Commits format and rerun the action.

Important! If you have closed a release PR manually, you need to change the label of closed release PR to autorelease: tagged. Otherwise, the release action will not create a new release PR.

Important! Extra label will force release-please to re-generate PR's. This is done when action is run manually with prlabel -option

Sometimes there might be a merge conflict in release PR - this should resolve itself on the next push to main. It is possible run release-please action manually with label, it should recreate the PR's. You can also resolve it manually, by updating the release-please-manifest.json file.

Fix merge conflicts by running release-please -action manually

  1. Open release-please github action
  2. Click Run workflow
  3. Check Branch is master
  4. Leave label field empty. New label is not needed to fix merge issues
  5. Click Run workflow -button

There's also a CLI for debugging and manually running releases available for release-please: release-please-cli

Publishing new versions manually without release-please

For canary release the naming convention is x.y.z-canary-[gitcommithash]. Running pnpm publish should ask for version number too, but a version property in package.json sets the version number.

  1. Build package with pnpm build
  2. Publish package pnpm publish

Note: A local tarball of built package can be created with pnpm pack. Just remember to build first.

Note: There is a known issue with publishing using Windows environment. If you are using Windows, use a Docker container to publish the package.

Known issues

  • Jest has difficulties loading this library. When this library is required in a test file, it's possible that some imports are cjs and some are esm. These two variants do not share a react context which can result in useConfig calls that return an empty config object even though <ConfigProvider> is declared correctly. I.e. <ConfigProvider> sets values for context1 and useConfig reads context2.
  • Some of the built packages created with pnpm build have some issues with some types. This can cause consuming applications to fail to read all exported types. In particular, exported enums in built packages may be handled incorrectly (https://github.com/rollup/rollup/issues/4291), though other type-related issues may also occur.

Contributing

Read the contributing guide to learn about our development process, how to propose bugfixes and improvements, and how to build and test your changes.

Issues

If you notice a bug or want to request a feature, please submit an issue to our GitHub repository.

License

MIT