ShipForge
Logistics platform where users create and track shipments and admins manage status. Multi-stage Docker images, a Jenkins pipeline and a Python health check.
Problem
Customers need to create and follow shipments, and admins need to update their status. Each role must be limited to its own actions, and the whole stack should start the same way on any machine.
How it works
Checkout
Jenkins pulls the repository. The pipeline is defined in the Jenkinsfile, so it is versioned with the code.
Next.js UI
Login, signup, user dashboard and an admin page, written in TypeScript with CSS Modules.
Approach
An Express API with a Next.js front end and a PostgreSQL database, packaged as separate Docker images and started with one docker compose command. A Jenkins pipeline checks, builds and publishes the images.
docker compose up -dWhat I implemented
- Layered Express API: routes, controllers and services, with middleware for JWT authentication, admin-only routes, validation, rate limiting and central error handling.
- Prisma schema for User, Shipment, Address and Package, a shipment status lifecycle (pending to delivered or cancelled), indexes on user, status and creation date, and a SQL migration.
- Helmet, CORS and express-rate-limit on the API, with Winston and Morgan logging.
- Multi-stage Dockerfiles for both services that run as a non-root user and define container health checks.
- docker-compose stack where the backend waits for the PostgreSQL health check before starting.
- Jenkins pipeline as code, and Jenkins itself run in Docker with configuration as code (casc.yml, plugins.txt).
- A Python health-check script with exit codes, JSON output and timeouts, used by the pipeline.
Technical challenges
- Getting frontend linting to run in CI took several iterations: Next.js 16 changed how next lint behaves, so the pipeline moved to a direct ESLint call with ESLint pinned to version 8 (visible in the commit history).
Decisions and trade-offs
- Replaced GitHub Actions with a Jenkins pipeline running in Docker (commit "ci: replace GitHub Actions with Jenkins pipeline").
- Image push and the integration health check run on main only; feature branches run lint and build.
Testing and verification
- The pipeline runs node --check, prisma validate and tsc --noEmit, builds both images, and on main boots the full stack and runs the Python health check.
Limitations and next steps
- No automated unit or integration tests yet. Verification is lint, type-check, image build and a health check.