A single-page application for maintaining conference and workshop events: create an event through a form with native validation, list and filter all events, select rows for editing or deletion, and preview the selected event as copy-pastable schema.org microdata. The entire state is persisted to localStorage on every change. An optional Quarkus backend (validator) verifies that entered links exist.
The events application was modernized along the lines of the bce.design quickstarter. External libraries were pruned and replaced with web standards — the numbers are the argument:
| external library | replaced with (web standard) | before | after |
|---|---|---|---|
| Vaadin Router | Navigation API + URLPattern + View Transitions in router.js | 2,924 lines | 55 lines |
| UI5 web components (DatePicker) | native input type="date" |
9.2 MB | 0 |
| Bulma | design tokens as CSS custom properties (tokens.css) + one plain stylesheet | 10,831 lines | 285 lines |
| Redux Toolkit | reduction.js — the used API (configureStore, createAction, createReducer) on structuredClone instead of Immer |
96 KB bundle | 77 lines |
Net effect in git: 44 files changed, 1,040 insertions, 14,640 deletions — roughly 93% less code delivering the same application, plus the untracked 9.2 MB UI5 distribution removed from the payload. The only remaining runtime dependency is lit-html (7 KB).
Redux Toolkit was kept as an option, not deleted: application code imports @reduxjs/toolkit either way, and the import map in events/src/index.html selects the implementation — switching back is a one-line change. Dependencies resolve through import maps; the responsive layout uses container queries.
There is no build system. lit-html ships as a single, self-contained ES module since 3.x and is vendored in events/src/lib/ directly from the npm registry:
./update-lit-html.sh 3.3.3Tip
LLMs love stable web standards: this project is easily maintained with AI coding agents using the web-components skill from airails.dev — the skill captures the architecture and naming rules (BCE modules, boundary facades, module-prefixed tags, standards-based routing) that this modernization follows.
The application follows the Boundary Control Entity (BCE) pattern: one folder per
business component, each split into boundary/ (web components), control/
(actions and dispatchers), and entity/ (reducers and state shape). Every module
documents its responsibility in a package-info.md:
- creation — event form and commit-to-list logic
- overview — event table, selection, bulk actions
- filter — keyword filtering of the overview
- status — application-wide request status and errors
- preview — schema.org microdata export
- inputs — reusable form inputs (native date picker)
- localstorage — state persistence
State always travels the same cycle — the view never mutates state directly:
graph LR
Boundary([Boundary<br/>web components]) -->|user event| Control([Control<br/>action creators])
Control -->|dispatches action| Store([Store<br/>reduction.js or Redux Toolkit])
Store -->|state, action| Entity([Entity<br/>reducers])
Entity -->|next state| Store
Store -->|notifies subscribers| Boundary
Store -.->|persists state| Storage([localStorage])
classDef boundary fill:#d5e8d4,stroke:#82b366,color:#000
classDef control fill:#e1d5e7,stroke:#9673a6,color:#000
classDef entity fill:#fff2cc,stroke:#d6b656,color:#000
classDef bc fill:#dae8fc,stroke:#6c8ebf,color:#000
classDef ext fill:#fff2cc,stroke:#d6b656,color:#000,stroke-dasharray:5 5
class Boundary boundary
class Control control
class Entity entity
class Store bc
class Storage ext
To launch the web application, serve events/src with any static web server that falls back to index.html for unknown paths (required for deep links like /preview), e.g. with zws (zero dependencies web server, requires Java):
cd events/src
zws.sh --single- Install quarkus
cd validator- Perform:
./mvnw compile quarkus:dev
A walk through the application code:
A quickstarter template was extracted from this application and is available from: https://github.com/adamBien/bce.design
