Keep your moving organized. BoxCopilot helps families stay sane during moves by tracking what's packed in each box and where it should go. No more opening 20 boxes to find your coffee maker.
Main dashboard showing all boxes with search and room filtering
Manage box contents and assign rooms
Share box contents with family members via QR code - no login required
Print labels with QR codes for easy scanning
-
Boxes
- Create boxes with current room, target room, description, and handling flags (Fragile, Do not stack).
- List and filter boxes: search by item name, filter by target room, and optionally show only fragile/no‑stack boxes.
- Quick actions per box: copy/open public link, edit, delete, and expand to preview items.
- Public sharing: per‑box UUID public page shows box details and items (no login required).
- Label printing: select boxes and generate an A4 PDF (3 labels/page) with QR codes to the public page, target room, and handling badges.
-
Items
- Create, edit, and delete items within a box.
- Bulk move: move one or many items to another box.
- Images: add via in‑app camera or gallery, view thumbnail and full‑size preview, and delete images when needed.
-
Camera (mobile‑friendly)
- In‑app camera with front/rear switch, pinch‑to‑zoom, torch/flash when supported, and capture/retake/accept flow.
-
Public Preview
- Read‑only preview at
/public/{uuid}; ideal for sharing with helpers and family. - Item images served via tokenized endpoints with sensible caching for fast loads.
- Read‑only preview at
-
Admin & Authentication
- Admin panel to manage users, roles, passwords, unlock accounts, and generate magic login links.
- Dual authentication: Nextcloud/OIDC and form login; account lockout after multiple failed attempts.
-
Language
- Switch between German and English; preference is remembered.
- Java 21
- Node.js 20+
- Maven 3.9+
Required Environment Variables:
# PowerShell
$env:FRONTEND_URL = 'http://localhost:3000'
$env:CLIENT_ID = 'your-nextcloud-client-id'
$env:CLIENT_SECRET = 'your-nextcloud-client-secret'
$env:NEXTCLOUD_URL = 'https://cloud.example.com'
$env:NEXTCLOUD_LOGOUT_URL = 'https://cloud.example.com/index.php/logout'
$env:SPRING_PROFILES_ACTIVE = 'dev'Run Backend (Maven ONLY - never execute JAR directly):
cd backend
mvn spring-boot:runRuns on port 8080 with H2 file-based database at ./data/boxcopilot-dev.
Default Admin User:
On first startup, a default admin account is created:
- Username:
admin - Password:
admin - Role:
ADMIN
Important: Change the default password immediately after first login.
cd frontend
npm install
npm run devRuns on port 5173 with Vite dev server. API calls are proxied to http://localhost:8080.
dev- H2 file database, JDBC sessions, OIDC enabled, dual authenticationprod- PostgreSQL, Redis sessions, OIDC enabled, dual authenticationtest- H2 in-memory, security disabled for testing
See application-*.yml for profile configurations.
Authentication:
POST /login- Form-based login (username + password)GET /oauth2/authorization/nextcloud- Initiate OIDC loginGET /api/v1/auth/magic-login?token={uuid}- Magic link authenticationPOST /api/v1/auth/logout- Logout current userGET /api/v1/me- Get current user info
User Management (ADMIN only):
GET /api/v1/admin/users- List all usersPOST /api/v1/admin/users- Create new userPUT /api/v1/admin/users/{id}- Update userDELETE /api/v1/admin/users/{id}- Delete userPOST /api/v1/admin/users/{id}/magic-link- Generate magic login link
Boxes (authenticated):
GET /api/v1/boxes- List all boxesPOST /api/v1/boxes- Create boxPUT /api/v1/boxes/{id}- Update boxDELETE /api/v1/boxes/{id}- Delete box
Items (authenticated):
GET /api/v1/items- List all itemsPOST /api/v1/items- Create itemPUT /api/v1/items/{id}- Update itemDELETE /api/v1/items/{id}- Delete itemPOST /api/v1/items/{id}/image- Upload item imageDELETE /api/v1/items/{id}/image- Delete item image
Public Access (no authentication):
GET /api/v1/public/{uuid}- Get box preview by UUIDGET /api/v1/public/items/{token}/image- Get item thumbnailGET /api/v1/public/items/{token}/image/large- Get large item image
- Docker & Docker Compose
- Traefik reverse proxy (must be running externally)
- Nextcloud instance for OIDC authentication
- Configure environment variables
Create .env file:
# Database
POSTGRES_USER=boxuser
POSTGRES_PASSWORD=secure-password-here
POSTGRES_DB=boxcopilot
# OAuth2/OIDC (Nextcloud)
CLIENT_ID=your-nextcloud-oauth-client-id
CLIENT_SECRET=your-nextcloud-oauth-client-secret
NEXTCLOUD_URL=https://cloud.example.com
NEXTCLOUD_LOGOUT_URL=https://cloud.example.com/index.php/logout
# Traefik Hosts
TRAEFIK_FRONTEND_HOST=boxes.example.com
TRAEFIK_BACKEND_HOST=boxes-api.example.com- Start services
docker-compose up -dRegister OAuth2/OIDC client in Nextcloud:
- Redirect URI:
https://boxes-api.example.com/login/oauth2/code/nextcloud - Grant Type: Authorization Code
- Scopes:
openid,profile,email
Use the generated client_id and client_secret in your .env file.
Important: BoxCopilot requires Traefik to be running externally before starting the application. The services connect to an existing Traefik instance via the traefik-proxy Docker network.
If you don't have Traefik running yet, create a separate traefik-compose.yml:
version: '3.8'
services:
traefik:
image: traefik:v2.10
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- traefik-proxy
ports:
- "80:80"
- "443:443"
environment:
- CLOUDFLARE_EMAIL=${CLOUDFLARE_EMAIL} # Optional: for DNS challenge
- CLOUDFLARE_API_KEY=${CLOUDFLARE_API_KEY} # Optional: for DNS challenge
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik/traefik.yml:/traefik.yml:ro
- ./traefik/acme.json:/acme.json
- ./traefik/config.yml:/config.yml:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.entrypoints=http"
- "traefik.http.routers.traefik.rule=Host(`traefik.example.com`)"
- "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
- "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https"
- "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
- "traefik.http.routers.traefik-secure.entrypoints=https"
- "traefik.http.routers.traefik-secure.rule=Host(`traefik.example.com`)"
- "traefik.http.routers.traefik-secure.tls=true"
- "traefik.http.routers.traefik-secure.tls.certresolver=cloudflare"
- "traefik.http.routers.traefik-secure.service=api@internal"
networks:
traefik-proxy:
external: falseCreate traefik/traefik.yml:
api:
dashboard: true
debug: true
entryPoints:
http:
address: ":80"
http:
redirections:
entryPoint:
to: https
scheme: https
https:
address: ":443"
serversTransport:
insecureSkipVerify: true
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
file:
filename: /config.yml
certificatesResolvers:
cloudflare:
acme:
email: your-email@example.com
storage: acme.json
# Use HTTP challenge for Let's Encrypt:
# httpChallenge:
# entryPoint: http
# Or DNS challenge (example with Cloudflare):
dnsChallenge:
provider: cloudflare
resolvers:
- "1.1.1.1:53"
- "1.0.0.1:53"Create empty traefik/acme.json with correct permissions:
mkdir -p traefik
touch traefik/acme.json
chmod 600 traefik/acme.jsonStart Traefik:
docker-compose -f traefik-compose.yml up -dVerify the traefik-proxy network exists:
docker network ls | grep traefik-proxyThen start BoxCopilot services with the main docker-compose.yml.
BoxCopilot's docker-compose.yml connects to the external traefik-proxy network:
networks:
traefik-proxy:
external: trueBoth frontend and backend services include Traefik labels for:
- HTTP → HTTPS redirect
- TLS certificate provisioning (Let's Encrypt)
- Host-based routing
Backend: Java 21, Spring Boot 3.5, Spring Security with OAuth2/OIDC, Spring Data JPA, PostgreSQL, Redis, Flyway
Frontend: React 18, TypeScript, Vite, Material-UI, Axios, React Router
Infrastructure: Docker, Docker Compose, Traefik, PostgreSQL 15, Redis
This project is licensed under the GNU General Public License v3.0 (GPL-3.0).
You are free to:
- ✅ Use - Run the program for any purpose
- ✅ Study - Access and study the source code
- ✅ Share - Copy and distribute the software
- ✅ Modify - Make changes and improvements to the software
Under the following terms:
- 📝 Copyleft - If you distribute modified versions, you must also license them under GPL v3.0
- 🔓 Source Code - You must make the source code available when you distribute the software
- 📄 License Notice - You must include a copy of the GPL v3.0 license and copyright notice
- 🔄 Same License - All derivative works must be licensed under the same GPL v3.0 terms
This ensures that BoxCopilot and all its derivatives remain free and open source software forever.
See LICENSE for full details or visit https://www.gnu.org/licenses/gpl-3.0.html