fix(examples): restore Vercel workspace deployments - #1908
Merged
Conversation
Contributor
Author
eoinest
enabled auto-merge (squash)
July 16, 2026 21:42
Contributor
Author
logflash
approved these changes
Jul 17, 2026
This was referenced Jul 20, 2026
JoshKappler
added a commit
that referenced
this pull request
Jul 22, 2026
Addition, take or leave. One of five SPA example PRs from this morning's list (webpack #1944, rollup #1945, react-router #1946, rsbuild #1951 on top of the compiler adapter #1950). ## Summary - New example `examples/vite-spa`: the finished product of the React SPA Quickstart plus the "Developing with SPA translations" guide, built to follow the docs faithfully so docs and example can't drift apart. - Runtime story: `src/index.ts` awaits `initializeGTSPA` then dynamically imports the app, so module-level `t()` resolves. No provider. `<T>`, `t()`, and `<LocaleSelector>` all demonstrated. - Buildtime story: the compiler's `vite` plugin with `parsingFlags.devHotReload`, matching vite-create-app. - Hand-written translation files under `src/_gt/` are keyed by the real content hashes, so language switching works offline with no account or API key. `npm run build` runs offline; a separate `translate` script regenerates the files with a production key. - `vercel.json` ships an SPA fallback rewrite so deployed deep links and locale-switch reloads resolve. ## Testing - typecheck, oxlint, offline build, and a frozen-lockfile install all pass on the current head. - Injected `_hash` values in the built bundle match the committed fixture keys, with the compiler on and with it removed (runtime hashing computes the same keys). - Headless Chromium: switching the LocaleSelector rendered en, es, and ja correctly with zero console errors. - CI lints examples but does not build them, so the build evidence above is from manual runs. ## Notes - This is a second Vite example on purpose: vite-create-app shows GT retrofitted onto a create-vite scaffold, vite-spa is the from-scratch docs companion. Both READMEs say which to use. If one Vite example is enough, happy to fold or drop this one. - Docs gap found while building, filed separately: the dev guide never mentions `parsingFlags.devHotReload`, but module-level `t()` strings won't hot-reload without it. - No changeset (example only, matches #1908/#1927). <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR adds a new `examples/vite-spa` example — the finished product of the React SPA Quickstart — demonstrating `gt-react` in a client-side-only Vite app. The runtime story uses top-level `await initializeGTSPA()` before dynamically importing `main.tsx`, so module-level `` t`...` `` calls in `navigation.ts` resolve correctly. Hand-written translation fixture files in `src/_gt/` enable offline switching across four locales without an API key. - **`src/index.ts`**: Imports `gt-react/macros`, awaits `initializeGTSPA` (passing config + env vars), then dynamically imports `./main` — ensuring GT is fully initialized before the component tree renders. - **`src/loadTranslations.ts`**: Dynamic-imports the per-locale JSON at runtime, returning `{}` on any missing locale so the app degrades gracefully. - **Root `.oxlintrc.json`**: Adds `t` as a global `readonly` identifier so the monorepo-wide `no-undef` rule does not flag the implicit `t` macro in `navigation.ts`. <details open><summary><h3>Confidence Score: 5/5</h3></summary> Safe to merge. The new example is a self-contained addition with no changes to production library code, and the one shared-config tweak is additive. All source changes are confined to the new examples/vite-spa directory. The only repo-wide modification is adding t to the oxlint globals block, which is additive and doesn't affect runtime behavior or library packages. The initialization sequence (macros → initializeGTSPA → dynamic import of main) is architecturally sound, offline build is verified, and the lockfile correctly reflects the package.json dependency placement. .oxlintrc.json — the t global is broader than needed; worth scoping to SPA examples via an override, but not a blocker. </details> <details><summary><h3>Important Files Changed</h3></summary> | Filename | Overview | |----------|----------| | examples/vite-spa/src/index.ts | Entry module: correctly sequences macro import, initializeGTSPA await, and dynamic app import to guarantee GT is ready before any module-level t`` calls execute. | | examples/vite-spa/src/navigation.ts | Uses implicit global t`` macro (attached by gt-react/macros in index.ts); intentional SPA-only pattern, well-documented in README. | | examples/vite-spa/src/loadTranslations.ts | Dynamic-imports locale JSON from src/_gt/; returns {} on missing locale. console.warn is explicitly allowed by the no-console lint rule. | | .oxlintrc.json | Adds 't' as a monorepo-wide readonly global so CI no-undef checks pass for navigation.ts; broader than strictly necessary since t is only a valid implicit global in SPA entry contexts. | | examples/vite-spa/vite.config.ts | Wires react() and gtCompiler(gtConfig) plugins; dedupe for react/react-dom handles workspace-link resolution correctly. | | examples/vite-spa/vercel.json | Uses turbo build command with --env-mode=loose; includes SPA fallback rewrite; matches conventions of sibling examples. | | examples/vite-spa/package.json | gt is correctly placed under devDependencies (matches its lockfile placement); gt-react in dependencies; all workspace:* pins consistent. | | examples/vite-spa/gt.config.json | Configures defaultLocale, four target locales, output path, and parsingFlags.devHotReload for hot-reload of module-level t`` strings during development. | </details> <details><summary><h3>Sequence Diagram</h3></summary> ```mermaid sequenceDiagram participant Browser participant index.ts participant loadTranslations.ts participant _gt/[locale].json participant initializeGTSPA participant main.tsx participant App Browser->>index.ts: load (module script) index.ts->>index.ts: import 'gt-react/macros' (attaches global t``) index.ts->>initializeGTSPA: "await initializeGTSPA({ ...gtConfig, projectId, devApiKey, loadTranslations })" initializeGTSPA->>loadTranslations.ts: call loadTranslations(locale) loadTranslations.ts->>_gt/[locale].json: dynamic import _gt/[locale].json-->>loadTranslations.ts: translation map loadTranslations.ts-->>initializeGTSPA: resolved translations initializeGTSPA-->>index.ts: resolved index.ts->>main.tsx: await import('./main') main.tsx->>App: createRoot().render(App) App->>App: navigation uses t`Home`, t`About` (resolved) App->>App: Welcome renders T and LocaleSelector ``` </details> <sub>Reviews (7): Last reviewed commit: ["fix(examples): use the global t macro an..."](3535245) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=45751551)</sub> <!-- /greptile_comment -->
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
workspace:*dependencies resolve from the monorepoinitializeGTSPAworkspace API before renderingTesting
cd examples/vite-create-app && corepack pnpm --version— passed (10.20.0)cd examples/vite-create-app && corepack pnpm install --frozen-lockfile— passed and linked all 47 workspace projectscd examples/next-gt-starter && corepack pnpm install --frozen-lockfile— passed and linked all 47 workspace projectspnpm --filter vite-create-app typecheck— passedpnpm exec turbo run typecheck --filter=next-starter— passedpnpm --filter vite-create-app lint— passedpnpm exec oxfmt --check examples/vite-create-app/package.json examples/vite-create-app/src/main.tsx examples/vite-create-app/vercel.json examples/next-gt-starter/package.json examples/next-gt-starter/vercel.json— passedpnpm --filter vite-create-app exec vite build— passedpnpm --filter next-starter exec next build— passedNotes
gt translateto avoid creating translation jobs.Greptile Summary
This PR fixes Vercel workspace deployments for both the
next-gt-starterandvite-create-appexamples by switching to Corepack-managed pnpm soworkspace:*dependencies resolve correctly from the monorepo root lockfile.\"packageManager\": \"pnpm@10.20.0\"to both examplepackage.jsonfiles and newvercel.jsonfiles that setinstallCommandtocorepack pnpm install --frozen-lockfileand route builds through Turbo.vite-create-app/src/main.tsxfrom the oldGTProviderJSX wrapper pattern to theinitializeGTSPASPA-init API, which blocks rendering until translations are loaded; a.catch()handler logs failures toconsole.errorso the promise rejection is no longer silently swallowed.next-gt-starterbuild command additionally installs the Ruststabletoolchain with thewasm32-wasip1target before invokingturbo run build, which is required by a WASM-compiled dependency in the workspace.Confidence Score: 5/5
Safe to merge — changes are confined to example app deployment config and initialization, with no impact on library packages or production code paths.
All five changed files are in example apps only. The Corepack/pnpm pinning correctly restores workspace resolution, the new vercel.json files follow standard Vercel configuration patterns, and the main.tsx refactor properly uses the SPA init API with credentials auto-read from environment variables via addRuntimeCredentials.
No files require special attention.
Important Files Changed
Sequence Diagram
%%{init: {'theme': 'neutral'}}%% sequenceDiagram participant Browser participant main.tsx participant initializeGTSPA participant addRuntimeCredentials participant BrowserI18nCache participant App Browser->>main.tsx: load module main.tsx->>initializeGTSPA: call with gtConfig + loadTranslations initializeGTSPA->>addRuntimeCredentials: read VITE_GT_PROJECT_ID / VITE_GT_DEV_API_KEY from import.meta.env addRuntimeCredentials-->>initializeGTSPA: merged config initializeGTSPA->>BrowserI18nCache: initialize i18n cache initializeGTSPA->>initializeGTSPA: getTranslationsSnapshot (await locale) initializeGTSPA-->>main.tsx: translations ready main.tsx->>App: dynamic import('./App.tsx') App-->>main.tsx: App component main.tsx->>Browser: "createRoot().render(<App />)" Note over main.tsx,Browser: .catch() logs console.error on any failure%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% sequenceDiagram participant Browser participant main.tsx participant initializeGTSPA participant addRuntimeCredentials participant BrowserI18nCache participant App Browser->>main.tsx: load module main.tsx->>initializeGTSPA: call with gtConfig + loadTranslations initializeGTSPA->>addRuntimeCredentials: read VITE_GT_PROJECT_ID / VITE_GT_DEV_API_KEY from import.meta.env addRuntimeCredentials-->>initializeGTSPA: merged config initializeGTSPA->>BrowserI18nCache: initialize i18n cache initializeGTSPA->>initializeGTSPA: getTranslationsSnapshot (await locale) initializeGTSPA-->>main.tsx: translations ready main.tsx->>App: dynamic import('./App.tsx') App-->>main.tsx: App component main.tsx->>Browser: "createRoot().render(<App />)" Note over main.tsx,Browser: .catch() logs console.error on any failureReviews (3): Last reviewed commit: "fix(examples): expose Vercel build envir..." | Re-trigger Greptile