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
10 changes: 9 additions & 1 deletion apps.html
Original file line number Diff line number Diff line change
Expand Up @@ -1424,7 +1424,15 @@ <h3>Chaos - Stranger Missions</h3>
ai: ['debate-me','voice-memo','future-me','date-pilot','global-news','pantry-ai','name-maker','idea-market','life-trace']
};
const clean = value => value.normalize('NFKC').toLocaleLowerCase().trim();
let goal = 'all', lastReportedSearch = '';
// Shareable, allowlisted category links from the four editorial guides.
// Never read or transmit arbitrary query text.
const requestedGoal = new URLSearchParams(window.location.search).get('goal');
let goal = ['quick-games', 'habits', 'decisions', 'ai'].includes(requestedGoal)
? requestedGoal : 'all';
let lastReportedSearch = '';
buttons.forEach(button => {
button.setAttribute('aria-pressed', String(button.dataset.goal === goal));
});
const slug = card => {
const src = card.querySelector('img')?.getAttribute('src') || '';
return src.split('/').pop()?.replace(/\.png$/, '') || '';
Expand Down
2 changes: 1 addition & 1 deletion guides/ai-tools/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ <h2 id="app-choices">Apps to explore</h2>
</div></article>
</section>
<section class="more"><h2>Not sure what to pick?</h2>
<p>Pick one thing you want to finish today. If you need more choices, <a href="/apps">search all published apps</a> or explore <a href="/guides/daily-habits/">daily habit apps</a>.</p></section>
<p>Pick one thing you want to finish today. If you need more choices, <a href="/apps?goal=ai">search all published apps</a> or explore <a href="/guides/daily-habits/">daily habit apps</a>.</p></section>
</main>
<footer>Links open Google Play. Features, pricing and availability may change by region and app version. The page does not claim any download or ranking performance.</footer>
<script>
Expand Down
2 changes: 1 addition & 1 deletion guides/daily-habits/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ <h1>Daily habit apps for journaling, reflection and routines</h1>
<article class="app"><img src="/icons/apps/water-reminder.png" alt="Water Reminder - Hydration app icon" width="76" height="76" loading="lazy"><div><p class="purpose">For a hydration routine</p><h3>Water Reminder - Hydration</h3><p>Water tracker and hydration reminders to drink enough water every day</p><a class="store" data-app="water-reminder" href="https://play.google.com/store/apps/details?id=jp.appdevelopsk.water_reminder&amp;utm_source=appdevelopsk&amp;utm_medium=guide&amp;utm_campaign=daily_habits&amp;referrer=utm_source%3Dappdevelopsk%26utm_medium%3Dguide%26utm_campaign%3Ddaily_habits" target="_blank" rel="noopener noreferrer">See on Google Play</a></div></article>
<article class="app"><img src="/icons/apps/gratitude-log.png" alt="Daily Reflect app icon" width="76" height="76" loading="lazy"><div><p class="purpose">For gratitude and daily reflection</p><h3>Daily Reflect</h3><p>Daily journal for gratitude, wins &amp; mood — build a positive daily habit</p><a class="store" data-app="gratitude-log" href="https://play.google.com/store/apps/details?id=jp.appdevelopsk.gratitudelog&amp;utm_source=appdevelopsk&amp;utm_medium=guide&amp;utm_campaign=daily_habits&amp;referrer=utm_source%3Dappdevelopsk%26utm_medium%3Dguide%26utm_campaign%3Ddaily_habits" target="_blank" rel="noopener noreferrer">See on Google Play</a></div></article>
</section>
<p>Already know what you want? <a href="/apps">Search all published apps</a> or explore <a href="/guides/quick-games/">quick games</a>.</p>
<p>Already know what you want? <a href="/apps?goal=habits">Search all published apps</a> or explore <a href="/guides/quick-games/">quick games</a>.</p>
</main>
<footer>These are apps by SK Apps. The links open Google Play; availability and features depend on your region and installed version. No ranking or performance claim is implied.</footer>
<script>document.querySelectorAll('a.store').forEach(a=>a.addEventListener('click',()=>{if(typeof gtag==='function')gtag('event','guide_store_click',{guide:'daily-habits',app:a.dataset.app})}));</script>
Expand Down
2 changes: 1 addition & 1 deletion guides/decision-helpers/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ <h2 id="app-choices">Apps to explore</h2>
</div></article>
</section>
<section class="more"><h2>Not sure what to pick?</h2>
<p>Pick one thing you want to finish today. If you need more choices, <a href="/apps">search all published apps</a> or explore <a href="/guides/quick-games/">quick mobile games</a>.</p></section>
<p>Pick one thing you want to finish today. If you need more choices, <a href="/apps?goal=decisions">search all published apps</a> or explore <a href="/guides/quick-games/">quick mobile games</a>.</p></section>
</main>
<footer>Links open Google Play. Features, pricing and availability may change by region and app version. The page does not claim any download or ranking performance.</footer>
<script>
Expand Down
2 changes: 1 addition & 1 deletion guides/quick-games/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ <h1>Quick mobile games for a short break</h1>
<article class="app"><img src="/icons/apps/nodo.png" alt="Nodo - Daily Node Puzzle app icon" width="76" height="76" loading="lazy"><div><p class="purpose">For logic puzzles</p><h3>Nodo - Daily Node Puzzle</h3><p>Daily logic puzzle: solve number node networks and climb the leaderboard</p><a class="store" data-app="nodo" href="https://play.google.com/store/apps/details?id=com.nodopuzzle.nodoPuzzle&amp;utm_source=appdevelopsk&amp;utm_medium=guide&amp;utm_campaign=quick_games&amp;referrer=utm_source%3Dappdevelopsk%26utm_medium%3Dguide%26utm_campaign%3Dquick_games" target="_blank" rel="noopener noreferrer">See on Google Play</a></div></article>
<article class="app"><img src="/icons/apps/brain-burst.png" alt="BrainBurst - Daily Trivia Quiz app icon" width="76" height="76" loading="lazy"><div><p class="purpose">For daily trivia</p><h3>BrainBurst - Daily Trivia Quiz</h3><p>Daily trivia quiz with 1v1 battles and fresh AI questions to grow your knowledge</p><a class="store" data-app="brain-burst" href="https://play.google.com/store/apps/details?id=com.brainburst.brain_burst&amp;utm_source=appdevelopsk&amp;utm_medium=guide&amp;utm_campaign=quick_games&amp;referrer=utm_source%3Dappdevelopsk%26utm_medium%3Dguide%26utm_campaign%3Dquick_games" target="_blank" rel="noopener noreferrer">See on Google Play</a></div></article>
</section>
<p>Already know what you want? <a href="/apps">Search all published apps</a> or explore <a href="/guides/daily-habits/">daily habits</a>.</p>
<p>Already know what you want? <a href="/apps?goal=quick-games">Search all published apps</a> or explore <a href="/guides/daily-habits/">daily habits</a>.</p>
</main>
<footer>These are apps by SK Apps. The links open Google Play; availability and features depend on your region and installed version. No ranking or performance claim is implied.</footer>
<script>document.querySelectorAll('a.store').forEach(a=>a.addEventListener('click',()=>{if(typeof gtag==='function')gtag('event','guide_store_click',{guide:'quick-games',app:a.dataset.app})}));</script>
Expand Down
44 changes: 44 additions & 0 deletions scripts/test_guide_catalog_links.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""Offline source checks for editorial-guide category deep links."""
from pathlib import Path
import re
import unittest

ROOT = Path(__file__).resolve().parent.parent
GUIDES = {
"quick-games": "quick-games",
"daily-habits": "habits",
"decision-helpers": "decisions",
"ai-tools": "ai",
}


class GuideCatalogDeepLinkTests(unittest.TestCase):
def test_category_links_are_consistent(self):
for slug, goal in GUIDES.items():
with self.subTest(guide=slug):
text = (ROOT / "guides" / slug / "index.html").read_text(encoding="utf-8")
self.assertEqual(text.count(f'href="/apps?goal={goal}"'), 1)
self.assertIn('href="/apps"', text) # unfiltered breadcrumb remains available

def test_catalog_reads_only_allowlisted_goals(self):
catalog = (ROOT / "apps.html").read_text(encoding="utf-8")
self.assertIn("new URLSearchParams(window.location.search).get('goal')", catalog)
self.assertIn("['quick-games', 'habits', 'decisions', 'ai'].includes(requestedGoal)", catalog)
self.assertIn("button.dataset.goal === goal", catalog)
self.assertIn("render();", catalog)
self.assertNotIn("utm_source=window.location.search", catalog)

def test_catalog_filter_buttons_cover_guides(self):
catalog = (ROOT / "apps.html").read_text(encoding="utf-8")
for goal in GUIDES.values():
with self.subTest(goal=goal):
self.assertIn(f'data-goal="{goal}"', catalog)

def test_catalog_cards_and_details_preserved(self):
catalog = (ROOT / "apps.html").read_text(encoding="utf-8")
self.assertEqual(len(re.findall(r'class="app-card"', catalog)), 92)
self.assertEqual(len(re.findall(r'data-detail-app="', catalog)), 5)


if __name__ == "__main__":
unittest.main()
Loading