Switch panel background to --paper, all dividers to --line, section
labels to --ink-3, active view/days/slot buttons to --accent/--ink.
Soften panel shadow to 4% opacity. No logic, structure, or API changes.
v1.105.2
Trim desktop header height (py-2 → py-1.5) and switch border to --line
token. Update .weekly-header CSS class to use --line. Add baseline
letter-spacing: -0.005em to body. No logic, structure, or API changes.
v1.105.1
Add --ink-*, --accent, --line, --bg, --paper, --tasks-bg, calendar-source
event palette, and all-day chip palette as CSS custom properties. Tokens
alias existing --weekly-* vars where a match exists so no existing styles
are affected. Also adds docs/design/ to .gitignore.
v1.105.0
Give the bottom-of-list "Add task..." input a framed background (white
with a subtle border in light mode, slate-800 with a darker border in
night mode) plus a small radius and padding, so it visually matches user
expectations of an input. The inline slot-editor that appears when you
click on an empty slot keeps the transparent look so it blends with the
surrounding task rows.
v1.104.1
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Pull-sync now runs on visibilitychange + window focus (in addition to mount
and the slow 15-min safety-net interval), throttled to one call per 5s. The
moment the user returns to the tab the app reconciles, so an Outlook-side
checkbox/star/title change shows up within a second of refocusing the tab
instead of after a 15-minute wait.
To keep this cheap, the Microsoft Graph delta endpoint
(/me/todo/lists/{id}/tasks/delta) is used when we have a stored deltaToken
for a synced list — typically a few hundred bytes per call when nothing
changed. Tokens are persisted on SomedayList.syncDeltaToken (new column,
migration applied) and refreshed each call. On 410 Gone (token expired
>30 days) we fall back to a full fetch and prime a new chain. Delta also
brings remote deletions (@removed) so they propagate locally without
needing a full list scan.
v1.104.0
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The previous timestamp gate (`if (remoteUpdated <= localUpdated) continue`)
hid genuine remote-side changes because every prior no-op pull bumped
lastSyncedAt to "now", making it newer than the Outlook lastModifiedDateTime
of a subsequent star toggle. Now the pull does a per-field comparison and
only writes lastSyncedAt when at least one field actually changed. Same fix
applied to the Google Tasks pull branch for consistency.
Also run a pull-sync once on mount instead of waiting up to 15 min, so
remote-side changes show up immediately on next page load.
v1.103.2
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- deleteCachedEvent now removes every cached row that belongs to the same
recurring series (master id + all "<masterId>::*" instances + rows whose
recurringEventId matches the master), so deleting "all occurrences" no
longer leaves orphan rows that resurface on the next read.
- getPriorityBadge: surface the yellow star whenever a task is marked
important (e.g. a starred Outlook To-Do task pulled in via sync), even
when the active priority style is Eisenhower / ABCDE / Ivy Lee.
v1.103.1
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Outlook recurring delete: also delete the specific instance after the master
to clean up orphaned first occurrences.
- CachedCalendarEvent gains busyStatus column (migration applied) so showAs
changes from Outlook flow back into the weekly view.
- Outlook create/update now round-trip the full event (busyStatus, visibility,
attendees, reminders, recurrence link) via a shared response mapper.
- MS To-Do importance ('high' star) ⇄ local importance flag in pull-sync,
push-sync, initial import, and local-task POST/PATCH; dueDateTime ⇄
scheduledDate added to pull-sync.
- Local task PATCH now fires a best-effort push to Outlook/Google/Synology so
any field change keeps both sides aligned.
- AnyDay list delete dialog now offers Cancel / hide locally / delete on both
sides; new deleteMsTodoList + deleteGoogleTaskList helpers.
v1.103.0
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add Show/Hide Priority Icons toggle in left settings panel under Project Icons
- Projects sidebar: move Add Project form to the top, add per-project
filter button (filters tasks across all views), expand/collapse to show
tasks underneath each project name, active-filter banner with clear
- Intro hints on first load: briefly reveal hidden header controls then
fade out, and bounce-scroll the main grid to reveal off-screen tasks
v1.102.0
- Bring back the dropdown UX for the language picker (the v1.99 button
grid was nicer at first but lost the at-a-glance affordance the user
preferred). New SearchableDropdown component renders a real dropdown
trigger + list, with each option carrying its inline-SVG flag.
- Timezone picker is now searchable. Match against IANA name, code
(CET, ET…), city/country label, and offset in multiple notations
("UTC+1", "+01:00", "GMT+01:00"). Used both for the user's primary
timezone and the additional-timezones add picker.
v1.101.1
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Wave-3 user feedback (points 1–3):
- Email templates: extract de/en/fr/es/it copy into emailTemplates.ts
and pick the user's language. Signup forwards navigator.language and
the API also respects Accept-Language; resend/reset reuse user.language.
- Verify link: the email button now points at the client page instead of
the API GET handler, so corporate inbox scanners (M365 Safe Links etc.)
can no longer pre-fetch and silently consume the one-shot token. The
client page requires a real click before calling PATCH /api/auth/
verify-email. The legacy GET handler now just redirects to the client
page so old in-flight emails keep working.
- Code expired UX: when users land via an expired-link redirect we no
longer leave them with a blank email field — the page exposes an email
input so the resend button has something to act on. The verify-email
redirect also forwards the email param.
Misc: tsconfig migrated to moduleResolution=bundler and dropped
downlevelIteration to clear the TS 7.0 deprecation errors.
v1.101.0
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Wave-2 user feedback (points 4–6):
- Language picker: replace emoji flags (which don't render reliably on
Windows) with inline-SVG flag components for GB/DE/FR/ES/IT. Used
in both the Settings localisation tab and the onboarding wizard.
- Timezone: replace the read-only Intl.DateTimeFormat display with a
real <select> over a curated list of major IANA zones. Each option
shows "(UTC±hh:mm) CODE — Region" and the list is sorted by current
offset, then code, then IANA name.
- Multi-timezone: new ExtraTimezonesEditor in the localisation tab lets
users pin additional zones (stored in user.viewSettings.extraTimezones
to avoid a migration). The time-grid axis now renders the equivalent
hour for each pinned zone next to the local label, helpful for
scheduling across regions.
v1.100.0
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
GridTaskBlock received showPriorityIcons + priorityStyle props but
never rendered the badge. Export getPriorityBadge from WeeklyView and
inject it before the project icon in the grid task title. Tasks
prioritised in the Eisenhower/ABCDE/Ivy Lee/Pareto picker now show
their indicator in the time-grid layout too.
v1.99.2
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- color now renders as a tinted background (alpha 0x1f) plus a 4px
accent border, matching the user's "background colorcoded" request.
- Migration 20260501 was unapplied locally; mark prior failed
20260403_add_task_url as applied and deploy 20260501. Without it
the API silently dropped color/icon and the SSE refetch wiped the
optimistic update, so visuals never appeared.
v1.99.1
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Wave-1 user feedback (points 7–10):
- Settings: new Projects tab with full CRUD (name, color, icon picker)
- Priority Icons render in simple/calendar/list views with style-specific
visuals (Eisenhower icons, ABCDE letters, Ivy Lee 1–6, Pareto star).
Toggle + style selector in Settings; Ivy Lee ranks now persist to
task.priority so cross-view badges stay consistent.
- Someday Lists gain optional icon (left of title) and color (left
border tint), edited via a pencil-popup with IconPicker + color picker.
- Tabs gain optional icon and color, stored in user.viewSettings JSON
and edited via the same popup pattern.
Schema: SomedayList.color/icon, User.showPriorityIcons/priorityStyle.
v1.99.0
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- tsconfig: remove deprecated downlevelIteration (es2017 has native iterators),
change moduleResolution from node to bundler
- auth: set allowDangerousEmailAccountLinking=false on all OAuth providers,
restrict debug mode to development only
- prisma: replace new PrismaClient() with singleton import in 10 API routes
to prevent connection pool exhaustion
- goal API: validate user-supplied quote URLs to block SSRF (private IPs,
non-http(s) schemes)
- email: guard DEV verification/reset link console.logs behind NODE_ENV check
v1.98.0
Add persistent inline rolling indicator to GridTaskBlock so rolling tasks
are visually marked in simple and calendar (time-grid) views, matching
the badge already shown in list view.
v1.97.4
Apple Calendar encodes calendar icons as =h=g / =i=g escape sequences in
iCalendar SUMMARY fields during CalDAV sync. Helvetica cannot render the
underlying glyphs, causing the raw escape bytes to appear verbatim in the
PDF. Add pdfTitle() helper that strips these patterns along with emoji
and Apple private-use area characters before rendering any title text.
The calendar color chip/dot already provides the visual calendar identity.
v1.97.3
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add page header per PDF page: KW + date range (headline font/accent
color) + motivational quote (right-aligned italic, from local quotes)
- Move all-day strip above weekday/date header to match webapp layout
- Increase font sizes across the board (task titles 7.5pt, time labels
7.5pt, day date 8pt) to better match the web view
- Remove time prefix from task rows (hour-row label already provides
context); completed tasks get strikethrough styling
- Calendar event chips in all-day strip now use solid calendar color +
white text + small dot indicator (replaces 📅 emoji, which Helvetica
cannot render in PDFs)
- Fix multi-day all-day events: expand CachedCalendarEvents across every
day they span (iCal endDate is exclusive); deduplicate by title to
prevent double-rendering when the same event exists in both Task and
CachedCalendarEvent tables
- Someday page is now landscape (matches main week pages)
- Print modal: fetch available someday tabs on open; show pill-checkbox
filter below "Aufgaben ohne Uhrzeit" toggle when multiple tabs exist;
selected tabs are passed to the export route as noTimeTabs param
- New API endpoint GET /api/user/someday-tabs for fetching tab list
- Export route filters someday lists by noTimeTabs when provided
v1.97.2
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Layout — switched from absolute-positioned calendar grid to agenda/list:
- Each day column divided into equal-height hour rows (flex: 1)
- Tasks listed as text rows within their hour slot (time + title inline)
- No absolute positioning, no background stripes, no floating blocks
- External calendar events: light tinted row with left border + bold title
- User tasks with project: left border in project color
- User tasks without project: plain text, no border
- Time column updated to flex rows, stays aligned with day column rows
Weather — switched to hourly API data (temperature_2m + weather_code):
- Small colored circle + temperature shown in top-right of each hour row
- Color encodes condition: amber=clear, gray=cloudy, blue=rain,
pale-blue=snow, purple=thunderstorm
- Removed WMO text dictionaries (no more written-out condition text)
v1.96.3
- Fix weather toggle disabled when lat/lon set but weatherEnabled=false:
now enabled whenever a weather location is configured
- Default task duration: no-endTime tasks default to 30min (not 60min)
- Tasks without a project: remove left border entirely — only project-
assigned tasks show a colored left border; this matches the user's
explicit request that only calendar events have background/indicators
- Header order: show date first (top), then weekday name below — matches
webapp "above" date layout setting
- Lighten grid lines (#ececec) and stripes (#fafafa/#f0f7ff) to reduce
the heavy calendar-grid appearance; remove half-hour separator lines
- Lighten outer grid border and time-column border/bg to match
v1.96.1
- Query CachedCalendarEvent table for all-day and timed external calendar
events (Google/MS/Apple), so GANZ-TAG strip now shows actual events
- Regular user tasks: remove white background — transparent with left
border only, matching the webapp's simple view style
- All-day strip: calendar events show light tinted chip, user tasks show
left-border text only (no fill background)
- Add 'Im Browser drucken / Print in Browser' button to the print modal
(opens PDF inline in new tab so browser print dialog can be triggered)
- Fix Content-Disposition to 'inline' when ?inline=1 param is passed
- Update modal preview to show left-border task style (not solid blocks)
v1.96.0
saveSetting() for DEVICE_SETTINGS_KEYS (viewDays, cellDuration, startHour,
endHour, fontSize, showSubHourSlots) was saving to the cookie but returning
early before calling setProfile — so profile.fontSize never changed and the
CSS class font-size-s/m/l was never applied. Adding setProfile() to the
device-settings path fixes all of these keys at once while still keeping
the setting out of the DB.
v1.95.6
Per webapp behavior: regular user tasks render as white background with a
thin colored left border (clean/minimal); external calendar events
(externalProvider != null) get a light tinted background box. Completed
tasks use a subtle gray style. The all-day strip keeps solid bars for all
entries (matching the webapp's ALL DAY section).
v1.95.5
- Fix all-day events: remove externalProvider distinction — ALL tasks with
scheduledDate but no startTime belong in the GANZ-TAG strip regardless of
source; was incorrectly routing them to a separate noTime strip that didn't
show external-provider=null events
- Remove noTime calendar strip: it was a wrong concept; tasks outside the
time window are simply not shown; someday page handles unscheduled tasks
- Solid task blocks: revert from light+border back to solid fill (matching
the webapp); use contrastColor() helper to pick white or dark text
automatically based on background luminance
- All-day strip also uses solid blocks (same style as webapp's ALL DAY bars)
- Someday page: group lists by their tab with a tab header row; query now
sorts by [tab, order]; lists without a tab get a General/Allgemein header
- Show up to 5 all-day tasks per column (was 4)
v1.95.4
- Always use full weekday names (MONTAG, DIENSTAG…) at all column counts;
adaptive font size 8.5pt–16pt based on number of columns
- Fix Oswald detection: Font.getRegisteredFontFamilies() doesn't exist in
react-pdf — now use module-level _oswaldRegistered flag set on successful
Font.register() call, so Oswald actually gets applied
- Fix headline fallback: Helvetica-Bold (not plain Helvetica) when no Oswald
- Increase strip heights: ALL_DAY_H 38→40, NO_TIME_H 28→52, DAY_HDR_H 40→44
- Show 4 tasks in both all-day and anyday strips (was 2/3)
- Add someday page: last page (portrait) with all SomedayList tasks grouped
by list, shown when showNoTime is enabled
v1.95.3
- Separate all-day (external calendar events) from anyday (user tasks
without time) using externalProvider field; each gets its own strip
- Increase ALL_DAY_H from 22→38px and add NO_TIME_H=28px so both rows
are actually visible
- Task blocks switch from solid fill to light-tinted background + colored
left border (Google Calendar style) — much easier to read in print
- Use user's taskColor setting as fallback instead of hardcoded indigo
- Show up to 3 items in all-day strip, 2 in anyday strip with overflow count
- GRID_H now accounts for both optional strips in height calculation
v1.95.2
The PDF was showing all day headers in the same weekdayColor. The webapp
uses three separate color settings: weekdayColor (Mon–Fri), weekendColorSat,
and weekendColorSun. Fetch both weekend colors from DB and apply via
dayColor() helper based on d.getDay().
v1.95.1
Adds a print/export modal (WeekPrintModal) accessible via a Printer icon
in the header toolbar. Users can configure date range, time window (startHour–endHour),
number of days, and toggle all-day, no-time, and weather sections. A live
CSS-grid preview updates as settings change. The PDF is generated server-side
via @react-pdf/renderer on the /api/user/export-week-view route:
- Landscape A4 with absolute-positioned time-spanning task blocks
- Day headers use the user's weekdayColor/dateColor/headlineFontWeight from DB
- Oswald font loaded dynamically from Google Fonts (falls back to Helvetica-Bold)
- Timezone-aware task grouping (±1 day query buffer + local date key)
- Optional weather line (Open-Meteo) and all-day strip
- Footer with date range, username, and page numbers
v1.95.0
viewStyle, showTimeGrid, and startDayOffset now also write to a device
cookie so each device remembers its own view independently. Cookie
wins over DB on load, giving phone/desktop their own default view
without losing the cross-device DB fallback.
- DEVICE_ALSO_COOKIE_KEYS: viewStyle, showTimeGrid, startDayOffset
- saveSetting writes cookie for these in addition to DB
- viewStyle and showTimeGrid lazy-init from cookie on first render
- Both fetchProfile and fetchUserInfo apply cookie overrides last
v1.94.1
The sidebar eye-toggles (Someday, All-day, Checkboxes, Project Icons,
Weather) and the sub-hour slots toggle now save to a device-local
cookie instead of the DB, so phone and desktop can have independent
display preferences.
- DEVICE_SETTINGS_KEYS extended with showSubHourSlots
- New DEVICE_VIEW_SETTINGS_KEYS for per-view sidebar toggles
(showSomeday, showAllDayEvents, showTaskCheckboxes, showProjectIcons, weatherEnabled)
- saveViewSetting writes cookie-only for device keys; DB untouched
- getEffective checks device cookie before DB per-view overrides
- Cookie restores applied after DB load in both fetchProfile and
fetchUserInfo so device preference always wins
v1.94.0
Font size (S/M/L) is now stored in the browser cookie
'setting_fontSize' alongside the other per-device settings
(viewDays, cellDuration, startHour, endHour).
This means mobile and desktop can each keep their own preferred font
size — changing it on your phone no longer overwrites the setting on
your desktop monitor and vice versa.
The cookie is read immediately at component init (before the DB load),
so there is no flash of the wrong size on page load. The DB value is
still written so that the setting has a reasonable default on new
devices before a local preference is set.
v1.93.1
Added @react-pdf/renderer for server-side PDF generation.
PDF report (/api/user/export-pdf):
- Indigo cover band: title, user name, period, export date
- Summary cards: total tasks / calendar weeks / projects
- Per-week sections with indigo header bar showing week label + count
- Goal of the week banner (blue left-border callout) when set
- Task table: priority-color dot, title, then selected columns
- Alternating row shading, column headers in grey
- Page numbers in footer
- A4, respects same field selection as CSV
CSV report updated:
- Added 'Goal of the week' as a section marker row (italic prefix)
- weekGoal field is default-on alongside week grouping
Both exports:
- New 'weekGoal' field in EXPORT_FIELDS (default on): shows the weekly
goal text only when the user has customised it (skips default placeholder)
- Language-aware (de/en) labels and date formats
Settings UI:
- Two download buttons: CSV (plain) + PDF (indigo, prominent)
- weekGoal checkbox in field picker grid
v1.93.0
Users can now choose exactly which columns appear in the CSV:
- Title (always included)
- Calendar week grouping header
- Completed date, Scheduled date, Created date
- Project, List
- Priority (Eisenhower label or ABCDE grade)
- Link / URL
- Notes, Description
- Delegated to, Delegation note
- Start time, Kanban stage
UI additions in Settings > Data Export:
- 2-column checkbox grid with Select All / Default reset buttons
- Quick date presets: This week / This month / Last month / This year
- Download button shows the active column count
Default-on fields: week, completed date, scheduled date,
project, list, priority. All others opt-in.
API: fields passed as comma-separated ?fields= param; falls back to
defaults when omitted. Column headers are language-aware (de/en).
v1.92.0
Priority View: filter panel (project / list / timespan) is now always
visible in the right column of every priority mode — Eisenhower,
ABCDE, Ivy Lee, and 80/20. Removed the collapse toggle. An 'active'
indicator in the header shows when any filter is set. On mobile the
filter appears above the main content.
Work Report CSV (Settings > Data Export):
- Columns: Week / Completed / Scheduled / Created / Task / Project /
List / Priority / Delegated to / Notes
- Rows grouped by calendar week (ISO week, most recent first), with a
section header row showing "KW 14 — 2026 (30 Mär – 05 Apr)"
- Priority shows Eisenhower label (Sofort erledigen / Planen /
Delegieren / Eliminieren) or ABCDE grade
- Includes project name, Someday list name, delegation info and notes
- UTF-8 BOM prepended so Excel opens German umlauts correctly
- Language-aware column headers (de/en) via ?lang= param
- Filename: arbeitsbericht_YYYY-MM-DD_bis_YYYY-MM-DD_date.csv
v1.91.0
All four priority modes (Eisenhower, ABCDE, Ivy Lee, Pareto) now use a
two-column layout on desktop: main content on the left, secondary panel
(unassigned tasks / pool / remaining) on the right. On mobile (<768px)
the layout stacks vertically automatically.
Eisenhower: filters are now always visible in the right panel instead
of behind a toggle button, making project/list/timespan selection more
accessible. The filter button is hidden for Eisenhower mode.
ABCDE: added full German translations for grade labels and descriptions
(A–E now show "Kritisch", "Sollte erledigt werden", etc. in German).
Ungraded tasks appear in the right column instead of below the buckets.
Pareto: remaining tasks (80%) are always visible in the right column,
no longer behind a show/hide toggle.
v1.90.0
Disconnecting a synced list (Google/Outlook/Synology) now uses a
soft-disconnect: tasks are soft-deleted and the external link is
cleared, but the SomedayList record is kept with its tab assignment
intact. When the user reconnects, the import route finds the list by
title, re-links the external provider, and restores tasks (clearing
deletedAt). Tabs survive the full disconnect/reconnect cycle without
the user needing to drag lists back to tabs.
Also clears deletedAt on task re-import so previously disconnected
tasks become visible again on reconnect.
v1.89.0
A small icon appears before each task title whenever priority has been set
in the Priority View. Works in simple, calendar, list, someday, and kanban.
Icon + color mapping
⚡ Zap red #ef4444 Sofort erledigen (urgent + important / ABCDE A)
🕐 CalendarClock blue #3b82f6 Planen (important, not urgent / B)
↗ CornerUpRight orange #f97316 Delegieren (urgent, not important / D)
📦 Archive gray #9ca3af Eliminieren (neither / E)
🕐 Clock yellow #eab308 ABCDE C only
Delegation badge
🤖 Bot purple task.delegatedTo === "AI"
👤 User purple task.delegatedTo = person name
Hover tooltip shows the full label (e.g. "Sofort erledigen", "Planen").
Icons are 11–12 px so they sit inline without disrupting the task row.
v1.88.2
- Priority view is "what to do next" — completed tasks have no place there.
Always filter them out; removed the "show completed" toggle button.
- Optimistic local hide: when you check a task off inside priority view it
disappears immediately (no waiting for API round-trip + parent re-render).
A `locallyDone` Set tracks tasks marked complete in the current session.
v1.88.1
Resize handle:
- Drag the divider between priority panel and calendar to resize it
- Height persists in cookie (priorityViewHeight)
Dense task cards:
- Single-row compact layout: [✓] date · title · action icons
- Date shown before the title
- Action icon bar: rename (✏), note (📝), link (🔗), project (📁), delegate (👤), remove (×)
- Inline title editing: double-click or click ✏ icon
- Inline note textarea: toggles on 📝 click, saves on blur
- Inline URL input with open-link button: toggles on 🔗 click
- Inline project selector: toggles on 📁 click
- Icons colored when field has a value (note, url, project, delegate)
- Export/import now round-trips url, kanbanStage, recurrenceDays fields
v1.88.0
- Export now includes kanbanStage, url, urgency, importance, priority,
delegatedTo, delegationNote, recurrenceDays so backups are complete
- Import now handles those same fields (round-trip fidelity)
- Error handler returns the actual error message instead of the generic
"Import failed. Please check the file format." — makes failures diagnosable
- Guard against empty task title with fallback '(untitled)'
v1.87.2