Your weekly overview at a glance. A beautiful, intuitive calendar app for planning your week.
Wochenschau (German for "weekly review") is a modern Progressive Web App built with SvelteKit (Svelte 5), TypeScript, Tailwind CSS and Vite. It blends iOS-inspired design patterns with fast, private, offline-first functionality.
- Week-at-a-glance grid view (MonβSun, ISO week)
- Manual activity creation with time range
- Activity templates (quick reuse of routine items)
- iCal calendar subscription (import external events)
- Local edit tracking for subscribed events (conflict resolution dialog)
- Multi-layout export (grid, list, compact)
- Image export (PNG) with clipboard and share-sheet support
- Local-first data with optional PocketBase account sync
- Responsive (mobile-first, tablet & desktop enhancements)
- Swipeable sheets & modals (mobile UX)
- Floating bottom navigation + Add button (FAB)
- Light/Dark mode (system detection with CSS variables)
- IndexedDB-backed background image handling (memory efficient)
- Local font set (reliable embedding for exports)
- Optional daily Bible verse (German verses)
- Customizable title, fonts, colors, accent, borders, opacity, corner radius
- Background: solid color or selected image (default gallery or user upload)
- Separate week container styling (overlay color + opacity)
- High-resolution rendering with platform-aware scale & caching heuristics
- Automatic iOS/Safari workarounds (background image capture reliability)
- Troubleshooting & platform-specific documentation (see
docs/)
- Works fully local without backend; optional PocketBase cloud sync
- IndexedDB storage for large background images (migrated from legacy localStorage)
- Graceful fallback if fonts/backgrounds unavailable
- Conflict-safe sync: local changes to imported iCal events are never silently overwritten
- Sync conflict detection groups modified subscribed items and prompts a global choice:
- Keep local changes (preserve overrides)
- Use fresh subscribed data (discard overrides)
- Local override tracking per field (
summary,description, times, color) - Derivable store helpers (
activitiesByWeek,activitiesByDay) - Structured design tokens via Tailwind utility composition
| Area | Status |
|---|---|
| Recurring iCal events (RRULE) | Not yet implemented (RRULE field parsed but unused) |
| Per-item conflict resolution | Global apply (dialog offers one decision for all conflicts) |
| Multi-week span events | Represented as single-day; week-crossing logic is minimal |
| Cloud sync conflict resolution | Last-write-wins by timestamp (no per-field merge yet) |
| Authentication providers | Email/password via PocketBase only |
src/
βββ routes/
β βββ +layout.svelte
β βββ +layout.ts
β βββ +page.svelte
βββ app.html
βββ app.css
βββ fonts.css
βββ App.svelte
βββ lib/
βββ components/
β βββ WeekView.svelte
β βββ DayColumn.svelte
β βββ ActivityCard.svelte
β βββ ActivityEditSheet.svelte
β βββ AddActivityModal.svelte
β βββ TemplateManager.svelte
β βββ SubscriptionManagerPanel.svelte
β βββ SyncConflictDialog.svelte
β βββ ExportSheet.svelte
β βββ SettingsSheet.svelte
β βββ DefaultBackgroundSelector.svelte
β βββ FloatingNav.svelte
β βββ WeekPicker.svelte
β βββ SwipeableSheet.svelte
β βββ RangeSlider.svelte
β βββ SettingIcon.svelte
β βββ Button.svelte / IconButton.svelte
β βββ Card.svelte / Input.svelte / List*.svelte
β βββ index.ts
βββ stores/
β βββ activities.ts
β βββ templates.ts
β βββ ical.ts
β βββ exportSettings.ts
β βββ imageStorage.ts
β βββ bibleVerse.ts
β βββ defaultBackgrounds.ts
β βββ week.ts
βββ utils/
β βββ date.ts
β βββ cn.ts
β βββ storage.ts
βββ types/
β βββ index.ts
βββ data/
βββ bibleVerses.ts
docs/
βββ export-troubleshooting.md
βββ ios-background-fix.md
static/
βββ backgrounds/ (default selectable images)
| Tech | Purpose |
|---|---|
| SvelteKit (Svelte 5) | App framework, routing, build |
| TypeScript | Type safety & domain modeling |
| Tailwind CSS | Utility-first styling |
| Vite | Underlying dev server and bundler |
| vite-plugin-pwa | Service worker + manifest |
| IndexedDB | Large background image persistence |
| LocalStorage | Lightweight structured data (activities, templates, subscriptions) |
| Custom render/export logic | High-quality image export (PNG) using tuned caching & scale |
source:"manual" | "ical" | "template"localOverrides: captured differences for iCal-origin events- Time stored in iCal-like (
YYYYMMDDTHHMMSS) for start/end + derived fields (startTime,day,week)
- Subscription refresh pulls raw iCal items.
- Items matched by
uid/ localid. - Modified subscribed items (with
localOverrides) aggregated. - Dialog: user chooses global resolution.
- Applied accordingly; local timestamps updated.
Adaptive strategies:
- Scale: Desktop up to 4Γ, iOS/Safari reduced to 3Γ (fallback 2Γ on memory pressure)
- Cache strategy: Disabled when using image background to avoid stale/corruption issues
- DOM layering: Real
<img>element for background (fixes iOS CSS background capture) - Font embedding: Local font families only (ensures reproducibility)
- Filter excludes transient UI elements (sheet chrome, buttons)
Troubleshooting references:
docs/export-troubleshooting.mddocs/ios-background-fix.md
| Concern | Approach |
|---|---|
| Large images | IndexedDB (blob) via imageStorage |
| Migration | Automatic from legacy base64 in export settings |
| Settings | Stored sans large base64 to keep localStorage lean |
| Activities | LocalStorage list with incremental append/replace |
| Templates | LocalStorage list |
| Subscriptions | LocalStorage list (items stored inside activities; no separate event cache now) |
- Node.js 18+
- pnpm β₯ 8
git clone https://github.com/meierac/wochenschau.git
cd wochenschau
pnpm installpnpm devVisit: http://localhost:5173
pnpm checkpnpm buildpnpm preview- In your GitHub repository, open Settings β Pages.
- Set Source to GitHub Actions.
- Ensure your default branch is
main(or update.github/workflows/deploy.ymlaccordingly).
A GitHub Actions workflow at .github/workflows/deploy.yml builds the app and deploys dist/ to GitHub Pages on every push to main.
The workflow automatically sets BASE_PATH from actions/configure-pages, so project-page URLs (e.g. /repo-name) work without manual edits.
pnpm deploy(Equivalent to pnpm build for producing dist/; publishing is handled by GitHub Actions.)
SPA fallback on GitHub Pages is handled by SvelteKit static adapter output (
fallback: "404.html").
This app requires an account login before use. After a user has logged in on a device once, offline mode remains supported on that device.
Copy .env.example to .env and adjust if needed:
cp .env.example .envDefaults:
VITE_POCKETBASE_URL=https://pocketbase.144t.orgVITE_POCKETBASE_AUTH_COLLECTION=usersVITE_POCKETBASE_DATA_COLLECTION=user_sync_states
A ready migration is included at:
pocketbase/pb_migrations/1782019200_create_users_and_sync_state.js
From your PocketBase app directory, run:
./pocketbase migrate upThis creates:
- Auth collection:
users - Base collection:
user_sync_statesuser(relation tousers, required)payload(json)clientUpdatedAt(number, required)- unique index on
user
If you prefer dashboard import/manual setup, use:
pocketbase/collections/user_sync_collections.json
(You can copy these definitions into PocketBase collection import/creation workflows.)
If your frontend runs on a different origin, add it to PocketBase allowed origins.
While this is a personal project, feel free to:
- Open issues describing UX or export reliability improvements.
- Suggest performance tweaks (DOM size during export, memory usage).
- Propose modularization (e.g., per-item conflict resolution, recurrence parsing).
Please:
- Keep PRs focused (one feature/fix).
- Include before/after screenshots for UI changes.
- Avoid adding external heavy dependencies without clear benefit.
| Idea | Description |
|---|---|
| Recurrence support | Parse & expand RRULE for weekly repeating events |
| Per-item conflict choices | Granular keep/replace decisions in dialog |
| Timezone handling | Explicit timezone conversions for cross-region subscriptions |
| Multi-day events | Span rendering across columns (current simplified to single-day) |
| Export presets | Save & load multiple export style configurations |
| Data portability | Import/export JSON bundle for activities & templates |
- No tracking, analytics, or network calls except explicit iCal subscriptions & background image fetches.
- All computation happens locally.
- Removing background image clears IndexedDB blob cleanly.
- Chrome / Edge (latest two versions)
- Firefox (recent ESR + latest)
- Safari (15.1+; iOS tweaks implemented)
- Progressive Web App install flows (Android Chrome, iOS Safari manual Add to Home Screen)
| File | Purpose |
|---|---|
docs/export-troubleshooting.md |
Debugging broken or corrupted exports |
docs/ios-background-fix.md |
Technical breakdown of iOS image rendering fix |
MIT
Created in the heart of Kaiserstuhl π
A focused weekly planner prioritizing clarity, speed, and local ownership of your data.
Version: 1.0.0
Repository: https://github.com/meierac/wochenschau