# lookimade

Web MD — a static-hosted markdown reader/editor. App source lives in [md/](md/); see
[md/CLAUDE.md](md/CLAUDE.md) for the architecture and conventions and
[md/PLAN.md](md/PLAN.md) for the current feature plan. Deployed on Vercel (static +
serverless `api/` functions).

## Clearing shared links

> Applies once **Phase 5 (Share as public link)** ships — see [md/PLAN.md](md/PLAN.md) §5.

Shared links (`/s/{id}`) are stored one JSON blob per share in **Vercel Blob** under
`shares/{id}.json` and **never expire** — a share lives until it is explicitly deleted.
The store only grows, so clear it periodically.

- **Delete a single share** — no server access needed. Whoever created it deletes it
  from the share dialog in the app (it holds the one-time delete token). This 404s the
  page within the cache TTL.

- **Bulk / owner cleanup** — needs `BLOB_READ_WRITE_TOKEN` in the environment. Any of:
  - **Vercel dashboard:** Storage → your Blob store → browse `shares/` → delete.
  - **Vercel CLI:** `vercel blob ls` to list, `vercel blob del <url>` to remove.
  - **Script** (delete shares older than N days, default 90):

    ```bash
    node scripts/clear-shares.mjs 90
    ```

    ```js
    // scripts/clear-shares.mjs
    import { list, del } from '@vercel/blob';
    const maxAgeDays = Number(process.argv[2] ?? 90);
    const cutoff = Date.now() - maxAgeDays * 864e5;
    const { blobs } = await list({ prefix: 'shares/' });
    const stale = blobs.filter(b => new Date(b.uploadedAt).getTime() < cutoff);
    if (stale.length) await del(stale.map(b => b.url));
    console.log(`deleted ${stale.length} share(s) older than ${maxAgeDays}d`);
    ```
