@lynx-js/go-web
v0.5.0
Published
Interactive <Go> component for embedding live Lynx examples on the web. The example/ website doubles as the community example gallery.
Readme
Lynx Go Web
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.
Usage
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>;With rspress
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>;SSG (Static Site Generation)
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.
Option A: React component (rspress / SSR frameworks)
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>;Option B: Pure function (build-time injection)
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.
Iframe Embed (no React required)
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 |
Viewport Mode (Web Preview)
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
Development
pnpm devThis starts the standalone example app at localhost:5969.
Lynx examples
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.
CI
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
License
Apache-2.0
