Skip to content

feat(templates): add live preview editing API - #2608

Open
HugoRCD wants to merge 5 commits into
mainfrom
codex/template-editor-backend
Open

HugoRCD wants to merge 5 commits into
mainfrom
codex/template-editor-backend

Conversation

@HugoRCD

@HugoRCD HugoRCD commented Nov 5, 2026 •

Copy link
Copy Markdown
Member

Written by an AI agent on behalf of @HugoRCD. @HugoRCD has not reviewed it yet.

Template previews currently serve a production build, so editing their source cannot update the page. This adds an owner-bound editing API that starts a development server alongside the preview, applies exact edits or file replacements, deletes files, installs modules, and checks rendered routes.

Stack (merge left to right): Backend API #2608 → Nuxi tools #2609 → Editor UI #2611. This PR targets main; the controls and assistant integration come in the following layers. Admin rechecks (#2619) and ZIP downloads (#2627) follow the editor UI.

Evidence

During restoration, a temporary Vercel Sandbox running the official Nuxt v4 starter received an app/app.vue edit and a nuxt.config.ts title change. Its open browser showed the new text after editing and kept working after the configuration restart. This is a direct tool demonstration with sanitised data, not a full Nuxi conversation or a production comparison.

Rendered page after the source edit

The final saved page-check response was:

{
  "status": 200,
  "text": "Nuxi edited template Template editor verification Hello from Nuxi"
}

For example, an authenticated internal caller submits this body to POST /api/internal/templates/preview:

{
  "action": "edit",
  "principalId": "visitor-principal",
  "sandboxId": "owned-preview",
  "path": "app/app.vue",
  "edits": [{ "find": "Before editing", "replace": "Hello from Nuxi" }]
}

Page-check limits

Rendered pages are capped at 1 MiB by curl and again during the SDK streamed read, before full buffering. Text extraction uses a non-executing SAX parser in server code, preserves the 1,500-character excerpt and omits scripts, styles and nested templates. Log excerpts are capped at 32 KiB. Parsing stops when the excerpt is full.

The same checkAppPage harness, with mocked sandbox I/O, gives this raw output for a response one byte over the limit:

Before:

Input: 1048577 response bytes; sandbox curl reports HTTP 200
Result: accepted; HTTP 200; 1500-character excerpt
Exit code: 1

After:

Input: 1048577 response bytes; sandbox curl reports HTTP 200
Result: HTTP 413; The page is too large to check (maximum 1 MiB).
Exit code: 0

Server bundle packaging

nitro.externals.inline includes parse5-sax-parser, parse5 and entities so Nitro can bundle this server dependency chain and remove unused exports instead of copying the external packages into the deployment. The wrapper uses parse5’s tokenizer and HTML namespace handling, which use the entities decoder; leaving those dependencies external would prevent that pruning. The compiled page-check chunk retains the SAX tokenizer/decoder and omits the full DOM parser and serializer. It does not execute HTML or add the parser to browser JavaScript.

Two local production analyses used the same resolved stack, Node server preset and analysis setup, before and after this packaging change and the excerpt early stop:

Measurement Before optimization After optimization
Nuxt-reported server output 79.2 MB (24.1 MB gzip) 78.2 MB (24 MB gzip)
All client JavaScript, Brotli 1,466,591 B 1,466,961 B
Minimal initial JavaScript + CSS, Brotli 490,443 B 490,471 B
Parser modules in client graph 0 0

Both analyses exited successfully and /templates/minimal returned HTTP 200. These measure the optimization within the stack, not the complete feature delta against main or the Vercel deployment size. Fresh per-PR CI bundle comparisons are still pending.

Validation

  • The current full stack passes 51 focused tests across four suites, plus lint and type checking. Backend cases cover path validation, exact-edit rejection, startup progress before readiness, restart failures, bounded reads and extracted text. Mocked preview lookups verify caller forwarding and missing/stopped handling; they do not independently test the real ownership lookup.

  • Checks against the compiled production handler pass for visible text, entities, split UTF-8 input, hidden script/style/template content, the 1,500-character excerpt and rejection above 1 MiB.

  • Earlier real temporary Vercel Sandbox runs verified normal HTML and rejection of a chunked response over 1 MiB. Deployment-wide concurrency was not measured.

  • Earlier runs of the reusable template verifier passed Minimal, Nuxt UI Dashboard and Docus, including file operations, rendered-page checks and configuration restarts. Minimal also passed installing @nuxt/image. These real-template runs were not repeated after the latest sync with main; each temporary sandbox was stopped afterward.

    node --env-file=<credentials.env> --import tsx scripts/templates/verify-editing.ts minimal nuxt-ui-dashboard docus
    node --env-file=<credentials.env> --import tsx scripts/templates/verify-editing.ts minimal --module=@nuxt/image
  • A full AI conversation and every gallery template were not exercised. Preview deployments need their own check snapshots; feat(templates): let admins recheck individual templates #2619 adds the admin action to create them.

ELI5: This gives each temporary template app a workshop where its files can change while it runs. The API checks that the person making a change owns that preview and reports whether the updated page works.

@HugoRCD
HugoRCD requested a review from atinux as a code owner November 5, 2026 13:02
@vercel

vercel Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
nuxt Ready Ready Preview Nov 9, 2026 10:41am UTC

Request Review

@coderabbitai

coderabbitai Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 7 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 2 included reviews currently available.

Learn how review limits work.

Review configuration:

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: a10eb5d3-a90a-4682-96e0-2e7ecff911c8
Commits

Reviewing files that changed from the base of the PR and between ad0a63c and 3537b7e.

Files ignored due to path filters: 1

  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
Files selected for processing: 11

  • nuxt.config.ts
  • package.json
  • scripts/templates/verify-editing.ts
  • server/api/internal/templates/preview.post.ts
  • server/api/templates/preview.post.ts
  • server/api/templates/preview/[id]/edit.post.ts
  • server/utils/templates/dev-server.ts
  • server/utils/templates/edit.ts
  • server/utils/templates/preview-bridge.ts
  • shared/types/templates.ts
  • test/unit/templates-edit.spec.ts
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@nuxt-com-bundle-report

nuxt-com-bundle-report Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Production bundle

Explore the comparison online →

Client JS 1.72 MiB $\color{red}\textsf{(+5.6 KiB, +0.3}\%\textsf{)}$ · CSS 33.6 KiB $\color{red}\textsf{(+105 B, +0.3}\%\textsf{)}$ · Brotli

Initial page load PR JS Δ JS Δ CSS Δ files
/ 558.3 KiB -543 B (-0.1%) +105 B (+0.3%) —
/docs/4.x/getting-started/introduction 617.7 KiB +26 B (+0.0%) +105 B (+0.3%) —
/modules/ui 548.8 KiB -500 B (-0.1%) +105 B (+0.3%) —
/updates 453.7 KiB -505 B (-0.1%) +105 B (+0.3%) —
/blog/v4-6 577.1 KiB -554 B (-0.1%) +105 B (+0.3%) —
/templates 452.5 KiB -506 B (-0.1%) +105 B (+0.3%) —
All client assets
Metric Base (Brotli) PR (Brotli) Δ Brotli Δ gzip
Client JavaScript 1.71 MiB 1.72 MiB +5.6 KiB (+0.3%) +6.1 KiB (+0.3%)
Client CSS 33.5 KiB 33.6 KiB +105 B (+0.3%) +197 B (+0.4%)
Other client assets 827.5 KiB 827.5 KiB -1 B (-0.0%) —
Total client assets 2.55 MiB 2.56 MiB +5.7 KiB (+0.2%) +6.3 KiB (+0.2%)
Largest module increases
Module Base (Brotli) PR (Brotli) Δ Brotli
/app/components/DocsL10nEditor.vue?vue&type=script&setup=true&lang.ts 5.9 KiB 8.7 KiB +2.8 KiB (+48.6%)
/shared/utils/l10n-editor.ts 0 B 2.8 KiB +2.8 KiB
/app/components/DocsPageAsideLinks.vue?vue&type=script&setup=true&lang.ts 0 B 1.1 KiB +1.1 KiB
/app/pages/nuxters/[username].vue?vue&type=script&setup=true&lang.ts 5.4 KiB 6.2 KiB +844 B (+15.3%)
virtual:nuxt-workers.mjs?source=%2Fhome%2Frunner%2Fwork%2Fnuxt.com%2Fnuxt.com%2Fapp%2Fworkers%2Fsearch.ts 0 B 408 B +408 B
/app/components/nuxters/NuxtersScoreBreakdown.vue?vue&type=script&setup=true&lang.ts 1.3 KiB 1.6 KiB +252 B (+18.4%)
/app/composables/async-data-chunk-27.js 0 B 248 B +248 B
/app/pages/nuxters/async-data-chunk-20.js 0 B 237 B +237 B
/app/pages/modules/[slug]/async-data-chunk-3.js 0 B 213 B +213 B
/app/async-data-chunk-25.js 0 B 187 B +187 B

Initial page load counts the entry script, modulepreload chunks and stylesheets referenced by the prerendered HTML. Module values are attribution estimates from Nuxt’s analyzer. This workflow is report-only. 226f195a → 6f902448

@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedparse5-sax-parser@​8.0.11001008584100

View full report

This branch was successfully deployed

1 active deployment
Preview — 3537b7ee Deployed Nov 9, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants