Skip to main content

Changelog

What's new in Stora. Latest updates, features, and improvements.

May 2026

feature

Visual evidence in creative intelligence reports

Competitor scans now point at the exact region of a screenshot that earns a pattern label — overlaid bounding boxes in both the full report and the chat card.

Show, don't summarize#

Until today the Creative Intelligence report told you which patterns competitors used and how often, but it never showed you where on the screenshot the pattern lived. You had to read the strategist's reasoning, open each thumbnail, and squint to find the coupon modal or the cashback stamp the report was citing. The visual proof was always one click away.

Today every creative intelligence report carries a typed visualEvidence array on the payload — one card per high-signal competitor screenshot, with normalized 0–1 bounding boxes anchoring each detected pattern to a specific region of the frame.

What changed#

Classifier returns bounding boxes#

The screenshot classifier (generateObject with a Zod schema, AI SDK v6) now asks the vision model to emit up to two boxes per detected pattern. Each box is a fraction of the image so the overlay scales perfectly without knowing the source resolution, and carries a short label ("Coupon modal", "Savings stamp", "Trust badge", "Price comparison chart"). Boxes that overflow the unit square or come back zero-sized are dropped at the boundary — the UI can never receive a misshapen rectangle.

When the model can label a pattern but can't visually anchor it (text-only captions, off-format compositions), the box list stays empty and the pattern still rolls up into the matrix as before. The fallback path that produced labels from metadata when vision failed continues to work; it just never produces boxes.

Visual evidence section in the full report#

The library detail view for a creative intelligence report has a new "Visual evidence" section sitting between the strategist thesis and the pattern matrix. It renders six to ten of the highest-signal annotated screenshots — competitor frames beat target frames at the same score because the report exists to surface what competitors do that we can borrow. Each card shows the overlay, the app + pattern label, and a one-sentence insight tying the screenshot back to the strategist's reasoning.

Cross-highlight is wired both ways. Clicking a pattern matrix row pulses the matching evidence cards (and dims the rest); clicking the "Show evidence" affordance on a recommendation does the same via inferred pattern match. There's also a "Clear filter" affordance so the workflow never feels stuck in a filtered view.

Visual takeaways in the chat card#

The Creative Intelligence inline card in chat now leads with a compact "Visual takeaways" carousel — the top three annotated thumbnails with hover-revealed labels — above the existing pattern pills. Reports without visualEvidence keep their original pill-only look, so older reports written before this shipped render exactly as they did yesterday.

Reusable annotated-screenshot component#

The overlay logic lives in a single AnnotatedScreenshot component used by both surfaces. It supports a full variant (labels always visible) for the report view and a compact variant (labels reveal on hover) for the chat carousel, plus a highlightedPatternId prop that lets the parent dim non-matching boxes during cross-highlight.

What this unlocks#

The pattern matrix used to ask the team to trust that the strategist read the screenshot correctly. Now the strategist has to point. Frames the model labels confidently get bright high-confidence outlines; ambiguous frames render in amber and tell you so. Disagreement with the model is now a one-click "this isn't where the savings stamp actually is" interaction instead of a multi-tab investigation.

improvement

Every import path now leaves a project in the same state

Competitor scan, ASO, and Store Listing now work the moment you finish importing — regardless of whether you came in from an App Store URL, a binary, or a GitHub repo.

Imports stopped being three different things#

Stora has four ways to start a project: paste an App Store URL, paste a Play URL, upload an IPA/APK/AAB, or connect a GitHub repo. Until today those four paths left projects in three different shapes. URL imports filled in the listing snapshot, ASO profile, screenshots, and a cold-start brief. Binary uploads created the project but skipped the listing baseline. Repo imports deferred bundle ID detection to whenever the user later opened a settings page.

That meant competitor intelligence, Store Listing readiness, and identity-aware ASO tools all silently treated "you uploaded an IPA five minutes ago" as "this project has no app yet." Pasting an App Store URL was the only fast path to a working setup.

Today every import lands at the same identity baseline. The competitor scan no longer hard-requires project.appStoreUrl, binary uploads seed the ASO profile + a minimal listing snapshot inline, and the GitHub repo flow extracts the iOS bundle ID and Android package name at import time instead of on the next root change.

What changed#

Competitor scan resolves identity from any usable source#

The competitor scan workflow used to refuse to run when project.appStoreUrl was null, even on projects that had been imported from an App Store URL and still carried the listing snapshot. It now resolves the target through a fallback chain: project URL → latest listing snapshot → empty (with a clearer setup message). The same fallback applies to the inline get_aso_competitors chat tool, which can now run on Play-side projects via the listing snapshot too.

Canonical project-identity resolver#

A new resolveProjectAppIdentity() helper composes the project row, latest listing snapshot, active ASO metadata version, and ASO profile into one typed shape with per-field provenance — so callers can see whether the App Store ID came from the user-configured URL or was inferred from a snapshot. Competitor scan, the chat tool, and the read_review_themes / read_intelligence_brief report tools all read through it.

Binary imports seed the ASO baseline#

Every binary upload — new project from IPA/APK/AAB, the /api/apple/upload-build re-upload route, and the /api/screenshots/binary-upload route — now upserts the analyzed bundle ID onto the ASO profile and inserts a minimal listing snapshot. The synthetic snapshot is marked with raw.source = 'synthetic_from_binary' so future readers can tell it apart from a real extracted listing, and it's idempotent so a later real listing isn't buried under a placeholder.

GitHub repo imports detect the bundle ID inline#

createProject() now runs the GitHub repo bundle ID extractor (app.json for Expo, project.pbxproj / .xcconfig / Info.plist for iOS, build.gradle applicationId for Android) inline at import. The detected identifiers go onto the ASO profile immediately, and a minimal listing snapshot is seeded for whichever platform resolved. The existing updateProjectRoot flow now does the same on re-root.

One way to write listing snapshots#

Four different projectListingSnapshots insert sites (modal App Store URL, sample fixture, onboarding, listing-refresh agent) had drifted in shape and carried no provenance. A single insertListingSnapshot() helper now stamps raw.source with app_store_extract, play_store_extract, sample_fixture, listing_refresh, or synthetic_from_binary so the resolver and UI can always tell where a row came from.

ASO quality score can't fake a 100 anymore#

The metadata writer's budget-exhausted fallback wrote qualityReport.score = lastDeterministic.score without folding in the critic result, so a draft could read score=100 with critic.passed=false. The score derivation now lives in an exported computeQualityScore() helper: when the critic rejected, the score is capped below 90 and a 10-point penalty is applied per listed failure, floored at 0. The "perfect 100" only survives when both deterministic and critic pass.

feature

Agent-composed reports + inline chat cards

Reports are now compiled by an agent loop, not hardcoded generators — and they render inline as custom cards in chat.

Reports are agents now#

Until today every Stora report — audit, keyword optimization, screenshot performance — was a hand-written generator with its own DB queries baked in. Adding a new report kind meant copy-pasting a generator file and rewiring it. The audit was useful but stateless: it forgot what it told you last week and re-surfaced the same recommendations until you acted on them.

Today every report flows through a single agent loop that:

  • picks a shape (audit, keyword optimization, creative intelligence, positioning brief) from a typed registry,
  • gathers signal via a medium-grain tool inventory (read_project_state, read_aso_metadata, read_keyword_data, read_competitor_data, read_review_themes, read_intelligence_brief, read_prior_reports, read_install_funnel),
  • produces a typed payload that matches the shape's schema in a single call (AI SDK v6's generateText with structured output),
  • persists to aso_reports + saves a Library pointer just like the old generators did.

The agent decides which tools to call based on the project's actual state. Empty projects short-circuit with an honest "set up the basics first" payload instead of fabricating zero-score analysis. Reports never invent metrics — every recommendation cites the data point that justifies it.

State-aware audits#

Before emitting a recommendation, the audit agent calls read_prior_reports and tags items that already appeared recently as previouslySurfaced. The inline card dims those items so the team sees "we already told you this — still relevant" rather than treating it as fresh insight. Creative intelligence has the same treatment for its top recommendation.

Inline cards in chat#

When a report finishes running in the chat thread, you no longer see "Saved to Library" — you see the report itself, inline, with chrome custom to the shape:

  • ASO Audit → score ring (color-coded by grade), top three recommendations with impact/effort chips, dim-out for previously surfaced items
  • Creative Intelligence → pattern matrix as pills (green = your app uses it, amber = gap), top recommendation, "Copy designer brief" button
  • Keyword Optimization → verdict from the t-test narrative, top movers with up/down icons, an inline visibility sparkline
  • Positioning Brief → thesis statement, persona list, voice trait chips, proof pillars
  • Import Brief → headline, rating chips, top next action

All four read the typed payload the agent already produced — no extra LLM cost per card render. A small REST endpoint serves the payload; the dispatcher fetches it on first paint with a skeleton fallback.

Cleanups while we were here#

  • annualizedUpliftEstimate on keyword optimization reports has been renamed to opportunityScoreTrend — the old name implied an install-count forecast it never was. The value is a signed directional signal for ordering iterations, not a projection.
  • The screenshot_performance launch path now returns 410 with a clear deprecation message. It depended on App Store Connect funnel data that isn't ingested yet; the deterministic "blocked" stub it was producing eroded trust in the reports that ARE real. Legacy reports still render in the Library. When real ASC funnel data lands, the launch path comes back behind a feature flag.

New shape: Positioning Brief#

The first report kind added on the new architecture. Produces a one-page market thesis: differentiation vs tracked competitors, target personas with motivation + objection, voice traits with copy examples, and proof pillars pulled from review themes + intelligence data. When signal is thin, the note field says so honestly rather than padding with fluff.

Structured output everywhere LLMs run#

The screenshot vision classifier and the competitor-scan strategist both used to freeform-parse JSON out of model responses. When the model hedged with prose or wrapped its output, parsing failed and either a screenshot got dropped from the pattern matrix or the whole strategist run fell back to its deterministic skeleton. Phia's first scan exhibited both failures.

Both now use AI SDK's generateObject with a Zod schema — the model can't return malformed output. The classifier additionally has a metadata-based backup: if a vision call still fails (rate limit, refused image), it infers 1-2 patterns from the competitor's title + subtitle + keywords rather than silently dropping the screenshot. Every URL gets a label.

What this unlocks#

Adding a new report kind is now ~150 lines: a shape file (Zod schema + compose prompt + default tool list) + a card renderer. No new generator, no new workflow, no schema changes beyond adding the kind to AsoReportType. The same eight tools serve every shape.

improvement

StoraIntelligence: AppTweak-alternative ASO data layer

StoraIntelligence: deep ASO data without AppTweak#

AppTweak charges $200/month minimum. We built an alternative that sources the same data from public APIs + the Wayback Machine, enriched with AI analysis.

What's new#

Historical metadata tracking — every time Stora fetches your app's metadata, it snapshots it. Over time you build a timeline of title/subtitle/description/screenshot changes. For apps we haven't been tracking yet, the Wayback Machine fills in historical captures automatically.

A/B test detection — the snapshot diff engine surfaces when a competitor changed their title or screenshots, so you can see exactly what they tested and when.

Review sentiment analysis — Claude Haiku reads recent reviews in batches and labels each one as positive, neutral, or negative. Summary stats (positive rate, average rating, trend over 30 days) surface patterns invisible in star ratings alone.

Keyword opportunity scoring — a 4-signal score (popularity 40%, difficulty 30%, chance 20%, competition 10%) that tells you which keywords have the best ROI for your app specifically.

Market intelligence — top developers, average ratings, and average review counts for any App Store category.

New API endpoints (all behind authentication)#

| Endpoint | What it returns | |----------|----------------| | GET /api/aso/intelligence/app/[appId] | Full app metadata profile | | GET /api/aso/intelligence/app/[appId]/history | Metadata change timeline | | GET /api/aso/intelligence/app/[appId]/keywords | Keyword ranks + opportunity scores | | GET /api/aso/intelligence/app/[appId]/competitors | Competitor list with rich metadata | | GET /api/aso/intelligence/app/[appId]/reviews | Reviews + sentiment analysis | | POST /api/aso/intelligence/keywords | Batch keyword metrics + suggestions | | GET /api/aso/intelligence/charts/[category] | Category top charts + history | | GET /api/aso/intelligence/market/[category] | Market-level aggregates | | GET /api/aso/intelligence/developer/[devId]/apps | Developer portfolio |

Enabling it#

Set STORA_INTELLIGENCE_ENABLED=true in your environment. Once the DB migration (0053_aso_intelligence.sql) is applied, all tracked apps start building historical snapshots automatically via the daily 4am cron.

Under the hood#

Built on app-store-scraper (live data) + Wayback Machine CDX API (historical depth), with Apple Search Ads keyword popularity when credentials are available. No third-party ASO API required.

improvement

Run view polish and competitor intelligence

Wider chat rail, animated copy button, cleaner integration icons, and a free-tier competitor scan workflow.

Run view polish and competitor intelligence#

A round of polish on the run/chat experience plus a new agent-powered competitor scan workflow.

Wider right-side panel#

The chat rail in the run view is now 580 px wide (up from 420 px), giving messages and tool call output more room to breathe without requiring horizontal scrolling.

Animated copy button#

The Copy button in chat messages now animates when clicked — the icon and label swap with a zoom-and-fade, and the button turns green briefly to confirm the copy. Clicking again resets it.

Cleaner integration icons#

Provider logos for Asana, Jira, Linear, Notion, PostHog, and Mobbin no longer carry a background rectangle. The marks now float directly on the card background, matching the cleaner style of the other providers in the grid.

Competitor scan workflow#

A new agent workflow can scan your top competitors and surface insights automatically. It:

  • Pulls your competitor list from your project's configured rivals
  • Fetches App Store metadata for each (ratings, category, description, screenshots)
  • Classifies screenshots by visual pattern (hero value prop, social proof, feature showcase, etc.)
  • Identifies shared themes across competitors and flags patterns your app is missing
  • Saves findings as a Library artifact and posts an inbox alert with the key gaps

This runs on free-tier App Store data — no AppTweak subscription required. The workflow is currently behind a feature flag (STORA_COMPETITOR_SCAN_ENABLED).

improvement

Persona detection + redesigned Home shell (dark-launched)

What changed#

  • Persona detection (ENG-204a). detectPersona(userId) reads the last 14 days of activity from inbox_items and chat_session and classifies the user as pm (≥10 inbox triage actions), designer (≥40 artifact-detail sessions on builds / screenshot sets / listings / releases), marketer (≥20 general chat sessions), or unknown (downstream falls back to marketer). Tie-breaks favour PM, then designer, then marketer — inbox triage is the strongest signal.
  • Persona override. Settings → General now has a "Home layout" card with four radio options: Auto, PM, Marketer, Designer. Auto means the Home shell auto-detects; the other three pin the layout. Stored on users.persona_override. Picks save optimistically with a toast.
  • getEffectivePersona(userId) = override ?? detect ?? 'unknown' — the override wins; absent that, detection runs; absent both, fall back to marketer downstream. This is the single function chunk 5.4 will call to pick the Home variant.
  • Redesigned Home shell (ENG-204b, dark-launched). Behind STORA_HOME_REDESIGN_ENABLED:
    • A new Greeting component above the hero: time-of-day + first name + attention count ("Good morning, Carlton. 3 things need your attention.").
    • The existing HomeHero + prompter stay as the composer.
    • A new StartersStrip underneath with 4 canonical-intent pills (Capture screenshots / Run compliance sweep / Audit my ASO / Generate listing copy). Pressing a pill seeds the prompter; the user can edit and submit.
    • A hairline + placeholder card where the "What Changed This Week" widget will land in the next chunk.
    • Classic post-hero modules (AgentPicker, ReadinessStrip, Active/Recent runs, Issues link) are hidden in this mode — they migrate to their owning surfaces in chunk 5.4.
  • Default off. Existing Home renders unchanged when the flag is false (today's production behaviour). Flip STORA_HOME_REDESIGN_ENABLED=true (or the Phia master STORA_PHIA_DEMO_ENABLED=true) to opt-in.

Why this matters#

Persona detection is the prerequisite for the Home page to feel adaptive — instead of forcing a role onto a user at signup, we infer it from what they actually do. The dark-launched redesign gives us a flag to flip when we want to A/B the new layout against the classic one without a code change. The override gives users (and us, during the rollout) escape hatches.

Behind the scenes#

  • detectPersona is pure — heuristics live in web/lib/users/persona.ts and accept an injectable ActivityCountFn so tests cover thresholds, priority ordering, and override resolution without standing up Postgres. 18 unit tests pass.
  • Migration 0056_user_persona_override.sql: ALTER TABLE "user" ADD COLUMN "persona_override" text;. Numbering gap 0054/0055 is intentional — those land with later chunks; Drizzle migrations are independent.
  • TasksHub gained three optional props — layoutMode, userName, attentionCount. The server page reads isHomeRedesignEnabled(), fetches an inbox count only when the flag is on (no extra query in the classic path), and passes both down.
  • Greeting is server-safe (passes a fresh Date per render so the time-of-day doesn't flicker on first paint); StartersStrip is hidden on narrow viewports per the spec — the composer is the priority mobile surface.

Tests#

  • 18 unit tests for classifyPersona / detectPersona / getEffectivePersona / resolveVariant cover the four thresholds, priority ordering (pm > designer > marketer), override-beats-detect, and the unknown→marketer fallback.
  • 10 RTL tests cover Greeting (first-name extraction, singular/plural attention copy, time-of-day at 3/10/14/20h) and StartersStrip (4 buttons render, onSelect fires the canonical intent string).

Deploy#

Run 0056_user_persona_override.sql on prod before the next deploy. Safe additive column with no backfill — null means auto-detect.

feature

Home redesign and integrations connect flows

Persona-aware home experience, WhatChanged digest widget, and AppTweak/ASC/Apple connect flows.

New home experience and integrations#

Today's update ships a redesigned home experience and the first round of App Store intelligence integrations.

Persona-aware home#

The home page now adapts to your role.

  • PM view — replaces the greeting with a digest hero: "Your digest, [name]. Here's what changed since you last checked in." Your activity feed is front and center, no scrolling required.
  • Designer view — surfaces your Pattern and Collection library artifacts in a horizontal scroll above the digest, so the design references you pull from Stora stay one click away.
  • Default view — unchanged for users who haven't been assigned a persona.

What changed this week#

A new digest widget shows what happened across your connected data sources since your last visit — metadata changes, review spikes, ranking shifts, and compliance alerts — grouped by severity. Each item links directly to the relevant section of the project. Items you've seen can be dismissed individually with Skip.

Integration connect flows#

Three new integrations are now fully connectable from Settings → Integrations:

  • AppTweak — paste your API key to connect. Keyword rankings, review monitoring, and competitor data will pull through once the sync is live.
  • App Store Connect — connect with your Key ID, Issuer ID, and .p8 private key. Credential validation is local (no round-trip required); the key pair is stored encrypted and used for metadata writes and submission.
  • Apple Developer — connect with your Team ID, Apple ID, and app-specific password for Transporter uploads and TestFlight operations.

All three providers validate credentials structurally before saving, so you get a clear error if a field is malformed rather than a silent failure later.

Integration icon refresh#

Provider icons in the integrations grid are now clean, background-free logos — no more white squares around them. All icons are self-contained SVG marks that render cleanly at any size and in both light and dark themes.

improvement

Library detail polish — properties, actions, and shared chrome on /screenshots

What changed#

  • Date Created + Last Updated moved out of the metadata chip row and into the Properties sidebar as real property rows. Relative dates inline (3d ago) with the full timestamp on hover. "Last Updated" suppresses itself when it matches "Date Created" so static items (reports, completed screenshot batches) don't show a redundant row.
  • Download in the overflow menu now forces a real download via a programmatic anchor click instead of window.open, which was opening the artifact in a new tab on browsers that didn't see a Content-Disposition header.
  • Delete was unreliable: Radix dropdown cleanup was racing the window.confirm prompt. Replaced with an inline AlertDialog owned by the overflow menu — the dropdown closes cleanly and the confirmation renders in its own portal.
  • Open in chat stopped copying-then-toasting. It now writes the artifact ref (@build:…, @report:…, @competitor:…) to a per-project sessionStorage seed and navigates to the project home. The TasksHub prompter picks the seed up on mount, prefills the textarea, and clears the key. Refresh-safe — a reload won't re-seed.
  • Screenshot collection cards kept their three-up fanned preview but now live inside the unified LibraryItemCard chrome. Same bg-surface + ring + shadow tokens as builds, reports, and the new artifact kinds. The dark gradient frame is gone.
  • /project/[id]/screenshots/[collectionId] now wears the same library detail chrome as every other detail view: sticky breadcrumb (Project › Library › Screenshots) at top-left, action buttons at top-right (Originals, Attach to release, Share, Download, kebab), and a Properties sidebar with Type, Status, Total, Devices, Locale, Store, Bundle ID, Target count, Inspiration, Date Created, Last Updated. The grid, locale picker, tabs, originals slide-out, lightbox post-editor, and activity log all still work — only the chrome changed.
  • Build viewer hero illustration was reverted. A centered rocket-on-stacked-cards visual under the title felt fussy; the empty space below the title and chips is better.

Why this matters#

The library detail surface ships its polish phase: properties read like a real properties panel, the overflow menu's destructive actions don't silently no-op, "Open in chat" actually opens chat, and the screenshot collection viewer no longer feels like a separate product. The seven detail kinds (build, screenshots, ASO report, competitor, pattern, variant, library collection, knowledge) plus /screenshots/[id] share one visual language top to bottom.

Behind the scenes#

  • LibraryDetailShell accepts createdAt + updatedAt as first-class props, threaded from getLibraryItem's meta.createdAt / meta.updatedAt through LibraryDetailPage to the shell. The shell renders the dates as PropertyRows with a formatRelative helper.
  • The five renderers that previously emitted a created/built/generated/added ${formatRelative} chip dropped it — the shell now owns date display. Renderer-specific date chips (scanned, detected, live since) stay because they're distinct from the universal created/updated timestamps.
  • The shell drops its own horizontal padding (px-4 sm:px-5 lg:px-6) and inherits the project layout's px-4 sm:px-8 lg:px-10 instead, so the detail surface and the library index page share gutters.
  • OverflowMenu is now self-contained: it owns the AlertDialog for delete and switched from Radix onSelect to onClick so menu-close cleanup can't race the handler.
  • KindThumbnail was extracted from library/page-client.tsx into a shared components/library/kind-thumbnail.tsx. The page-client now imports it, and a scale prop is available for callers that want a larger or smaller variant.
  • Routing for collection cards: /library server now sets href to /project/[id]/screenshots/[id] directly, and the /library/[itemId] route server-redirects collection IDs to the same place — visiting either URL lands on the same view.

Tests#

  • 39 library + ASO tests pass under vitest run --pool=forks --poolOptions.forks.singleFork.
  • Three new shell tests cover the Date Created / Last Updated rows: a row renders when createdAt is passed; "Last Updated" is suppressed when it matches createdAt; "Last Updated" shows when newer than createdAt.

No migrations. No schema changes. No kill-switch flip.

improvement

Library item detail redesign — one consistent surface for nine kinds

What changed#

The Library detail surface used to be ASO-only. Click a competitor card and you'd land on a 404. Click an ASO audit and you'd get a wall of raw markdown with no header, no metadata, no chrome — the body was the whole page. Today's release replaces that with a unified detail surface.

  • Slide-out by default. Clicking any of the nine Library item kinds (build, screenshot collection, ASO report, agent artifact, competitor, pattern, variant, library collection, knowledge source) now opens a Drive-style sheet from the right. The grid stays visible underneath. The URL state lives in ?item=<id> so deep-links and back/forward work.
  • Hybrid full-page route. An "⤢ Expand" button promotes the slide-out to /project/[id]/library/[itemId] for shareable URLs. The same shell renders inside both surfaces — no duplicate code.
  • Shared shell, blocks system. Every detail view renders inside LibraryDetailShell: header (back arrow, type chip, title, primary actions), inline chip row, hero block, and an ordered list of typed body blocks. Six body blocks ship today — StatGrid, ScreenGallery (with lightbox + arrow-key navigation), ProseBlock (markdown + GFM), KeyValueList, LinkedItems (cross-artifact mini-cards that open in place), and LegacyAsoBody (drop-in for the four existing ASO viewers).
  • "Open in chat" everywhere. Every renderer that has a stable slug surfaces a primary action in the header that copies the artifact reference (@competitor:notion, @pattern:single-stat-hero, @variant:hero-a, @collection:research-q2, @doc:<uuid>) to the clipboard, ready to paste into a chat composer.
  • Cross-artifact navigation without remounts. Clicking a LinkedItems mini-card inside an open sheet swaps content in place via router.replace('?item=<newId>') — no flash, no scroll reset. The renderer registry handles the new kind transparently.
  • Public share preserved. /share/[token] was migrated to the same shell with hideOwnerChrome, so anonymous report views still work — back link, share button, and overflow menu hidden.

Why this matters#

The Library now reads like Drive: one surface, content-aware, navigable. The old detail view answered "show me the raw markdown for this one report"; the new one answers "show me whatever this thing is, with the metadata that makes sense for its kind." Competitors get a stat grid + bundle/developer row + screenshot gallery. Variants get the cover screenshot + reasoning prose. Knowledge docs render the extracted body. ASO reports keep their four existing viewers wrapped as a single body block.

The redesign also lays the groundwork for the next chunk — interactive competitor depth. The shared block library is what FlowPlayer, PatternBoard, and CompareView will plug into when they ship, so competitor detail can show scrubable onboarding flows, annotated pattern boards, and side-by-side comparisons without rewriting any of the shell or chrome.

Behind the scenes#

  • getLibraryItem tries each of five source tables (library_artifact, knowledge_item, aso_report, app_build_artifact, screenshot_collection) and returns the first hit — UUIDs don't overlap across them.
  • Renderers are pure functions in web/lib/library/detail/renderers/. Each kind owns one file that maps payload to a typed DetailViewModel. Adding a kind means writing one renderer file; no shell or block changes needed.
  • A per-block error boundary catches render-time throws — one bad block shows a small fallback inline, surrounding blocks still render.
  • 48 new tests cover the registry, every renderer, every block, and the shell's chrome. RTL + jsdom; no E2E was added (slide-out wiring is RTL-testable).

No migrations. No schema changes. The STORA_LIBRARY_ARTIFACT_TYPES_V2 kill switch from last week still gates the five new artifact types — those land in a notFound() under flag-off, but the new shell still renders for the four existing kinds, so a rollback still buys the layout improvement.

improvement

Live device sessions stay mounted, Approve never hangs, composer matches the side rails

What changed#

Four polish fixes shipped on main around the chat-runtime device experience:

  • Live device stays mounted after boot. When start_device finished provisioning, the right-pane device frame would appear for a few seconds and then revert to the "Setting up your device…" placeholder. The events list inside useSessionRuns was being wiped the moment the underlying run hit __end__, which destroyed the device_session event holding the live frame. The frame now persists through the run ending, exactly as you'd expect.
  • Approve never hangs. The start_device tool no longer awaits its chat_runs insert — that's fire-and-forget now, and the agent-task insert is capped at five seconds. The "Approving…" spinner used to sit for over a minute when the chat-runs link was slow; the model now gets its tool_result within ten milliseconds and the chat closes its turn immediately.
  • Approve click shows in-flight state and surfaces failures. Clicking Approve now flips the button label to "Approving…" while the permission POST is in-flight, and any non-410 server error is shown inline above the buttons with the buttons re-enabled so you can retry. The previous silent-swallow path was the source of the "I hit Approve and nothing happened" report.
  • Composer plus right pane share the side-rail chrome. The floating composer and the right-pane tab card now use the same rounded-xl bg-surface ring-1 ring-[--surface-edge] shadow-sm recipe as the left primary rail, so all three panels read as part of the same surface family. The "⌘↵ to send" hint is gone (Enter alone sends), the send arrow is thicker, and the stop button is fully rounded while the agent is streaming.

Why this matters#

The confirm-lane device flow is the most-watched part of the chat runtime: the user clicks Approve, sees a permissioned action take place, and expects feedback within a second. Every silent failure here erodes trust in the agent. This iteration closes the four feedback loops that were leaking — Approve responsiveness, in-flight signal, error visibility, and device-frame persistence after the boot completes.

improvement

Background runs narrate themselves back into chat; right rail loses its five-tab maze

What changed#

Two Plan-sized shifts shipped on main for the chat-runtime cohesion thread:

  • Background runs narrate themselves back into the parent chat. When a run_qa, run_compliance, run_screenshot_v2, run_aso_generate, run_aso_report, run_capture, run_readiness_loop, or run_pipeline workflow reaches a terminal state, the workflow now posts a synthetic assistant_turn_start + assistant_message + assistant_turn_end into the chat session that spawned it. Each tool kind has a hand-written digest template that picks the highest-signal fields from agent_task.result — issue count, top issue titles, screen counts, listing title, readiness score — so the user sees an actual sentence in the chat instead of staring at an inline run pane with no narration. The notification is single-writer idempotent via a new agent_task.parent_notified_at column.
  • Right rail goes from five tabs to one accordion. The run detail page-client (web/app/project/[projectId]/tasks/[runId]/page-client.tsx) used to surface Device, Artifacts, Info, Issues, and Git as separate tabs in the top-right corner. The Device frame is now always pinned at the top when the run owns a live device, and Artifacts, Run info, and Git all collapse into a single Details accordion underneath. Issues content moves into the run timeline where it actually belongs.

Why this matters#

The cohesion gap was the loudest piece of feedback on the agent shell: a user would ask "run a QA sweep," the chat agent would call the tool, the right rail would fill with five tabs, the run would finish, and the chat thread would sit silent. The user had to manually click "Open full run" to find out what happened. Result-piping closes that loop without a second model round-trip — the digest is deterministic, written once, persisted into the JSONL stream so it survives the user navigating away or closing the tab, and the future-replay path puts it into model context naturally so the next user turn can reason over the outcome.

The right-rail collapse cuts cognitive overhead on an already-busy screen. Most users only wanted the Device frame and one or two lines of metadata; the five-tab layout forced a click for every glance. Stacked Device + Details accordion is the same information in two scan-able regions.

Migration#

Apply drizzle/0049_agent_task_parent_notified_at.sql on the next deploy:

sql
ALTER TABLE "agent_task"
  ADD COLUMN IF NOT EXISTS "parent_notified_at" timestamp;

The column is nullable and the workflow code defaults to null for rows that pre-date this release — they will not be retro-narrated, but they also will not block on a missing column.

improvement

Chat turns never end silently after tool calls, generative asks now route through pick-an-option

What changed#

Two contract-level changes to the chat runtime, plus a defensive fallback and a small chrome match.

  • Closing-text rule. Every chat turn that calls tools now ends with at least a one-sentence synthesis. For state-inspection questions ("is my app submission-ready?", "what's my status?", "how am I doing?"), the answer is a direct yes/no with the two or three concrete factors driving it — not a list of which tools ran. After the synthesis, the agent proposes one clear next action.
  • Generative-UI rule. Open-ended creative requests — "design a new screenshot set", "rewrite my listing", "build me a hero image", "give me keyword variants" — now route through a clickable option picker first. The agent presents three to five concrete shapes (e.g. "Modern minimal", "Bold typography", "Photographic"), the user clicks one, and the matching run_* tool fires with that choice baked into the input. The right-pane RunCard mounts immediately so the work is visible while it streams.
  • Silent-turn fallback. If a future model regression ever lets a turn end with tool results but zero closing prose, a fallback message lands in the replay log so the conversation stays well-formed and the user always has something to read.
  • Orphan-tool-use hardening. A class of "messages.N: tool_use ids were found without tool_result blocks" 400s is gone — the conversation sanitizer now patches tool parts in any non-terminal state, including the confirm-lane "awaiting_approval" state that surfaced when users typed a follow-up instead of clicking Approve.
  • Surface chrome match. The ask-user dock above the composer now uses the same surface-edge ring and shadow as the composer and the left and right rails, so the three panels read as one family.

Why this matters#

Before today: ask "is my app submission ready?" and the agent would run four read-only tools, paint four green pills, and stop. The user was left to interpret raw tool output themselves — or worse, refresh the page and lose the turn. Open-ended creative asks had the same silent failure mode plus a guessing problem: the agent would pick one shape and ship it without telling the user there were other shapes to choose from.

Both modes are gone. State questions get a real answer. Creative requests get a picker. The chat composer, the option dock, and the side rails all share the same chrome so the surface feels like one tool instead of three glued together.

improvement

Tool call results stay inside the context window and never strand the conversation

What changed#

Two more chat-runtime hardenings followed today's cohesion work.

  • Tool results never exceed a 60KB JSON budget. Five parallel read-only tools used to be enough to push the next-turn prompt past Anthropic's 1M-token limit — get_screenshots and get_runs returned full database rows with componentCode, metadata, and result JSON columns. Every tool's execute() return now flows through a central trimmer that strips known-huge fields outright, caps strings at 2KB with a head + length marker, caps arrays at 30 entries with a dropped-count marker, and progressively prunes the largest top-level entries if the result still overshoots the total budget. Five-way parallel reads now fit in under 75K tokens combined.
  • Tool parts without a result are rescued at the contract level. The previous fixes patched specific bad state names (input-available, awaiting_approval, approval-requested). The new check is contract-based: a tool part is "well-formed" only if it is in one of the three terminal states (output-available / output-error / output-denied), has the payload that state implies (output / errorText / approval object), and is not marked providerExecuted: true. Anything that fails any of those checks becomes output-error with a synthetic message before the request reaches Anthropic. Same predicate runs on session hydration so historical JSONL with bad shapes gets repaired on reload.

Why this matters#

Two failure modes are gone. Long-tail "prompt is too long: 1,037,780 tokens > 1,000,000 maximum" errors that surfaced for projects with many screenshot collections or long run histories are closed off at the trim boundary. And the "messages.N: tool_use ids were found without tool_result blocks" class of 400s is closed at the contract level rather than by enumerating known-bad states — any AI SDK v6 state or shape that would make convertToModelMessages skip a tool_result now triggers the rescue.

Combined with this afternoon's closing-text rule and generative-UI rule in the identity prompt, the chat surface should feel cohesive: state questions get real answers, creative requests get clickable options, big projects don't overflow context, and stale sessions repair themselves on the next reload.

improvement

Analytics priors — screenshots and ASO now lead with your most-used features

What changed#

Two new product-analytics providers have landed in the Integrations Hub, and a new pipeline now feeds your real usage data into both the screenshot agent and the ASO keyword researcher.

  • Amplitude and Mixpanel join PostHog as supported analytics sources. Each connects via API key (or service-account credentials for Mixpanel) and includes a "test connection" verifier.
  • A new analytics-priors pipeline pulls top events over the last 30 days, rolls them up into product features via Claude, and surfaces the result to specialised agents:
    • The screenshot agent v2 plan call now sees a "Real usage signals" block listing your top features. The first three frames in any new 8-frame plan are biased toward the top three features, so screenshots lead with what users actually use. Per-frame edits inherit the same priors so re-painted frames stay coherent with the original set.
    • The ASO keyword researcher weights core-functionality and feature-specific keywords 2–3x toward the same top features, so the seed keyword list reflects user-language for the moments that matter.
    • The iOS + Android metadata writer sees the same brief and is instructed to mention your top feature within the first two lines of the description, plus pull 2–4 user-search terms from the feature list into the keyword field.
  • A kill switch, STORA_ANALYTICS_PRIORS=0, disables the pipeline cleanly. Every consumer fails open: if no analytics provider is connected, or the upstream call errors, agents proceed exactly as they did before.

Why this matters#

Until today the screenshot agent and the ASO writer had to guess which features were "core" from app metadata and source code alone. For teams with real users on PostHog / Amplitude / Mixpanel, "core" is already measured — that signal now flows into the agents that need it most.

If your team uses Phia-style hooks across product analytics and growth marketing, this is the integration that closes the loop.

Where to find it#

Settings → Integrations → connect Amplitude or Mixpanel (PostHog stays where it was). The next screenshot or ASO run on a project belonging to that org picks up the priors automatically.

feature

Unified memory, chat runtime, and action-surface home

Cross-agent memory and knowledge feed, unified chat runtime across entity surfaces, and a redesigned dashboard built around actions.

A smarter platform that talks back#

Three large internals shipped together this week.

Memory and knowledge unification (Phase 1)#

Cross-agent summarizers now write to a single feed, so anything one Stora agent learned (a screenshot preference, a compliance gotcha, a build quirk) is available to every other agent automatically. The unified inbox lets you edit, promote, or evict entries, with a nightly eviction cron keeping the feed lean.

Chat runtime#

A new chat panel mounts on every entity surface — projects, runs, library items, audits — and talks to Stora as the same agent driving the work in front of you. Source cards show what files, runs, or knowledge entries the answer is built from.

Action-surface home#

The dashboard "overview" was an analytics scorecard that nobody clicked. The new home is a list of next actions: builds waiting on submission, runs that need review, suggestions ready to apply. Stora tells you what to do, not what already happened.

If your sessions are starting to feel less like file-shuffling and more like a conversation, that's why.

improvement

ASO keyword field linter

Seven iOS-specific keyword rules and a primary-keyword-in-name advisor wired into ASO Audit and the metadata writer.

Catch keyword field mistakes before review does#

Apple's 100-character keyword field has rules nobody documents in one place. Stora now lints them.

Seven iOS rules#

  • No spaces after commas (Apple counts them; competitors don't)
  • No singular and plural of the same word
  • No competitor or trademarked terms
  • No words already in your title or subtitle
  • No special characters that get stripped
  • No exceeding 100 characters
  • No empty or duplicate entries

Each rule fires inline on the metadata editor and blocks submission until resolved or explicitly waived.

Primary-keyword-in-name advisor#

A new dual-name advisor recommends moving your primary keyword into the app name itself, where it carries the most ranking weight. Suggestions are tailored to your app and locale and can be applied with one click.

Wired into both ASO Audit and the metadata-writer critic, so the same checks run whether you're auditing manually or letting Stora generate a fresh listing.

April 2026

feature

Cinematic v2 onboarding

A new Mac-native tri-pane analyze/sim onboarding plus seven web routes for the same flow.

A first-run that actually shows you what Stora does#

The old onboarding asked you to fill out a form. The new one runs Stora.

Mac tri-pane#

The Stora desktop app now opens to a SwiftUI tri-pane that analyzes your repo, spins up a simulator, and captures a sample screenshot — all before asking you for anything. By the time it shows the connect-account button, you've seen what the product does.

Web parity#

Seven new web routes (/onboarding/analyze, /onboarding/sim, /onboarding/capture, etc.) mirror the desktop flow for users coming in from a browser. Same demo, same feel.

Org-aware scope selector#

Once Stora for Teams shipped, onboarding learned about it: when you connect a repo or upload a build, you pick which org owns it before anything else writes.

If you've shown someone Stora and watched them bounce on the setup screen, this release is for them.

feature

Android audit engine, public Stora Check, and CLI v0.1

Real AAB/APK analyzer, Play Data Safety writer, policy rule engine, public stora.sh/check scanner, and @stora-sh/cli + mcp v0.1.

Three releases in one week#

This week we finished the Android audit pipeline, opened a free public scanner, and shipped the first CLI and MCP packages.

Android Phase 4 — real binary analyzer#

Stora now parses your APK and AAB directly: app-info-parser for APKs, a custom protobuf scanner for AABs. Permissions, target SDK, and binary version are persisted per build and feed into compliance.

Android Phase 5 — Play Data Safety writer#

A full Data Safety form lives in project settings → Android, plus a summary card on the readiness page. Stora writes your declarations directly to Play Console through the Developer API.

Android Phase 6 — policy rule engine#

A pure-function rule engine cross-references the manifest permissions from Phase 4 with the Data Safety declarations from Phase 5. Six new issue types catch April 2026 contacts/location educational warnings and three categories of declaration mismatch before the Play reviewer does.

Public scanner at stora.sh/check#

Drop in any App Store or Play Store URL and get a free read-only audit of the app's compliance posture, ASO, and metadata health. No login required.

CLI and MCP v0.1#

npm i -g @stora-sh/cli for CI invocations from your repo. @stora-sh/mcp exposes Stora's tools to Claude Code, Cursor, and any other MCP client.

Six full audit phases, three new surfaces, one good week.

feature

Android and Google Play submission

Signed AAB and APK output, encrypted upload keystore, and a Play Store submit drawer that mirrors the App Store flow.

Stora ships on Android too#

For months, Stora has been an iOS-first tool with Android support that stopped at "we'll capture screenshots." Android Phase 1-3 closes the loop: from signed binary all the way to a Play Console submission.

Signed binaries (Phase 1)#

Stora now produces signed AABs and APKs from any captured Android build. Upload an existing keystore or let Stora generate one and store it encrypted at rest. The signing card lives in project settings → Android → signing.

Play submit backend (Phase 2)#

A new Play Developer API client handles draft creation, track promotion, and rollout percentage in 25 tested helper paths. Like the App Store equivalent, it's persistence-backed and re-runnable.

Submit drawer (Phase 3)#

The /releases page now shows a Google submit drawer side-by-side with the Apple drawer, with track selection (internal, alpha, beta, production), staged rollout, multi-locale release notes, and the same readiness gates the iOS flow uses. Plus the first RTL test suite.

If you've been waiting on Android because the submission step was manual, you can stop waiting.

feature

Stora for Teams

Organizations, invites, shared credits, role-based access, and Polar-backed team billing — the multi-seat layer of Stora.

Multi-seat Stora is here#

Until now, Stora was a single-developer tool. With ENG-150, you can invite a team to share a project, pool credits across members, and manage billing centrally.

Organizations and invites#

Create an organization, invite collaborators by email, and assign roles (owner, admin, member). Projects, runs, screenshots, and submissions can be scoped to an org so the whole team sees the same source of truth.

Shared credits#

Teams share a single credit balance. Whichever member kicks off a screenshot run, ASO sweep, or submission, the org gets billed — not the individual. The dashboard shows credit usage per project, per member, and per run type.

Team-aware everything#

Every route, server action, and agent now respects org membership. Apple submission routes, knowledge persistence, library sharing, and inbox notifications all check team scope before reading or writing.

Polar billing#

Team plans are billed through Polar with a starter and pro tier; webhooks keep credit balances live across the platform. Free trials and one-off credit top-ups work the same as on individual plans.

If you're an existing solo user, nothing changes — your projects stay yours. If you want to add a teammate, head to settings → organization.

March 2026

improvement

SEO foundations and marketing site overhaul

Sitemaps, robots, structured data, OG image pipeline, blog, and a polished marketing site across stora.sh.

A real foundation under stora.sh#

Last week's release shipped the new product surfaces. This one shipped the discoverability layer underneath them.

What's in#

  • Comprehensive SEO — Sitemaps, robots, structured JSON-LD on every product, use-case, and blog page; descriptive titles and metadata. Search engines and LLM crawlers both index the site cleanly now.
  • Static OG images — Replaced dynamic OG generation with prerendered assets, so link previews on Slack, X, and LinkedIn always render fast and stay sharp.
  • Marketing nav and footer — Mega-menu nav with product and use-case columns, trimmed footer with the links that matter.
  • Blog at /blog — Full MDX blog with author bylines, tags, sentence-case headings, and an RSS feed.
  • 404 redesign — A 404 you don't mind landing on, with a search bar and the most common destinations.
  • stora.devstora.sh — All canonical URLs unified on stora.sh with proper redirects.

The product hasn't changed. How fast someone finds it has.

feature

Context Manager, AI App Icons, Build Repair Agent, and Developer Docs

Project context manager, AI-generated app icons, automatic build failure repair, API key management, new landing page, and developer documentation.

New tools for managing projects, generating icons, and fixing builds#

Today's release adds several features that make Stora smarter about your project and more capable of handling problems on its own.

Context Manager#

The new Context Manager (ENG-145) gives you a central place to configure project-level settings that flow through every Stora feature. Set your app's target audience, tone of voice, brand colors, and key selling points once — and every AI-generated asset (screenshots, metadata, compliance suggestions) will reflect those settings automatically.

AI App Icon Generation#

Stora can now generate app icons using AI (ENG-144). Describe what you want, pick a style (flat, 3D, gradient, minimal), and Stora generates multiple options that meet Apple and Google's icon specifications — correct dimensions, no transparency on iOS, proper safe zones, and rounded corner handling.

Build Repair Agent#

The build repair agent (ENG-143) monitors your builds and automatically diagnoses common failures. When a build fails due to a known issue — missing provisioning profile, expired certificate, incorrect build settings — the agent suggests a fix and can apply it with one click. This catches the problems that waste hours of developer time and usually have straightforward solutions.

API Key Management and MCP Configuration#

The new settings page at /settings lets you create, rotate, and revoke API keys for the REST API. Each key can be scoped to specific permissions (read-only, screenshots, compliance, publishing). The page also provides copy-paste MCP configuration for connecting Stora to Claude Code.

Landing Page Overhaul#

The marketing site has been rebuilt with a mega-menu navbar, dedicated product pages for each feature area (screenshots, compliance, publishing), and a new pricing page. The design is cleaner, faster, and better communicates what Stora does for developers who are discovering it for the first time.

Developer Documentation#

A full documentation site is now live at /docs with:

  • MCP server reference — Every tool, its parameters, and example usage with Claude Code
  • REST API reference — OpenAPI-style documentation for all endpoints with request/response examples
  • Getting started guides — Step-by-step tutorials for common workflows
  • Authentication — How API keys work, scopes, and rate limits

The docs are built into the main app, so they stay in sync with the product automatically.

feature

Major Platform Update: MCP Server, REST API, Binary-Only Mode, and More

The biggest Stora release yet — MCP server for Claude Code, public REST API, binary uploads without GitHub, magic link auth, compliance v2, and build management.

The biggest Stora update yet#

This is a landmark release. Stora is no longer just a web app — it is now a platform with a public API, an MCP server for AI-powered development workflows, and the ability to use the entire product without ever connecting a GitHub repository.


Stora MCP Server#

Stora now ships an open-source MCP (Model Context Protocol) server with 10 tools that plug directly into Claude Code. This means you can manage your entire app store presence from your terminal, inside your existing AI coding workflow.

bash
# Install the MCP server
npm install -g @stora/mcp-server

# Add to your Claude Code config
claude mcp add stora -- npx @stora/mcp-server

Available tools include creating projects, generating screenshots, running compliance checks, uploading binaries, and submitting to the App Store — all callable by Claude Code as part of a natural conversation.

REST API v1#

The new REST API opens Stora to any integration. Authenticate with an API key and access every core feature programmatically:

  • POST /api/v1/projects — Create and manage projects
  • POST /api/v1/screenshots/capture — Trigger screenshot generation
  • GET /api/v1/compliance/{projectId} — Run compliance checks
  • POST /api/v1/builds/upload — Upload IPA/APK binaries
  • POST /api/v1/publish — Submit to App Store or Google Play

API keys are managed from the new settings page with granular permission scopes.

Binary-Only Mode#

You can now use Stora without connecting a GitHub repository. Upload your .ipa or .apk file directly, and Stora will analyze the binary to extract metadata, detect permissions, identify frameworks, and generate compliance reports.

This unlocks Stora for teams using private CI/CD pipelines, enterprise build systems, or any workflow where source code access is not available. The binary analysis engine extracts:

  • App permissions and entitlements
  • Linked frameworks and SDK versions
  • Bundle identifier, version, and build number
  • Privacy manifest declarations (iOS 17+)

Sign up and log in with just your email address. No GitHub account required. Magic links are sent via email and expire after 15 minutes. This pairs with binary-only mode to make Stora accessible to non-developer roles like product managers and QA engineers.

Compliance System v2#

The compliance engine has been rewritten with 40+ rules covering both App Store and Google Play requirements:

  • Permission sequence checking — Verifies that your app requests permissions in the correct order (e.g., showing a purpose string before the system prompt).
  • Account deletion tracing — Confirms that apps offering account creation also provide a discoverable account deletion flow, as required by both stores since 2024.
  • AI-powered analysis — Uses AI to analyze screenshots and metadata for policy violations that rule-based checks would miss.
  • Google Play Console deep validation — Checks data safety declarations, content ratings, target audience settings, and store listing completeness against Google's latest requirements.
  • Pre-submission readiness checklist — A single dashboard showing every blocker and warning before you hit submit.

Build Management#

A new build management tab provides an Expo-like dashboard for tracking your app's builds:

  • View build history with status, version, and timestamps
  • Upload new builds directly from the browser
  • Track which build is attached to which release
  • Monitor processing status after upload to App Store Connect

Project Version Tracking#

Stora now tracks your app's version history across submissions. See which version is live, which is in review, and which is in preparation — with full metadata diffs between versions.

Additional Fixes#

  • Character limits on generated metadata — AI-generated titles, subtitles, and descriptions now strictly respect App Store and Google Play character limits.
  • Age rating always configured — The age rating questionnaire is now required before submission, preventing a common rejection reason.
  • Screenshot config UX — Improved the screenshot configuration flow with better device selection, locale management, and preview layouts.
  • Apple ID session persistence — Your App Store Connect session is now persisted securely, enabling one-click publishing without re-authenticating each time.
feature

App Store Connect Submission Hub

End-to-end App Store Connect submission with credential encryption, release wizard, and AI-powered age ratings.

Ship to the App Store without leaving Stora#

The new App Store Connect Submission Hub brings the entire release workflow into Stora. Connect your Apple Developer account once, then manage versions, fill out metadata, and submit for review — all from a single interface.

What shipped#

  • Full submission hub — A dedicated workspace for managing your App Store Connect submissions. View your app's current status, create new versions, and submit for review without switching to Apple's portal.
  • Credential encryption — Store connection credentials (App Store Connect API keys, Google Play service accounts) are encrypted at rest using AES-256. Keys are never stored in plaintext.
  • Release wizard — A step-by-step flow for creating new releases: set the version number, attach a build, fill in release notes, configure phased rollout, and submit. The wizard validates everything before submission so you catch issues early.
  • AI auto-fill for age ratings — Stora analyzes your app's content and source code to pre-fill the age rating questionnaire. It also detects whether your app uses encryption (for HTTPS, cryptographic APIs, etc.) and fills the export compliance section accordingly.
  • App review information tab — Add demo account credentials, review notes, and attachments that Apple's review team needs — all stored securely and pre-filled on subsequent submissions.

Design improvements#

  • Unified input/textarea design — Every text input across the platform now uses a consistent style: rounded-xl corners, dark background, subtle border. This applies to the submission hub, screenshot editor, and settings pages.
  • Welcome modal redesign — The onboarding modal has been updated to match the Spawnlabs design language with a white logo and cleaner copy.

Why it matters#

The average developer spends 30-45 minutes per submission clicking through App Store Connect's labyrinthine UI. The submission hub reduces that to under 5 minutes. Combined with AI-powered age ratings, most of the tedious form-filling is handled automatically.

fix

Stability and Billing Fixes

Stale job cleanup, tier overrides, billing portal fixes, and demo updates.

Stability improvements and operational fixes#

A focused update on reliability and operational tooling.

  • Auto-cleanup of stale runner jobs — Jobs that hang due to runner crashes or network issues are now automatically detected and cleaned up. No more phantom "in progress" states blocking new captures.
  • Tier override for manual upgrades — Added admin tooling to manually set account tiers, useful for enterprise onboarding and promotional upgrades outside of Stripe.
  • Billing portal error handling — Fixed edge cases where the Stripe billing portal would fail silently when a customer's subscription was in an unexpected state. Errors now surface clearly with actionable next steps.
  • Demo video updates — Refreshed the onboarding demo videos to reflect the current UI and workflow.
feature

Screenshot Pipeline Redesign

New project dashboard, AI-powered ASO, capture method toggle, and locked bundle IDs.

A smarter screenshot pipeline and a new project dashboard#

The screenshot capture experience has been rebuilt from the ground up, and the project dashboard now surfaces the information that actually matters.

What shipped#

  • Redesigned project dashboard — The new layout leads with status: build health, screenshot freshness, and compliance score are all visible at a glance. No more digging through tabs to figure out where your project stands.
  • AI-powered ASO — App Store Optimization metadata generation now uses an upgraded AI model that analyzes your app's actual source code to generate more accurate, contextual keywords and descriptions.
  • Capture method toggle — Choose between live device capture and simulator-based capture directly from the screenshot wizard. Simulators are faster for iteration; live devices produce pixel-perfect results for submission.
  • Locked bundle IDs — Once a project's bundle identifier is set and connected to App Store Connect, it can no longer be accidentally changed. This prevents a class of submission failures caused by mismatched identifiers.

Why it matters#

With source code analysis, Stora now understands what your app actually does, not just what you tell it. ASO suggestions are more specific, more relevant, and require less manual editing before submission.

improvement

Platform Polish and Flutter Fixes

UI refinements, Flutter capture pipeline fixes, and credential cleanup.

A round of polish across the platform#

This update focuses on fit and finish — the kind of work that does not get its own launch post but makes the product noticeably better to use every day.

What shipped#

  • UI polish — Platform tags, modal transitions, and dashboard layout improvements. Small things that add up: better spacing, consistent typography, and smoother interactions throughout the app.
  • Flutter capture pipeline fixes — Resolved issues with dynamic screen dimensions during Flutter app capture and fixed SSH session flushing that was causing stale frames. Flutter apps now capture as reliably as native Swift/Kotlin projects.
  • Credential cleanup — Continued the security work from last month by removing the last hardcoded credentials from build and capture scripts.

These changes ship quietly but they make the difference between a tool that feels rough and one that feels solid.

February 2026

feature

Multi-Runner Architecture

Parallel capture across multiple runners with health checks, heartbeat sync, and a security overhaul.

Scaling screenshot capture with multi-runner provisioning#

Stora's capture pipeline just got a major upgrade. Instead of relying on a single runner to process jobs sequentially, the platform now provisions multiple runners in parallel with full health monitoring.

What shipped#

  • Multi-runner provisioning — Capture jobs are distributed across available runners with automatic health checks and heartbeat synchronization. If a runner goes down, Stora detects it and reroutes work.
  • Explore-once-replay-everywhere (V2 capture flow) — Stora captures your app's screens once, then replays across every device size and locale. This dramatically reduces capture time for apps targeting multiple device types.
  • Per-device status tracking — Each device in a capture job now reports its own status independently. Partial success is supported — if one device fails, the rest still complete.
  • Job status polling with SSE fallback — Real-time status updates stream over Server-Sent Events, with automatic fallback to polling if the connection drops.
  • Security hardening — Removed hardcoded credentials from 17 scripts across the runner fleet. All secrets are now injected via environment variables at runtime.

Why it matters#

Screenshot generation for a typical app (6 device sizes, 3 localizations) used to take 15+ minutes. With parallel runners and the replay-everywhere flow, the same job completes in under 3 minutes. The security cleanup also means the runner codebase is safe to open-source down the line.

January 2026

feature

Stora Platform Launch

Cloud orchestration, device mockups, and the foundation of automated app store optimization.

The beginning of Stora#

Today we are shipping the first version of Stora — a platform built to automate the painful parts of shipping apps to the App Store and Google Play. This initial release lays the groundwork for everything that follows: cloud orchestration, screenshot generation, and intelligent metadata optimization.

What shipped#

  • Cloud orchestrator with Socket.io job dispatch — Stora now manages remote runners that capture real device screenshots on demand. Jobs are dispatched over WebSockets with full status tracking and interactive prompt forwarding across the cloud.
  • Device mockup compositing — Generated screenshots are automatically framed inside pixel-perfect iPhone, Pixel, and Galaxy device bezels. No more fiddling with Photoshop templates.
  • Inspiration gallery — Browse real App Store screenshots from top apps to find layout and design inspiration before generating your own.
  • E2E testing with Playwright — The platform ships with end-to-end test coverage from day one, ensuring reliability as we iterate fast.

Why it matters#

Publishing an app should not require a design degree. Stora handles the visual and metadata busywork so you can focus on building your product. This foundation — cloud runners, compositing, and job orchestration — is the infrastructure every future feature builds on top of.