Remove CDN dependencies: build-time Tailwind + inline SVG icons - #11
Merged
Conversation
UI/UX audit follow-through: the app previously rendered completely unstyled whenever the Tailwind Play CDN was slow, blocked, or offline, and the Material Symbols icon font degraded to raw ligature words. The free-trial messaging was also contradictory. This makes the whole app render reliably with no blocking CDN dependency and makes the trial honest and visible. Rendering / robustness - Compile Tailwind at build time (tailwind.config.js + PostCSS) and inline it into the single-file bundle instead of the runtime Play CDN. - Replace the Material Symbols icon font with inline lucide-react SVGs via a new Icon component (name -> component map, sized to 1em so existing text-* classes still control size/color). - Load the Inter/Roboto web fonts non-render-blocking (preload swap + noscript) so a slow/blocked font host never delays first paint or the page load event; text falls back to system-ui. - Tighten the CSP (drop cdn.tailwindcss.com from script-src/style-src) across app.html, nginx.conf, and public/_headers. - Result: the production build renders fully with every external request blocked (verified offline). Free-trial / bring-your-own-key clarity - Centralize the limit as TRIAL_TURN_LIMIT and add getTrialStatus() / hasUserApiKey() helpers. - Show remaining free turns honestly on the hero, Create, and Studio screens (new TrialNotice component) and in Settings. - Fix the Settings panel claiming a key was "saved" during an active trial and hiding the turn counter (it now bases that on the user's own key, not the built-in trial key). Simplification / mobile polish - Remove the non-functional grayed-out "Upgrade to 2K/4K Premium" buttons from the Studio action row. - Reorder the hero so the primary Get Started CTA leads (above the fold on mobile) with the mode shortcuts below. Docs - Update README (new "API Keys & the Free Trial" section), SECURITY.md, AGENTS.md, CHANGELOG.md, and docs/learnings.md to match. Verified: tsc, eslint, 68 unit tests, and 42 Playwright e2e tests all pass; screenshots reviewed across desktop/mobile in light and dark mode. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PNNzU5kBGqjsD4FsLpMTHD
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
Eliminates all runtime CDN dependencies by compiling Tailwind at build time and replacing the Material Symbols icon font with inline
lucide-reactSVG icons. The app now renders fully with zero blocking external requests—fonts load non-render-blocking, and the single-file bundle is completely self-contained.Changes
Iconcomponent (src/components/Icon.tsx): Maps Material Symbols ligature names tolucide-reactSVG components, sized to1emso existingtext-*classes control dimensions and color viacurrentColor.<script>inapp.htmltotailwind.config.js+postcss.config.js. CSS is now compiled at build time and inlined byvite-plugin-singlefile.<link rel="preload" as="style" onload="...">+<noscript>fallback. Slow/blocked font host no longer delays first paint orloadevent; text falls back tosystem-uistack.cdn.tailwindcss.com) fromapp.html. Updated CSP to remove those hosts.TrialNoticecomponent (src/components/TrialNotice.tsx): Slim free-trial indicator showing remaining turns and one-click path to add a user key.src/services/geminiService.ts): AddedgetTrialStatus(),hasTrialKey(),hasUserApiKey(), andTRIAL_TURN_LIMITconstant for consistent trial messaging across the app.<span className="material-symbols-outlined">...</span>with<Icon name="..." />throughout components.src/index.css: Tailwind directives + custom utilities (e.g.,.scrollbar-thin).docs/learnings.mdnow documents the self-contained rendering pattern and non-blocking font loading strategy.How Tested
npm run lint)npm test)npm run build)loadevent fires in ~140ms even when font host hangsNotes
dist/index.html) now has zero blocking CDN dependencies. The only optional, non-blocking fetch is Google Fonts, which gracefully degrades to the system sans-serif stack.https://cdn.tailwindcss.comfrom bothscript-srcandstyle-src.https://claude.ai/code/session_01PNNzU5kBGqjsD4FsLpMTHD