# Rename Tape to Options and Replace the Web Rail

Created: 2026-05-23 19:36 EDT · Repo: `islandflow` · Branch: `sidebar-redesign`

Beads: islandflow-7ez Follow-up: islandflow-3by Scope: web shell, routing, desktop compatibility

## Summary

The Tape surface is now presented to users as `Options`, with `/options` as the canonical web route and `/tape` preserved as a compatibility redirect. The shared web shell no longer reserves a persistent left rail; every route now gets full-width content under a sticky top header, with navigation, branding, and shell metrics moved into a top-left overlay drawer.

## Changes Made

- Added canonical web route `/options` via `apps/web/app/options/page.tsx` and changed `apps/web/app/tape/page.tsx` to redirect to it.
- Updated route helpers in `apps/web/app/terminal.tsx` so `/options` is canonical while `/tape` remains accepted during transition.
- Renamed top-level navigation copy from `Tape` to `Options`.
- Replaced the persistent web rail with a sticky header plus overlay drawer in `apps/web/app/terminal.tsx` and `apps/web/app/globals.css`.
- Changed the Options page layout to a full-width two-section stack: `OptionsPane` first, `FlowPane` below with title `Packets`, and removed `EquitiesPane` from this route.
- Updated route, redirect, and desktop trust tests plus desktop README guidance to prefer `/options` while documenting `/tape` compatibility.

## Context

This change consolidates two related UX issues: the product naming mismatch around the Tape surface, and the layout cost of the always-visible left rail. The product/design context for Islandflow emphasizes investigation workflows, stable rhythm under live updates, and full-width evidence surfaces over decorative chrome.

The drawer keeps navigation and shell instrumentation available without permanently consuming horizontal space on dense data routes.

## Important Implementation Details

- `normalizeTerminalPathname()` now treats `/tape` as an alias of `/options`, which keeps route-feature decisions, live subscriptions, and nav highlighting aligned from one helper.
- The new Options route intentionally drops the Equities subscription and pane. The canonical route now subscribes only to `options`, `nbbo`, and `flow`.
- The drawer closes on route change, backdrop click, and `Escape` via client-side state in `TerminalAppShell`.
- Desktop trust remains origin-based, so no Electron security model change was required. The desktop updates only clarify preferred route examples and add explicit `/options` coverage.

## Relevant Diff Snippets

apps/web/app/terminal.tsx · canonical /options routing and nav labels

    - export const NAV_ITEMS = [
    -   { href: "/", label: "Home" },
    -   { href: "/tape", label: "Tape" },
    -   { href: "/news", label: "News" }
    - ] as const;
    + const CANONICAL_OPTIONS_PATH = "/options";
    + const TAPE_COMPAT_PATH = "/tape";
    + export const normalizeTerminalPathname = (pathname: string): string => {
    +   if (pathname === TAPE_COMPAT_PATH) return CANONICAL_OPTIONS_PATH;
    +   return KNOWN_TERMINAL_PATHS.has(pathname) ? pathname : "/";
    + };
    + export const NAV_ITEMS = [
    +   { href: "/", label: "Home" },
    +   { href: "/options", label: "Options" },
    +   { href: "/news", label: "News" }
    + ] as const;

apps/web/app/terminal.tsx · sticky header, overlay drawer, and Options page layout

    - <aside className="terminal-rail">...</aside>
    + const [drawerOpen, setDrawerOpen] = useState(false);
    + useEffect(() => { setDrawerOpen(false); }, [pathname]);
    + useEffect(() => {
    +   if (!drawerOpen) return;
    +   const handleKeyDown = (event: KeyboardEvent) => {
    +     if (event.key === "Escape") setDrawerOpen(false);
    +   };
    +   document.addEventListener("keydown", handleKeyDown);
    +   return () => document.removeEventListener("keydown", handleKeyDown);
    + }, [drawerOpen]);
    + <header className="terminal-topbar">
    +   <button className="terminal-button terminal-menu-trigger">Menu</button>
    +   ...
    + </header>
    + {drawerOpen ? <>...overlay drawer...</> : null}
    - export function TapeRoute() {
    -   return <PageFrame title="Tape">...<EquitiesPane />...</PageFrame>;
    - }
    + export function OptionsRoute() {
    +   return <PageFrame title="Options">...<FlowPane title="Packets" />...</PageFrame>;
    + }

apps/web/app/globals.css · full-width shell and drawer styling

    - --rail-width: 236px;
    - .terminal-shell { display: grid; grid-template-columns: var(--rail-width) minmax(0, 1fr); }
    - .terminal-rail { ... }
    - .page-grid-tape { grid-template-columns: minmax(0, 1.5fr) minmax(320px, 1fr); }
    + --drawer-width: min(320px, calc(100vw - 28px));
    + .terminal-shell { position: relative; min-height: 100vh; }
    + .terminal-nav-drawer { position: fixed; inset: 0 auto 0 0; width: var(--drawer-width); ... }
    + .terminal-drawer-backdrop { position: fixed; inset: 0; ... }
    + .terminal-topbar { justify-content: space-between; backdrop-filter: blur(12px); }
    + .page-grid-options { grid-template-columns: minmax(0, 1fr); }

route + desktop compatibility · redirect and trust coverage

    + // apps/web/app/options/page.tsx
    + import { OptionsRoute } from "../terminal";
    + export default function Page() {
    +   return <OptionsRoute />;
    + }

    - // apps/web/app/tape/page.tsx
    - return <TapeRoute />;
    + redirect("/options");

    + expect(isTrustedAppUrl("https://flow.deltaisland.io/options?symbol=SPY")).toBe(true);
    + expect(isTrustedAppUrl("https://flow.deltaisland.io/tape?symbol=SPY")).toBe(true);

Snippets are rendered client-side with Diffs (diffs.com project) and include inline fallback text for offline viewing.

## Expected Impact for End-Users

Users now land on a more clearly named `Options` route, keep old `/tape` links working, and get more horizontal space across the web app because navigation no longer consumes a permanent left column. The Options route is simpler and more focused: options flow first, packets below, without the Equities panel competing for width.

## Validation

- Passed: `bun test apps/web/app/routes.test.ts apps/web/app/terminal.test.ts apps/desktop/src/security.test.ts` (85 passing tests).
- Passed: `bun --cwd=apps/web run build` including production build, TypeScript, and app-route generation for `/options` and `/tape`.
- Skipped by request: browser visual probes for the drawer/header refactor.

## Issues, Limitations, and Mitigations

- The current web test suite is still mostly route/helper-level, so the new drawer interactions are not covered by DOM/browser tests yet. Mitigation: filed follow-up issue `islandflow-3by`.
- Internal code still uses some `Tape`-named helpers and hooks. This was left intentionally to keep the rename low-risk while user-facing copy and routing moved to `Options`.
- The Options route no longer shows Equities. That is intentional for layout clarity, but it does change the previous multi-pane surface composition.

## Follow-up Work

- `islandflow-3by`: add interaction coverage for drawer open/close, `Escape` dismissal, backdrop dismissal, and route-change dismissal.
- If we later want a broader naming cleanup, isolate internal `Tape*` renames into a separate low-risk refactor rather than coupling them to route behavior again.