Expo app that embeds the Polotno editor (React + Vite) in a react-native-webview. The app passes design JSON to the editor, receives the saved design and a PNG preview back, and exports PNG and PDF to the system share sheet.
- Node.js 20+ and npm
- Xcode with an iOS simulator, or Android Studio with an emulator
| Path | Role |
|---|---|
App.tsx |
Home screen with the last saved preview and Open Editor |
src/EditorScreen.tsx |
Native bar (Close, PNG, PDF, Save), the WebView, message handling |
src/storage.ts |
Latest design and preview in app storage, export files |
src/sampleDesign.json |
Design the editor opens before the first save |
web-editor/ |
Vite React app that hosts the Polotno editor |
cd web-editor
npm install
npm run build:rnbuild:rn runs vite build with vite-plugin-singlefile and writes the one-file editor to src/editorHtml.ts, which the app imports. Run it again after changing anything in web-editor/.
Note: Set your Polotno API key before building. Create one at polotno.com/login, then add
VITE_POLOTNO_KEY=your-keytoweb-editor/.env.local. in the dashboard, addlocalhostto the key's allowed domains: the app loads the editor withbaseUrl: 'http://localhost/', so that is the origin it runs on. ChangeEDITOR_ORIGINinsrc/EditorScreen.tsxto use your own domain instead.
npm install
npx expo startPress i for the iOS simulator or a for an Android emulator. react-native-webview, expo-file-system and expo-sharing are all in Expo Go, so no development build is needed.
Tap Open Editor. Save posts { docJson, previewBase64 } to React Native; the home screen shows the returned PNG and the next session starts from the saved design. PNG and PDF export the current design and open the share sheet.
- Bundled editor. The WebView loads the editor from a string with
source={{ html, baseUrl }}. Nothing is fetched to start the editor, andbaseUrlgives the page a regularhttporigin for the license check. - React Native → editor.
injectJavaScript("window.polotnoNative.save(); true;"). The trailingtrue;is required on iOS. - Editor → React Native.
window.ReactNativeWebView.postMessage(JSON.stringify(message)), received inonMessage. - Handshake. The editor posts
{ type: "ready" }oncewindow.polotnoNativeexists. The app answers withload(<design JSON>). - Exports. The editor's toolbar download button is hidden in the app, because a browser download does nothing in a WebView. Exports cross the bridge as base64; the app writes them with
expo-file-systemand opens them withexpo-sharing.
webviewDebuggingEnabled is on in development. Inspect the editor from Safari's Develop menu (iOS simulator) or chrome://inspect (Android).