Public
Mockup: Val Town-native mobile AI chat (fake AI, PWA feel)
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.

πŸ“± townie-mobile

A UI mockup of a Val Town-native mobile AI chat β€” what a first-party "Townie in your pocket" app could feel like. Not wired to a real model: responses are canned, Val Town-flavored, and streamed token-by-token to feel alive.

Live: open the val's HTTP endpoint on your phone (or a narrow browser window). Add to Home Screen for the full standalone PWA feel.

What it does

Studies the latest ChatGPT and Claude mobile apps and remixes their best interactions into Val Town's own design language (per the valtown-ui skill: IBM Plex Sans, slate + sky, true-black text, 8px radius, iA Writer Quattro eyebrows).

  • πŸ’¬ Fake streaming chat β€” typing dots β†’ token stream β†’ blinking caret, with effort-dependent "thinking" time. Markdown rendering with copyable code blocks. Stop, retry, copy, thumbs.
  • πŸ—‚οΈ Push-style sidebar drawer β€” edge-swipe to open, pinned + recents (persisted to localStorage), New chat FAB, avatar.
  • 🧠 Model bottom sheet β€” drag-to-dismiss, Townie 2 / Townie / Townie Mini, plus an Effort sub-view (High / Medium / Instant) that actually changes streaming speed.
  • βž• Attach popover β€” Camera / Photos / Files / Connectors with blur backdrop.
  • πŸŽ™οΈ Voice mode chip β€” animated waveform (mock).
  • πŸ‘» Incognito mode β€” chats created while on are never persisted.
  • πŸ“² PWA-level native feel β€” manifest + service worker (network-first shell cache), safe-area insets, 100dvh, no tap highlights, overscroll containment, haptics via navigator.vibrate, reduced-motion support.

Architecture

Rendering mermaid diagram...
  • Styling: Twind (Tailwind runtime) + a small style.css for fonts, keyframes, and safe areas.
  • Types shared in shared/types.ts.
  • No backend state β€” everything is client-side; the val only serves files.

Swapping in a real model

frontend/lib/fakeAI.ts exposes pickResponse() + streamResponse(). Replace those two with a fetch to a streaming endpoint and the whole UI comes alive unchanged.


Mockup by Charlie (dcm31) Β· view source