248ad9eb966fcb6b46d2fa92de02e72398d901a0
Node's built-in DNS resolver (c-ares) can fail to resolve hostnames that the system resolver handles fine. Set dns.setDefaultResultOrder to use the system resolver order. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Booking EWA
Embedded Web App (EWA) for managing EV charging station bookings. The application provides a mobile-optimized UI for creating, viewing, updating, and cancelling charger bookings. It is designed to be embedded within a native mobile app via a JWT-based session handoff.
Architecture Overview
The application consists of two parts:
- Backend -- Express.js server (port 3001) that validates JWT tokens, manages sessions, and proxies API requests to the AMPECO public API.
- Frontend -- React SPA (Vite dev server on port 5173) using Tailwind CSS and the
@ampeco/ewa-uidesign system. UsesHashRouterfor client-side routing.
See docs/ARCHITECTURE.md for the full architecture document.
Prerequisites
- Node.js >= 18
- npm >= 9
- Local sibling packages (linked via
file:references inpackage.json):@ampeco/design-tokensat../design-tokens@ampeco/ewa-uiat../ewa-ui
Setup
- Clone the repository and ensure sibling packages are present:
parent-directory/
booking-ewa/ <-- this project
design-tokens/ <-- @ampeco/design-tokens
ewa-ui/ <-- @ampeco/ewa-ui
- Copy the example environment file and configure it:
cp .env.example .env
- Edit
.envwith your values:
API_BASE_URL=https://your-instance.charge.ampeco.tech/public-api
API_TOKEN=your-api-token-here
JWT_SECRET=your-jwt-secret-here
PORT=3001
NODE_ENV=development
| Variable | Description |
|---|---|
API_BASE_URL |
Base URL of the AMPECO public API instance |
API_TOKEN |
Bearer token for authenticating with the public API |
JWT_SECRET |
Shared secret for signing/verifying HS256 JWT tokens |
PORT |
Port for the Express backend server (default: 3001) |
NODE_ENV |
Set to development to enable dev fallback session and /dev/jwt endpoint |
- Install dependencies:
npm install
- Start the development servers:
npm run dev
This starts both the Vite dev server (http://localhost:5173) and the Express backend (http://localhost:3001) concurrently.
Available Scripts
| Script | Description |
|---|---|
npm run dev |
Start Vite frontend and Express backend in parallel |
npm run build |
Build the frontend (Vite) and compile the backend (TypeScript) |
npm run typecheck |
Run TypeScript type checking (no emit) |
Project Structure
booking-ewa/
.env.example # Environment variable template
index.html # Vite HTML entry point
package.json # Dependencies and scripts
vite.config.ts # Vite config (proxy /api and /dev to backend)
tailwind.config.ts # Tailwind CSS with ewa-ui plugin
postcss.config.js # PostCSS (Tailwind + Autoprefixer)
tsconfig.json # Frontend TypeScript config
backend/
tsconfig.json # Backend TypeScript config
src/
index.ts # Express server entry, JWT middleware, dev fallback
jwt.ts # JWT verification and dev token creation
proxy.ts # Generic API proxy utility
routes.ts # Route definitions (session, bookings, availability)
types.ts # Backend type definitions (JwtPayload, SessionData)
src/
main.tsx # React entry point
App.tsx # Root component (SessionProvider + routing guard)
app.css # Global styles (design-tokens CSS variables, Tailwind)
env.d.ts # TypeScript ambient declarations
api/
client.ts # Fetch wrapper with error handling (ApiRequestError)
bookings.ts # Booking list/detail API functions
bookingRequests.ts # Create/update/cancel booking request API
availability.ts # Check availability API
context/
SessionContext.tsx # React context for session state and theme application
hooks/
useSession.ts # Hook to consume SessionContext
useBookings.ts # Hooks for booking list and detail (with polling)
useAvailability.ts # Hook for availability checking
components/
Layout/Layout.tsx # App shell with bottom tab navigation
BookingCard/BookingCard.tsx # Booking summary card
AvailabilitySlots/AvailabilitySlots.tsx # Slot selection grid
DateTimePicker/DateTimePicker.tsx # datetime-local input wrapper
pages/
Home/Home.tsx # Dashboard with upcoming bookings
CreateBooking/CreateBooking.tsx # Two-step booking creation flow
MyBookings/MyBookings.tsx # Upcoming/Past tabs
BookingDetail/BookingDetail.tsx # Detail view with cancel action
UpdateBooking/UpdateBooking.tsx # Edit booking time range
UserIdFallback/UserIdFallback.tsx # Manual user ID entry (dev mode)
router/
index.tsx # HashRouter route definitions
types/
index.ts # Frontend type definitions (Booking, BookingRequest, etc.)
i18n/
init.ts # i18next initialization
locales/
en.json # English translations
Key Dependencies
| Package | Purpose |
|---|---|
@ampeco/design-tokens |
CSS custom properties for theming (LIGHT/DARK) |
@ampeco/ewa-ui |
Shared UI component library and Tailwind plugin |
react-router-dom |
Client-side routing (HashRouter) |
i18next / react-i18next |
Internationalization |
lucide-react |
Icon library |
express |
Backend HTTP server |
jsonwebtoken |
JWT signing and verification |
Development Notes
- In
developmentmode, if no JWT is provided, the backend falls back to a default session withuserId: 775. - If the fallback session has no
userId(set tonull), the frontend displays aUserIdFallbackpage where you can manually enter a user ID. - Use
POST /dev/jwtto generate a JWT token with custom session overrides. See docs/USER-GUIDE.md for details.
Description
Languages
TypeScript
98.4%
HTML
0.8%
CSS
0.7%
JavaScript
0.1%