perf: stop inlining the model snapshot and build scripts into every page - #387
Merged
Conversation
Mintlify injects every .js file in the content directory into every page, so model-search.js was carried on all ~2,000 page variants. Because the HTML is served with Cache-Control: no-store, that payload was re-downloaded on every navigation rather than cached. - Move the 125KB STATIC_MODELS literal into data/static-models.json and load it on demand, falling back to the live models API if the snapshot is unavailable. Cuts model-search.js from 265KB to 143KB. - Add .mintignore so the build-time Node scripts in scripts/ are no longer published and injected into pages. - Point the sync workflow and pricing generator at the new snapshot path. Also fixes the Buy Credits CTA, which pointed at venice.ai/settings/billing (a 404) in all nine locales, and a stale llms.txt link to the removed overview/getting-started page.
Contributor
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
The hourly snapshot job rewrites the STATIC_MODELS line in model-search.js, which this branch removes, so main conflicts with it on every sync. Resolved by keeping this branch's loader in model-search.js and carrying main's newer model data into data/static-models.json, so no snapshot updates are lost. overview/pricing.mdx regenerates byte-identically from it.
This was referenced Aug 3, 2026
sabrinaaquino
added a commit
that referenced
this pull request
Aug 5, 2026
The three cards were hand-written, so they rotted: the page still advertised Kimi K2.6 and Claude Opus 4.7 well after both were superseded, and #387 left behind empty stats divs when it stripped the inlined model data. scripts/generate-popular-models.js now renders the grid from data/static-models.json, which the hourly workflow already refreshes, so the name, provider, context window, privacy tier, and model ID always match the catalog. Which models are featured stays an editorial choice, so the ids are pinned; if a pinned id leaves the catalog the newest model from the same provider takes the slot rather than leaving a card for a model nobody can call. Cards now carry the provider logo. The SVGs in images/icons/models are authored with fill="currentColor", so they are painted through a CSS mask the way the model catalog avatars are, instead of via an img tag that would render nothing. Restoring the model ID to each card also makes the section subtitle true again, so it goes back to telling readers to pass the ID as their model parameter.
sabrinaaquino
added a commit
that referenced
this pull request
Aug 5, 2026
…catalog (#389) * docs: tighten landing page copy and drop em dash Rewrite the endpoint card descriptions so they add information instead of restating the chips directly beneath them, and give the hero and Endpoints subtitles distinct jobs rather than both ending in "behind one API key". The Popular models subtitle told readers to use the model ID as their model parameter, but the cards stopped rendering IDs in #387, so it now points at the full catalog instead. * docs: lead the landing hero with models and tools OpenAI compatibility is a migration detail rather than the reason to pick Venice, so the hero now leads with private, unrestricted access to the leading models. The subtitle adds the tool surface (web search, document parsing, MCP) so the page reads as more than a model gateway. Compatibility is still called out in the meta description and on the Chat Completions card, where developers evaluating a switch will look for it. * docs: generate Popular models cards from the live snapshot The three cards were hand-written, so they rotted: the page still advertised Kimi K2.6 and Claude Opus 4.7 well after both were superseded, and #387 left behind empty stats divs when it stripped the inlined model data. scripts/generate-popular-models.js now renders the grid from data/static-models.json, which the hourly workflow already refreshes, so the name, provider, context window, privacy tier, and model ID always match the catalog. Which models are featured stays an editorial choice, so the ids are pinned; if a pinned id leaves the catalog the newest model from the same provider takes the slot rather than leaving a card for a model nobody can call. Cards now carry the provider logo. The SVGs in images/icons/models are authored with fill="currentColor", so they are painted through a CSS mask the way the model catalog avatars are, instead of via an img tag that would render nothing. Restoring the model ID to each card also makes the section subtitle true again, so it goes back to telling readers to pass the ID as their model parameter. * docs: name the modalities in the landing hero The hero now states the full surface in one line rather than splitting the models claim and the modality list across the tagline and subtitle. The subtitle keeps the tool surface, which nothing else above the fold covers. Moving "behind one API key" into the tagline meant the Endpoints subtitle was repeating it, so that subtitle switches to what is actually shared across modalities: auth, error codes, and rate limit headers. * docs: generate the catalog count and stop printing the hero claim twice The banner claimed 250+ models while the catalog held 293 live ones, and any hand-picked replacement would drift the same way. The count now comes from the same snapshot as the cards, rounded down to the nearest 10 so the claim is always true rather than aspirational. That puts the banner at "290+ models" today, and it promotes itself to "300+" once the catalog gets there without anyone editing the page. Mintlify renders frontmatter `description` as a visible subtitle under the H1, not just as metadata, so tightening it to match the hero put the same sentence on screen twice. The page now carries og:description instead, which keeps the social card text without repeating the hero. Search engines will build the snippet from the hero line, which says the same thing. * docs: give the landing page a description distinct from the hero Restores the visible subtitle, and with it the meta description, but pointed at what the page is for rather than repeating the hero's product claim. og:description keeps the claim for social cards. * docs: rebuild the landing page Agents section around real integrations The three Agents cards described categories rather than products and all pointed at anchors on the AI Agents hub. Split them into agent apps, coding agents, and MCP and skills, with one card per integration linking straight to its own guide. Each card carries the project's own brand logo. Marks that ship as single colour artwork get flipped in dark mode via an is-mono class, so the monochrome and full colour logos both read on either theme. Also folds the section eyebrow labels into the headings, drops the hero subtitle, and renames the Search and RAG section to Tools.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Mintlify injects every
.jsfile in the content directory into every page, and one line ofmodel-search.js— theSTATIC_MODELSliteral — was 125KB of model catalog. It was being inlined into all ~2,000 page variants, including the majority that never display model data. Because the HTML is servedCache-Control: no-store, it was re-downloaded on every navigation instead of cached.This PR moves that data to a cacheable file and stops publishing the build scripts. It also fixes two broken links found while investigating.
Scope check: this trims ~17KB per page over the wire (13.5% gzipped). It is real but modest, and it is not a fix for the slow docs loads. That is dominated by 13–24s cold-render TTFB at the origin (see Not addressed). Treat this as payload hygiene plus a JS error fix, not a page-speed fix.
Changes
model-search.jsintodata/static-models.json, fetched on demand.model-search.jsdrops from 265KB to 143KB, and the snapshot is served withCache-Control: public, max-age=1800instead of being embedded inno-storeHTML.scripts/*.jsare build-time Node scripts with#!/usr/bin/env nodeshebangs that were being shipped to browsers. Added a.mintignore.scripts/update-static-models.jswrites the JSON snapshot instead of regex-patchingmodel-search.js,scripts/generate-pricing-static.jsreads from it, and the hourly sync workflow diffs/commits the new path.The loader degrades safely: if the snapshot can't be fetched it falls back to the live models API, the same source the page refreshes from a moment later anyway.
This also fixes two uncaught JS errors on every page
Browser testing showed production currently throws these on every page load:
That's the two injected build scripts: both start with
const fs = require('fs'), so the second redeclaresfsand neither can callrequirein a browser. Both errors are gone on the preview.Also fixed
about-venicepointed athttps://venice.ai/settings/billing, which returns a real Next.js 404, in all nine locales. Now points athttps://venice.ai/settings/api, which is what the rest of the docs already use for buying credits.llms.txtlink tooverview/getting-started, a page that no longer exists and only resolved via redirect. Now points atgetting-started/quick-start.Static models are already current — the hourly job synced them in f84b849, and the extracted JSON is byte-identical to what the updater produces.
Verification
Payload, preview vs. production
/it/overview/beta-models/overview/about-veniceThe gzipped column is the number that matters; the uncompressed column only shows where the bytes went.
Headless Chrome, every component that reads the snapshot
Each page loaded on both sites and item counts compared. Identical on preview and production:
/models/overview/overview/pricing/overview/beta-models/overview/deprecations/overview/deprecations/guides/features/prompt-caching/guides/features/reasoning-models/models/text-to-speechFully-rendered pricing page layout is identical to the pixel on both (
12468.2px/1018.25px/6490pxfor the chat, embedding and image sections)./data/static-models.jsonreturns 200application/json,Cache-Control: public, max-age=1800, and is requested on every model-driven page/scripts/*.jsnow return 404 — no longer published or injectedsettings/billinggone fromabout-venice, replaced bysettings/apinode scripts/update-static-models.jsreports the snapshot up to date, confirming a lossless extractionnode scripts/generate-pricing-static.jsregeneratesoverview/pricing.mdxbyte-identically from the new pathRemaining console noise (a 403 and a Reddit pixel CORS failure) is present on production too and is unrelated to this change.
Not addressed
Cache-Control: no-storeon HTML, which prevents browsers caching pages at all, even on immediate re-visit.style.cssinlined twice by Mintlify (~133KB uncompressed per page), once as a<style>tag and once in the flight payload.The last three are Mintlify platform behavior and likely need a support conversation rather than a repo change.