#!/usr/bin/env node
import { createRequire } from "node:module";
import { mkdir, readFile } from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const rootDir = path.resolve(__dirname, "..");
const requireFromApp = createRequire(path.join(rootDir, "app/package.json"));
const { chromium } = requireFromApp("@playwright/test");
const outDir = path.join(rootDir, "fastlane/screenshots/en-US");
const width = 1320;
const height = 2868;
async function pngDataUri(relativePath) {
const buffer = await readFile(path.join(rootDir, relativePath));
return `data:image/png;base64,${buffer.toString("base64")}`;
}
function escapeHtml(value) {
return value
.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">")
.replaceAll('"', """);
}
function shell(content) {
return `
`;
}
function pairScreen() {
return shell(`
Pair with your desktop
Scan the QR code from OpenHuman on your computer and connect your phone in seconds.
- Open OpenHuman on desktop
- Go to Settings > Devices
- Tap Pair phone to show QR
`);
}
function chatScreen() {
return shell(`
I found the latest thread context from your desktop workspace.
Summarize what needs my attention.
You have two follow-ups, one meeting note, and a draft ready to send.
`);
}
function privacyScreen() {
return shell(`
Anchored to your desktop
Your phone is a companion surface. Memory, tools, and integrations stay with the OpenHuman runtime you paired.
Short-lived QR pairingConnect intentionally
Push-to-talk voiceSpeak when you choose
Desktop-owned contextUse the assistant you already set up
`);
}
function html({ title, kicker, body, iconUri, wordmarkUri }) {
return `
${escapeHtml(kicker)}
${escapeHtml(title)}
${escapeHtml(body)}
${body.includes("QR") ? pairScreen() : title.includes("voice") ? chatScreen() : privacyScreen()}
`;
}
const shots = [
{
file: "iPhone_6_9_01_pair_with_desktop.png",
kicker: "OpenHuman for iPhone",
title: "Pair with your desktop",
body: "Scan the QR code from OpenHuman on your computer and connect your phone to the assistant you already trust.",
},
{
file: "iPhone_6_9_02_chat_and_voice.png",
kicker: "Text and push-to-talk",
title: "Chat by text or voice",
body: "Send quick messages, dictate thoughts, and get spoken replies while your desktop runtime does the work.",
},
{
file: "iPhone_6_9_03_desktop_anchored.png",
kicker: "Desktop-owned context",
title: "Your memory stays anchored",
body: "Use your paired OpenHuman setup for memory, tools, and integrations without turning the phone into a separate workspace.",
},
];
await mkdir(outDir, { recursive: true });
const iconUri = await pngDataUri(
"app/src-tauri-mobile/icons/store/appstore.png",
);
const wordmarkUri = await pngDataUri(
"app/public/brand/OpenhumanLogo+wordmark-White.png",
);
const browser = await chromium.launch();
try {
const page = await browser.newPage({
viewport: { width, height },
deviceScaleFactor: 1,
});
for (const shot of shots) {
await page.setContent(html({ ...shot, iconUri, wordmarkUri }), {
waitUntil: "load",
});
const destination = path.join(outDir, shot.file);
await page.screenshot({ path: destination, fullPage: false });
console.log(
`[ios-appstore-assets] wrote ${path.relative(rootDir, destination)}`,
);
}
} finally {
await browser.close();
}