[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-2969":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":14,"subscribersCount":14,"size":14,"stars1d":13,"stars7d":15,"stars30d":16,"stars90d":14,"forks30d":14,"starsTrendScore":17,"compositeScore":18,"rankGlobal":9,"rankLanguage":9,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":22,"hasPages":20,"topics":23,"createdAt":9,"pushedAt":9,"updatedAt":24,"readmeContent":25,"aiSummary":26,"trendingCount":14,"starSnapshotCount":14,"syncStatus":15,"lastSyncTime":27,"discoverSource":28},2969,"aso-tracker","dsm5e\u002Faso-tracker","dsm5e","Self-hosted open-source App Store toolkit for indie iOS devs — keyword tracking, AI screenshot generation, PPO experiments, and UGC video pipeline.",null,"TypeScript",114,14,1,0,2,15,3,3.53,"MIT License",false,"main",true,[],"2026-06-12 02:00:45","# ASO Studio\n\n> Self-hosted open-source App Store toolkit for indie iOS developers — **keyword tracking, screenshot generation, video pipelines, PPO experiments, and Apple Search Ads optimization**, all in one place. Pair it with [Claude Code](https:\u002F\u002Fclaude.com\u002Fclaude-code) and you get an AI co-pilot that actually understands your App Store.\n\nStop paying \\$500–999\u002Fmo to Sensor Tower \u002F AppTweak \u002F SplitMetrics \u002F SearchAds.com. ASO Studio runs on your machine, uses public APIs where possible, and stores everything locally.\n\n![ASO Studio demo](docs\u002Fdemo.gif)\n\n## What's inside\n\nASO Studio is a monorepo of **four** connected tools sharing one origin (`localhost:5173`) with a top-left app switcher:\n\n| Tool | Path | What it does |\n|---|---|---|\n| **Keywords** | `\u002F` | Per-keyword, per-locale rank tracking across 50+ countries. Snapshot engine, week-over-week deltas, competitor intelligence. |\n| **Screenshots \u002F PPO** | `\u002Fstudio\u002F` | App Store screenshot generator with AI hero enhancement (fal.ai gpt-image-2). Templates, scaffolds, headline overlays, locale translations. Multi-strategy A\u002FB treatment generator for ASC PPO. |\n| **Video** *(beta)* | `\u002Fvideo\u002F` | UGC video pipeline for ad creative — script → voiceover → b-roll → captions. |\n| **ASA Ads** *(new)* | `\u002Fasa\u002F` | Apple Search Ads optimization — ROI projection, per-keyword bid intelligence, search-term cleanup, ASC trial cross-match, Telegram alerts. Self-hosted alternative to SearchAds.com. |\n\nAll four sub-tools share one Settings page and one local key vault.\n\n### 💸 ASA Ads — Apple Search Ads optimization\n\n![ASA Ads demo](asa-ads\u002Fdocs\u002Fdemo.gif)\n\nWhat it does for your ASA campaigns:\n\n- **ROI projection** — *\"spend $1000 on this keyword\u002Fcampaign → expect N installs, M trials, $X revenue, Y% ROI\"*. Honest about data quality: `WAIT · need 3 more days` instead of fake numbers.\n- **Bid intelligence** — per-keyword recommendations with high\u002Fmedium\u002Flow confidence. Bulk apply or one-click `−10% \u002F +10% \u002F → recommended`.\n- **Spend impact preview** — every bid change opens a modal showing projected daily\u002Fweekly\u002Fmonthly spend delta + ROI verdict before you confirm.\n- **Search terms cleanup** — auto-suggests negatives (terms with taps but no installs) and discovery candidates (terms that converted but aren't in your keyword list).\n- **Geo heatmap + hero chart** — see which countries are winners at a glance.\n- **Background sync** — start sync, navigate to another tool, come back to see the progress bar still ticking.\n- **Telegram alerts** — 🔥 Burn, 💸 High CPI, ⚠️ Stalled, 📈 Spend spike.\n- **Multi-app** — separate ROI\u002Fsettings\u002Frecommendations per app.\n- **Settings auto-suggestion** — `trial_to_paid_rate` computed from real ASC events (`Crossgrade from Introductory Offer` + `Billing Retry`).\n\nFull details: [`asa-ads\u002FREADME.md`](asa-ads\u002FREADME.md) (incl. how to drive it from an LLM via REST + SQLite).\n\n## Why use it with Claude Code\n\nASO Studio is built to be driven by AI. Every editor state is a JSON file under `~\u002F.aso-studio\u002F` so an LLM agent can read\u002Fwrite it directly. Two MCP servers sit on top:\n\n- **`asc-mcp`** ([dsm5e\u002Fnomly-asc-mcp](https:\u002F\u002Fgithub.com\u002Fdsm5e\u002Fnomly-asc-mcp)) — full App Store Connect API: builds, versions, localizations, screenshots, in-app purchases, subscriptions, PPO experiments, custom product pages, reviews.\n- **`apple-search-ads-mcp`** ([AppVisionOS](https:\u002F\u002Fgithub.com\u002FAppVisionOS\u002Fapple-search-ads-mcp)) — full Apple Ads (Search Ads) Campaign Management API v5: campaigns, ad groups, keywords, negative keywords, budget orders, reports.\n\nWhat Claude can do for you (with these MCPs + this studio):\n\n- 🤖 **Audit your ASO** — pull current title\u002Fsubtitle\u002Fkeywords across all locales, score them against competitors, suggest specific replacements.\n- 🤖 **Run keyword research** — fetch competitor app metadata, analyze top apps for any keyword in any country, score difficulty\u002Ftraffic ratios.\n- 🤖 **Generate App Store screenshots end-to-end** — pick a preset, write headlines per locale, generate AI hero images, export PNGs for ASC.\n- 🤖 **Run PPO experiments** — design 3 treatment concepts (palette \u002F signature element \u002F 3D break-out \u002F story arc), generate 5-15 screens per concept, export ZIPs, create the ASC PPO experiment via API.\n- 🤖 **Launch Apple Search Ads campaigns** — generate keyword lists from competitor research, set bids based on traffic\u002Fdifficulty scores, create campaigns + ad groups + budget orders programmatically.\n- 🤖 **Run ASA Ads day-to-day** — the ASA Ads sub-tool itself is agent-friendly (REST + SQLite). See [`asa-ads\u002FREADME.md`](asa-ads\u002FREADME.md#how-llm-agents-use-this) for the full API surface and example workflows: audit campaigns, find waste, apply bid recommendations in bulk, monitor live via SSE.\n- 🤖 **Track campaign performance** — pull daily reports, surface wasted spend, suggest pause\u002Fscale\u002Fraise\u002Flower-bid actions.\n\n## Quickstart\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Fdsm5e\u002Faso-tracker.git aso-studio\ncd aso-studio\nnpm install          # registers all 4 workspaces\nnpm run dev          # launches all 4 tools in parallel\n# open http:\u002F\u002Flocalhost:5173\n```\n\nAll 4 tools share the same origin via the Keywords vite proxy:\n\n| Tool | URL | Vite | API |\n|---|---|---|---|\n| Keywords | http:\u002F\u002Flocalhost:5173\u002F | 5173 | 5174 |\n| Screenshots | http:\u002F\u002Flocalhost:5173\u002Fstudio\u002F | 5180 | 5181 |\n| Video | http:\u002F\u002Flocalhost:5173\u002Fvideo\u002F | 5190 | 5191 |\n| ASA Ads | http:\u002F\u002Flocalhost:5173\u002Fasa\u002F | 5193 | 5194 |\n\nFirst-time setup:\n1. **Settings** (gear icon, top-right) — paste API keys you have. `FAL_API_KEY` is needed for AI image generation, `OPENAI_API_KEY` for translations.\n2. **Keywords**: empty dashboard → **+ Add your first app**, paste your iTunes App ID, hit **Test connection** → **Add app & start tracking**.\n3. **Snapshot**: pick a locale, add 5-10 keywords, click **Run snapshot** — watch live progress.\n4. **Screenshots \u002F PPO**: open the **Studio** tab → pick a preset → upload your simulator screenshots → write headlines or per-strategy prompts → generate.\n\n## API keys & local storage\n\n> **TL;DR — keys never leave your machine.** ASO Studio is a local-first tool. Every key you paste is stored in a single JSON file on your own filesystem, sent only to the upstream API it belongs to, and never to any backend we control (we don't run a backend at all).\n\n### What's required\n\nThe studio uses two third-party APIs for its AI features. Both are pay-per-use; you only pay for what you generate.\n\n| Key | Required for | Free tier? | Where to get |\n|---|---|---|---|\n| `FAL_API_KEY` | AI image generation (gpt-image-2) — Screenshots hero, PPO renders, Polish | $1 free credit on signup; ~$0.05 per medium-quality render after | [fal.ai\u002Fdashboard\u002Fkeys](https:\u002F\u002Ffal.ai\u002Fdashboard\u002Fkeys) |\n| `OPENAI_API_KEY` | Locale translations of headlines (gpt-4o-mini) | $5 free credit on signup; ~$0.0001 per headline after | [platform.openai.com\u002Fapi-keys](https:\u002F\u002Fplatform.openai.com\u002Fapi-keys) |\n\nThe Keywords tool (rank tracking) needs **no API keys at all** — it uses the public iTunes Search API.\n\n### Where keys are stored\n\n```\n~\u002F.aso-studio\u002Fkeys.json   ← single file, JSON, mode 0600 (owner-only readable)\n```\n\nThe `0600` permission means only your user account can read or write the file — not other users on the machine, not background processes running as different users. The studio's backend (`aso-screenshots\u002Fserver`) is the only thing that opens this file, and it does so in-process (no network call).\n\nWhen the studio needs a key, it resolves in this order:\n\n1. **Environment variable** (`FAL_API_KEY=...` in your shell) — for CI \u002F Docker \u002F direct override\n2. **`~\u002F.aso-studio\u002Fkeys.json`** — what the Settings UI writes to\n3. **Throw** with a \"configure key in Settings\" message — never silently fails\n\n### How keys are entered\n\nIn the Settings modal (gear icon, top-right):\n\n- All inputs are `\u003Cinput type=\"password\">` — your screen never displays the key while you're pasting it.\n- Click 👁 to reveal a draft (only the value you're typing right now, never an already-saved one).\n- Once saved, the UI shows a **masked preview** (`fal_••••••AbCd`) and never round-trips the full key back to the browser.\n- The \"Clear\" button removes the key from disk; env-var-set keys can't be cleared from the UI (clear the env var instead).\n\n### What we DO NOT collect\n\nASO Studio has no telemetry, no analytics, no crash reporter, no remote config. The only outbound network calls are:\n\n- iTunes Search API (for app metadata + keyword ranks) — no auth, no keys\n- fal.ai API (when you click \"Generate\") — only with your `FAL_API_KEY`\n- OpenAI API (when you click \"Translate\") — only with your `OPENAI_API_KEY`\n\nThere is literally no other backend in this stack.\n\n## Examples\n\n### PPO renders\n\nGenerated by the studio for [Dream Journal: AI Meanings](https:\u002F\u002Fapps.apple.com\u002Fapp\u002Fid6761296564) — three treatment concepts in different visual languages, all from the same source screenshots:\n\n| A · Anxious Dreamer | B · Sleep Paralysis | D · Voice-First |\n|---|---|---|\n| painterly moonlit dreamscape, drifting feathers, navy + violet | dark horror, faceless shadow entity, crimson + black | high-energy kinetic motion, electric cyan + violet |\n| ![A · Anxious Dreamer](docs\u002Fppo\u002Fa-anxious-dreamer.png) | ![B · Sleep Paralysis](docs\u002Fppo\u002Fb-sleep-paralysis.png) | ![D · Voice-First](docs\u002Fppo\u002Fd-voice-first.png) |\n\nEach treatment uses a locked **palette + atmosphere + lighting + signature element** anchor across all 5-7 screens, with composition variance (tilt, framing distance, 3D break-out elements) telling a story arc through the set. Prompts authored conversationally with Claude; renders done in batch via fal.ai's gpt-image-2.\n\n### ASO Video pipeline\n\nThree UGC ad creatives generated end-to-end by the video sub-tool — script → voiceover → b-roll selection → captions → endcard:\n\n\u003Ctable>\n  \u003Ctr>\n    \u003Ctd>\u003Cimg src=\"docs\u002Fvideo\u002Fexample-1.gif\" width=\"100%\">\u003C\u002Ftd>\n    \u003Ctd>\u003Cimg src=\"docs\u002Fvideo\u002Fexample-2.gif\" width=\"100%\">\u003C\u002Ftd>\n    \u003Ctd>\u003Cimg src=\"docs\u002Fvideo\u002Fexample-3.gif\" width=\"100%\">\u003C\u002Ftd>\n  \u003C\u002Ftr>\n\u003C\u002Ftable>\n\n## LLM context\n\nFor AI agents working with this codebase, see [`llms-full.txt`](llms-full.txt) — full architectural context, file map, state schema, and command examples. Compatible with the [llmstxt.org](https:\u002F\u002Fllmstxt.org\u002F) standard.\n\n## Your data stays yours\n\n- `config\u002Fapps.json` — your tracked apps (gitignored)\n- `config\u002Fkeywords\u002F*.json` — your keyword lists per app (gitignored; only `*.example.json` committed)\n- `data\u002Frankings.db` — local SQLite with snapshot history (gitignored)\n- `~\u002F.aso-studio\u002F` — keys, editor state, exports (outside the repo, mode 0600)\n\nNothing leaves your machine. You bring your own keywords, your own keys, your own creative.\n\n## Tech stack\n\n- **Frontend**: React 19 + Vite + TypeScript\n- **Backend**: Express + better-sqlite3 + Sharp (image processing)\n- **AI**: fal.ai (gpt-image-2 for image edits), OpenAI (translations)\n- **Data source**: public iTunes Search API (no keys), optional App Store Connect \u002F Apple Ads APIs through their respective MCP servers (your own auth)\n- **Rate limit**: conservative 2 workers × 500ms sleep → ~240 req\u002Fmin (Apple's limit is ~500). Auto-abort + Resume on persistent 502.\n\n## CLI (headless snapshots)\n\n```bash\nnpm run snapshot -- --app=dream                 # all locales for one app\nnpm run snapshot -- --app=dream --locales=us,tr,de\nnpm run snapshot                                 # every app, every locale\n```\n\nStreams line-by-line progress. Suitable for cron, CI, or Claude Code automation.\n\n### Import existing jsonl snapshots\n\n```bash\nnpm run migrate-jsonl -- \u002Fpath\u002Fto\u002Faso-rankings.jsonl\n```\n\n## Keyword methodology\n\nTrack **search phrases** (2-4 words) — what real users type into App Store search. Not single words from the Keywords field in ASC.\n\nLocalize by **intent**, not literal translation. Example: Turkish users search `rüya tabiri` (\"dream interpretation\") — not `rüya günlüğü` (\"dream journal\").\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n\n---\n\nBuilt in public as part of the [Nomly](https:\u002F\u002Fnomly.space) indie portfolio.\n","ASO Studio 是一个面向独立iOS开发者的自托管开源应用商店工具包，集成了关键词追踪、AI生成截图、视频制作流程、PPO实验以及Apple Search Ads优化等功能。项目使用TypeScript编写，通过公共API实现大部分功能，并将所有数据本地存储，确保用户数据安全。其核心特色包括跨50多个国家的关键词排名跟踪、基于AI的App Store截图增强与A\u002FB测试素材生成器、UGC视频广告创意流水线以及针对Apple Search Ads的ROI预测和竞价智能建议等。非常适合希望降低营销成本同时提升应用商店优化效果的小团队或个人开发者使用。","2026-06-11 02:51:59","CREATED_QUERY"]