The <Go> component for embedding live Lynx examples on the web — with code browsing, web preview, and QR code for on-device testing. Initially built for lynxjs.org, now extracted for everyone to embed their Lynx apps.
The <Go> with Examples gallery showcases examples from @lynx-example, @vue-lynx-example, and more.
import { GoConfigProvider, Go } from '@lynx-js/go-web';
const config = {
exampleBasePath: '/lynx-examples',
};
<GoConfigProvider config={config}>
<Go example="hello-world" defaultFile="src/App.tsx" />
</GoConfigProvider>;import { GoConfigProvider, Go } from '@lynx-js/go-web';
import { rspressAdapter } from '@lynx-js/go-web/adapters/rspress';
const config = {
exampleBasePath: '/lynx-examples',
...rspressAdapter,
};
<GoConfigProvider config={config}>
<Go example="hello-world" />
</GoConfigProvider>;go-web ships a built-in SSG component and a pure generation function so that pre-rendered pages include a meaningful code preview instead of an empty placeholder.
Use ExamplePreviewSSG as the SSGComponent in your GoConfig. It reads example files from disk at render time during SSG.
import { GoConfigProvider, Go } from '@lynx-js/go-web';
import { rspressAdapter } from '@lynx-js/go-web/adapters/rspress';
import { ExamplePreviewSSG } from '@lynx-js/go-web/ssg';
import path from 'path';
const config = {
exampleBasePath: '/lynx-examples',
...rspressAdapter,
SSGComponent: ExamplePreviewSSG,
ssgExampleRoot: path.join(__dirname, '../docs/public/lynx-examples'),
};
<GoConfigProvider config={config}>
<Go example="hello-world" defaultFile="src/App.tsx" />
</GoConfigProvider>;Use generateSSGHTML() in your build config to pre-render example previews as static HTML strings at build time, then inject them as environment variables.
// rsbuild.config.ts
import { generateSSGHTML } from '@lynx-js/go-web/ssg';
const html = generateSSGHTML({
exampleRoot: path.resolve(__dirname, 'public/lynx-examples'),
example: 'hello-world',
defaultFile: 'src/App.tsx',
lang: 'en',
});The ./ssg export uses Node.js fs/path and must not be bundled into browser code.
For non-React sites (Hugo, Jekyll, plain HTML, etc.), use the iframe embed API. The host page only loads a tiny JS file — React runs inside the iframe.
<div id="demo" style="height: 500px;"></div>
<script type="module">
import { mount } from 'https://go.lynxjs.org/embed.js';
const embed = mount('#demo', {
example: 'hello-world',
defaultFile: 'src/App.tsx',
});
// Switch example dynamically:
// embed.update({ example: 'css' });
// Clean up:
// embed.destroy();
</script>Options:
| Option | Type | Description |
|---|---|---|
example |
string |
Required. Example folder name, e.g. 'hello-world' |
defaultFile |
string |
Initial file to display (default: 'src/App.tsx') |
mode |
'linked' | 'preview' | 'source' |
Overall layout mode (default: 'linked'). 'linked' shows code + preview together; 'preview' shows preview only; 'source' shows code only. |
defaultTab |
'preview' | 'web' | 'qrcode' |
Default preview tab |
exampleBasePath |
string |
Base path or full URL for example data, e.g. '/lynx-examples' |
img |
string |
Static preview image URL |
defaultEntryFile |
string |
Default entry bundle file path (relative to the example folder), e.g. 'dist/main.lynx.bundle'. Must match example-metadata.json (templateFiles[].file). Prefix match is supported (e.g. 'dist/main'). |
defaultEntryName |
string |
Default entry name (from templateFiles[].name), e.g. 'main'. Convenience alternative to defaultEntryFile and only used when defaultEntryFile is not provided. |
highlight |
string | Record<string, string> |
Line highlight spec, e.g. '{1,3-5}'. When passing a map, the key is the file path and the value is that file’s highlight spec. |
entry |
string | string[] |
Filter entry files in tree, useful for example with multiple entries, e.g. 'src/basic' |
schema |
string |
URL schema template for Lynx Explorer QR code. Use {{{url}}} as placeholder for the resolved entry URL, e.g. {{{url}}}?bar_color=000000&back_button_style=dark |
These options control how lynx-view renders inside the web preview panel.
Web preview bundle resolution is driven by example-metadata.json (templateFiles[].webFile) for the selected entry; it is not inferred from the Lynx bundle filename automatically.
| Option | Type | Default | Description |
|---|---|---|---|
webPreview |
boolean |
true |
Enable/disable the web preview tab even if templateFiles[].webFile exists |
webPreviewMode |
'fit' | 'responsive' | 'auto' |
'responsive' |
Viewport rendering mode |
designWidth |
number |
375 |
Design canvas width in pixels. Used in fit mode. |
designHeight |
number |
812 |
Design canvas height in pixels. Used in fit mode. |
fitThresholdScale |
number |
1.0 |
Width enter threshold for webPreviewMode='auto'. Exit back to responsive uses a built-in hysteresis band. |
fitMinScale |
number |
0.5 |
Height enter threshold for webPreviewMode='auto'. Exit back to responsive uses a built-in hysteresis band. |
fit |
'contain' | 'cover' | 'auto' |
'cover' |
Fit strategy inside the fit path. auto uses built-in heuristics, including hysteresis-aware mode transitions. |
Mode behavior:
| Mode | Behavior |
|---|---|
'responsive' |
lynx-view fills the container. browserConfig uses measured container dimensions. |
'fit' |
lynx-view is fixed at designWidth × designHeight. CSS transform: scale fits it into the container. browserConfig uses design dimensions. |
'auto' |
Switches based on container size. Behaves like fit for small/narrow containers and responsive for wide ones, with a built-in hysteresis band to reduce resize flicker. |
Auto switching logic:
const ratioW = containerWidth / designWidth;
const ratioH = containerHeight / designHeight;
// Enter condition only:
// - containerWidth < designWidth * fitThresholdScale
// - containerHeight < designHeight * fitMinScale
const shouldUseFit = ratioW < fitThresholdScale || ratioH < fitMinScale;Exit back to responsive uses slightly larger internal thresholds, so auto
does not switch back and forth on every tiny resize near the boundary.
Transition behavior:
fit → fiton container resize: smoothtransformtransitionfit ↔ responsivemode switch: hard cut, no transition
pnpm devThis starts the standalone example app at localhost:5969.
The @lynx-example/* packages are fetched directly from the npm registry at build time — no need to declare them as dependencies. The prepare script handles discovery, download, and metadata generation automatically.
# Local dev: uses cached examples if available (instant)
pnpm prepare
# Force re-fetch latest from npm registry
pnpm prepare:cleanCI always runs prepare:clean to ensure that examples are up to date.
All three checks must pass on every PR:
- Type Check —
pnpm typecheckat the repo root - Build Example App — standalone Rsbuild example
- Build Rspress Example — rspress integration example
Apache-2.0