geonetwork-ui is a powerful framework designed to help you build modern, user-friendly, fast, and responsive interfaces for your GeoNetwork catalog.
You can use it in a variety of ways:
- Use ready-made applications, such as the Datahub.
- Embed the provided web components directly into your site.
- Fork the repository to create your own application or customize the existing ones.
- Use the GNUI library via CDN to interact with your GeoNetwork backend using JavaScript.
- Build a custom application using the gnui npm package.
This last option offers the most flexibility and freedom, allowing you to build a custom catalog interface with minimal effort. The gnui library already includes all the logic required to interact with GeoNetwork, along with a rich set of ready-to-use components for your application.
Let’s see how you can quickly build a custom, working application that searches your catalog and displays the results! 🚀
Create your workspace
For this exercice, we will create a Nx workspace, which helps scaffolding all your Angular setup. geonetwork-ui
itself is a monorepo powered by Nx.
npx create-nx-workspace@20.1 custom-app
and choose the following options
✔ Which stack do you want to use? · angular
✔ Integrated monorepo, or standalone project? · integrated
✔ Application name · dataportal
✔ Which bundler would you like to use? · esbuild
✔ Default stylesheet format · css
✔ Do you want to enable Server-Side Rendering (SSR) ? · No
✔ Test runner to use for end to end (E2E) tests · none
✔ Which CI provider would you like to use? · github
⚠️ Caution : the generated application in the monorepo is a standalone application, which is not compatible with geonetwork-ui package. So you have to delete the generated app and create a new app which is not standalone :
cd custom-app
rm -rf apps/
npx nx g @nx/angular:application \
--bundler=esbuild \
--directory=apps/dataportal \
--routing=true \
--standalone=false \
--addTailwind=true \
--inlineStyle=true \
--skipTests=true \
--ssr=false \
--name=dataportal
Set up required dependencies
📦 GNUI package requires peer dependencies to work seamlessly. You have to install stuff like :
- NgRx for the store management
- Ngx-translate for translation
- Angular Material for out of the box UI components
- and obviously, load the GNUI npm package !
npx nx g ngrx-root-store --project=gps --addDevTools=true --minimal=true
npm install --save \
@ngrx/component@18.0.2 \
@angular/material@18.2.13 \
@angular/material-moment-adapter@18.2.13 \
@angular/cdk@18.2.13 \
@ngx-translate/core@15.0.0 \
@ngx-translate/http-loader@16.0.1 \
@biesbjerg/ngx-translate-extract-marker@1.0.0 \
@vendure/ngx-translate-extract@9.0.3
npm i geonetwork-ui
Set up your custom application
- First, link the GNUI CSS at the top of
apps/dataportal/src/styles.css
@import 'geonetwork-ui/style.css';
- And load GNUI tailwind setup by modifying the
apps/dataportal/tailwind.config.js
file.
const baseConfig = require('../../node_modules/geonetwork-ui/tailwind.base.config');
module.exports = {
presets: [baseConfig],
content: [
'./node_modules/geonetwork-ui/**/*.mjs',
join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'),
...
}
- In
index.html
, load your desired google font, which will be used for any text or title in the GNUI components :
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
Now, we need to correctly initiate GNUI Angular modules and services.
In app.module.ts
imports: [
BrowserModule,
...
BrowserAnimationsModule,
FeatureSearchModule,
FeatureCatalogModule,
TranslateModule.forRoot({
...TRANSLATE_DEFAULT_CONFIG,
loader: {
provide: TranslateLoader,
useClass: EmbeddedTranslateLoader,
},
}),
],
...
providers: [
importProvidersFrom(FeatureAuthModule),
provideGn4(),
provideRepositoryUrl(() => 'https://geonetwork-ui.labs.camptocamp.com/geonetwork/srv/api'),
Gn4PlatformService,
],
...
export class AppModule {
constructor() {
ThemeService.applyCssVariables(
'#0c4a6e',
'#0c4a6e',
'rgb(85,85,85)',
'white',
'Noto Sans',
'Noto Sans'
)
}
}
Create your own application now !
Now that everything is set up, you can start using GNUI components. You can take advantage of the library's presentation components, but more powerfully, you can use logic containers that interact with GNUI states (such as the search state!).
For that, you need to create a new component where you put your catalog interfaces, leveraging GNUI search components.
npx nx g @nx/angular:component \
--changeDetection=OnPush \
--standalone=true \
--path=apps/dataportal/src/app/search/search \
--inlineStyle=true \
--inlineTemplate=true \
--skipTests=true
In this component, inject the SearchFacade
to setup the search state, and trigger a search on page loading to have first results.
export class SearchComponent implements OnInit {
constructor(public searchFacade: SearchFacade) {}
ngOnInit() {
this.searchFacade.setResultsLayout('ROW');
this.searchFacade.requestMoreResults();
}
}
and put the search input, and the search results like this :
<div class="flex flex-col gap-14">
<header
class="flex flex-col items-center justify-center
bg-gradient-to-r from-indigo-400 from-10%
via-sky-500 via-30% to-emerald-500 to-90%
h-96 gap-14"
>
<h1 class="text-title text-5xl font-bold uppercase">
My Data Portal
</h1>
<gn-ui-fuzzy-search
class="text-[18px] pointer-events-auto container-lg w-full "
style="--gn-ui-text-input-padding: 1.1em"
[autoFocus]="true"
></gn-ui-fuzzy-search>
</header>
<main >
<gn-ui-results-list-container
[metadataQualityDisplay]="false"
showMore="button"
></gn-ui-results-list-container>
</main>
</div>
Final touch, you need to initialize a search state container in your app.component.html
file and nest your search component inside it. All DOM elements under the gnUiSearchStateContainer directive will be linked to a specific search state.
<div class="" gnUiSearchStateContainer="mainSearch">
<app-search></app-search>
</div>
That’s it! 🎉 You’ve now created a search state and connected two gnui components to it:
-
FuzzySearch
– provides the search input. -
ResultsListContainer
– displays the search results.
This is a very basic setup, but you're fully ready to expand it the way you like : add routing, permalink-based searches, record detail pages, news feeds, search filters, maps, and much more.
Give it a try, and feel free to comment if you get stuck or want to share what you've built! 💫
Find a working exemple in my github repo.
Find a real world production ready custom application : the Métropole de Lille data platform.