docs: App Store screenshots placeholders + APPSTORE_METADATA.md

App Store Connect requires screenshots at 1290x2796 (6.7") and
1179x2556 (6.1") for the iPhone 17 Pro Max / 17 / Pro lineup,
with at least 3 and at most 10 images per size. The repository
previously had no screenshots in docs/.

This commit adds:
  - scripts/generate_screenshot_placeholders.py - PIL-based
    generator that produces 5x 6.7" + 5x 6.1" placeholders with
    status bar, mock device frame, keyboard mock, and headline /
    subtitle text.
  - docs/screenshots/6.7/ and 6.1/ with 5 placeholder PNGs each
    (10 total, all at the correct Apple-mandated dimensions).
  - docs/screenshots/README.md explaining the dimensions,
    generation script, and how to capture real Simulator
    screenshots via `xcrun simctl io booted screenshot`.
  - docs/APPSTORE_METADATA.md - a single source of truth for
    every field in App Store Connect: name, subtitle, URLs,
    pricing, description (<=4000 chars), promotional text
    (<=170 chars), keywords (<=100 chars), release notes
    (<=4000 chars), what's new, App Privacy answers
    (Data Not Collected), encryption declaration, and reviewer
    notes.
  - AUDIT_APPSTORE.md - the v0.1.2 pre-launch audit report
    with 6 P0 items, 5 P1 items, 4 P2 items, and a 9-item
    "cross-cutting observations" section addressing the items
    in the original brief that turned out to be non-issues
    (CFBundleURLTypes in keyboard ext, NSSupportsLiveText,
    AppGroup fatalError inconsistency, AudioCaptureService
    interaction with AVAudioSession, ASRService SFSpeechRecognizer
    references). Includes an Appendix A with the local
    xcodebuild build + test results.

Important: the placeholder PNGs are intentionally bland - they
exist so App Store Connect accepts the dimensions. They MUST
be replaced with real Simulator screenshots before the actual
upload, see docs/screenshots/README.md for the workflow.

Refs: AUDIT_APPSTORE.md P0-5
This commit is contained in:
Zhongshu Audit
2026-06-20 21:34:04 +08:00
parent 97a410ca39
commit ce39ab8be1
14 changed files with 854 additions and 0 deletions
+286
View File
@@ -0,0 +1,286 @@
# App Store Connect — OSGKeyboard v0.1.2
> Use this document as a single source of truth for App Store Connect
> version metadata. All values are Apple-compliant (character limits
> respected, no marketing claims that would trigger Guideline 4.0).
---
## App Information
| Field | Value | Notes |
|---|---|---|
| **App name** | `OSGKeyboard` | CFBundleDisplayName. ≤ 30 chars. |
| **Subtitle** | `Voice input, everywhere` | ≤ 30 chars. |
| **Bundle ID** | `com.osgkeyboard.ios` | project.yml `bundleIdPrefix` + target name. |
| **SKU** | `OSGKB-001` | Internal; not user-visible. |
| **Primary locale** | `en-US` | |
| **Category (primary)** | `Utilities` | LSApplicationCategoryType. |
| **Category (secondary)** | `Productivity` | Optional, helps discovery. |
| **Content rights** | `No third-party content` | Default. |
| **Age rating** | `4+` | No objectionable content. |
---
## URLs (required)
| Field | Value |
|---|---|
| **Support URL** | `https://github.com/hkgood/OSGKeyboard/issues` |
| **Marketing URL** | `https://github.com/hkgood/OSGKeyboard` |
| **Privacy Policy URL** | `https://hkgood.github.io/OSGKeyboard/privacy/` |
| **EULA** | *Leave blank* — use Apple's standard EULA |
---
## Pricing & Availability
| Field | Value |
|---|---|
| **Price** | Free (0 USD) |
| **Availability** | All App Store territories (default) |
| **Pre-order** | No |
| **Volume purchase** | No |
---
## Description (≤ 4000 chars)
```
OSGKeyboard is a free, open-source custom keyboard for iOS 26 that turns
your voice into clean, AI-polished text — in any app.
Hold the mic key, speak naturally, release. The keyboard transcribes
your voice entirely on-device (Apple's iOS 26 SpeechAnalyzer +
DictationTranscriber), and only the final text is sent to the AI you
choose to polish it. Your audio never leaves your iPhone.
WHY OSGKEYBOARD
• Works everywhere — Messages, Notes, Mail, Slack, ChatGPT, Claude,
Cursor, browsers, terminal apps. Anywhere you can type, OSGKeyboard
types for you.
• Push-to-talk, the way voice should work. No more "Hey Siri" mode that
listens to the whole room.
• On-device speech recognition. Powered by Apple's iOS 26 speech
pipeline — no cloud ASR, no audio upload.
• Bring-your-own AI. Connect any OpenAI-compatible endpoint (OpenAI,
DeepSeek, Qwen DashScope, Moonshot, Zhipu, your own self-hosted
server). Your API key stays in the iOS Keychain.
• Three polish modes:
Off: raw transcript.
Transcribe: just the cleaned-up text.
Polish: punctuation, structure, and grammar via your chosen LLM.
• Continuous flow. One session, many utterances — no need to re-open
the host app between thoughts.
• Zero dependencies. No trackers, no analytics, no crash reporters.
The whole project is ~8,700 lines of Swift you can audit in an
afternoon.
• Privacy first. PrivacyInfo.xcprivacy declares zero collected data;
we don't run a server.
BUILT FOR
• iOS 26 and later, iPhone only.
• Anyone who types more than 100 words a day on their phone.
• Developers, writers, students, and translators who want voice input
that respects their privacy.
OPEN SOURCE
OSGKeyboard is MIT-licensed and developed in the open. Issues, pull
requests, and translations are welcome on GitHub.
https://github.com/hkgood/OSGKeyboard
```
---
## Promotional Text (≤ 170 chars, editable without new build)
```
Voice input, everywhere. Hold the mic, speak, release — AI-polished
text lands at your cursor. On-device speech, your own API key, zero
trackers. iOS 26+, free & open-source.
```
> Apple allows you to change the Promotional Text at any time without
> submitting a new build. Use it for launch-day announcements.
---
## Keywords (≤ 100 chars, comma-separated)
```
keyboard,voice,dictation,speech,transcribe,AI,polish,whisper,gpt,openai,productivity,accessibility
```
> 97 chars. Apple matches keywords against search terms; avoid the
> app name (already indexed) and competitor names.
---
## Release Notes (for v0.1.2, ≤ 4000 chars)
```
Welcome to OSGKeyboard v0.1.2 — our App Store debut!
This release focuses on review-driven polish for the iOS 26 launch:
NEW
• Dynamic ASR locale picker — Settings now lists every locale Apple's
speech framework supports, with an on-device badge so you know which
ones keep your audio on your phone.
• Apple-on-device flow polish — the continuous-capture session survives
app switching and can run for up to an hour in the foreground.
• Per-locale on-device indicator — choose Chinese (Simplified) and
you'll see the iPhone icon next to it, confirming audio never leaves
your device.
FIXED
• Light/dark mode is now consistent — cards and buttons follow the
active theme everywhere, including the in-app keyboard preview.
• iPhone-only lock — we removed iPad multitasking support; the app
declares iPhone as the only target family. This fixed TestFlight
error 90474 and the previously-misleading "supports iPad" badge.
• Keyboard preview cycling — tapping the disc now correctly cycles
through idle → recording → processing → idle, with sample
transcripts in the recording state.
• Embedded keyboard strings — Chinese and English keyboard strings
are now properly bundled into the extension binary, so language
switching works the moment you install the keyboard.
• Actool crash on iOS 26 — the legacy Icon Composer icon was removed
to stop App Store Connect rejecting the build.
CHANGED
• The keyboard's top divider line is gone — the subtle highlight
gradient is retained for visual structure without the hard separator.
• README is consistent with the implemented capability set (iOS 26
on-device SpeechAnalyzer + DictationTranscriber only).
KNOWN ISSUES
• Continuous mode requires Full Access (Apple's policy, not ours).
The onboarding flow walks you through enabling it.
• Some iCloud-synced keyboards can take a few seconds to appear in
the Add New Keyboard list. This is iOS 26 behavior.
We'd love to hear from you — open an issue on GitHub, or rate this
version to help others find it.
```
---
## What's New in This Version
*(Same as Release Notes, but shorter; the What's New field is also
capped at 4000 chars. Apple displays it in the Updates tab.)*
```
Welcome to v0.1.2 — our App Store debut!
NEW: Dynamic ASR locale picker with on-device indicator. Continuous
flow sessions survive app switching for up to an hour. Polish modes:
off / transcribe / polish.
FIXED: Light/dark mode is now consistent across the keyboard preview.
TestFlight error 90474 (iPhone-only) is resolved. Keyboard preview
disc correctly cycles idle → recording → processing. Keyboard
strings are properly embedded in the extension bundle for instant
language switching.
CHANGED: The hard divider line on the keyboard is gone; the subtle
gradient highlight remains.
We'd love your feedback — open an issue on GitHub or rate this app.
```
---
## App Privacy (App Store Connect "Privacy" section)
Choose **"Data Not Collected"** in the first question.
The OSGKeyboard app and keyboard extension collect **no data** from
you. All processing happens on-device or through the LLM endpoint you
explicitly configure. The app does not embed any analytics, crash
report, or tracking SDK.
| Question | Answer |
|---|---|
| Data collected from this app? | **No** |
| Data used to track you? | **No** |
| Data linked to your identity? | **No** |
The `PrivacyInfo.xcprivacy` files in both `OSGKeyboard/` and
`OSGKeyboardExt/` declare `NSPrivacyTracking: false` and
`NSPrivacyCollectedDataTypes: []` to match.
---
## Encryption (annual survey)
`Info.plist` declares `ITSAppUsesNonExemptEncryption = false`. The
annual survey will be auto-skipped on upload. If prompted manually:
* Does your app use encryption? **No** (the LLM call uses HTTPS, which
Apple classifies as "standard internet protocols" and is exempt
under category 5 part 2 note 4 of the EAR).
* Is your app exempt under Category 5 Part 2? **Yes** (HTTPS only).
---
## App Review information
When the build is uploaded and you click "Add for Review", fill in:
| Field | Value |
|---|---|
| **Sign-in required** | No (no account) |
| **Demo account** | n/a |
| **Contact info** | (your Apple Developer account email) |
| **Phone** | (your phone; only Apple sees it) |
| **Notes to reviewer** | (see below) |
### Notes to App Review
```
OSGKeyboard is a free, open-source custom keyboard. To test it end
to end, please:
1. Install the keyboard:
Settings → General → Keyboard → Keyboards → Add New Keyboard →
under "Third-Party Keyboards" choose "OSGKeyboard".
2. Enable Full Access for OSGKeyboard (onboarding in the app walks
through this, but you can also tap it in the keyboard settings).
Full Access is required for the continuous-capture flow session
(network access for the LLM polish step + shared App Group
container with the main app). The mic is captured on-device; the
network call only sends the final text transcript to the LLM
endpoint configured in Settings.
3. In any app, switch to OSGKeyboard (globe key), then hold the
purple mic key, speak, and release.
4. For the LLM polish demo: open OSGKeyboard's main app, Settings,
Provider. Enter any OpenAI-compatible key (OpenAI, DeepSeek,
Qwen, Moonshot, Zhipu, or a self-hosted URL). The default
provider "Custom" works with a local mock server if you have
one running.
5. The privacy policy is at
https://hkgood.github.io/OSGKeyboard/privacy/
Source code: https://github.com/hkgood/OSGKeyboard
```
---
## Submission checklist
- [ ] All 10 screenshots replaced with real Simulator captures
(5 × 1290×2796 + 5 × 1179×2556)
- [ ] Archive in Xcode → Product → Archive → Distribute App → App
Store Connect → Upload
- [ ] Select the new build under "Builds" in the version
- [ ] Fill in metadata from this document
- [ ] Privacy: "Data Not Collected"
- [ ] Encryption: skip (auto-skipped via Info.plist key)
- [ ] Add for review
- [ ] Submit
Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

+73
View File
@@ -0,0 +1,73 @@
# App Store Screenshots
> ⚠️ **PLACEHOLDERS.** The 10 PNGs in this directory are
> automatically generated blanks produced by
> `scripts/generate_screenshot_placeholders.py` and must be
> **replaced with real Simulator screenshots** before App Store
> submission. They use the correct dimensions (1290×2796 for
> 6.7", 1179×2556 for 6.1") so the upload validator will accept
> them, but they contain no real UI.
## Required dimensions (2026)
| Size | Devices | Dimensions | Apple requirement |
|------|---------|-----------|---|
| 6.7" | iPhone 17 Pro Max, 17, 16 Pro Max, 16 Plus, 15 Pro Max, 15 Plus | 1290 × 2796 px | **Required** (3-10 images) |
| 6.1" | iPhone 17 Pro, 17, 16 Pro, 16, 15 Pro, 15, 14 Pro, 14 | 1179 × 2556 px | **Required** (3-10 images) |
| 5.5" | iPhone 8 Plus (legacy) | 1242 × 2208 px | Optional since 2024 |
iPad screenshots are not required because OSGKeyboard is iPhone-only
(`TARGETED_DEVICE_FAMILY = 1`).
## Layout
```
docs/screenshots/
├── 6.7/ ← 1290×2796 (iPhone 17 Pro Max / 17)
│ ├── 01-keyboard-default.png
│ ├── 02-flow-session.png
│ ├── 03-on-device-asr.png
│ ├── 04-llm-polish.png
│ └── 05-providers.png
└── 6.1/ ← 1179×2556 (iPhone 17 Pro / 17)
├── 01-keyboard-default.png
├── 02-flow-session.png
├── 03-on-device-asr.png
├── 04-llm-polish.png
└── 05-providers.png
```
## How to capture real screenshots
1. Open `OSGKeyboard.xcodeproj` in Xcode 26+
2. Run on **iPhone 17 Pro** simulator (6.1" set) and **iPhone 17 Pro Max** simulator (6.7" set)
3. For each scene:
```bash
# Take a screenshot of the simulator window
xcrun simctl io booted screenshot ~/Desktop/shot.png
```
4. Process for App Store (Apple rejects frames containing the device bezel — full-screen content only):
```bash
# The simulator screenshot already has a thin device frame.
# Open in Preview, crop to full screen (⌘+K with ⌥ for precision),
# export as PNG at 1290×2796 or 1179×2556.
sips -z 2796 1290 shot.png --out final-6.7.png
sips -z 2556 1179 shot.png --out final-6.1.png
```
5. Replace the placeholders with the real captures, keeping the
same filenames so the App Store Connect → Version → Uploads UI
auto-pairs by file.
## Scenes to capture
The 5 placeholders are intentional scene placeholders. Capture these
*exact* screens, in this order:
1. **Keyboard at rest** — the iOS keyboard, OSGKeyboard mode, no recording
2. **Flow session active** — keyboard with the green/orange recording ring,
partial transcript visible in the host text field
3. **On-device ASR** — Settings view with the locale list, the on-device
indicator (iPhone icon) visible next to ≥ 3 supported locales
4. **LLM polish** — Settings view with the API provider card, a sample
"polish" transformation shown in the inline preview
5. **Providers** — API Settings card scrolled to show all 6 provider logos