Skip to content

mathim/GardenKeeper

Repository files navigation

GardenKeeper Web

Port van de iOS GardenKeeper app naar SvelteKit + Konva.js, uitsluitend via Docker containers.

Stack

Onderdeel Technologie Port
Reverse proxy nginx:alpine 80
Web app SvelteKit + Konva.js 3000 (intern)
Backend PocketBase 8090 (intern)

Mappenstructuur

gardenkeeper-web/
├── docker-compose.yml
├── docker-compose.dev.yml     ← dev mode met live reload (./app:/app mount)
├── nginx.conf
├── .env                       ← CLAUDE_API_KEY (niet committen!)
└── app/                       ← SvelteKit project
    ├── Dockerfile
    └── src/
        ├── lib/
        │   ├── types.ts               ← alle models + helpers
        │   ├── stores/
        │   │   ├── app.ts             ← state (gardens, zones, plants, placements)
        │   │   └── logs.ts            ← AI-actie logging
        │   └── services/
        │       ├── pocketbase.ts      ← PocketBase client + pbUrl
        │       └── claude.ts          ← AI service (Claude API)
        └── routes/
            ├── +layout.svelte         ← nav + auth guard
            ├── +page.svelte           ← tuinoverzicht
            ├── api/
            │   ├── ai/+server.ts      ← Claude proxy endpoint
            │   └── photo/+server.ts   ← Wikipedia foto endpoint
            ├── auth/login/            ← login + registratie
            └── garden/[id]/
                ├── +page.svelte          ← tuin detail (tabs: Canvas / Planten / Zones)
                ├── GardenCanvas.svelte   ← Konva canvas met zones + planttokens
                ├── PlantDetail.svelte    ← plant detail sidebar
                └── ZoneDetail.svelte     ← zone detail (sidebar of modal)

Functies

Canvas (Konva.js)

  • Pan (sleep) en zoom (scroll/knop) over het tuincanvas
  • Rasteroverlay (25px minor, 1m major gridlines)
  • Optionele plattegrond als achtergrondafbeelding
  • Zones: teken nieuw (⬜+), sleep om te verplaatsen, resize via hoekhandvat
    • Enkele klik = selecteren; dubbelklik = zone detail openen als modal
  • Plant tokens: sleepbaar, toont foto + naam + gestippelde groeiradius

Plant detail

  • Foto uploaden of automatisch ophalen van Wikipedia
  • AI-data ophalen via Claude (hoogte, zon, water, onderhoud, snoeien, bloeitijd)
  • Plantkalender: bloei- en snoeimalanden visueel gemarkeerd
  • Zones toewijzen / verwijderen via chip-UI
  • Plant direct zichtbaar na aanmaken

Zone detail (sidebar of modal)

  • Mini zone-map: visuele weergave van de zone met meterraster
    • Plant tokens sleepbaar voor herpositionering (opgeslagen in PocketBase)
    • Groeiradius ring op basis van plantdiameter
  • Zone bewerken (naam, kleur, afmeting)
  • Planten toevoegen uit plantenlijst (naam + variëteit zichtbaar)
  • Planten verwijderen uit zone

Zones-tab

  • Overzicht van alle zones met kleur, afmeting en plantencount
  • "Geen zone"-rij toont planten nog niet aan een zone toegewezen
  • Klik op zone opent zone detail als modal

Draaien op een QNAP NAS via Container Station

Container Station op QNAP ondersteunt Docker Compose. Hieronder stap voor stap hoe je de app op je NAS krijgt.

Vereisten

  • QNAP NAS met Container Station 3.x geïnstalleerd
  • SSH-toegang tot de NAS (of File Station om bestanden te uploaden)
  • Git beschikbaar op de NAS (optioneel, anders handmatig uploaden)

Stap 1 — Bestanden op de NAS zetten

Via SSH:

ssh admin@JOUW-NAS-IP

# Maak een map aan in de shared folder
mkdir -p /share/Container/gardenkeeper
cd /share/Container/gardenkeeper

# Optie A: via git
git clone https://github.com/JOUW-REPO/gardenkeeper-web.git .

# Optie B: upload de map via File Station naar
# /share/Container/gardenkeeper/

Stap 2 — API key instellen

cd /share/Container/gardenkeeper
cp .env.example .env
vi .env   # vul CLAUDE_API_KEY=sk-ant-... in

Stap 3 — Deployen via Container Station UI

  1. Open Container Station in het QNAP-beheerportaal
  2. Klik op MakenMaak via Docker Compose
  3. Geef het project een naam, bv. gardenkeeper
  4. Plak de inhoud van docker-compose.yml in het tekstveld — of wijs het pad /share/Container/gardenkeeper/docker-compose.yml aan
  5. Voeg onder Omgevingsvariabelen toe: CLAUDE_API_KEY = jouw Claude API key
  6. Klik Maken — Container Station bouwt de images en start de containers

Tip: Als je liever via SSH werkt:

cd /share/Container/gardenkeeper
docker-compose up -d --build

QNAP gebruikt Docker Compose v1 — gebruik docker-compose (met koppelteken), niet docker compose.

Stap 4 — PocketBase admin instellen

  1. Ga naar http://JOUW-NAS-IP/_/
  2. Maak een admin-account aan
  3. Maak de collections aan (zie tabel verderop in deze README)

Stap 5 — App bereikbaar

http://JOUW-NAS-IP/ — via de nginx reverse proxy op poort 80.

Als poort 80 al in gebruik is door een andere container of de QNAP-webserver, pas dan de poortmapping aan in docker-compose.yml:

ports:
  - "8080:80"   # bereikbaar op poort 8080

Data bewaren bij herstart

De PocketBase-data zit in Docker named volumes (pb_data, pb_migrations). Deze blijven behouden bij docker-compose down en NAS-reboots. Om een backup te maken:

# Op de NAS via SSH
docker run --rm \
  -v gardenkeeper_pb_data:/data \
  -v /share/Backup:/backup \
  alpine tar czf /backup/pb_data_$(date +%Y%m%d).tar.gz -C /data .

Updaten

cd /share/Container/gardenkeeper
git pull
docker-compose up -d --build gardenkeeper

Probleemoplossing (QNAP)

docker-compose.yml staat niet in git

docker-compose.yml wordt niet bijgehouden in git (om API keys uit de geschiedenis te houden). Pas het bestand rechtstreeks aan op de NAS als er iets gewijzigd moet worden:

# Controleer de huidige waarde
grep PUBLIC_PB_URL docker-compose.yml

# Pas een waarde aan (voorbeeld: PocketBase URL)
sed -i 's|PUBLIC_PB_URL=http://pocketbase:8090|PUBLIC_PB_URL=${PUBLIC_PB_URL:-http://192.168.1.99:8090}|' docker-compose.yml

Container draait nog met oude omgevingsvariabelen

Als je docker-compose.yml hebt aangepast maar de container gedraagt zich nog als voorheen, is de container niet opnieuw aangemaakt. Gebruik --force-recreate:

docker-compose up -d --force-recreate gardenkeeper

Controleer achteraf welke waarden de draaiende container heeft:

docker inspect gardenkeeper_gardenkeeper_1 | grep PUBLIC_PB_URL

.env controleren en aanpassen

# Bekijk huidige .env
cat .env

# Pas een waarde aan via sed
sed -i 's/OUDE_WAARDE/NIEUWE_WAARDE/' .env

# Of bewerk handmatig
vi .env

De .env moet minimaal bevatten:

CLAUDE_API_KEY=sk-ant-...

PUBLIC_PB_URL hoeft niet in .env — de standaardwaarde in docker-compose.yml wordt dan gebruikt.

Controleer welke containers draaien

docker-compose ps
docker-compose logs gardenkeeper --tail=50
docker-compose logs nginx --tail=20

nginx blijft herstarten

Controleer of de pocketbase-hostnaam oplosbaar is vanuit de nginx-container. Als PocketBase buiten dit Compose-project draait, gebruik dan het NAS IP-adres rechtstreeks in nginx.conf (bv. http://192.168.1.99:8090) in plaats van http://pocketbase:8090.

nginx pikt gewijzigde nginx.conf niet op na git pull

Op QNAP vervangt git pull bestanden met een nieuw inode. nginx's reload (nginx -s reload) herlaadt de configuratie maar houdt de file descriptor van het oude inode vast — de nieuwe inhoud wordt dan niet opgepikt.

Gebruik na elke git pull die nginx.conf wijzigt een volledige container-restart in plaats van enkel reload:

docker-compose restart nginx

Controleer daarna of de nieuwe config actief is:

docker exec gardenkeeper_nginx_1 cat /etc/nginx/conf.d/default.conf | grep -A3 "api/photo"

Eerste keer opzetten

# 1. API key instellen
cp .env.example .env
nano .env   # vul CLAUDE_API_KEY in

# 2. Bouwen en starten
docker compose up -d --build

# 3. PocketBase admin instellen
# Ga naar http://JOUW-IP/_/
# Maak admin account aan
# Maak de collections aan (zie hieronder)

# 4. App bereikbaar op http://JOUW-IP/

Ontwikkeling (live reload)

docker compose -f docker-compose.dev.yml --env-file .env up

De app/ map wordt als volume gemount — wijzigingen in app/src/ zijn direct zichtbaar.

Update deployen

git pull
docker compose up -d --build gardenkeeper

PocketBase collections (vereist)

Collection Velden
users standaard auth
gardens owner, name, width_m, height_m, floorplan_photo, notes
garden_zones garden, name, color, x_pos, y_pos, width_m, height_m, notes
plants garden, name, variety, photo, category, size_m, ai_*
placed_plants garden, plant, zone (optioneel), x_pos, y_pos, rotation, scale
vegetable_patches owner, name, width_m, height_m, floorplan_photo, notes
vegetables patch, name, status, photo, planned_count, ai_*, size_m
placed_vegetables patch, vegetable, x_pos, y_pos, rotation

AI-velden op plants

ai_height, ai_sun, ai_water, ai_maintenance, ai_pruning, ai_pruning_instruction, ai_pruning_months, ai_bloom_season, ai_bloom_months, ai_diameter_m, ai_category, ai_winterhard, ai_tip, ai_fetched_at

Canvas technologie

iOS → Web mapping:

iOS Web
UIScrollView zoom/pan Konva.Stage (draggable + wheel zoom)
ZoneUIView (UIKit) Konva.Rect in Konva.Group (draggable)
PlantToken (SwiftUI) Konva.Group met Circle + Image + label
UIPanGestureRecognizer Konva drag events
@Published / AppState Svelte writable stores

Konva verwerkt alle gesture-conflicten automatisch.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors