# scripts/mobile-showcase.config.ts · screen/t3code-personal

[View on GitCafe](https://git.cafe/screen/t3code-personal/blob/c9a0e8a119271765196dec38ef91395713da4213/scripts/mobile-showcase.config.ts)

Repository: [screen/t3code-personal](https://git.cafe/screen/t3code-personal)

Visibility: public

Requested revision: c9a0e8a119271765196dec38ef91395713da4213

Requested commit: c9a0e8a119271765196dec38ef91395713da4213

Commit: c9a0e8a119271765196dec38ef91395713da4213

Blob: 544d8056981ee2366be5960c7ca94d7cc9a81774

Size: 7886 bytes

[Immutable source](https://git.cafe/screen/t3code-personal/blob/c9a0e8a119271765196dec38ef91395713da4213/scripts/mobile-showcase.config.ts?format=markdown)

```
import {
  MOBILE_DEFAULT_THEME_ID,
  MOBILE_THEME_IDS,
  type MobileThemeId,
} from "@t3tools/shared/themePalettes";

import { SHOWCASE_SCENES, type ShowcaseScene } from "./mobile-showcase-environment.ts";

export { SHOWCASE_SCENES };
export type { ShowcaseScene };

export type ShowcaseAppearance = "light" | "dark";

/** Every palette the mobile appearance settings can select. */
export const SHOWCASE_THEMES = MOBILE_THEME_IDS;
export const DEFAULT_SHOWCASE_THEME = MOBILE_DEFAULT_THEME_ID;
export type ShowcaseTheme = MobileThemeId;

export interface ShowcaseStoreAssetSpec {
  readonly store: "apple" | "google-play";
  /** Device directory relative to ShowcaseConfig.outputDirectory. */
  readonly directory: string;
  readonly width: number;
  readonly height: number;
  readonly minimumUploadCount: number;
  readonly maximumUploadCount: number;
  readonly maximumFileSizeBytes?: number;
}

export interface ShowcaseIosDevice {
  readonly id: string;
  readonly platform: "ios";
  /** Exact name from `xcrun simctl list devices available`. */
  readonly simulator: string;
  /** Device type used to create a disposable simulator when the named one is absent. */
  readonly simulatorDeviceType?: string;
  /** Appearance used when the CLI does not pass --appearance. */
  readonly appearance: ShowcaseAppearance;
  /** Palette used when the CLI does not pass --theme. */
  readonly theme: ShowcaseTheme;
  /** Orientation applied by the capture harness. Defaults to portrait. */
  readonly orientation?: "portrait" | "landscape";
  readonly scenes: ReadonlyArray<ShowcaseScene>;
  readonly storeAsset: ShowcaseStoreAssetSpec;
}

export interface ShowcaseAndroidDevice {
  readonly id: string;
  readonly platform: "android";
  /** Exact name from `emulator -list-avds`. */
  readonly avd: string;
  /** Appearance used when the CLI does not pass --appearance. */
  readonly appearance: ShowcaseAppearance;
  /** Palette used when the CLI does not pass --theme. */
  readonly theme: ShowcaseTheme;
  /** Native ABI used by the AVD, from its config.ini `abi.type`. */
  readonly abi?: "arm64-v8a" | "x86_64" | "x86" | "armeabi-v7a";
  readonly scenes: ReadonlyArray<ShowcaseScene>;
  /** Optional capture viewport. Omit to use the AVD's native size and density. */
  readonly viewport?: {
    readonly width: number;
    readonly height: number;
    readonly density?: number;
  };
  readonly storeAsset: ShowcaseStoreAssetSpec;
}

export type ShowcaseDevice = ShowcaseIosDevice | ShowcaseAndroidDevice;

export interface ShowcaseConfig {
  readonly outputDirectory: string;
  readonly metroPort: number;
  readonly settleDelayMs: number;
  readonly devices: ReadonlyArray<ShowcaseDevice>;
}

const ANDROID_ABIS = ["arm64-v8a", "x86_64", "x86", "armeabi-v7a"] as const;

export function resolveShowcaseAndroidAbi(
  value: string | undefined,
): NonNullable<ShowcaseAndroidDevice["abi"]> {
  if (!value) return "arm64-v8a";
  if (ANDROID_ABIS.some((abi) => abi === value)) {
    return value as NonNullable<ShowcaseAndroidDevice["abi"]>;
  }
  throw new Error(
    `Unsupported T3_SHOWCASE_ANDROID_ABI '${value}'. Use ${ANDROID_ABIS.join(", ")}.`,
  );
}

/**
 * The defaults cover every App Store Connect and Google Play upload slot used
 * by the mobile app. Edit this matrix (or pass --device / --scene) without
 * changing the runner. Every target declares and validates its exact upload
 * dimensions so SDK or emulator changes cannot silently produce invalid files.
 */
const config: ShowcaseConfig = {
  outputDirectory: "artifacts/app-store/screenshots",
  // Dedicated port so the harness cannot attach to a normal mobile dev server
  // (or a second worktree) and capture the wrong bundle.
  metroPort: 8199,
  settleDelayMs: 2_500,
  devices: [
    {
      id: "iphone-6.9",
      platform: "ios",
      // A disposable device lands on the newest runtime, whose default lock
      // screen wallpaper suits both appearances; a stock one may be older.
      simulator: "T3 Showcase iPhone 17 Pro Max",
      simulatorDeviceType: "com.apple.CoreSimulator.SimDeviceType.iPhone-17-Pro-Max",
      appearance: "dark",
      theme: DEFAULT_SHOWCASE_THEME,
      scenes: ["thread", "terminal", "review", "threads", "environments", "agent-activity"],
      storeAsset: {
        store: "apple",
        directory: "apple/iphone-6.9",
        width: 1320,
        height: 2868,
        minimumUploadCount: 1,
        maximumUploadCount: 10,
      },
    },
    {
      id: "iphone-6.5",
      platform: "ios",
      simulator: "T3 Showcase iPhone 14 Plus",
      simulatorDeviceType: "com.apple.CoreSimulator.SimDeviceType.iPhone-14-Plus",
      appearance: "dark",
      theme: DEFAULT_SHOWCASE_THEME,
      scenes: ["thread", "terminal", "review", "threads", "environments", "agent-activity"],
      storeAsset: {
        store: "apple",
        directory: "apple/iphone-6.5",
        width: 1284,
        height: 2778,
        minimumUploadCount: 1,
        maximumUploadCount: 10,
      },
    },
    {
      id: "ipad-13",
      platform: "ios",
      simulator: "iPad Pro 13-inch (M5)",
      simulatorDeviceType: "com.apple.CoreSimulator.SimDeviceType.iPad-Pro-13-inch-M5-16GB",
      appearance: "dark",
      theme: DEFAULT_SHOWCASE_THEME,
      orientation: "landscape",
      // The lock screen does not follow the app's self-rotation, so a
      // headless landscape capture of it would come out sideways.
      scenes: ["thread", "terminal", "review", "threads", "environments"],
      storeAsset: {
        store: "apple",
        directory: "apple/ipad-13",
        width: 2752,
        height: 2064,
        minimumUploadCount: 1,
        maximumUploadCount: 10,
      },
    },
    {
      id: "pixel",
      platform: "android",
      avd: "Pixel_10_Pro",
      // Apple Silicon uses ARM64 locally; CI overrides this with x86_64 so its
      // Blacksmith Linux runner can use KVM acceleration.
      abi: resolveShowcaseAndroidAbi(process.env.T3_SHOWCASE_ANDROID_ABI),
      appearance: "dark",
      theme: DEFAULT_SHOWCASE_THEME,
      viewport: {
        width: 1080,
        height: 1920,
        density: 420,
      },
      scenes: ["thread", "terminal", "review", "threads", "environments", "agent-activity"],
      storeAsset: {
        store: "google-play",
        directory: "google-play/phone",
        width: 1080,
        height: 1920,
        minimumUploadCount: 2,
        maximumUploadCount: 8,
        maximumFileSizeBytes: 8 * 1024 * 1024,
      },
    },
    {
      id: "android-tablet-7",
      platform: "android",
      avd: "Pixel_10_Pro",
      abi: resolveShowcaseAndroidAbi(process.env.T3_SHOWCASE_ANDROID_ABI),
      appearance: "dark",
      theme: DEFAULT_SHOWCASE_THEME,
      viewport: {
        width: 1080,
        height: 1920,
        density: 288,
      },
      scenes: ["thread", "terminal", "review", "threads", "environments", "agent-activity"],
      storeAsset: {
        store: "google-play",
        directory: "google-play/tablet-7",
        width: 1080,
        height: 1920,
        minimumUploadCount: 4,
        maximumUploadCount: 8,
        maximumFileSizeBytes: 8 * 1024 * 1024,
      },
    },
    {
      id: "android-tablet-10",
      platform: "android",
      avd: "Pixel_10_Pro",
      abi: resolveShowcaseAndroidAbi(process.env.T3_SHOWCASE_ANDROID_ABI),
      appearance: "dark",
      theme: DEFAULT_SHOWCASE_THEME,
      viewport: {
        width: 1440,
        height: 2560,
        density: 288,
      },
      scenes: ["thread", "terminal", "review", "threads", "environments", "agent-activity"],
      storeAsset: {
        store: "google-play",
        directory: "google-play/tablet-10",
        width: 1440,
        height: 2560,
        minimumUploadCount: 4,
        maximumUploadCount: 8,
        maximumFileSizeBytes: 8 * 1024 * 1024,
      },
    },
  ],
};

export default config;

```
