Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .github/workflows/app-discovery-qa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ on:
- tests/blur-support-growth.test.mjs
- support/instant-judge/index.html
- tests/instant-judge-support-growth.test.mjs
- tests/ios-store-conversion.test.mjs
- support/roast-me/index.html
- tests/roastme-support-growth.test.mjs
- support/future-me/index.html
Expand Down Expand Up @@ -51,7 +50,6 @@ on:
- tests/blur-support-growth.test.mjs
- support/instant-judge/index.html
- tests/instant-judge-support-growth.test.mjs
- tests/ios-store-conversion.test.mjs
- support/roast-me/index.html
- tests/roastme-support-growth.test.mjs
- support/future-me/index.html
Expand Down Expand Up @@ -93,4 +91,4 @@ jobs:
- name: Verify non-destructive release scripts have valid shell syntax
run: bash -n scripts/publish_app_discovery.sh scripts/check_app_discovery_live.sh scripts/publish_stale_policy_pages.sh
- name: Verify search, referral links and guide listings
run: node --test tests/catalog-growth.test.mjs tests/catalog-positioning-regression.test.mjs tests/search-landing-growth.test.mjs tests/dotchi-support-growth.test.mjs tests/debate-me-support-growth.test.mjs tests/idea-market-support-growth.test.mjs tests/blur-support-growth.test.mjs tests/ios-store-conversion.test.mjs tests/instant-judge-support-growth.test.mjs tests/roastme-support-growth.test.mjs tests/futureme-support-growth.test.mjs
run: node --test tests/catalog-growth.test.mjs tests/catalog-positioning-regression.test.mjs tests/search-landing-growth.test.mjs tests/dotchi-support-growth.test.mjs tests/debate-me-support-growth.test.mjs tests/idea-market-support-growth.test.mjs tests/blur-support-growth.test.mjs tests/instant-judge-support-growth.test.mjs tests/roastme-support-growth.test.mjs tests/futureme-support-growth.test.mjs
56 changes: 15 additions & 41 deletions apps.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@
.app-card h3 { font-size:1rem; margin-bottom:.15rem; }
.app-card p { font-size:.82rem; color:var(--sub); display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }
.store-badge { display:inline-block; margin-top:.4rem; font-size:.78rem; font-weight:600; color:var(--accent); }
.app-card-dual .app-card-body { min-width:0; }
.store-links { display:flex; flex-wrap:wrap; gap:.45rem; margin-top:.55rem; }
.store-link { color:var(--accent); text-decoration:underline; font-size:.78rem; font-weight:700; padding:.3rem .2rem; }
.store-link:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }

footer { text-align:center; color:var(--sub); font-size:.85rem; padding:2rem; }
footer a { color:var(--accent); }
/* Browse purpose or search without hiding cards from non-JS crawlers. */
Expand Down Expand Up @@ -107,17 +102,14 @@ <h3>SheetDecode: Excel Formula Fix</h3>
<span class="store-badge">Google Play &rarr;</span>
</div>
</a>
<div class="app-card app-card-dual">
<a class="app-card" href="https://play.google.com/store/apps/details?id=jp.appdevelopsk.debate_me&amp;utm_source=appdevelopsk&amp;utm_medium=web&amp;utm_campaign=apps_catalog&amp;referrer=utm_source%3Dappdevelopsk%26utm_medium%3Dweb%26utm_campaign%3Dapps_catalog" target="_blank" rel="noopener">
<img src="icons/apps/debate-me.png" alt="Debate Me - AI Debate Practice icon" loading="lazy" width="64" height="64">
<div class="app-card-body">
<h3>Debate Me - AI Debate Practice</h3>
<p>Practice debating with an AI opponent, get feedback and share your results</p>
<div class="store-links">
<a class="store-link" href="https://play.google.com/store/apps/details?id=jp.appdevelopsk.debate_me&amp;utm_source=appdevelopsk&amp;utm_medium=web&amp;utm_campaign=apps_catalog&amp;referrer=utm_source%3Dappdevelopsk%26utm_medium%3Dweb%26utm_campaign%3Dapps_catalog" data-store="google_play" target="_blank" rel="noopener">Google Play &rarr;</a>
<a class="store-link" href="https://apps.apple.com/app/id6760968208?ct=apps_catalog_debate-me" data-store="app_store" target="_blank" rel="noopener">App Store &rarr;</a>
</div>
<span class="store-badge">Google Play &rarr;</span>
</div>
</div>
</a>
<a class="app-card" href="https://play.google.com/store/apps/details?id=jp.appdevelopsk.roast_me_app&amp;utm_source=appdevelopsk&amp;utm_medium=web&amp;utm_campaign=apps_catalog&amp;referrer=utm_source%3Dappdevelopsk%26utm_medium%3Dweb%26utm_campaign%3Dapps_catalog" target="_blank" rel="noopener">
<img src="icons/apps/roast-me.png" alt="RoastMe - Community Roasts icon" loading="lazy" width="64" height="64">
<div class="app-card-body">
Expand All @@ -134,17 +126,14 @@ <h3>Feels Like Weather &amp; Comfort</h3>
<span class="store-badge">Google Play &rarr;</span>
</div>
</a>
<div class="app-card app-card-dual">
<a class="app-card" href="https://play.google.com/store/apps/details?id=com.dotchi.dotchi_app&amp;utm_source=appdevelopsk&amp;utm_medium=web&amp;utm_campaign=apps_catalog&amp;referrer=utm_source%3Dappdevelopsk%26utm_medium%3Dweb%26utm_campaign%3Dapps_catalog" target="_blank" rel="noopener">
<img src="icons/apps/twotaku.png" alt="Dotchi: This or That Polls icon" loading="lazy" width="64" height="64">
<div class="app-card-body">
<h3>Dotchi: This or That Polls</h3>
<p>Pick A or B on everyday questions. Vote, see results and compare opinions with friends.</p>
<div class="store-links">
<a class="store-link" href="https://play.google.com/store/apps/details?id=com.dotchi.dotchi_app&amp;utm_source=appdevelopsk&amp;utm_medium=web&amp;utm_campaign=apps_catalog&amp;referrer=utm_source%3Dappdevelopsk%26utm_medium%3Dweb%26utm_campaign%3Dapps_catalog" data-store="google_play" target="_blank" rel="noopener">Google Play &rarr;</a>
<a class="store-link" href="https://apps.apple.com/app/id6760481027?ct=apps_catalog_twotaku" data-store="app_store" target="_blank" rel="noopener">App Store &rarr;</a>
</div>
<span class="store-badge">Google Play &rarr;</span>
</div>
</div>
</a>
<a class="app-card" href="https://play.google.com/store/apps/details?id=com.fileforce.fileforce_app&amp;utm_source=appdevelopsk&amp;utm_medium=web&amp;utm_campaign=apps_catalog&amp;referrer=utm_source%3Dappdevelopsk%26utm_medium%3Dweb%26utm_campaign%3Dapps_catalog" target="_blank" rel="noopener">
<img src="icons/apps/fileforce.png" alt="FileForce - PDF &amp; File Manager icon" loading="lazy" width="64" height="64">
<div class="app-card-body">
Expand Down Expand Up @@ -217,17 +206,14 @@ <h3>Trend - Anime &amp; Game Picker</h3>
<span class="store-badge">Google Play &rarr;</span>
</div>
</a>
<div class="app-card app-card-dual">
<a class="app-card" href="https://play.google.com/store/apps/details?id=com.blurapp.blur_app&amp;utm_source=appdevelopsk&amp;utm_medium=web&amp;utm_campaign=apps_catalog&amp;referrer=utm_source%3Dappdevelopsk%26utm_medium%3Dweb%26utm_campaign%3Dapps_catalog" target="_blank" rel="noopener">
<img src="icons/apps/blur.png" alt="Blur: Guess the Image icon" loading="lazy" width="64" height="64">
<div class="app-card-body">
<h3>Blur: Guess the Image</h3>
<p>Guess the photo as it slowly unblurs — a fun image guessing brain game</p>
<div class="store-links">
<a class="store-link" href="https://play.google.com/store/apps/details?id=com.blurapp.blur_app&amp;utm_source=appdevelopsk&amp;utm_medium=web&amp;utm_campaign=apps_catalog&amp;referrer=utm_source%3Dappdevelopsk%26utm_medium%3Dweb%26utm_campaign%3Dapps_catalog" data-store="google_play" target="_blank" rel="noopener">Google Play &rarr;</a>
<a class="store-link" href="https://apps.apple.com/app/id6759920723?ct=apps_catalog_blur" data-store="app_store" target="_blank" rel="noopener">App Store &rarr;</a>
</div>
<span class="store-badge">Google Play &rarr;</span>
</div>
</div>
</a>
<a class="app-card" href="https://play.google.com/store/apps/details?id=com.brainburst.brain_burst&amp;utm_source=appdevelopsk&amp;utm_medium=web&amp;utm_campaign=apps_catalog&amp;referrer=utm_source%3Dappdevelopsk%26utm_medium%3Dweb%26utm_campaign%3Dapps_catalog" target="_blank" rel="noopener">
<img src="icons/apps/brain-burst.png" alt="BrainBurst - Daily Trivia Quiz icon" loading="lazy" width="64" height="64">
<div class="app-card-body">
Expand Down Expand Up @@ -588,17 +574,14 @@ <h3>Travel Safety Map &amp; Scam Alert</h3>
<span class="store-badge">Google Play &rarr;</span>
</div>
</a>
<div class="app-card app-card-dual">
<a class="app-card" href="https://play.google.com/store/apps/details?id=com.instantjudge.instant_judge&amp;utm_source=appdevelopsk&amp;utm_medium=web&amp;utm_campaign=apps_catalog&amp;referrer=utm_source%3Dappdevelopsk%26utm_medium%3Dweb%26utm_campaign%3Dapps_catalog" target="_blank" rel="noopener">
<img src="icons/apps/instant-judge.png" alt="Instant Judge: Vote in 3s icon" loading="lazy" width="64" height="64">
<div class="app-card-body">
<h3>Instant Judge: Vote in 3s</h3>
<p>Vote on community dilemmas, post your own and see results when revealed</p>
<div class="store-links">
<a class="store-link" href="https://play.google.com/store/apps/details?id=com.instantjudge.instant_judge&amp;utm_source=appdevelopsk&amp;utm_medium=web&amp;utm_campaign=apps_catalog&amp;referrer=utm_source%3Dappdevelopsk%26utm_medium%3Dweb%26utm_campaign%3Dapps_catalog" data-store="google_play" target="_blank" rel="noopener">Google Play &rarr;</a>
<a class="store-link" href="https://apps.apple.com/app/id6759920352?ct=apps_catalog_instant-judge" data-store="app_store" target="_blank" rel="noopener">App Store &rarr;</a>
</div>
<span class="store-badge">Google Play &rarr;</span>
</div>
</div>
</a>
<a class="app-card" href="https://play.google.com/store/apps/details?id=com.keyclash.key_clash&amp;utm_source=appdevelopsk&amp;utm_medium=web&amp;utm_campaign=apps_catalog&amp;referrer=utm_source%3Dappdevelopsk%26utm_medium%3Dweb%26utm_campaign%3Dapps_catalog" target="_blank" rel="noopener">
<img src="icons/apps/key-clash.png" alt="KeyClash: Typing Battle icon" loading="lazy" width="64" height="64">
<div class="app-card-body">
Expand Down Expand Up @@ -895,18 +878,9 @@ <h3>Chaos - Stranger Missions</h3>
buttons.forEach(b => b.setAttribute('aria-pressed', String(b === button)));
fire('catalog_filter_used', {goal, results: render()});
}));
cards.forEach(card => {
const links = card.querySelectorAll?.('a[data-store]') || [];
if (links.length) {
links.forEach(link => link.addEventListener('click', () => {
fire('catalog_store_click', {app: slug(card), goal, source: 'apps_catalog', store: link.dataset.store});
}));
} else {
card.addEventListener('click', () => {
fire('catalog_store_click', {app: slug(card), goal, source: 'apps_catalog', store: 'google_play'});
});
}
});
cards.forEach(card => card.addEventListener('click', () => {
fire('catalog_store_click', {app: slug(card), goal, source: 'apps_catalog'});
}));
render();
})();
</script>
Expand Down
14 changes: 5 additions & 9 deletions apps_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@
"pkg": "jp.appdevelopsk.debate_me",
"title": "Debate Me - AI Debate Practice",
"desc": "Practice debating with an AI opponent, get feedback and share your results",
"installs": 28,
"ios_app_id": 6760968208
"installs": 28
},
{
"app": "roast-me",
Expand All @@ -40,8 +39,7 @@
"pkg": "com.dotchi.dotchi_app",
"title": "Dotchi: This or That Polls",
"desc": "Pick A or B on everyday questions. Vote, see results and compare opinions with friends.",
"installs": 22,
"ios_app_id": 6760481027
"installs": 22
},
{
"app": "fileforce",
Expand Down Expand Up @@ -111,8 +109,7 @@
"pkg": "com.blurapp.blur_app",
"title": "Blur: Guess the Image",
"desc": "Guess the photo as it slowly unblurs — a fun image guessing brain game",
"installs": 15,
"ios_app_id": 6759920723
"installs": 15
},
{
"app": "brain-burst",
Expand Down Expand Up @@ -474,8 +471,7 @@
"pkg": "com.instantjudge.instant_judge",
"title": "Instant Judge: Vote in 3s",
"desc": "Vote on community dilemmas, post your own and see results when revealed",
"installs": 13,
"ios_app_id": 6759920352
"installs": 13
},
{
"app": "key-clash",
Expand Down Expand Up @@ -703,4 +699,4 @@
"desc": "Daily missions from strangers to break your routine and rediscover the world",
"installs": null
}
]
]
20 changes: 2 additions & 18 deletions scripts/build_catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,21 +51,6 @@
</a>
"""

# Two independent links only for apps with a verified owner-maintained App Store ID.
# Do not put an anchor inside another anchor; keep crawlers and keyboard users safe.
CARD_DUAL = """ <div class="app-card app-card-dual">
<img src="icons/apps/{app}.png" alt="{title} icon" loading="lazy" width="64" height="64">
<div class="app-card-body">
<h3>{title}</h3>
<p>{desc}</p>
<div class="store-links">
<a class="store-link" href="https://play.google.com/store/apps/details?id={pkg}&amp;utm_source=appdevelopsk&amp;utm_medium=web&amp;utm_campaign=apps_catalog&amp;referrer=utm_source%3Dappdevelopsk%26utm_medium%3Dweb%26utm_campaign%3Dapps_catalog" data-store="google_play" target="_blank" rel="noopener">Google Play &rarr;</a>
<a class="store-link" href="https://apps.apple.com/app/id{ios_app_id}?ct=apps_catalog_{app}" data-store="app_store" target="_blank" rel="noopener">App Store &rarr;</a>
</div>
</div>
</div>
"""

LANGS = ["en", "ja", "zh", "zh_TW", "ko", "es", "pt", "fr", "de", "it", "ru", "ar",
"th", "id", "tr", "nl", "vi"]

Expand Down Expand Up @@ -160,9 +145,8 @@ def load_counts(apps, refresh_total):


def build_apps_html(t, apps, n):
cards = "".join((CARD_DUAL if a.get("ios_app_id") else CARD).format(
pkg=a["pkg"], app=a["app"], title=html.escape(a["title"]),
desc=html.escape(a["desc"]), ios_app_id=a.get("ios_app_id", ""))
cards = "".join(CARD.format(pkg=a["pkg"], app=a["app"], title=html.escape(a["title"]),
desc=html.escape(a["desc"]))
for a in apps if not a.get("hidden"))
t = sub1(r'(<div class="grid">\n).*?( </div>\n </main>)',
lambda m: m.group(1) + cards + m.group(2), t, "apps.html の grid", re.S)
Expand Down
8 changes: 0 additions & 8 deletions scripts/check_app_discovery_live.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,11 @@ grep -Fq 'data-alternative="blur"' "$tmp/face-battle.html" || { echo 'FAIL secon
fetch '/support/twotaku/' 'dotchi.html'
grep -Fq '<h1>Dotchi: This or That Polls</h1>' "$tmp/dotchi.html" || { echo 'FAIL Dotchi anime-only support content still live' >&2; exit 1; }
grep -Fq 'data-position="hero"' "$tmp/dotchi.html" || { echo 'FAIL Dotchi store call-to-action absent' >&2; exit 1; }
grep -Fq 'apps.apple.com/app/id6760481027?ct=support_twotaku_hero' "$tmp/dotchi.html" || { echo 'FAIL twotaku hero App Store CTA missing' >&2; exit 1; }
grep -Fq 'apps.apple.com/app/id6760481027?ct=support_twotaku_details' "$tmp/dotchi.html" || { echo 'FAIL twotaku details App Store CTA missing' >&2; exit 1; }
grep -Fq 'const FEAT_T={en:{0:"Choose A or B on a question."' "$tmp/dotchi.html" || { echo 'FAIL Dotchi translated feature claims still stale' >&2; exit 1; }
# Read-only release gate for the recently corrected Debate Me SEO landing.
fetch '/support/debate-me/' 'debate-me.html'
grep -Fq 'AI Debate Practice &amp; Argument Skills' "$tmp/debate-me.html" || grep -Fq 'AI Debate Practice & Argument Skills' "$tmp/debate-me.html" || { echo 'FAIL Debate Me product title is not live' >&2; exit 1; }
grep -Fq 'data-position="hero"' "$tmp/debate-me.html" || { echo 'FAIL Debate Me first-screen Play CTA not live' >&2; exit 1; }
grep -Fq 'apps.apple.com/app/id6760968208?ct=support_debate_me_hero' "$tmp/debate-me.html" || { echo 'FAIL debate_me hero App Store CTA missing' >&2; exit 1; }
grep -Fq 'apps.apple.com/app/id6760968208?ct=support_debate_me_details' "$tmp/debate-me.html" || { echo 'FAIL debate_me details App Store CTA missing' >&2; exit 1; }
grep -Fq 'data-position="details"' "$tmp/debate-me.html" || { echo 'FAIL Debate Me details Play CTA missing' >&2; exit 1; }
grep -Fq 'support_debate_me_hero' "$tmp/debate-me.html" || { echo 'FAIL Debate Me Play attribution missing' >&2; exit 1; }
if grep -Eq 'Hundreds of meal ideas|Filter by ingredients|Can.t decide what to cook tonight' "$tmp/debate-me.html"; then
Expand All @@ -75,8 +71,6 @@ fi
fetch '/support/blur/' 'blur.html'
grep -Fq '<h1>Blur: Guess the Image</h1>' "$tmp/blur.html" || { echo 'FAIL Blur support landing missing' >&2; exit 1; }
grep -Fq 'data-position="hero"' "$tmp/blur.html" || { echo 'FAIL Blur first-screen Play CTA not live' >&2; exit 1; }
grep -Fq 'apps.apple.com/app/id6759920723?ct=support_blur_hero' "$tmp/blur.html" || { echo 'FAIL blur hero App Store CTA missing' >&2; exit 1; }
grep -Fq 'apps.apple.com/app/id6759920723?ct=support_blur_details' "$tmp/blur.html" || { echo 'FAIL blur details App Store CTA missing' >&2; exit 1; }
grep -Fq 'support_blur_hero' "$tmp/blur.html" || { echo 'FAIL Blur Play campaign missing' >&2; exit 1; }
if grep -Eq 'Multiplayer mode|Multiple difficulty levels|Timed challenges' "$tmp/blur.html"; then
echo 'FAIL Blur advertises unverified game modes' >&2; exit 1
Expand All @@ -86,8 +80,6 @@ fetch '/support/instant-judge/' 'instant-judge.html'
grep -Fq 'Vote on everyday dilemmas, create your own post' "$tmp/instant-judge.html" || { echo 'FAIL Instant Judge hero is stale' >&2; exit 1; }
grep -Fq 'data-position="hero"' "$tmp/instant-judge.html" || { echo 'FAIL Instant Judge first-screen Play CTA missing' >&2; exit 1; }
grep -Fq 'support_instant_judge_hero' "$tmp/instant-judge.html" || { echo 'FAIL Instant Judge campaign tagging missing' >&2; exit 1; }
grep -Fq 'apps.apple.com/app/id6759920352?ct=support_instant_judge_hero' "$tmp/instant-judge.html" || { echo 'FAIL Instant Judge hero App Store CTA missing' >&2; exit 1; }
grep -Fq 'apps.apple.com/app/id6759920352?ct=support_instant_judge_details' "$tmp/instant-judge.html" || { echo 'FAIL Instant Judge details App Store CTA missing' >&2; exit 1; }
grep -Fq 'Results appear at their reveal time' "$tmp/instant-judge.html" || { echo 'FAIL Instant Judge reveal copy missing' >&2; exit 1; }
if grep -Eiq 'Thousands of scenarios|Real-time results|Many features work offline' "$tmp/instant-judge.html"; then
echo 'FAIL Instant Judge advertises unsupported immediate results or scale' >&2; exit 1
Expand Down
2 changes: 1 addition & 1 deletion scripts/publish_app_discovery.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ done
echo "Source checkout: $(git rev-parse --short HEAD 2>/dev/null || echo unknown)"
echo "Target: $host:$root; mode: $mode"
# --relative recreates only the listed nested file paths. No --delete.
rsync -avR --itemize-changes "${flags[@]}" -- "${files[@]}" "$host:$root/"
rsync -avR --itemize-changes ${flags[@]+"${flags[@]}"} -- "${files[@]}" "$host:$root/"
if [[ "$mode" == '--apply' ]]; then
echo 'Files transferred. Check CDN/VPS output (the publish command does not prove it is live):'
echo ' bash scripts/check_app_discovery_live.sh'
Expand Down
2 changes: 1 addition & 1 deletion scripts/publish_stale_policy_pages.sh
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ flags=(--dry-run)
echo "Policy recovery: ${#files[@]} already public paths, target $host:$root; mode $mode"
echo "Source checkout: $(git rev-parse --short HEAD 2>/dev/null || echo unknown)"
# Non-destructive. Never use --delete, and never publish unpublished paths.
rsync -avR --itemize-changes "${flags[@]}" -- "${files[@]}" "$host:$root/"
rsync -avR --itemize-changes ${flags[@]+"${flags[@]}"} -- "${files[@]}" "$host:$root/"
if [[ "$mode" == '--apply' ]]; then
echo 'Upload attempted. Confirm live pages with:'
echo ' bash scripts/publish_stale_policy_pages.sh --check-live'
Expand Down
Loading
Loading