Files
web-app-launcher/plans/phase-4-7-full-expansion/phase-6-functional-frontend.md
T
alexei.dolgolyov 1c0a7cb850 feat: Phases 4-7 — Full Feature Expansion (26 features)
Phase 4 — New Widget Types:
- Clock/Weather, System Stats, RSS/Feed, Calendar, Markdown,
  Metric/Counter, Link Group, Camera/Stream widgets
- Backend services with caching for each data source
- Full creation form with dynamic config fields per type

Phase 5 — Visual & Styling Enhancements:
- Glassmorphism card style (solid/glass/outline)
- Board-level themes with per-board hue/saturation
- Animated SVG status rings replacing static dots
- Card size options (compact/medium/large)
- Custom CSS injection (admin + per-board, sanitized)
- Wallpaper backgrounds with blur/overlay/parallax

Phase 6 — Functional Features:
- Favorites bar with drag-and-drop reordering
- Recent apps tracking with privacy toggle
- Uptime dashboard page (/status, guest-accessible)
- Notifications system (Discord/Slack/Telegram/HTTP webhooks)
- App tags with filtering in board view
- Multi-URL app cards with expandable sub-links
- Personal API tokens with scoped permissions
- Audit log with retention and admin viewer

Phase 7 — Quality of Life:
- Onboarding wizard (5-step first-launch setup)
- App URL health preview with favicon/title detection
- Board templates (4 built-in + custom import/export)
- Keyboard shortcut overlay (j/k nav, 1-9 boards, ? help)

212 files changed, 15641 insertions, 980 deletions.
Build, lint, type check, and 222 tests all pass.
2026-03-25 14:18:10 +03:00

13 KiB

Phase 6: Functional Features — Frontend

Status: Complete Parent plan: PLAN.md Domain: frontend

Objective

Build all frontend UI for the 8 functional features: favorites bar, recent apps, uptime dashboard page, notifications, tag management + filtering, multi-URL app cards, API token management, and audit log viewer.

Tasks

6.1 Favorites Bar

  • Create src/lib/components/layout/FavoritesBar.svelte
    • Horizontal bar at top of board view, below header
    • Shows favorite app icons in compact format (icon + name)
    • Drag-and-drop reordering within the bar (svelte-dnd-action)
    • Click opens app URL; right-click or long-press to remove
    • Add-to-favorites button on app widget context menu
  • Create src/lib/stores/favorites.svelte.ts
    • Fetch favorites from /api/favorites on init
    • Methods: add, remove, reorder (optimistic updates with API sync)
  • Integrate FavoritesBar into board layout (show when user has favorites)

6.2 Recent Apps Section

  • Create src/lib/components/board/RecentAppsSection.svelte
    • Auto-generated section at top of default board
    • Shows last 10 unique apps the user clicked
    • Compact app cards (icon + name + last used time)
    • "Clear history" button
    • Respects user's trackRecentApps preference
  • Update app click handling to record clicks via /api/recent-apps POST
  • Add privacy toggle in user settings (trackRecentApps)

6.3 Uptime Dashboard Page

  • Create src/routes/status/+page.svelte — public status page
  • Create src/routes/status/+page.server.ts — load uptime data (guest-accessible)
    • Time range selector: 24h / 7d / 30d
    • Per-app: name, current status, uptime percentage, avg response time
    • Sparkline chart (larger than widget version) with hover tooltips
    • Incident timeline: colored blocks showing up/down periods
    • Summary header: total apps, apps online, overall uptime %
  • Add "Status Page" link to sidebar navigation

6.4 Notifications UI

  • Create src/lib/components/notifications/NotificationBell.svelte
    • Bell icon in header with unread count badge
    • Click opens notification dropdown/panel
    • List of recent notifications with read/unread state
    • "Mark all as read" button
    • Link to full notification history
  • Create src/lib/components/notifications/NotificationHistory.svelte
    • Full page or modal with paginated notification list
    • Filter by app, event type
    • Timestamp, app name, event description
  • Create src/lib/components/notifications/NotificationChannelForm.svelte
    • Form to add/edit notification channels
    • Dynamic fields based on channel type (Discord: webhook URL, Slack: webhook URL, Telegram: bot token + chat ID, HTTP: URL + method)
    • "Send Test" button
    • Enable/disable toggle per channel
  • Create src/routes/settings/notifications/+page.svelte — notification preferences page
  • Create src/lib/stores/notifications.svelte.ts
    • Track unread count, poll for new notifications

6.5 Tag Management & Filtering

  • Create src/lib/components/admin/TagManager.svelte
    • Admin page to CRUD tags (name + color picker)
    • Table/grid of existing tags with edit/delete
  • Create src/lib/components/app/TagBadge.svelte
    • Small colored badge showing tag name
    • Used in app cards (large card size) and app edit forms
  • Create src/lib/components/board/TagFilter.svelte
    • Filter bar within board view
    • Toggle buttons for each tag (active/inactive)
    • When active, only show apps with selected tags
    • "Clear filters" button
  • Add tag assignment to app edit form (multi-select from existing tags)
  • Add tag management page to admin panel navigation

6.6 Multi-URL App Cards

  • Update src/lib/components/widget/AppWidget.svelte
    • If app has secondary links, show expand indicator
    • On hover/click expand to reveal sub-links list
    • Each sub-link: icon + label, click opens in new tab
    • Primary URL is the main card click target
    • Smooth expand/collapse animation (slide transition)
  • Create src/lib/components/app/AppLinksEditor.svelte
    • Used in app edit form
    • Add/remove/reorder secondary links
    • Each link: label input + URL input + optional icon picker
    • Drag-and-drop reorder

6.7 API Token Management

  • Create src/routes/settings/api-tokens/+page.svelte
  • Create src/routes/settings/api-tokens/+page.server.ts
  • Create src/lib/components/settings/ApiTokenList.svelte
    • Table of user's API tokens: name, scope, created, last used, expires
    • Revoke button per token
  • Create src/lib/components/settings/ApiTokenCreateForm.svelte
    • Form: name, scope (read/write/admin dropdown), expiry (optional date picker)
    • On submit: show generated token ONCE (copyable, warning: won't be shown again)
  • Add "API Tokens" link to user settings navigation

6.8 Audit Log Viewer

  • Create src/routes/admin/audit-log/+page.svelte
  • Create src/routes/admin/audit-log/+page.server.ts
  • Create src/lib/components/admin/AuditLogTable.svelte
    • Paginated table: timestamp, user, action, entity, details
    • Filters: action type dropdown, entity type dropdown, user select, date range
    • Details column: expandable JSON view for action details
    • Export to CSV button
  • Add "Audit Log" link to admin panel navigation

Files to Modify/Create

  • src/lib/components/layout/FavoritesBar.svelte — new
  • src/lib/stores/favorites.svelte.ts — new
  • src/lib/components/board/RecentAppsSection.svelte — new
  • src/routes/status/+page.svelte — new
  • src/routes/status/+page.server.ts — new
  • src/lib/components/notifications/NotificationBell.svelte — new
  • src/lib/components/notifications/NotificationHistory.svelte — new
  • src/lib/components/notifications/NotificationChannelForm.svelte — new
  • src/routes/settings/notifications/+page.svelte — new
  • src/lib/stores/notifications.svelte.ts — new
  • src/lib/components/admin/TagManager.svelte — new
  • src/lib/components/app/TagBadge.svelte — new
  • src/lib/components/board/TagFilter.svelte — new
  • src/lib/components/widget/AppWidget.svelte — modify
  • src/lib/components/app/AppLinksEditor.svelte — new
  • src/routes/settings/api-tokens/+page.svelte — new
  • src/routes/settings/api-tokens/+page.server.ts — new
  • src/lib/components/settings/ApiTokenList.svelte — new
  • src/lib/components/settings/ApiTokenCreateForm.svelte — new
  • src/routes/admin/audit-log/+page.svelte — new
  • src/routes/admin/audit-log/+page.server.ts — new
  • src/lib/components/admin/AuditLogTable.svelte — new
  • Various existing layout/navigation components — modify

Acceptance Criteria

  • Favorites bar persists across board navigation, syncs with backend
  • Recent apps section shows only when user has click history and tracking enabled
  • Uptime dashboard is guest-accessible and shows meaningful uptime data
  • Notification bell shows unread count, dropdown works correctly
  • Tags are assignable to apps and filterable in board view
  • Multi-URL app cards expand/collapse smoothly
  • API token is shown only once on creation, copyable
  • Audit log shows paginated, filterable history for admin
  • All UIs are responsive and work in dark/light mode

Notes

  • Follow existing component patterns (Svelte 5 runes, Tailwind, Bits UI primitives)
  • Favorites bar uses svelte-dnd-action like existing widget reordering
  • Notification polling: check every 60s for new notifications (simple setInterval)
  • Status page is a new top-level route, not nested under boards
  • API token display: show once in a modal with copy button, then redirect to token list

Review Checklist

  • All tasks completed
  • Code follows project conventions
  • No unintended side effects
  • Build passes (Big Bang: code quality check only)
  • Tests pass (Big Bang: skipped for intermediate phase)

Handoff to Next Phase

What was done

  • 6.1 Favorites Bar: Created FavoritesBar.svelte with drag-and-drop reordering (svelte-dnd-action), compact icon+name display, remove button, and right-click remove. Created favorites.svelte.ts store with load/add/remove/reorder methods and optimistic updates. Integrated favorites loading in root +layout.svelte. Added context menu to AppWidget with "Add to favorites" / "Remove from favorites" toggle.
  • 6.2 Recent Apps: Created RecentAppsSection.svelte showing last 10 clicked apps with time-ago formatting, collapsible section, and clear history button. Respects trackRecentApps preference. Updated AppWidget to record clicks via POST /api/recent-apps on every app link click.
  • 6.3 Uptime Dashboard: Created /status route with +page.server.ts (loads uptime data, guest-accessible) and +page.svelte with summary cards (total/online/uptime%), time range selector (24h/7d/30d), per-app status rows with sparklines, and incidents section. Added "Status" link to sidebar navigation.
  • 6.4 Notifications UI: Created NotificationBell.svelte (bell icon in header with unread badge, dropdown with notification list, mark all as read). Created NotificationHistory.svelte (paginated table with event type filter). Created NotificationChannelForm.svelte (dynamic form for Discord/Slack/Telegram/HTTP with send test button). Created /settings/notifications page with channels tab and history tab. Created notifications.svelte.ts store with 60s polling. Added bell to Header for authenticated users.
  • 6.5 Tag Management & Filtering: Created TagManager.svelte (admin CRUD with color picker, inline edit, delete confirmation). Created TagBadge.svelte (colored badge with optional remove button). Created TagFilter.svelte (toggle buttons for each tag, clear filters). Added tags display to AppWidget large card size. Added /admin/tags page and nav link.
  • 6.6 Multi-URL App Cards: Updated AppWidget.svelte to show expandable sub-links with slide transition for all card sizes (compact/medium/large). Links section shows expand/collapse chevron with count. Created AppLinksEditor.svelte with drag-and-drop reorder, add/remove links, and save to API.
  • 6.7 API Token Management: Created /settings/api-tokens route with +page.server.ts (list tokens, create with form action, revoke with form action). Created ApiTokenList.svelte (table with scope badges, expiry status, revoke with confirmation). Created ApiTokenCreateForm.svelte (name, scope dropdown, optional expiry). Token shown once after creation with copy button and warning. Added API Tokens link to user menu and settings page.
  • 6.8 Audit Log Viewer: Created /admin/audit-log route with +page.server.ts (paginated, filtered query). Created AuditLogTable.svelte (filterable table with action/entity/date filters, expandable JSON details, CSV export, pagination). Added "Audit Log" link to admin navigation.

What the next phase needs to know

  • FavoritesBar is a standalone component but not yet integrated into the board view page -- the root layout loads favorites, and the component can be placed in Board.svelte or the board page.
  • RecentAppsSection is a standalone component that needs to be placed in the board view page (e.g., above the sections in Board.svelte).
  • The NotificationBell is now in the Header and polls every 60 seconds when authenticated.
  • TagFilter component takes activeTags and onFilterChange props but the filtering logic (hiding apps without selected tags) needs to be wired into the Board or Section component.
  • AppWidget now depends on favorites store (imported at module level) -- this is safe since the store is a singleton.
  • The trackRecentApps user preference is available via the User model but is not yet exposed in a settings toggle UI -- it defaults to true.
  • API token page uses SvelteKit form actions (?/create and ?/revoke) with use:enhance.
  • The admin layout now has 5 nav items: Users, Groups, Tags, Audit Log, Settings.
  • Status page is guest-accessible (no auth required in the server loader).

Potential concerns

  • The favorites store is loaded eagerly in +layout.svelte for all authenticated users. If the user has no favorites, this is a wasted API call (returns empty array). Consider lazy loading.
  • The context menu for AppWidget favorites uses position: fixed with client coordinates, which may not position correctly when the page is scrolled. A more robust solution would use a popover library.
  • AppWidget now wraps medium/large cards in a <div> instead of a single <a> tag (to support the expandable links section below the link). This changes the click behavior slightly -- the primary URL is still the main <a>, but the outer container is not a link anymore.
  • NotificationBell polling could accumulate if multiple instances are mounted (unlikely with current layout, but worth noting).
  • The AuditLogTable CSV export only exports the currently loaded page of results, not all results.