nl-portal-libraries
is a collection of packages aimed at providing a configurable portal
implementation for municipalities.
The resulting portal implementation is built up of reusable components that fit the specifications of the NL Design System.
The look and feel of these components can be customized through the use of design tokens. Moreover, the back-end systems with which the implementation communicates can be configured, providing each municipality with their own unique environment and data.
All such configuration takes place in the implementation @nl-portal/nl-portal-app.
To contribute to this repository, first clone it to your device.
Make sure to install pnpm.
Install dependencies for all projects in the packages directory with the following command:
pnpm install
After installing dependencies, start the project with:
pnpm dev
This commands runs all the start
scripts of each of the individual packages in the
packages directory in parallel.
Please note that on first run, all packages must have been built first. Please refer to the section below.
Tip: Packages can started individually by running pnpm dev
from their respective
directories.
After installing dependencies, build the project with pnpm build
from the project root.
This commands runs all the build
scripts of each of the individual packages in the
packages directory.
Tip: Packages can built individually by running pnpm build
from their respective
directories.
Testing in this project is done with Vitest. Run the tests of all packages with
pnpm test
from the project root. To keep watching the tests for any changes, use pnpm test:watch
.
Testing in this project is done with ESLint. Look for linting errors in all
packages by running pnpm lint
from the project root. Use pnpm lint:fix
to automatically fix these errors.
Prettifying in this project is done with Prettier. Look for formatting
errors in all packages by running pnpm prettier
from the project root. Use
pnpm prettier:fix
to automatically fix these errors.
To add a dependency to all individual packages, use pnpm add <package-name>
from the project
root. For example: pnpm add vitest
.
To add a dependency to one or more specific packages use
pnpm add <package-name> --scope=<package-name>
. For example, to add Vitest as a dependency to
@nl-portal/nl-portal-app and
@nl-portal/nl-portal-user-interface, use:
pnpm add vitest --scope=@nl-portal/nl-portal-app --scope=@nl-portal/nl-portal-user-interface
.
If you must add a devDependency to the root project, use pnpm add <package-name> --dev -W
from the
project root. For example: pnpm add vitest --dev -W
.
Packages inside the packages folder may depend on each other, simply by adding them to
their respective package.json
files and running pnpm install
from the project root
afterwards.
For example, the package.json
of @nl-portal/nl-portal-app might include
"@nl-portal/nl-portal-user-interface": "0.1.0"
in its list of dependencies. For this to work, the
version number in the package.json
of
@nl-portal/nl-portal-user-interface must also be "0.1.0"
.
- It is advisable to install IDE plugins for ESLint and Prettier. Make sure they use the configurations from the project root. You can set the plugins to automatically fix any errors on saving your files.
- Please use TypeScript as much as possible.
- Use index files for more readable imports.
- Please write unit tests for your code.
The set-up of this project is a Lerna monorepo using pnpm Workspaces.
Individual packages are stored in the packages directory. Each package has its own
package.json
file, which includes dependencies and its own build
and start
scripts.
The implementation package @nl-portal/nl-portal-app was generated with Vite using the TypeScript preset. It uses other packages in this project as dependencies. Custom implementations can be based on this package.
Other packages - such as @nl-portal/nl-portal-user-interface - were generated with vite. They serve as dependencies for the implementation, so that each future implementation can be kept up-to-date easily.
New packages can be created in their own directory, inside the packages directory.
Although not obligatory, it is advised to follow the example of packages like @nl-portal/nl-portal-user-interface.
Please prefix your package name with @nl-portal/*
and include the following in its package.json
:
"author": "Municipality of The Hague",
"license": "EUPL-1.2",
Tip: Make sure your newly created package does not contain its own git repository.
Please set the version number of your package dependencies to match the version numbers of dependencies of other packages, so that Lerna can combine these dependencies.
Each package must have their own .eslintignore
, .gitignore
and .prettierignore
files. These
files include things such as the dist
and node_modules
folders.
Linting and prettifying is done from the root project, so make sure to remove any configuration
files (such as .eslintrc.json
or .prettierrc.json
) from your project if they are included by
default.
Environment variables are loaded from the implementation @nl-portal/nl-portal-app by default. Possible configuration values are specified in the Config interface.
These values are set to the window object by config.js, which also contains the default values for local development.
Another configuration option is the authentication methods, which must include the mapping for the 'middel' claim in the JWT token, and the type of login (person, company, proxy). Example snippet for in the implementation:
...
const authenticationMethods = {
person: ["digid", "machtigen"],
company: ["eherkenning", "bewindvoering"],
proxy: ["machtigen", "bewindvoering"],
};
...
const App = () => {
...
return (
<div className={config.THEME_CLASS}>
<KeycloakWrapper
clientId={config.KEYCLOAK_CLIENT_ID}
realm={config.KEYCLOAK_REALM}
url={config.KEYCLOAK_URL}
redirectUri={config.KEYCLOAK_REDIRECT_URI}
authenticationMethods={authenticationMethods}
>
...
</KeycloakWrapper>
</div>
);
};
...
When starting the app through Docker, these values can be optionally overridden, i.e.:
docker run --name test -e KEYCLOAK_URL=thekeycloakurl -e KEYCLOAK_REALM=therealrealm -e KEYCLOAK_CLIENT_ID=theclientid -e KEYCLOAK_REDIRECT_URI=theredirecturi GRAPHQL_URI=thegraphqluri -dp 3000:3000 test1
The implementation @nl-portal/nl-portal-app uses Apollo Client through the package @nl-portal/nl-portal-api to communicate with the GraphQL back-end.
New queries can be added as exported JavaScript variables from separate files in the queries folder.
Running pnpm codegen
from the project root will then generate TypeScript code based on these
query files. For this to succeed, the GraphQL API endpoint specified in
codegen.yml must be available.
Once the codegen completes, the queries are exported as hooks from @nl-portal/nl-portal-api and can be imported and used inside a functional component:
...
import {useGetZakenQuery} from '@nl-portal/nl-portal-api';
const CasesPage = () => {
const {data, loading, error, refetch} = useGetZakenQuery();
...
}