A full-stack TypeScript application for managing maritime fuel compliance according to EU Regulation 2023/1805.
This project follows Hexagonal Architecture (Ports & Adapters) principles:
┌─────────────────────────────────────────┐
│ Application │
├─────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────┐ │
│ │ Core Domain │ │
│ │ (Business Logic & Entities) │ │
│ └─────────────────────────────────┘ │
│ ↕️ Ports │
│ ┌──────────────┐ ┌─────────────┐ │
│ │ Inbound │ │ Outbound │ │
│ │ (HTTP) │ │ (Postgres) │ │
│ └──────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────┘
backend/
├── src/
│ ├── core/ # Business logic layer
│ │ ├── domain/ # Entities and value objects
│ │ ├── application/ # Use cases
│ │ └── ports/ # Interfaces
│ ├── adapters/
│ │ ├── inbound/http/ # REST API controllers
│ │ └── outbound/postgres/ # Database repositories
│ ├── infrastructure/
│ │ ├── db/ # Database connection & migrations
│ │ └── server/ # Express server setup
│ └── shared/ # Utilities
├── tests/ # Unit & integration tests
└── package.json
frontend/
├── src/
│ ├── core/ # Business logic layer
│ │ ├── domain/ # Entities and types
│ │ ├── application/ # (Reserved for complex logic)
│ │ └── ports/ # Service interfaces
│ ├── adapters/
│ │ ├── ui/ # React components & hooks
│ │ └── infrastructure/ # API clients
│ ├── shared/ # Utilities
│ ├── App.tsx # Main application
│ └── index.tsx # Entry point
└── package.json
- Node.js 18+ and npm
- PostgreSQL 15+
- macOS, Linux, or Windows with WSL
# Navigate to backend directory
cd backend
# Install dependencies
npm install
# Create database
createdb fueleu_maritime
# Configure environment
cp .env.example .env
# Edit .env with your database credentials
# Run migrations and seed data
npm run migrate
# Start development server
npm run devBackend will run on http://localhost:3001
# Navigate to frontend directory
cd frontend
# Install dependencies
npm install
# Configure environment
cp .env.example .env
# Ensure REACT_APP_API_URL=http://localhost:3001/api
# Start development server
npm startFrontend will run on http://localhost:3000
- View all maritime routes with filtering
- Filter by vessel type, fuel type, and year
- Set baseline route for comparisons
- Display GHG intensity, fuel consumption, distance, and emissions
- Compare routes against baseline
- Calculate percentage difference in GHG intensity
- Visualize data with interactive charts
- Target intensity: 89.3368 gCO₂e/MJ (2% below 91.16)
- Compliance indicators (✅ compliant / ❌ non-compliant)
- Bank positive compliance balance for future use
- Apply previously banked surplus to deficits
- View banking history and available balance
- Validation: Cannot bank when CB ≤ 0
- Create compliance pools with multiple ships
- Transfer surplus from positive CB ships to deficit ships
- Greedy allocation algorithm
- Constraints:
- Total pool CB must be ≥ 0
- Deficit ships cannot exit worse
- Surplus ships cannot exit negative
cd backend
# Run all tests
npm test
# Run with coverage
npm test -- --coverage
# Run specific test suite
npm test -- ComputeComparison- ✅ Unit tests for all use cases
- ✅ Integration tests for API endpoints
- ✅ Database operations
- ✅ Edge cases and error handling
GET /api/routes- Get all routes (with filters)POST /api/routes/:routeId/baseline- Set baseline routeGET /api/routes/comparison- Get comparison data
GET /api/compliance/cb?shipId=X&year=Y- Get compliance balancePOST /api/compliance/cb- Compute and save CBGET /api/compliance/adjusted-cb?shipId=X&year=Y- Get adjusted CB
POST /api/banking/bank- Bank surplusPOST /api/banking/apply- Apply banked surplusGET /api/banking/records?shipId=X&year=Y- Get banking records
POST /api/pools- Create poolGET /api/pools?year=Y- Get pools by year
CB = (Target Intensity - Actual Intensity) × Energy in Scope
Energy in Scope = Fuel Consumption × 41,000 MJ/t
Target Intensity (2025) = 89.3368 gCO₂e/MJ
Percentage Difference = ((Comparison / Baseline) - 1) × 100
- Sort members by CB descending (surplus first)
- Transfer surplus to deficits using greedy algorithm
- Validate constraints after allocation
- Runtime: Node.js 18+
- Language: TypeScript 5+
- Framework: Express.js
- Database: PostgreSQL 15+
- ORM: Direct SQL with
pgdriver - Testing: Jest + Supertest
- Framework: React 18+
- Language: TypeScript 5+
- Styling: Tailwind CSS
- Charts: Recharts
- Icons: Lucide React
- HTTP Client: Axios
npm run dev- Start development server with hot reloadnpm run build- Build for productionnpm run start- Run production servernpm test- Run testsnpm run lint- Lint codenpm run migrate- Run database migrations
npm start- Start development servernpm run build- Build for productionnpm test- Run testsnpm run lint- Lint code
The database is seeded with 5 sample routes:
| Route | Vessel Type | Fuel | Year | GHG Intensity |
|---|---|---|---|---|
| R001 | Container | HFO | 2024 | 91.0 |
| R002 | BulkCarrier | LNG | 2024 | 88.0 |
| R003 | Tanker | MGO | 2024 | 93.5 |
| R004 | RoRo | HFO | 2025 | 89.2 |
| R005 | Container | LNG | 2025 | 90.5 |
# Check if PostgreSQL is running
pg_isready
# Restart PostgreSQL (macOS)
brew services restart postgresql@15
# Check database exists
psql -l | grep fueleu_maritime# Kill process on port 3001 (backend)
lsof -ti:3001 | xargs kill -9
# Kill process on port 3000 (frontend)
lsof -ti:3000 | xargs kill -9# Clean install
rm -rf node_modules package-lock.json
npm installDisplays all maritime routes with filtering options and baseline selection.
Shows comparison analysis with charts and compliance indicators.
Manage compliance balance banking and application.
Create and manage compliance pools with multiple ships.
- FuelEU Maritime Regulation (EU) 2023/1805
- Annex IV - Well-to-Wake Emissions Factors
- Article 20 - Banking
- Article 21 - Pooling
This project was developed as part of a technical assessment for Full-Stack Developer position.
MIT License - See LICENSE file for details