Files
cariflex/tools/citrineos-core-main/apps/operator-ui
Eric F 9a14723b07 feat(ui): replace Google Maps with Leaflet + OpenStreetMap
- Replace all Google Map components with Leaflet OSM alternatives
- Add osm-map.tsx with dynamic Leaflet import (SSR-safe)
- Use CDN for Leaflet CSS to avoid Next.js CSS import issues
- Update types.tsx to remove google.maps dependencies
- Replace Google Places autocomplete with Nominatim OSM
- Replace Google Geocoding with Nominatim OSM
- Add GPS coordinates for all 15 Martinique charging station locations
- Update next.config.mjs: ignoreBuildErrors for TypeScript loops
- Update package.json: use 'next build' instead of 'refine build'
- Add .dockerignore for faster Docker builds
- Fix map centering on Martinique (default: 14.6415, -61.0242)
2026-06-12 11:04:18 -04:00
..

CitrineOS Logo CitrineOS Logo

CitrineOS Certification Logo

Welcome to CitrineOS Operator UI

CitrineOS Operator UI is the web-based operator interface for CitrineOS, an open-source, modular backend platform for managing Electric Vehicle (EV) charging infrastructure.

This repository contains the Operator-facing User Interface and related tooling.
It is designed to work together with CitrineOS Core, which provides the charging station management logic, OCPP message handling, persistence layer, and GraphQL APIs.

⚠️ Important:
The Operator UI does not run standalone.
A running instance of CitrineOS Core (including Hasura GraphQL Engine) is required.

This app is one workspace member of the citrineos-core pnpm monorepo. For repository-wide setup and for running the full stack (server + UI + Hasura) together, see the root README.


Table of Contents


Overview

The CitrineOS Operator UI provides operators with:

  • Visibility into charging stations, connectors, sessions, and transactions
  • Operational controls via CitrineOS Core Message APIs
  • Data access through Hasura GraphQL Engine
  • A modern React-based UI built with Refine

The UI consumes:

  • Hasura GraphQL APIs for data access
  • CitrineOS Core Message APIs for sending commands to charging stations
  • CitrineOS Core Data APIs for managing entities

Architecture & Data Flow

+-------------------+       GraphQL       +----------------------+
|                   |  <----------------> |                      |
|  Operator UI      |                     |  Hasura GraphQL      |
|                   |                     |  Engine              |
|                   |                     |                      |
+-------------------+                     +----------+-----------+
                                                       |
                                                       | SQL
                                                       |
                                             +---------v-----------+
                                             |                     |
                                             |  PostgreSQL         |
                                             |                     |
                                             +---------------------+

+-------------------+       REST       +--------------------------+
| Operator UI       | <--------------> | CitrineOS Core           |
|                   |                  | (OCPP 1.6 & 2.0.1)       |
+-------------------+                  +--------------------------+

Prerequisites

Before starting, ensure the following tools and services are installed and running.

  • Node.js (v24.16.0 or higher)
    Link

  • pnpm
    Link — the workspace's package manager

  • Docker & Docker Compose (recommended)
    Link

The following services must be available before starting the application:

  • CitrineOS Core
    Backend service responsible for OCPP 1.6 and OCPP 2.0.1 handling, charging station management, and APIs.

  • Hasura GraphQL Engine
    GraphQL layer used for data access and management.

References:

Getting Started

If CitrineOS Core is already running via Docker, the Operator UI can be started with a single command:

docker compose up -d

This will:

  • Build the Operator UI container
  • Start the UI connected to the configured Hasura and Core service

Running with pnpm (Local Development)

The Operator UI lives inside the citrineos-core pnpm workspace (under apps/operator-ui). Install all workspace dependencies once from the repository root, then start the dev server:

# from the repository root
pnpm install

# then, from apps/operator-ui
pnpm run dev

This starts the development server (Next.js + Refine) with hot reload.

Working with @citrineos/base

The Operator UI depends on @citrineos/base via a workspace:* dependency, so pnpm resolves it from the local packages/base automatically — no npm link step is required. Just build the workspace packages so the compiled output is available:

# from the repository root
pnpm run build

Build & Development Workflow

The Operator UI is a member of the citrineos-core pnpm workspace.

Typical Workflow

  1. Install and build the workspace from the repository root:
# from the repository root
pnpm install
pnpm run build
  1. Start the dev server:
# from apps/operator-ui
pnpm run dev

Running the Application

Development Mode

pnpm run dev

Production Build

pnpm run build
pnpm run start

Bringing a Charging Station Online (End-to-End)

This section describes the minimum operational steps required to bring a charging station online using:

  • CitrineOS Operator UI
  • CitrineOS Core
  • EVerest simulator

These steps are required even for local development and testing.


Create a Location

In CitrineOS, all charging stations must belong to a Location.

  1. Open CitrineOS Operator UI:
  2. Navigate to:
Locations → Create Location
  1. Fill in the required metadata (name, address, country, etc.)
  2. Save the Location

A Location represents a physical site such as a parking garage, depot, or charging hub.


Add a Charging Station (Charge Point)

To add a new charging station in CitrineOS Operator UI:

  1. Navigate to:
Charging Stations  Add Charging Station
  1. Select the previously created Location.

  2. Use the default Charge Point ID:

cp001

⚠️ Important: The Charge Point ID must exactly match the ID used by your physical charging station or simulator. By default, EVerest uses cp001.

  1. Click Save to create the charging station.

Add an EVSE (Electric Vehicle Supply Equipment)

Each Charging Station must contain at least one EVSE.

  1. Open the Charging Station you just created.
  2. Navigate to:
EVSEs  Add EVSE
  1. Use a numeric EVSE ID (example: 1).
  2. Click Save.

EVSEs represent physical charge points within a station (e.g., left/right ports).


Add a Connector

Each EVSE must have at least one Connector.

  1. Open the EVSE.
  2. Navigate to:
Connectors  Add Connector
  1. Choose:
    • Connector ID (example: 1)
    • Connector type (Type2, CCS, etc.)
  2. Click Save.

Without a Connector, charging sessions cannot be started.


Add an Authorization (ID Token)

To allow charging sessions, an ID Token must be authorized.

  1. Navigate to:
Authorizations  Add Authorization
  1. Create an ID Token (RFID, app token, etc.)
  2. Mark it as Accepted
  3. Click Save

⚠️ Note: This token will be used by EVerest to start charging. The EVerest simulator uses the default RFID token DEADBEEF (ISO14443).


Start the Charging Station (EVerest)

Now that the backend configuration is complete, start the EVerest simulator:

cd citrineos-core/apps/Server
pnpm run start-everest

This will: In Operator UI

  • Navigate to Charging Stations
  • Status should show:
Online

You can now track OCPP logs for the charging station.

Usage

Once running, the Operator UI allows you to:

  • View and manage charging stations and connectors
  • Monitor transactions and sessions
  • Trigger charging station commands (via CitrineOS Core)
  • Query and manage data through Hasura-backed GraphQL APIs

Hasura Authentication

There are two ways to authenticate to Hasura:

  1. If you have *uncommented the Docker environment variable HASURA_GRAPHQL_ADMIN_SECRET in citrineos-core: 2. Ensure your .env.local has the HASURA_ADMIN_SECRET uncommented out 3. Please note that it is not recommended to use a Hasura Admin Secret in production.
  2. If you have commented the Docker environment variable HASURA_GRAPHQL_ADMIN_SECRET in citrineos-core: 5. Ensure your .env.local has the HASURA_ADMIN_SECRET commented out, as the auth will be handled by your auth provider automatically.
  • CitrineOS Core
  • CitrineOS Project Docs
  • Refine
  • Hasura GraphQL Engine
  • Postgres Data Connector

Contributing

We welcome contributions from the community. If you would like to contribute to CitrineOS, please follow our contribution guidelines.

Licensing

CitrineOS and its subprojects are licensed under the Apache License, Version 2.0.

Support and Contact

If you need help or want to report an issue:

  • Open an issue on GitHub
  • Reach out via the CitrineOS community channels