First, make sure you have installed Sketch version 50+, & a recent npm.
Open a new Sketch file, then in a terminal:
git clone https://github.com/airbnb/react-sketchapp.git
cd react-sketchapp/examples/basic-setup && npm install
npm run renderNext, check out some more examples!
Managing the assets of design systems in Sketch is complex, error-prone and time consuming. Sketch is scriptable, but the API often changes. React provides the perfect wrapper to build reusable documents in a way already familiar to JavaScript developers.
import * as React from 'react';
import { render, Text, Artboard } from 'react-sketchapp';
const App = props => (
<Artboard>
<Text style={{ fontFamily: 'Comic Sans MS', color: 'hotPink' }}>{props.message}</Text>
</Artboard>
);
export default context => {
render(<App message="Hello world!" />, context.document.currentPage());
};- Manage design systemsβ
react-sketchappwas built for Airbnbβs design system; this is the easiest way to manage Sketch assets in a large design system - Use real components for designsβ Implement your designs in code as React components and render them into Sketch
- Design with real dataβ Designing with data is important but challenging;
react-sketchappmakes it simple to fetch and incorporate real data into your Sketch files - Build new tools on top of Sketchβ the easiest way to use Sketch as a canvas for custom design tooling
Found a novel use? We'd love to hear about it!
Read more about why we built it
react-sketchapp renders your React tree into a design-app-neutral intermediate tree (pages,
frames, shapes, text with style runs, fills, strokes, effects, auto-layout, etc.) and then hands
that tree to a backend that converts it to a native output format. Backend selection is
explicit, and new backends can be registered without touching the core reconciler/layout code.
Two backends ship today:
sketchβ the original, unchanged renderer. Produces Sketch file-format JSON headlessly (no behavior change from previous versions).figmaβ new. Produces Figma's REST-API-like file-format JSON headlessly (no Figma API/ network calls, no live/hot renderer). A separate Figma plugin imports this JSON and creates the corresponding pages, frames, text, styles, etc.
import { render, renderToJSON, Text, Artboard } from 'react-sketchapp';
export default context => {
render(<App message="Hello world!" />, context.document.currentPage());
};import * as React from 'react';
import { renderToJSON, Text, Artboard } from 'react-sketchapp/figma';
const App = () => (
<Artboard name="Page 1">
<Text style={{ fontFamily: 'Open Sans', fontSize: 40 }}>Hello Figma!</Text>
</Artboard>
);
const figmaFileJSON = renderToJSON(<App />);
// write `figmaFileJSON` to disk / hand it to the Figma plugin to importOr, from the main package, using renderToFigmaJSON directly:
import { renderToFigmaJSON } from 'react-sketchapp';
const figmaFileJSON = renderToFigmaJSON()(<App />);You can also pick a backend explicitly through a single, generic entry point:
import { renderToDesignJSON } from 'react-sketchapp';
const json = renderToDesignJSON(<App />, { backend: 'figma' }); // or 'sketch'renderToDesignJSON/renderToFigmaJSON use a pure Node.js PlatformBridge by default (no native
addon required), so the Figma backend β and headless Sketch JSON generation β both run in plain
Node.js environments (CI, servers, etc.) without Sketch or its native node-sketch-bridge
dependency installed. You may still pass a custom PlatformBridge (e.g. the native macOS one used
by the sketch backend when run inside Sketch) via the platformBridge option.
The Figma backend outputs the same shape returned by Figma's GET /v1/files/:key REST endpoint:
a document (DOCUMENT β CANVAS pages β nodes such as FRAME/RECTANGLE/TEXT/VECTOR), plus
top-level components, componentSets, styles, schemaVersion, name, version, etc.
Frames carry Figma auto-layout fields (layoutMode, paddingLeft/Right/Top/Bottom, itemSpacing,
primaryAxisAlignItems, counterAxisAlignItems, cornerRadius, β¦) derived from your flexbox
styles, and text nodes carry rich-text styling via characterStyleOverrides +
styleOverrideTable when you nest <Text> spans with different styles. <Svg> trees are
serialized to a flat SVG string carried on a VECTOR node's svg field (a custom extension, since
Figma's own file format has no raw-SVG field) for the companion plugin to turn into real vector
geometry β see Backends: SVG handling for details.
Generated node ids (e.g. "1:2") are a JSON-document-local addressing scheme only β Figma's
plugin API does not allow assigning custom ids when creating real nodes. These generated ids are
useful as stable references inside the JSON document itself (e.g. for a future diff/update
interface built into the companion Figma plugin), but they are not literal Figma node ids.
Backends implement the RenderBackend interface (src/backends/types.ts):
type RenderBackend<Json, Options> = {
name: string;
defaultPlatformBridge: PlatformBridge;
renderToJSON: (element: React.ReactElement, options?: Options, platformBridge?: PlatformBridge) => Json;
};and register themselves with the backend registry (src/backends/registry.ts):
import { registerBackend } from 'react-sketchapp';
registerBackend({
name: 'penpot',
defaultPlatformBridge: myHeadlessBridge,
renderToJSON(element, options, platformBridge = myHeadlessBridge) {
// build the shared intermediate tree (same `buildTree`/Yoga layout core
// used by the Sketch and Figma backends) and emit Penpot's native format
},
});Once registered, it becomes selectable via renderToDesignJSON(<App />, { backend: 'penpot' }).
A Penpot backend is not implemented yet β this is only the extension point for one.

