Add @chenglou/pretext dependency and fitTextFontSize() utility that uses
canvas measureText to compute the largest font size that fits text within
a given width. Replaces character-count heuristics with actual font-aware
measurement.
- New fitTextFontSize() in @hyperframes/core/text, exposed on window.__hyperframes
- Generalized for all text elements (captions, titles, etc.), not just captions
- Unit tests (mocked pretext) + browser integration test (real Chromium canvas)
- Updated captions skill docs with usage, exit guarantee, and self-lint patterns
Co-authored-by: James <james.russo@heygen.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary
Extracts all studio API routes into a shared Hono-based module at `@hyperframes/core/studio-api`.
### Architecture
- **`StudioApiAdapter` interface** — consumers inject host-specific behavior (project resolution, bundling, rendering, thumbnails)
- **Shared route modules**: projects, files, preview, lint, render, thumbnail
- **Shared helpers**: `isSafePath`, `walkDir`, `getMimeType`, `buildSubCompositionHtml`
### What this PR does
- Creates the shared module with all API routes extracted from both `vite.config.ts` and `studioServer.ts`
- Both consumers will be refactored in follow-up commits to mount this module with their own adapter
### What stays in each consumer
- **Vite**: SSR module loading, Puppeteer thumbnails, file watcher + HMR, producer HTTP proxy, multi-project scanning
- **CLI**: in-process `executeRenderJob`, local runtime serving, browser management, SPA static file serving
### Follow-up needed
- [ ] Refactor `packages/studio/vite.config.ts` to use `createStudioApi(adapter)` via `@hono/node-server`'s `getRequestListener`
- [ ] Refactor `packages/cli/src/server/studioServer.ts` to use `createStudioApi(adapter)`
- [ ] Add `./studio-api` export path to `packages/core/package.json`
- [ ] Add `hono` as peer dependency of `@hyperframes/core`
## Test plan
- [ ] Verify shared module compiles without type errors
- [ ] After consumer refactoring: all studio features work identically via both vite dev and CLI embedded servers
🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Summary
- Add render queue panel with progress tracking, download, and delete actions
- Restructure App layout: home page with project picker, session-based routing
- Add ExpandOnHover component for preview-on-hover interactions (uses motion/react)
- CompositionsTab now supports hover preview with expanded iframe view
- Vite config: guard setInterval cleanup to dev-only (fixes CI build timeout)
- Add favicon and update studio package deps
## Test plan
- [x] Render queue shows progress, completes, and allows download
- [x] Home page lists projects and navigates to session view
- [x] ExpandOnHover shows expanded preview on mouse hover with spring animation
- [x] `vite build` exits cleanly (no hanging process from setInterval)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Reverting the package rename — Vance needs @hyperframes/cli for local
dev workflow. Instead, rewrite the name to "hyperframes" in the publish
workflow just before npm publish, so the monorepo name stays intact.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(cli): rename workspace package so npx resolves from registry
Rename packages/cli from "hyperframes" to "@hyperframes/cli" so that
npm/npx stops resolving it as a local workspace package when run from
inside the monorepo. The publish workflow sets the name back to
"hyperframes" before publishing so the npm package name is unchanged.
Root cause: npm sees workspaces in root package.json, finds packages/cli
named "hyperframes", assumes it's local, but bun manages node_modules
so there's no bin symlink — npx fails with "command not found" instead
of falling back to the registry.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(cli): update lockfile for workspace package rename
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(ci): publish CLI from temp copy to avoid workspace mutation
Copy packages/cli to a temp directory before renaming to "hyperframes"
for publish. Avoids corrupting the workspace if the job fails mid-way.
Addresses review feedback on #47.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(ci): resolve leftover conflict markers in publish.yml
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>