Fill in before sending
[site address][server name][site key][heaviest page]["./*.html", "./**/*.html"]
My site [site address] on my Opus Growth server (server [server name], site key [site key] if it is an extra site) was built with the site kit and is slow on phones. The kit loads Tailwind through the Play CDN that compiles in the browser, the fonts from Fontshare and the motion libraries from jsDelivr, and prints the menu with JavaScript. Without changing how the site looks, turn all of this into compiled files hosted on my own server. The goal: while a page loads, the site sends not a single request outside its own domain.
1. Baseline. Note the current version with site_versions. Run core_web_vitals for the home page and [heaviest page] on mobile and desktop with resources=true. Put the performance score, LCP, CLS, total request count, total size and the requests leaving your own domain in a table. List the HTML files with site_list_files and pull every `<script>` and `<link>` tag from each page.
2. Show me the plan and wait for my approval. List every file that will change or be added.
3. Compile Tailwind. Move the inline `tailwind.config` setting from the pages into `_src/tailwind.config.js`; set content to `["./*.html", "./**/*.html"]`, and add any JavaScript file that still generates classes. Create `_src/input.css` from the lines `@tailwind base; @tailwind components; @tailwind utilities;` followed by the contents of assets/app.css. Run `npx --yes tailwindcss@3 -c _src/tailwind.config.js -i _src/input.css -o assets/site.css --minify` with site_run_command. Give the file a name derived from a hash of its content, for example `assets/site.3f9a1c2b.css`, update the link on every page and delete the Play CDN script and the inline setting. Rebuild after every HTML edit that changes classes, otherwise the new classes are missing from the CSS.
4. Host the fonts yourself. Fetch the Fontshare CSS with a SEPARATE request for every family and weight, for example `https://api.fontshare.com/v2/css?f[]=satoshi@400&display=swap`; we saw other families come back when several families or weights were requested at once, so check the returned font-family name every time. Download the woff2 files into `assets/fonts/`, write the `@font-face` rules with `font-display: swap` at the top of assets/app.css (design-check looks for distinctive typography there), and preload the body font and the font used by the large heading on the first screen with `<link rel="preload" as="font" type="font/woff2" crossorigin>`. Delete the Fontshare `preconnect` and stylesheet links. Check that the font licence allows self-hosting.
5. Regenerate the images. Move the source JPG and PNG files into `_src/img/`. Install sharp outside the site folder: start `mkdir -p /data/_build && cd /data/_build && npm init -y && npm i sharp` with site_run_command and background=true, and follow it with site_command_status; if that folder is not writable, tell me why. With a node script, produce WebP (quality 72) and AVIF (quality 50) at 480, 800, 1200 and 1600 pixels wide for every image. In the HTML wrap each image in `<picture>`: a `<source type="image/avif" srcset sizes>` for AVIF, a WebP `<img>` as the fallback with its own srcset and sizes, and the real width and height of the source image. The main image on the first screen gets `fetchpriority="high"` and is not lazy; all others get `loading="lazy" decoding="async"`. Write sizes to match the width the image really takes.
6. Clean up the scripts. If the site has no motion, or only decorative hooks like `data-reveal`, remove GSAP, ScrollTrigger, SplitText, Lenis, Swiper, motion.js and the inline script that adds the `anim` class completely, and delete the Lenis and anim rules from app.css. If motion really is needed, copy the library into `assets/vendor/`, load it with `defer` only on the pages that use it and check that content stays visible with `prefers-reduced-motion`. Turn the menu and footer into static HTML with a `chrome-stamp.mjs` script: it reads site.config.js, writes between the `<!-- chrome:nav:start -->`, `<!-- chrome:nav:end -->` and chrome:footer markers, builds the mobile menu with `<details>`, keeps links at least 44 pixels tall and uses paragraphs, not h4, for the footer column titles. Then remove chrome.js and the site.config.js script tag from the pages; site.config.js stays only as the data file the scripts read.
7. Get third-party requests to zero. With site_run_command, search the HTML and CSS for src and href values starting with `https://`; move every resource outside your own domain, tel:, mailto: and wa.me links to the site or remove it. Put the favicon in `assets/img/` and link it on every page, otherwise the browser requests /favicon.ico and logs a 404 in the console.
8. Cache headers. Run site_headers with mode="list". If no file under assets will ever be replaced under the same name (the CSS name carries a hash, images get a new name when they change), preview the line `/assets/* Cache-Control: public, max-age=31536000, immutable` with confirm=false and apply it with confirm=true after my approval. Do not ask for Cache-Control on HTML; the platform already serves HTML as no-cache.
9. Gates and the new measurement. Run `node seo-stamp.mjs`, `node chrome-stamp.mjs`, the CSS build, `node seo-check.mjs`, `node design-check.mjs` and `npx --yes html-validate "**/*.html"` in that order and bring them all to zero errors. Check every page with site_preview at 360, 390, 768 and 1440 pixels wide. Repeat the core_web_vitals measurement from step 1 on the same pages, and also run seo_audit with runs=2 for the home page. If mobile performance is under 95, find the cause in the resources=true lists and fix it; the most common cause is layout shift from a heading font that was not preloaded.
Output: a before and after table (page, device, performance, LCP, CLS, request count, total KB, third-party request count), the list of added and deleted files, the active site_headers lines and a short note on which commands to rerun, in which order, after the next edit. If a step breaks the site, go back to the version you noted with site_restore and tell me.
Example result
An example of the output this prompt produces. Its structure comes from the tools' real output; numbers and names are fictional.
Example output (on a fictional demo site; the business is fictional, the measurements were really taken on this demo)
The performance pack was applied to a four page site whose content was complete but which still ran on the kit's default stack.
| Page | Device | Performance before | Performance after | LCP before | LCP after | CLS before | CLS after |
|---|
| Home | Mobile | 73 | 100 | 3.5 s | 1.5 s | 0.304 | 0 |
| Services | Mobile | 75 | 100 | 2.9 s | 1.5 s | 0.381 | 0 |
| About | Mobile | 86 | 100 | 2.8 s | 1.4 s | 0.163 | 0.002 |
| Contact | Mobile | 91 | 100 | 2.9 s | 1.4 s | 0.079 | 0 |
| Services | Desktop | 83 | 100 | 0.8 s | 0.4 s | 0.324 | 0.003 |
| Measure (home page) | Before | After |
|---|
| Requests | 18 | 6 |
| Third-party requests | 11 | 0 |
| Total transfer | 465 KB | 80 KB |
| CSS | Play CDN script | site.70672cc5.css, 11.7 KB |
Added: assets/fonts/switzer-400.woff2, switzer-600.woff2, WebP and AVIF at 480, 800, 1200 and 1600 pixels for every image, chrome-stamp.mjs, _src/tailwind.config.js. Removed: chrome.js, motion.js, the GSAP, ScrollTrigger, SplitText, Lenis and Swiper links, the Fontshare links.
site_headers proposal: /assets/* Cache-Control: public, max-age=31536000, immutable (waiting for your approval). Order after the next edit: seo-stamp, chrome-stamp, Tailwind build, seo-check, design-check, html-validate.