Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GroundNote

GroundNote is a full-stack, offline-first field intelligence demo built to showcase senior-level product + engineering ownership across:

  • multimodal capture (text, image, voice),
  • AI structuring of unstructured field data,
  • resilient offline/online sync,
  • production-minded API and frontend architecture,
  • polished enterprise UX for operations teams.

The project is intentionally designed as a portfolio-grade reference for modern AI-enabled line-of-business applications.


What GroundNote Demonstrates

  • AI-assisted field workflows: convert raw observations into structured records (title, summary, category, priority, actions).
  • Multimodal ingestion: capture from text, image, and audio endpoints.
  • Offline-first UX: local outbox + cache in IndexedDB, with idempotent batch sync.
  • Corporate-grade frontend: Angular app shell, authenticated routes, dashboard cards, queue visibility, and clean data-dense screens.
  • Pragmatic backend design: Spring Boot API with clear service boundaries, DTOs, validation, centralized exception handling, health endpoints, and OpenAPI docs.

Tech Stack

Backend

  • Java 25
  • Spring Boot 4.0.5
  • Spring AI 2.0.0-M7
  • Spring Data JPA + H2 (in-memory for demo)
  • Spring Actuator
  • Springdoc OpenAPI (Swagger UI)
  • Maven

Frontend

  • Angular 22.0.0-rc.1 (standalone components)
  • TypeScript 6
  • RxJS
  • Dexie (IndexedDB)
  • Angular Service Worker (PWA support)
  • SCSS design system (tokens + reusable UI primitives)

Monorepo Layout

groundnote/
  backend/    # Spring Boot + Spring AI API
  frontend/   # Angular PWA app

Key frontend modules:

  • core/services: API, auth, connectivity, offline store, sync orchestration
  • features/login: sign-in flow
  • features/notes: dashboard list + note detail
  • features/capture: text/photo/voice capture flow
  • shared/*: icons, stat cards, empty states

Key backend modules:

  • api: REST controllers
  • service: orchestration + business logic
  • ai: demo and OpenAI-based structuring/transcription implementations
  • domain/repository: JPA entities + repositories
  • dto: request/response contracts
  • exception: global API exception mapping

Architecture Overview

flowchart LR
  U[Field User] --> FE[Angular PWA]
  FE -->|/api via proxy| BE[Spring Boot API]
  FE --> IDB[(IndexedDB<br/>Dexie outbox + cache)]
  BE --> DB[(H2 Demo DB)]
  BE --> AI[AI Structuring Port]
  AI --> DEMO[Demo Heuristic Service]
  AI --> OPENAI[OpenAI Service<br/>Spring AI]
  BE --> MEDIA[(Local Media Storage)]
Loading
flowchart TB
  subgraph Frontend
    APP[App Shell + Routes]
    AUTH[AuthService + AuthGuard]
    CAP[Capture Feature]
    NOTES[Notes Dashboard]
    SYNC[SyncService]
    STORE[OfflineStoreService]
    API[GroundNoteApiService]
  end

  APP --> AUTH
  APP --> CAP
  APP --> NOTES
  CAP --> STORE
  CAP --> API
  NOTES --> API
  NOTES --> STORE
  SYNC --> STORE
  SYNC --> API
Loading

Runtime Profiles and AI Modes

GroundNote supports two backend AI modes:

  1. demo profile (default)
    Uses deterministic heuristics for structuring so the app works without external API keys.

  2. openai profile
    Uses Spring AI + OpenAI for richer structuring and audio transcription.

Configuration is in:

  • backend/src/main/resources/application.yml
  • backend/src/main/resources/application-demo.yml

To run OpenAI mode, set:

  • OPENAI_API_KEY=<your key>
  • active profile: openai

Prerequisites

  • Java 25
  • Maven 3.9+
  • Node 22.22.3+
  • npm (bundled with Node)

Quick Start (Local)

1) Backend

cd backend
mvn spring-boot:run -Dspring-boot.run.profiles=demo -Dmaven.test.skip=true

Backend runs on: http://localhost:8080

Useful URLs:

  • Swagger UI: http://localhost:8080/swagger-ui.html
  • OpenAPI docs: http://localhost:8080/api-docs
  • Health: http://localhost:8080/api/v1/system/health

2) Frontend

cd frontend
npm install
npm start

Frontend runs on: http://localhost:4200

The Angular dev server proxies /api to http://localhost:8080 via frontend/proxy.conf.json.


Demo Login Credentials

The frontend includes a demo auth layer (session-backed):

  • admin@groundnote.dev / demo1234
  • inspector@groundnote.dev / demo1234

Logout always redirects to /login.


Core API Endpoints

Notes

  • GET /api/v1/notes - list notes
  • GET /api/v1/notes/{id} - get one note
  • POST /api/v1/notes - create structured note from raw text
  • DELETE /api/v1/notes/{id} - delete note

AI

  • POST /api/v1/ai/structure - preview structure without persisting
  • POST /api/v1/ai/capture/text
  • POST /api/v1/ai/capture/image (multipart/form-data)
  • POST /api/v1/ai/capture/audio (multipart/form-data)

Offline Sync

  • POST /api/v1/sync/batch - idempotent outbox sync by clientId

System

  • GET /api/v1/system/health

Offline-First Design

Frontend stores:

  • outbox entries (pending captures),
  • notes cache (last known server records),

in IndexedDB via Dexie.
When online, sync pushes pending entries in batch and refreshes server-backed notes.

Backend sync behavior is idempotent using client-generated clientId values to prevent duplicates on retries.


Offline Capture to Sync Sequence

sequenceDiagram
  participant User
  participant FE as Angular Capture UI
  participant IDB as IndexedDB Outbox
  participant SYNC as SyncService
  participant API as Spring Boot API
  participant DB as Database

  User->>FE: Capture note (text/image/voice)
  alt Offline
    FE->>IDB: enqueue(outbox item, clientId)
    FE-->>User: "Saved locally"
  else Online
    FE->>API: create/capture request
    API->>DB: persist structured note
    API-->>FE: created note
  end

  Note over SYNC,IDB: Connectivity restored or manual sync
  SYNC->>IDB: list pending outbox
  SYNC->>API: POST /api/v1/sync/batch
  API->>DB: upsert by clientId (idempotent)
  API-->>SYNC: synced + failed clientIds
  SYNC->>IDB: mark synced / keep failed
  SYNC->>API: GET /api/v1/notes
  API-->>SYNC: latest notes
  SYNC->>IDB: refresh notes cache
  SYNC-->>User: Updated dashboard + queue
Loading

Testing and Quality Gates

Backend

cd backend
mvn test -Dspring.profiles.active=demo

Frontend

cd frontend
npm run build -- --configuration=production

The production Angular build currently passes with bundle budgets configured in frontend/angular.json.


PWA Notes

GroundNote includes:

  • service worker config (frontend/ngsw-config.json)
  • web manifest (frontend/public/manifest.webmanifest)
  • icons in frontend/public/icons/

To test installability behavior, run a production build/serve context (not plain dev mode).


Enterprise stack (auth, Postgres, async, observability, S3)

GroundNote includes an optional docker profile with production-oriented building blocks:

Capability Implementation
Auth + RBAC JWT login (POST /api/v1/auth/login), roles INSPECTOR, SUPERVISOR, ADMIN, Spring Security on /api/v1/**
Database PostgreSQL 16 + Flyway migrations (backend/src/main/resources/db/migration/)
Async AI pipeline RabbitMQ queue + DLQ, processingStatus on notes (QUEUEDPROCESSINGCOMPLETED / FAILED)
Observability JSON logs with traceId (MDC), Prometheus metrics, Grafana datasource provisioning, Sentry DSN hook
Media Local disk (local profile) or MinIO/S3 (s3 profile), MIME/size validation, virus-scan hook

Demo users (seeded at startup)

Email Password Role
admin@groundnote.dev demo1234 ADMIN
supervisor@groundnote.dev demo1234 SUPERVISOR
inspector@groundnote.dev demo1234 INSPECTOR

The Angular app calls the login API and sends Authorization: Bearer <token> on subsequent requests.

Run full stack with Docker

docker compose up -d
cd backend
set JAVA_HOME=C:\Program Files\Java\jdk-25.0.2
mvn spring-boot:run -Dspring-boot.run.profiles=demo,docker

Services: Postgres :5432, RabbitMQ :5672 (UI :15672), MinIO :9000, Prometheus :9090, Grafana :3000.

Profiles

  • demo,local (default): H2 in-memory, local media, sync login, RabbitMQ disabled
  • demo,docker: Postgres, Flyway, RabbitMQ workers, MinIO object storage
flowchart LR
  FE[Angular PWA] -->|JWT| API[Spring Boot API]
  API --> PG[(PostgreSQL)]
  API --> Q[RabbitMQ]
  Q --> W[Note processing worker]
  W --> AI[AI structuring]
  API --> S3[(MinIO / S3)]
  API --> PROM[Prometheus]
Loading

Why This Project Is Portfolio-Relevant

GroundNote is not just CRUD + UI polish. It demonstrates:

  • system thinking across product, UX, backend, frontend, and AI integration,
  • reliability under poor connectivity constraints,
  • practical tradeoffs between demo-mode determinism and real model providers,
  • enterprise-friendly UX patterns for operational users.

License

This project is licensed under the MIT License.

About

Offline-first field intelligence demo: multimodal capture, AI structuring, and resilient sync - Spring Boot API + Angular PWA.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages