A multi-module Spring Boot application for storing and analyzing fitness activities from Garmin FIT files, GPX files, and TCX files. The application has a domain-driven modular architecture with separate storage engines and a unified Angular frontend.
- Import and store activities from Garmin FIT, GPX, and TCX file formats
- Query and filter activities by distance, ascent, location, and more
- Export activities in multiple formats (GPX, CSV)
- Analyze metrics: power, heart rate, cadence, elevation
- Interactive map visualization with Leaflet
- GeoJSON support for advanced geospatial queries
- JWT-based authentication with role-based access control
- EclipseStore for high-performance object persistence
- Full REST API for programmatic access
- JDK 25+
- Gradle 9.6+ (included via
gradlew) - Node.js 24+ (Gradle downloads and manages it)
- Optional: Docker for container deployment
-
Clone the repository:
git clone https://github.com/your-org/privactivity-activity-store.git cd privactivity-activity-store -
Build the application:
./gradlew build
-
Configure storage: The default directory for temporary application data is
${HOME}/tmp/privactivity. Either create that directory or change it inprivactivity-app/src/main/resources/application-dev.properties.The application reads/writes long-term data and imported data by default in
${PRIVATE_DATA_DIR}. Set this variable or change it in the file above.On first startup, the application reads the initial admin password
${HOME}/tmp/privactivity/admin-password.txtand uses it to create the defaultadminaccount inusers.jsonif that file does not already exist.
Optionally download Shapefiles for the countries of your activities.
- For Switzerland go to https://portal.topax.ch/wizard/claim/file (for example https://data.geo.admin.ch/ch.swisstopo.swissboundaries3d/swissboundaries3d_2026-01/swissboundaries3d_2026-01_2056_5728.shp.zip) and download the latest ".shp.zip" file. Unzip it and copy all "HOHEITSGEBIET" files to "privactivty-app/data/shapefiles/switzerland".
- For Germany go to https://gdz.bkg.bund.de and get the latest "Verwaltungsgebiete 1:250 000" (VG250) in UTM32s shape format. E.g. from e.g. https://gdz.bkg.bund.de/index.php/default/verwaltungsgebiete-1-250-000-stand-01-01-vg250-01-01.html download and https://daten.gdz.bkg.bund.de/produkte/vg/vg250_ebenen_0101/aktuell/vg250_01-01.utm32s.shape.ebenen.zip. Unzip it and copy the vg250_ebenen_0101 folder to "privactivty-app/data/shapefiles/germany/„
If the shapefiles are not present, there will be a warning and a stacktrace in the startup log but most of the features will still work.
- Run locally:
This starts the application in development mode at
./bootRun.sh
http://localhost:8090with hot-reload enabled. To use hot-reload web-frontend:./gradlew ngServe
-
Build the image:
./build-docker-image.sh
This creates the
org.privactivity/activity-store:latestimage in the registry configured byDOCKER_REGISTRY(localhostby default). -
Prepare persistent files and directories: The Docker profile expectes application data under
/privactivity. Create a local directory/path/to/privactivityfor it. -
Initial admin password: Create a file
/path/to/privactivity/admin-password.txtand add a line with the initial password for the admin user. -
Generate the JWT key pair: The Docker profile expects PEM-encoded RSA keys at
/privactivity/jwt/app.keyand/privactivity/jwt/app.pub. Generate them once:mkdir -p /path/to/privactivity/jwt openssl genpkey -algorithm RSA -out /path/to/privactivity/jwt/app.key -pkeyopt rsa_keygen_bits:2048 openssl rsa -pubout -in /path/to/privactivity/jwt/app.key -out /path/to/privactivity/jwt/app.pub
-
Run the container:
docker run --rm \ -p 8090:8090 \ -e SPRING_PROFILES_ACTIVE=docker \ -v /path/to/privactivity:/privactivity \ localhost/org.privactivity/activity-store:latest
The application is then available at
http://localhost:8090.
- DEVELOPMENT.md — Architecture, layering, workflow, and testing conventions
- .github/copilot-instructions.md — AI coding agent guidelines
./bootRun.sh # Development server with hot-reload
./gradlew build # Full build (all modules + Angular frontend)
./gradlew ngServe # Start Angular dev server only- Backend: Spring Boot 4, EclipseStore, JUnit 5
- Frontend: Angular 21, Material UI, Leaflet
- Build: Gradle multi-project, Node.js (managed by Gradle)
- Storage: EclipseStore (object database, not SQL)
Please refer to DEVELOPMENT.md for detailed architecture, layering principles, and coding conventions.
See LICENSE file for details.