Files
jarvis/docs/KICKOFF_PROMPT.md
Robin Kutesa 27d0e22767 Initial commit: Jarvis iOS app
SwiftUI client for a self-hosted RSS news-correlation platform: signal feed,
story detail, article reader, feed manager, and LAN⇄Tailscale connectivity.
Project generated from project.yml via XcodeGen.

Includes CI build matrix (macOS 14/15 × Debug/Release), issue templates,
backlog, and API/backend handoff docs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 18:04:59 +03:00

6.1 KiB
Raw Permalink Blame History

Jarvis iOS — Claude Code Kickoff Prompt

Paste this entire prompt into Claude Code to begin.


Prompt

You are building Jarvis — a SwiftUI iOS app that connects to a self-hosted RSS news correlation platform and displays stories ranked by signal score.

Read CLAUDE.md before writing a single line of code. It contains every architecture decision already made. Do not deviate from it.


Your job

Build the remaining SwiftUI views. The networking layer, models, stores, and onboarding screen are already written. You are building the UI on top of them.

Views to build

  1. SignalFeedView — the home screen

    • Wordmark Jarvis with J in #FF5C00, rest white, weight 800, kerning -2
    • Live/Offline connection indicator (driven by WebSocketManager.shared.connectionState)
    • Sync bar: "Synced X min ago · N cached" when live, "Last synced X min ago" when offline
    • Topic filter pills: All · Finance · Tech · Politics · Africa (calls store.setTopic())
    • Column headers: Story / Signal ↓
    • List of StoryRowView sorted by signalScore descending
    • Pull to refresh calls store.loadStories(refresh: true)
    • Infinite scroll: call store.loadMore() when last row appears
    • Tap row → navigate to StoryDetailView
  2. StoryRowView — one row in the signal feed

    • Left edge stripe: 3pt wide, color opacity tied to signal score (97 = #FF5C00, fades to #1a1a1a at 0)
    • Story title, dimmed proportionally to score (97 = white, 20 = #444)
    • Signal score number, same fade behaviour
    • Source count, topic, time ago in monospaced font
    • Source chips (first 2 named, rest "+N")
    • Small green dot if story is fully cached offline
  3. StoryDetailView — full story

    • Back button "Signal feed"
    • Category label + signal score pill (e.g. "Finance · 97 signal")
    • Large headline, weight 800
    • Source chips
    • "All N articles cached · available offline" line if cached
    • Consensus block: orange left border, dark orange background
    • Conflicting block: dark red left border, dark red background (only if conflict != nil)
    • Coverage timeline: chronological list of TimelineEntry, first item has orange node
    • Tapping a timeline entry → navigate to ArticleReaderView
  4. ArticleReaderView — full article

    • Back button showing parent story headline (truncated to 30 chars)
    • Source pill in #FF5C00, timestamp in monospaced
    • Cached badge inline (green, only if article is in SwiftData)
    • Large headline weight 800
    • Hero image placeholder (AsyncImage with grey fallback)
    • Body text, #4a4a4a, size 16, line spacing 1.65
    • Divider then "More from this cluster" section
    • 23 other articles from same story as tappable rows
  5. FeedManagerView — feed health and management

    • Wordmark Jarvis header + "+ Add feed" button
    • Platform connection card: server URL, live/offline dot (from WebSocketManager)
    • Search bar to filter feed list
    • Two sections: "Healthy" and "Needs attention"
    • Each row: RSS icon, feed name, poll interval + article count, health dot
    • Health dot: green (#2a5a2a) = active, amber (#AA6600) = failing with retry countdown, red (#5a1a1a) = dead
    • Swipe to delete calls APIClient.shared.deleteFeed(id:)
    • "+ Add feed" sheet: URL input + name field + confirm button

Design rules — non-negotiable

  • Background: Color.black / #000000 everywhere
  • Accent: Color("KisaniOrange") = #FF5C00
  • Surface cards: #111111, #1A1A1A
  • All screens: .preferredColorScheme(.dark)
  • Font weight: 800 for headlines, 700 for labels, 400 for body — never use 600
  • Monospaced font for: timestamps, signal scores, server URLs, feed metadata
  • No gradients. No shadows. Flat surfaces only.
  • Minimum tap target: 44pt
  • Signal score stripe and text both fade: score 80100 = full orange, 5079 = dimmed orange, 2049 = dark brown, 019 = near invisible

Data flow rules — non-negotiable

  • Views never call APIClient directly — always go through StoryStore or a dedicated @StateObject ViewModel
  • Signal scores are server-computed — never calculate or modify them in the UI
  • WebSocket events trigger REST refetches — the store handles this already
  • SwiftData (CachedStory, CachedArticle) is the offline source — query it when the server is unreachable
  • Use @EnvironmentObject var store: StoryStore in views that need stories
  • Use @EnvironmentObject var ws: WebSocketManager for connection state

Xcode project setup

  1. Create new Xcode project: iOS App, named Jarvis, Swift, SwiftUI
  2. Set minimum deployment target: iOS 17.0 (required for SwiftData)
  3. Add all provided .swift files to the project
  4. In Assets.xcassets add a new Color Set named KisaniOrange:
    • Any / Dark: #FF5C00
  5. Add Assets.xcassets Color Set AppBackground: #000000
  6. The SwiftData model container is already configured in JarvisApp.swift

File structure to produce

Jarvis/
  Views/
    Home/
      SignalFeedView.swift
      StoryRowView.swift
    Story/
      StoryDetailView.swift
    Reader/
      ArticleReaderView.swift
    Feeds/
      FeedManagerView.swift
      AddFeedSheet.swift
    Shared/
      SignalStripe.swift       ← reusable 3pt stripe component
      SourceChips.swift        ← reusable chips row
      CachedBadge.swift        ← reusable green cached indicator
      ConnectionBanner.swift   ← offline warning banner

Start here

  1. Read CLAUDE.md
  2. Create the Xcode project and add all existing files
  3. Build SignalStripe.swift, SourceChips.swift, CachedBadge.swift — shared components used by multiple views
  4. Build StoryRowView.swift
  5. Build SignalFeedView.swift
  6. Build StoryDetailView.swift
  7. Build ArticleReaderView.swift
  8. Build FeedManagerView.swift + AddFeedSheet.swift
  9. Run on simulator, fix layout issues, verify dark mode renders correctly
  10. Confirm WebSocket connection state drives the live/offline indicator on the home screen

Do not skip steps. Do not simplify the signal stripe fade logic. Do not use placeholder colours — every hex value is specified above.