Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

Aesthetic Computer — Apple TV (tvOS) App Plan#

0. Product Intent#

Build a tvOS Apple TV app that functions as a passive, cinematic playback surface for Aesthetic Computer artifacts—primarily pre-rendered MP4 "Tapes" generated by Oven.

Core rule:
Oven renders. Apple TV plays.

Explicit Non-Goals#

  • No WebViews / no WebKit
  • No KidLisp editor or generative rendering
  • No chat, wallets, minting, or comments
  • No dense menus or text input
  • No feature parity with the website

1. Primary User Experience#

Tape Mode (default)#

  • App launch → immediate fullscreen playback
  • Sequential playback of tapes
  • Auto-advance on end
  • Optional loop or shuffle

Siri Remote mapping

  • ▶︎ Play / Pause
  • ← Previous tape
  • → Next tape
  • ↑ Show overlay (metadata)
  • ↓ Hide overlay
  • Long-press ▶︎ (optional): Favorite / Unfavorite

Minimal Overlay (auto-hide)#

Shown only when requested.

Aesthetic Computer
Tape 014 · 3:44 · 1280×720 @ 30fps
Seed: 839201 · Generator: kidlisp-oven

2. Content Model#

Tape (canonical artifact)#

A Tape is a finished audiovisual unit.

Required

  • id
  • MP4 URL (H.264 + AAC)
  • Duration (seconds)

Recommended

  • Title
  • Creation timestamp
  • Resolution / FPS
  • Seed
  • Generator name + version
  • Tags (tape, gallery, ambient, etc.)

Tape JSON Schema (draft)#

{
  "id": "tape-014",
  "title": "Tape 014",
  "mp4": "https://aesthetic.computer/tapes/014.mp4",
  "duration": 224,
  "resolution": "1280x720",
  "fps": 30,
  "seed": 839201,
  "generator": "kidlisp-oven",
  "created_at": "2025-01-03T10:42:00Z",
  "tags": ["tape", "glitch"]
}

Feed Format#

v1

  • GET /tv/tapes.json
{ "tapes": [Tape] }

v2 (future)

  • Multiple feeds: tapes, ambient, highlights, live

3. Oven Responsibilities (Upstream)#

Rendering#

  • Deterministic, seeded runs
  • Headless Chromium / WebGL / KidLisp
  • Fixed resolution
  • Fixed framerate
  • Fixed duration

Encoding (Apple-safe, frozen)#

  • Video: H.264
  • Pixel format: yuv420p
  • Audio: AAC LC
  • Constant framerate
  • No alpha, no exotic color spaces

Outputs#

  • MP4 files
  • Optional HLS (live / long-form)
  • JSON feed index

Hosting#

  • HTTPS only
  • CDN-friendly
  • Permissive CORS for JSON + MP4
  • Long cache headers for MP4s

4. Apple TV App Responsibilities#

Must Do#

  • Fetch JSON feeds
  • Parse into models
  • Cache feed locally
  • Fullscreen playback via AVPlayer
  • Auto-advance and retry logic
  • Minimal overlays

Must Not Do#

  • No WebViews
  • No private APIs
  • No rendering or heavy computation
  • No complex UI hierarchy

5. App Modes (Phased)#

Phase 1#

  • Tape Mode only

Phase 2#

  • Gallery Mode (slower pacing)
  • Local favorites

Phase 3#

  • Ambient Mode (screensaver-grade loops)

Phase 4#

  • Live Mode (HLS + fallback to archive)

6. Architecture Overview#

Tech Stack#

  • SwiftUI (tvOS)
  • AVKit / AVPlayer
  • URLSession + Codable
  • On-disk caching (Application Support)

Module Sketch#

AppleTVApp/
├─ App/
│  ├─ AestheticTVApp.swift
│  └─ AppState.swift
├─ Models/
│  ├─ Tape.swift
│  └─ Feed.swift
├─ Services/
│  ├─ FeedService.swift
│  ├─ CacheService.swift
│  └─ ReachabilityService.swift
├─ Player/
│  ├─ PlayerCoordinator.swift
│  ├─ PlayerView.swift
│  └─ OverlayView.swift
└─ Utilities/
   └─ Logger.swift

7. Playback Logic#

  • Maintain tapes: [Tape]
  • Track currentIndex
  • On playback end:
    • Advance sequentially or shuffle
    • Wrap if loop enabled
  • On error:
    • Skip tape
    • Continue playback
  • Overlay never blocks playback

8. Physical Apple TV Build & Test Plan#

Goal#

Validate real-device playback ASAP.

Fastest MVP Test#

  1. Create tvOS SwiftUI app
  2. Hardcode one Oven MP4 URL
  3. Fullscreen AVPlayer playback
  4. Pause / resume via remote
  5. Run for 5–10 minutes

Pairing#

Apple TV:

  • Settings → Remotes and Devices → Remote App and Devices

Xcode:

  • Window → Devices and Simulators → Pair Apple TV

Signing#

  • Use Automatic Signing
  • Resolve provisioning before feed logic

Definition of Done#

  • App installs from Xcode
  • Smooth playback
  • Relaunch resumes correctly

9. Performance Constraints#

  • Prefer 720p for reliability, 1080p optional
  • H.264 baseline / main profile
  • Stable framerate
  • App runs unattended for hours

10. Security & Compliance#

  • Public HTTPS endpoints only
  • No WebKit
  • No private APIs
  • App Store–safe playback behavior

11. Phased Delivery#

Phase 1 — MVP Player#

  • Single hardcoded MP4
  • Play / pause
  • Real-device validation

Phase 2 — Feed Playback#

  • Fetch + cache JSON feed
  • Auto-advance playlist
  • Prev / next controls

Phase 3 — Experience Polish#

  • Gallery / Ambient modes
  • Better pacing + overlays

Phase 4 — Live#

  • HLS stream support
  • Archive fallback

12. Success Criteria#

  • Launch → playback in under 1 second
  • Zero dropped frames
  • Stable for long sessions
  • Feels calm, intentional, gallery-grade

Summary#

This app is a television for Aesthetic Computer, not a computer on a television.

Oven produces finished tapes.
Apple TV presents them beautifully.


Integration Notes#

Existing Infrastructure#

MongoDB tapes Collection#

The codebase already has a tapes collection with this schema:

{
  _id: ObjectId,
  code: string,          // 3-char short code (e.g., "xyz")
  slug: string,          // piece-timestamp format
  user: string | null,   // auth0 subject or null for guests
  when: Date,
  bucket: string,        // "user-aesthetic-computer" or "art-aesthetic-computer"
  at: {                  // ATProto record (if synced)
    rkey: string,
    uri: string,
    cid: string
  },
  nuked: boolean
}

Existing API Endpoints#

GET /api/tv (tv.mjs)

  • Already fetches tapes with ATProto video URLs
  • Supports ?types=tape filter
  • Returns structured feed with video URLs from ATProto PDS
  • Response includes: id, type, code, slug, owner, when, acUrl, media.videoUrl

GET /api/get-tape (get-tape.mjs)

  • Query by ?code=xyz or ?slug=...
  • Returns: slug, code, when, bucket, user, nuked

Video Hosting#

  • Primary: ATProto PDS blobs at https://at.aesthetic.computer/xrpc/com.atproto.sync.getBlob
  • Source ZIPs: DigitalOcean Spaces (art-aesthetic-computer bucket)
  • Oven Server: oven.aesthetic.computer processes ZIPs → MP4s

Create a dedicated Apple TV feed endpoint:

// system/netlify/functions/tv-tapes.mjs
// GET /api/tv/tapes - Returns tape feed for Apple TV

export async function handler(event) {
  const database = await connect();
  const tapes = await fetchTapes(database.db, { limit: 100 });
  
  // Transform to Apple TV schema
  const feed = tapes.map(t => ({
    id: t.code,
    title: `Tape ${t.code.toUpperCase()}`,
    mp4: t.media.videoUrl,
    duration: null, // Would need to store in MongoDB
    resolution: "1280x720",
    fps: 30,
    seed: null,
    generator: "kidlisp-oven",
    created_at: t.when,
    tags: ["tape"]
  }));
  
  return respond(200, { 
    tapes: feed,
    total: feed.length,
    lastUpdated: new Date().toISOString()
  });
}

Integration Recommendations#

  1. Extend tapes MongoDB schema to include:

    • duration (seconds) - from metadata.json
    • resolution - from metadata.json
    • fps - from metadata.json
    • seed - if available from piece
  2. Update Oven to store this metadata when processing

  3. Create /api/tv/tapes.json endpoint that:

    • Returns Apple TV-friendly JSON
    • Filters to only tapes with valid ATProto video blobs
    • Includes CORS headers for tvOS fetch
    • Caches response (5-10 minute TTL)
  4. Video URL Pattern:

    https://at.aesthetic.computer/xrpc/com.atproto.sync.getBlob?did={did}&cid={videoCid}
    

    These are direct H.264 MP4 URLs suitable for AVPlayer.

Data Flow#

┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│  Recording  │────▶│   Oven      │────▶│  ATProto    │
│  (ZIP)      │     │  (H.264)    │     │  (Blob)     │
└─────────────┘     └─────────────┘     └─────────────┘
                           │                   │
                           ▼                   │
                    ┌─────────────┐            │
                    │  MongoDB    │◀───────────┘
                    │  (tapes)    │
                    └─────────────┘
                           │
                           ▼
                    ┌─────────────┐
                    │/api/tv/tapes│
                    │   .json     │
                    └─────────────┘
                           │
                           ▼
                    ┌─────────────┐
                    │  Apple TV   │
                    │    App      │
                    └─────────────┘

Phase 1 MVP Implementation Path#

  1. Week 1: Create tvOS app scaffold with hardcoded test MP4 URL
  2. Week 2: Implement /api/tv/tapes.json endpoint using existing fetchTapes() logic
  3. Week 3: Connect app to endpoint, implement playlist navigation
  4. Week 4: Polish overlay UI, test on physical device