Add tvOS App Store metadata, screenshots, and icon assets
- Add English metadata and review notes for tvOS - Add tvOS screenshots folder and README shot list - Add tvOS App Store icon and top shelf assets - Align tvOS bundle identifier with main app - Update release and TestFlight checklists for tvOS - Fix AskSheetView keyboard shortcut for tvOS - Update docs for tvOS target and App Store submission
Seto Elkahfi committed
May 15, 2026 at 13:22 UTC
cf5a0b1c9173b256efed3d639aca32a649565d27
44 files changed
+307
-18
AppStore/README.md
+3
@@ -6,15 +6,18 @@ This folder keeps the App Store-facing copy and planning docs for Klepon.
6
7
- `metadata/en-US/` — English metadata copy for the iPhone app
8
- `metadata-macos/en-US/` — English metadata copy for the macOS app
9
+- `metadata-tvos/en-US/` — English metadata copy for the tvOS app
10
- `metadata-visionos/en-US/` — English metadata copy for the visionOS app
11
- `screenshots/iphone/` — iPhone screenshot exports
12
- `screenshots/macos/` — macOS screenshot exports
13
+- `screenshots/tvos/` — tvOS screenshot exports
14
- `screenshots/visionos/` — visionOS screenshot exports
15
- `screenshots/watch/` — watchOS screenshot exports
16
- `screenshots/README.md` — screenshot shot list and titles
17
- `testflight-checklist.md` — pre-TestFlight checklist
18
- `release-checklist.md` — broader release checklist
19
- `macos-appstore-notes.md` — macOS-specific submission notes
20
+- `tvos-appstore-notes.md` — tvOS-specific submission notes
21
- `visionos-appstore-notes.md` — visionOS-specific submission notes
22
23
The screenshot folders are intentionally empty in Git until real exports are added.
AppStore/metadata-tvos/en-US/description.txt
new
+16
@@ -0,0 +1,16 @@
1
+Discover Indonesian food on Apple TV with warmth, clarity, and privacy.
2
+
3
+Klepon helps you explore dishes, ingredients, and food traditions from across Indonesia in a simple living-room experience that feels calm, readable, and easy to browse.
4
+
5
+Browse curated guides to iconic dishes, regional favorites, sweet treats, and essential ingredients. Learn what a dish is, what it tastes like, what usually goes into it, and what to try next.
6
+
7
+When you want a little more context, Klepon can answer short follow-up questions privately on device with an optional local guide.
8
+
9
+What you can do in Klepon:
10
+- Explore curated Indonesian food guides
11
+- Learn dishes, ingredients, and traditions
12
+- Search quickly when you spot an unfamiliar name
13
+- Save dishes you want to remember
14
+- Ask short follow-up questions privately on device
15
+
16
+Klepon is for curious eaters, travelers, diaspora families, and anyone who wants a more thoughtful way to discover Indonesian food.
AppStore/metadata-tvos/en-US/keywords.txt
new
+1
@@ -0,0 +1 @@
1
+indonesian food,dishes,ingredients,cuisine,guide,travel
AppStore/metadata-tvos/en-US/name.txt
new
+1
@@ -0,0 +1 @@
1
+Klepon: Taste of Indonesia
AppStore/metadata-tvos/en-US/promotional_text.txt
new
+1
@@ -0,0 +1 @@
1
+A calm Apple TV guide to Indonesian dishes, ingredients, and food traditions.
AppStore/metadata-tvos/en-US/review_notes.txt
new
+5
@@ -0,0 +1,5 @@
1
+This tvOS app is a browse-first guide and is fully usable without enabling the private guide.
2
+
3
+The private guide is optional. If the user chooses to enable it, the app downloads a local on-device model and uses it for short follow-up answers inside the guide.
4
+
5
+The tvOS target uses the same main app bundle identifier as the iPhone app and uses the shared app group container for local model storage when available.
AppStore/metadata-tvos/en-US/subtitle.txt
new
+1
@@ -0,0 +1 @@
1
+Indonesian food guide
AppStore/release-checklist.md
+4
@@ -4,6 +4,7 @@
4
5
- [ ] iPhone app builds cleanly
6
- [ ] macOS app builds cleanly
7
+- [ ] tvOS app builds cleanly
8
- [ ] visionOS app builds cleanly
9
- [ ] watchOS companion builds cleanly
10
- [ ] README is current
@@ -18,6 +19,7 @@
19
- [ ] Ask flow works on device with acceptable latency
20
- [ ] Watch app content is readable and useful at a glance
21
- [ ] macOS window flows feel native and polished enough for v1
22
+- [ ] tvOS focus and remote navigation feel polished enough for v1
23
- [ ] visionOS window flows feel polished enough for a simple v1
24
- [ ] No obvious sample-app copy remains
25
@@ -25,6 +27,7 @@
27
28
- [ ] iPhone bundle identifier is correct
29
- [ ] macOS bundle identifier is correct
30
+- [ ] tvOS bundle identifier is correct
31
- [ ] visionOS bundle identifier is correct
32
- [ ] watch bundle identifier is correct
33
- [ ] App Group entitlement is correct for the shipping account
@@ -35,6 +38,7 @@
38
39
- [ ] TestFlight build installed on at least one real iPhone
40
- [ ] macOS archive validates cleanly for App Store submission
41
+- [ ] tvOS archive validates cleanly for App Store submission
42
- [ ] visionOS archive validates cleanly for App Store submission
43
- [ ] Watch companion installed and tested on at least one real Apple Watch
44
- [ ] Release notes are written
AppStore/screenshots/README.md
+9
@@ -24,6 +24,15 @@
24
3. `Ask privately on device`
25
- Show the ask flow with a grounded answer card and source chips.
26
27
+## tvOS screenshots
28
+
29
+1. `A calm guide on Apple TV`
30
+ - Show the Discover screen with focus on the featured dish and one visible collection rail.
31
+2. `Browse and save from the couch`
32
+ - Show a readable Search or Saved view with a realistic shortlist.
33
+3. `Ask privately on device`
34
+ - Show the ask flow with a grounded answer card and focus-friendly suggestions.
35
+
36
## visionOS screenshots
37
38
1. `A calm guide in your space`
AppStore/screenshots/tvos/.gitkeep
AppStore/testflight-checklist.md
+2
@@ -13,6 +13,7 @@
13
- [ ] iPhone target builds on simulator
14
- [ ] iPhone target runs on a real device
15
- [ ] macOS target builds on the release Xcode version
16
+- [ ] tvOS target builds on the release Xcode version
17
- [ ] visionOS target builds on the release Xcode version
18
- [ ] Watch target builds on simulator
19
- [ ] Watch target runs with the paired iPhone app
@@ -39,4 +40,5 @@
40
- [ ] No local machine junk files are staged
41
- [ ] Bundle identifiers and App Group values are intentional for the release build
42
- [ ] macOS release signing uses the sandboxed entitlements file
43
+- [ ] tvOS release signing uses the shared app identifier and App Group entitlement
44
- [ ] visionOS release signing uses the shared app identifier and App Group entitlement
AppStore/tvos-appstore-notes.md
new
+62
@@ -0,0 +1,62 @@
1
+# tvOS App Store notes
2
+
3
+## Bundle identifier
4
+
5
+The tvOS target uses the same bundle identifier as the iPhone app:
6
+
7
+- `ai.splitfire.klepon`
8
+
9
+That keeps the main Apple-platform app identity aligned across iPhone, Apple TV, Mac, and visionOS. The watch companion still uses its own watch bundle identifier, which Apple requires for the companion app target.
10
+
11
+## App shape
12
+
13
+The current tvOS target is intentionally simple for v1.
14
+
15
+- It is a focus-friendly SwiftUI app
16
+- It uses tabs and navigation stacks
17
+- It keeps the private guide inside the existing browse-first experience
18
+
19
+This is deliberate. The goal is a clean, stable App Store MVP for Apple TV without overbuilding the first release.
20
+
21
+## Required configuration
22
+
23
+The tvOS target uses:
24
+
25
+- `KleponTV/Info.plist`
26
+- `KleponTV/KleponTV.entitlements`
27
+
28
+Important settings:
29
+
30
+- `ITSAppUsesNonExemptEncryption = false`
31
+- `com.apple.security.application-groups = group.com.ondeinference.apps`
32
+
33
+The App Group keeps local model storage aligned with the other Apple targets.
34
+
35
+## Build and archive
36
+
37
+Generate the project:
38
+
39
+```/dev/null/sh#L1-1
40
+xcodegen generate
41
+```
42
+
43
+Build the tvOS target locally:
44
+
45
+```/dev/null/sh#L1-1
46
+xcodebuild build -project Klepon.xcodeproj -scheme 'Klepon TV' -destination 'generic/platform=tvOS Simulator'
47
+```
48
+
49
+Archive the tvOS target:
50
+
51
+```/dev/null/sh#L1-1
52
+xcodebuild archive -project Klepon.xcodeproj -scheme 'Klepon TV' -destination 'generic/platform=tvOS' -archivePath build/KleponTV.xcarchive
53
+```
54
+
55
+## Submission checklist
56
+
57
+Before upload, confirm:
58
+
59
+- the signing profile is for `ai.splitfire.klepon`
60
+- the App Group capability exists for the shipping team
61
+- the app feels clean and navigable with the Siri Remote focus model
62
+- tvOS screenshots and metadata are ready in `AppStore/screenshots/tvos/` and `AppStore/metadata-tvos/en-US/`
Klepon.xcodeproj/project.pbxproj
+2
-2
@@ -1276,7 +1276,7 @@
1276
"@executable_path/Frameworks",
1277
);
1278
MARKETING_VERSION = 1.0.0;
1279
- PRODUCT_BUNDLE_IDENTIFIER = ai.splitfire.klepon.tv;
1279
+ PRODUCT_BUNDLE_IDENTIFIER = ai.splitfire.klepon;
1280
PRODUCT_NAME = Klepon;
1281
SDKROOT = appletvos;
1282
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -1441,7 +1441,7 @@
1441
"@executable_path/Frameworks",
1442
);
1443
MARKETING_VERSION = 1.0.0;
1444
- PRODUCT_BUNDLE_IDENTIFIER = ai.splitfire.klepon.tv;
1444
+ PRODUCT_BUNDLE_IDENTIFIER = ai.splitfire.klepon;
1445
PRODUCT_NAME = Klepon;
1446
SDKROOT = appletvos;
1447
SWIFT_OPTIMIZATION_LEVEL = "-O";
Klepon/Assets.xcassets/AppIconTV.appiconset/AppIconTV-Large.png
Binary files a/Klepon/Assets.xcassets/AppIconTV.appiconset/AppIconTV-Large.png and /dev/null differ
Klepon/Assets.xcassets/AppIconTV.appiconset/AppIconTV-Large@2x.png
Binary files a/Klepon/Assets.xcassets/AppIconTV.appiconset/AppIconTV-Large@2x.png and /dev/null differ
Klepon/Assets.xcassets/AppIconTV.appiconset/AppIconTV-Small.png
Binary files a/Klepon/Assets.xcassets/AppIconTV.appiconset/AppIconTV-Small.png and /dev/null differ
Klepon/Assets.xcassets/AppIconTV.appiconset/AppIconTV-Small@2x.png
Binary files a/Klepon/Assets.xcassets/AppIconTV.appiconset/AppIconTV-Small@2x.png and /dev/null differ
Klepon/Assets.xcassets/AppIconTV.appiconset/Contents.json
deleted
-12
@@ -1,12 +0,0 @@
1
-{
2
- "images" : [
3
- { "idiom" : "tv", "size" : "400x240", "scale" : "1x", "filename" : "AppIconTV-Small.png" },
4
- { "idiom" : "tv", "size" : "400x240", "scale" : "2x", "filename" : "AppIconTV-Small@2x.png" },
5
- { "idiom" : "tv", "size" : "1280x768", "scale" : "1x", "filename" : "AppIconTV-Large.png" },
6
- { "idiom" : "tv", "size" : "1280x768", "scale" : "2x", "filename" : "AppIconTV-Large@2x.png" }
7
- ],
8
- "info" : {
9
- "author" : "xcode",
10
- "version" : 1
11
- }
12
-}
Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS - App Store.imagestack/Back.imagestacklayer/Content.imageset/Back.png
Binary files /dev/null and b/Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS - App Store.imagestack/Back.imagestacklayer/Content.imageset/Back.png differ
Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json
new
+12
@@ -0,0 +1,12 @@
1
+{
2
+ "images" : [
3
+ {
4
+ "filename" : "Back.png",
5
+ "idiom" : "tv"
6
+ }
7
+ ],
8
+ "info" : {
9
+ "author" : "xcode",
10
+ "version" : 1
11
+ }
12
+}
Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS - App Store.imagestack/Back.imagestacklayer/Contents.json
new
+6
@@ -0,0 +1,6 @@
1
+{
2
+ "info" : {
3
+ "author" : "xcode",
4
+ "version" : 1
5
+ }
6
+}
Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS - App Store.imagestack/Contents.json
new
+14
@@ -0,0 +1,14 @@
1
+{
2
+ "info" : {
3
+ "author" : "xcode",
4
+ "version" : 1
5
+ },
6
+ "layers" : [
7
+ {
8
+ "filename" : "Front.imagestacklayer"
9
+ },
10
+ {
11
+ "filename" : "Back.imagestacklayer"
12
+ }
13
+ ]
14
+}
Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json
new
+12
@@ -0,0 +1,12 @@
1
+{
2
+ "images" : [
3
+ {
4
+ "filename" : "Front.png",
5
+ "idiom" : "tv"
6
+ }
7
+ ],
8
+ "info" : {
9
+ "author" : "xcode",
10
+ "version" : 1
11
+ }
12
+}
Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS - App Store.imagestack/Front.imagestacklayer/Content.imageset/Front.png
Binary files /dev/null and b/Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS - App Store.imagestack/Front.imagestacklayer/Content.imageset/Front.png differ
Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS - App Store.imagestack/Front.imagestacklayer/Contents.json
new
+6
@@ -0,0 +1,6 @@
1
+{
2
+ "info" : {
3
+ "author" : "xcode",
4
+ "version" : 1
5
+ }
6
+}
Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS.imagestack/Back.imagestacklayer/Content.imageset/Back.png
Binary files /dev/null and b/Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS.imagestack/Back.imagestacklayer/Content.imageset/Back.png differ
Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS.imagestack/Back.imagestacklayer/Content.imageset/Back@2x.png
Binary files /dev/null and b/Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS.imagestack/Back.imagestacklayer/Content.imageset/Back@2x.png differ
Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS.imagestack/Back.imagestacklayer/Content.imageset/Contents.json
new
+18
@@ -0,0 +1,18 @@
1
+{
2
+ "images" : [
3
+ {
4
+ "filename" : "Back.png",
5
+ "idiom" : "tv",
6
+ "scale" : "1x"
7
+ },
8
+ {
9
+ "filename" : "Back@2x.png",
10
+ "idiom" : "tv",
11
+ "scale" : "2x"
12
+ }
13
+ ],
14
+ "info" : {
15
+ "author" : "xcode",
16
+ "version" : 1
17
+ }
18
+}
Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS.imagestack/Back.imagestacklayer/Contents.json
new
+12
@@ -0,0 +1,12 @@
1
+{
2
+ "info" : {
3
+ "author" : "xcode",
4
+ "version" : 1
5
+ },
6
+ "properties" : {
7
+ "frame-size" : {
8
+ "height" : 240,
9
+ "width" : 400
10
+ }
11
+ }
12
+}
Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS.imagestack/Contents.json
new
+14
@@ -0,0 +1,14 @@
1
+{
2
+ "info" : {
3
+ "author" : "xcode",
4
+ "version" : 1
5
+ },
6
+ "layers" : [
7
+ {
8
+ "filename" : "Front.imagestacklayer"
9
+ },
10
+ {
11
+ "filename" : "Back.imagestacklayer"
12
+ }
13
+ ]
14
+}
Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS.imagestack/Front.imagestacklayer/Content.imageset/Contents.json
new
+18
@@ -0,0 +1,18 @@
1
+{
2
+ "images" : [
3
+ {
4
+ "filename" : "Front.png",
5
+ "idiom" : "tv",
6
+ "scale" : "1x"
7
+ },
8
+ {
9
+ "filename" : "Front@2x.png",
10
+ "idiom" : "tv",
11
+ "scale" : "2x"
12
+ }
13
+ ],
14
+ "info" : {
15
+ "author" : "xcode",
16
+ "version" : 1
17
+ }
18
+}
Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS.imagestack/Front.imagestacklayer/Content.imageset/Front.png
Binary files /dev/null and b/Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS.imagestack/Front.imagestacklayer/Content.imageset/Front.png differ
Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS.imagestack/Front.imagestacklayer/Content.imageset/Front@2x.png
Binary files /dev/null and b/Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS.imagestack/Front.imagestacklayer/Content.imageset/Front@2x.png differ
Klepon/Assets.xcassets/AppIconTV.brandassets/App Icon - tvOS.imagestack/Front.imagestacklayer/Contents.json
new
+12
@@ -0,0 +1,12 @@
1
+{
2
+ "info" : {
3
+ "author" : "xcode",
4
+ "version" : 1
5
+ },
6
+ "properties" : {
7
+ "frame-size" : {
8
+ "height" : 240,
9
+ "width" : 400
10
+ }
11
+ }
12
+}
Klepon/Assets.xcassets/AppIconTV.brandassets/Contents.json
new
+32
@@ -0,0 +1,32 @@
1
+{
2
+ "assets" : [
3
+ {
4
+ "filename" : "App Icon - tvOS - App Store.imagestack",
5
+ "idiom" : "tv",
6
+ "role" : "primary-app-icon",
7
+ "size" : "1280x768"
8
+ },
9
+ {
10
+ "filename" : "App Icon - tvOS.imagestack",
11
+ "idiom" : "tv",
12
+ "role" : "primary-app-icon",
13
+ "size" : "400x240"
14
+ },
15
+ {
16
+ "filename" : "Top Shelf Image.imageset",
17
+ "idiom" : "tv",
18
+ "role" : "top-shelf-image",
19
+ "size" : "1920x720"
20
+ },
21
+ {
22
+ "filename" : "Top Shelf Image Wide.imageset",
23
+ "idiom" : "tv",
24
+ "role" : "top-shelf-image-wide",
25
+ "size" : "2320x720"
26
+ }
27
+ ],
28
+ "info" : {
29
+ "author" : "xcode",
30
+ "version" : 1
31
+ }
32
+}
Klepon/Assets.xcassets/AppIconTV.brandassets/Top Shelf Image Wide.imageset/Contents.json
new
+18
@@ -0,0 +1,18 @@
1
+{
2
+ "images" : [
3
+ {
4
+ "filename" : "TopShelfImageWide.png",
5
+ "idiom" : "tv",
6
+ "scale" : "1x"
7
+ },
8
+ {
9
+ "filename" : "TopShelfImageWide@2x.png",
10
+ "idiom" : "tv",
11
+ "scale" : "2x"
12
+ }
13
+ ],
14
+ "info" : {
15
+ "author" : "xcode",
16
+ "version" : 1
17
+ }
18
+}
Klepon/Assets.xcassets/AppIconTV.brandassets/Top Shelf Image Wide.imageset/TopShelfImageWide.png
Binary files /dev/null and b/Klepon/Assets.xcassets/AppIconTV.brandassets/Top Shelf Image Wide.imageset/TopShelfImageWide.png differ
Klepon/Assets.xcassets/AppIconTV.brandassets/Top Shelf Image Wide.imageset/TopShelfImageWide@2x.png
Binary files /dev/null and b/Klepon/Assets.xcassets/AppIconTV.brandassets/Top Shelf Image Wide.imageset/TopShelfImageWide@2x.png differ
Klepon/Assets.xcassets/AppIconTV.brandassets/Top Shelf Image.imageset/Contents.json
new
+18
@@ -0,0 +1,18 @@
1
+{
2
+ "images" : [
3
+ {
4
+ "filename" : "TopShelfImage.png",
5
+ "idiom" : "tv",
6
+ "scale" : "1x"
7
+ },
8
+ {
9
+ "filename" : "TopShelfImage@2x.png",
10
+ "idiom" : "tv",
11
+ "scale" : "2x"
12
+ }
13
+ ],
14
+ "info" : {
15
+ "author" : "xcode",
16
+ "version" : 1
17
+ }
18
+}
Klepon/Assets.xcassets/AppIconTV.brandassets/Top Shelf Image.imageset/TopShelfImage.png
Binary files /dev/null and b/Klepon/Assets.xcassets/AppIconTV.brandassets/Top Shelf Image.imageset/TopShelfImage.png differ
Klepon/Assets.xcassets/AppIconTV.brandassets/Top Shelf Image.imageset/TopShelfImage@2x.png
Binary files /dev/null and b/Klepon/Assets.xcassets/AppIconTV.brandassets/Top Shelf Image.imageset/TopShelfImage@2x.png differ
Klepon/Features/Ask/AskSheetView.swift
+6
-2
@@ -34,7 +34,9 @@ struct AskSheetView: View {
34
Button("Close") {
35
dismiss()
36
}
37
- .keyboardShortcut(.cancelAction)
37
+ #if os(macOS)
38
+ .keyboardShortcut(.cancelAction)
39
+ #endif
40
}
41
#endif
42
@@ -187,7 +189,9 @@ struct AskSheetView: View {
189
Button("Close") {
190
dismiss()
191
}
190
- .keyboardShortcut(.cancelAction)
192
+ #if os(macOS)
193
+ .keyboardShortcut(.cancelAction)
194
+ #endif
195
.tint(KleponColor.accent)
196
}
197
}
README.md
+1
-1
@@ -68,7 +68,7 @@ python3 Scripts/validate_content.py
68
69
If you run your own fork, change the bundle identifier and App Group to values you control.
70
71
-The macOS and visionOS targets use the same main app bundle identifier as iPhone. The macOS target also uses a sandboxed entitlements file for App Store distribution.
71
+The macOS, tvOS, and visionOS targets use the same main app bundle identifier as iPhone. The macOS target also uses a sandboxed entitlements file for App Store distribution.
72
73
## License
74
project.yml
+1
-1
@@ -322,7 +322,7 @@ targets:
322
echo "Updated CFBundleVersion to ${BUNDLE_VERSION}"
323
settings:
324
base:
325
- PRODUCT_BUNDLE_IDENTIFIER: ai.splitfire.klepon.tv
325
+ PRODUCT_BUNDLE_IDENTIFIER: ai.splitfire.klepon
326
PRODUCT_NAME: Klepon
327
MARKETING_VERSION: "1.0.0"
328
CURRENT_PROJECT_VERSION: 1