Hinatadocs

Development#

This page gets you from a fresh clone to a running server and app on your own machine. Hinata is two repositories — a Spring Boot server and a Flutter client — and each has a short, predictable dev loop. Work through the server first (it is what the app talks to), then the app.

Server (Spring Boot, Java 21)#

Prerequisites#

  • JDK 21 (Temurin is what CI uses).
  • Docker with Compose, for the local infrastructure.
  • No global Gradle needed — the repo ships the Gradle Wrapper (./gradlew).

1. Start the infrastructure#

A dedicated Compose file brings up only the backing services the server needs — a MongoDB replica set, Mailpit (a local SMTP catcher) and MinIO (S3-compatible storage) — so you can run the server itself from your IDE or the wrapper:

docker compose -f docker-compose.dev.yml up -d   # Mongo RS, Mailpit, MinIO
Service URL What it is
Mailpit http://localhost:8025 Catches all outbound mail — open it to read verification / reset / notification e-mails.
MinIO console http://localhost:9001 Browse the object storage bucket that holds attachments and avatars.
MongoDB localhost:27017 Replica set rs0, reached with directConnection=true.

2. Run the server#

Point the server at the local Mongo and MinIO and start it with the wrapper:

HINATA_MONGODB_URI="mongodb://localhost:27017/hinata?replicaSet=rs0&directConnection=true" \
HINATA_S3_ACCESS_KEY=hinata HINATA_S3_SECRET_KEY=hinata-dev-secret \
./gradlew bootRun

Seed a realistic demo workspace

Add HINATA_DEMO_SEED=true to populate a full English demo workspace (projects, issues, sprints, a knowledge base) so you have something to click through. It also completes first-run setup and logs in as rebar / hinata-demo-2026. The seeder is annotated @Profile("!prod"), so it is compiled out of production builds entirely — it is a dev-only convenience.

3. Run the tests#

The quality gate is a single command — the same one CI runs:

./gradlew build

Dev vs prod profiles

Local development uses the dev Spring profile (standalone Mongo). Production uses prod (a TLS + X.509 replica set). You almost never need the prod profile on your machine; see MongoDB & X.509 if you want to reproduce it.

App (Flutter)#

Prerequisites#

  • The Flutter toolchain (stable channel — the same channel CI builds with). Run flutter doctor and resolve anything it flags for your target platforms.
  • Platform SDKs only for the targets you build: Android Studio / SDK for Android, Xcode for iOS and macOS. Web needs nothing extra.

Run it#

flutter pub get
flutter run

flutter run targets whatever device is connected. To pick a target explicitly:

flutter run -d chrome    # web
flutter run -d macos     # macOS desktop
flutter devices          # list attached devices/emulators

On first launch the app asks for your server URL. Point it at your local server:

  • Desktop / web / iOS simulator: http://localhost:8080
  • Android emulator: http://10.0.2.2:8080 (the emulator's alias for your host)

Quality gate#

The same checks CI runs, locally:

flutter analyze && flutter test

Internationalization (i18n)#

Hinata is multilingual, and every user-facing string must be translated — the app ships English and German. Strings live in i18next JSON under assets/i18n/{en,de}/ and are read through the localization layer (never hardcoded in a widget).

Every new string needs en + de

When you add UI text, add the key to both assets/i18n/en/ and assets/i18n/de/ and resolve it via the translation function. A missing key silently renders the raw key string. This is a hard requirement for any PR that touches the UI — see Contributing.

Project layout#

The app follows a feature-first structure. Each feature owns its screens and state; shared plumbing lives under core/. Data flows in one direction:

Features (screens/widgets)
    │
    ▼
Bloc / Cubit            state management
    │
    ▼
HinataRepository        domain-facing data access
    │
    ▼
ApiClient (dio)         REST /api/v1, token refresh, Accept-Language
    │
    ▼
Hinata Server           Spring Boot, /api/v1  ──SSE──▶ back to Bloc
lib/
  core/        theme, responsive system, i18n, api, models, blocs,
               router, storage, widgets
  features/    connect, setup, onboarding, auth, shell, dashboard,
               projects, issues, board, sprint, gantt, timesheet,
               reports, knowledge, search, notifications, settings, admin
packages/
  liquid_glass_widgets/   vendored glass surfaces (full control)

A screen never talks to dio directly: it dispatches to a bloc/cubit, which calls a method on HinataRepository, which uses the ApiClient. That single client is where the Bearer token, automatic refresh and the Accept-Language header are handled once for the whole app. Live changes arrive back over SSE and update the relevant bloc.

CI/CD#

Both repositories use GitHub Actions.

  • Server (ci.yml): on every push and pull request, runs ./gradlew build. On pushes to main and on version (v*) tags, it builds and publishes a Docker image to the GitHub Container Registry (GHCR) under ghcr.io/hinata-platform, tagged latest on main and with the semantic version on tags.
  • App (ci.yml): on every push and pull request, runs flutter analyze and flutter test, and builds the web release. On pushes to main and v* tags it publishes the compiled Flutter web image to GHCR. A separate release workflow handles store builds for the mobile apps.

The image tags you deploy

Operators pull those GHCR images by tag — HINATA_SERVER_TAG and HINATA_APP_TAG in the deployment .env (default latest). See Production deployment.

Where to go next#

© 2026 Hinata · GPL-3.0 GitHub