Skip to content

feat(onboarding): import organization from store listing#2504

Open
riderx wants to merge 2 commits into
mainfrom
codex/onboarding-store-import-shortcut
Open

feat(onboarding): import organization from store listing#2504
riderx wants to merge 2 commits into
mainfrom
codex/onboarding-store-import-shortcut

Conversation

@riderx

@riderx riderx commented Jun 15, 2026

Copy link
Copy Markdown
Member

Summary (AI-generated)

Adds a faster organization onboarding path for users who already have a published app:

  • New "Import from published app" option in organization onboarding.
  • App Store / Google Play metadata import fills the organization name from the developer name and imports the app icon as the org logo.
  • The imported store URL carries into app onboarding so the first app is prefilled as an existing published app.
  • Adds an authenticated private store metadata endpoint that reuses the existing public app metadata parser.

Motivation (AI-generated)

A common onboarding case is that the organization name and first app name come from the same published app listing. Asking users to enter both manually slows down setup. Importing the developer name and app details from the store listing reduces duplicate typing while still allowing users to edit the generated values.

Business Impact (AI-generated)

This should reduce friction in the first-run setup flow, especially for teams migrating an existing production app to Capgo. A shorter path from store link to org + app setup can improve activation and make the onboarding flow feel more tailored to existing app publishers.

Demo (AI-generated)

New onboarding store-import flow

Test Plan (AI-generated)

  • bun lint
    • Passes with the existing src/services/compatibilityEvents.ts JSDoc warning.
  • bun typecheck
  • Commit hook typecheck passed.
  • Recorded the onboarding path headlessly with mocked auth/store metadata and generated the WebP demo above.

Summary by CodeRabbit

  • New Features
    • Added a new “store” import option (App Store / Google Play) to organization onboarding, including store URL–driven prefill and an import flow.
    • Importing now enriches fetched app metadata with developer name and developer URL.
  • Improvements
    • Refined store metadata importing for more reliable, race-safe state handling.
    • Improved imported-logo behavior and icon upload/preview handling.
    • Updated the “copy” controls to use button-based UI in onboarding steps.
  • Chores
    • Added a new backend endpoint to support store metadata fetching.

@codspeed-hq

codspeed-hq Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 43 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing codex/onboarding-store-import-shortcut (6a7a996) with main (4fec440)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: edb5c9dbb3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/pages/onboarding/organization.vue Outdated
Comment thread src/pages/onboarding/organization.vue
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@riderx, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 40 minutes and 51 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: efbcd29f-46e2-4d61-b0f7-babba3bf956c

📥 Commits

Reviewing files that changed from the base of the PR and between 7bd8d05 and 6a7a996.

📒 Files selected for processing (6)
  • messages/en.json
  • src/components/dashboard/AppOnboardingFlow.vue
  • src/pages/onboarding/organization.vue
  • supabase/functions/_backend/private/store_metadata.ts
  • supabase/functions/_backend/public/app/store_metadata.ts
  • supabase/functions/private/index.ts
📝 Walkthrough

Walkthrough

Adds a "store" onboarding mode to organization setup, allowing users to import metadata from an App Store or Google Play URL. A new private backend endpoint scrapes developer name, URL, and icon from store pages. The frontend gains store-mode state, UI, and computed values. The app onboarding flow supports pre-filling via a store_url query parameter and is refactored for modular creation logic and race-safe store imports.

Changes

Store Import Onboarding Flow

Layer / File(s) Summary
Store metadata scraping — developer fields and private endpoint
supabase/functions/_backend/public/app/store_metadata.ts, supabase/functions/_backend/private/store_metadata.ts, supabase/functions/private/index.ts
Extends AppleLookupResult with artistName, sellerName, and artistViewUrl; adds JSON-LD and Google Play HTML parsing helpers to extract developer name and URL; derives developer_name and developer_url in fetchStoreMetadata response; creates an authenticated Hono POST endpoint at /store_metadata with CORS support and registers it in the private router.
Organization onboarding — store mode state and data flow
src/pages/onboarding/organization.vue
Adds StoreMetadata interface, expands OnboardingMode to include 'store', introduces store URL input/metadata/loading state; extends activeOrgName, importedLogoUrl, importedLogoFilenameBase, and sourceSummaryLabel computed values; implements fetchStoreMetadata() action; refactors org-creation helpers to normalize website field per mode and unify logo upload; routes finishOnboarding() with store query params; adds watcher to reset store state on mode change.
Organization onboarding — UI and sidebar updates
src/pages/onboarding/organization.vue
Adds a Store button to mode selection; introduces store URL input block with fetch trigger and conditional helper text; updates org-name helper paragraph, create-button label condition, sidebar source display, selected-path branching, next-steps messaging, and logo-step label to be store-aware and source-agnostic.
App onboarding flow — store prefill, import safety, and creation modularization
src/components/dashboard/AppOnboardingFlow.vue
Adds type interfaces for store URLs and app creation values; implements query-parameter reading (getInitialStoreUrlFromQuery, applyStorePrefillFromQuery) to prefill existing-app mode from store_url; refactors importStoreMetadata with run/URL guards to prevent stale updates; adds icon-file normalization and remote HTTPS icon fetching; modularizes app creation into discrete helpers for validation, candidate creation with conflict handling, and finish steps; refactors watch(existingApp) with a helper; updates onMounted to attempt store prefill before falling back to details; changes CLI copy UI from role-managed div to button in details and install steps.
Localization for store onboarding mode
messages/en.json
Refines existing onboarding choice and logo strings to be source-agnostic; adds organization-onboarding-import-store and store mode label/helper text; adds store-import flow strings (fetch failure, validation, label, placeholder, developer-name helpers).

Sequence Diagram(s)

sequenceDiagram
  actor User
  participant OrgOnboarding as organization.vue
  participant PrivateAPI as /private/store_metadata
  participant Scraper as fetchStoreMetadata()
  participant AppOnboarding as AppOnboardingFlow.vue

  User->>OrgOnboarding: selects "Store" mode, enters store URL
  OrgOnboarding->>PrivateAPI: POST {url: storeUrlInput}
  PrivateAPI->>Scraper: parse Apple/Google Play page
  Scraper-->>PrivateAPI: {developer_name, developer_url, icon_url}
  PrivateAPI-->>OrgOnboarding: StoreMetadata response
  OrgOnboarding->>OrgOnboarding: populate orgNameInput, storeMetadata, importedLogoUrl
  User->>OrgOnboarding: finishOnboarding()
  OrgOnboarding->>AppOnboarding: navigate /app/new?existing_app=1&store_url=...
  AppOnboarding->>AppOnboarding: applyStorePrefillFromQuery() sets existingApp/existingAppSetup
  AppOnboarding->>PrivateAPI: importStoreMetadata() via storeUrl
  PrivateAPI-->>AppOnboarding: updated app metadata
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Cap-go/capgo#2190: Modifies src/components/dashboard/AppOnboardingFlow.vue around store-import flow and state management (storeImportRun, import mode), building directly on the same onboarding app-creation UI refactor.
  • Cap-go/capgo#2118: Updates src/pages/onboarding/organization.vue organization setup flow UI (mode selection, stepper layout), with this PR extending mode selection to add the new "store" import mode.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main feature: enabling organization onboarding via store listing imports, which is the core objective of this changeset.
Description check ✅ Passed The description includes a comprehensive AI-generated summary explaining the feature, motivation, business impact, and test results, though it lacks explicit manual testing steps and screenshots for the frontend UI.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added the codex label Jun 15, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/pages/onboarding/organization.vue`:
- Around line 406-441: The fetchStoreMetadata function has a race condition
where stale responses can overwrite recent user input if the storeUrlInput
changes while a request is in flight. Capture the storeUrl value at the start of
the function before making the async request, then after receiving the response,
verify that storeUrlInput.value.trim() still matches the original captured
storeUrl before updating storeMetadata.value and orgNameInput.value on lines 431
and 435. If the URLs no longer match, skip updating the state and return early
to discard the stale response. Apply the same fix to the other location
mentioned at lines 695-703.

In `@supabase/functions/_backend/public/app/store_metadata.ts`:
- Around line 147-153: The issue is that the loop in store_metadata.ts
immediately returns an author object even when both the name and url properties
are empty strings after decoding and trimming. This stops the JSON-LD scanning
prematurely, skipping potential valid author data in later JSON-LD blocks. Fix
this by constructing the author object and only returning it if at least one of
the name or url properties is non-empty; otherwise, continue to the next
iteration of the loop so that additional JSON-LD blocks can be scanned for valid
author information.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d10ee883-22fe-4124-81c6-df05777160ef

📥 Commits

Reviewing files that changed from the base of the PR and between bf283f4 and edb5c9d.

📒 Files selected for processing (6)
  • messages/en.json
  • src/components/dashboard/AppOnboardingFlow.vue
  • src/pages/onboarding/organization.vue
  • supabase/functions/_backend/private/store_metadata.ts
  • supabase/functions/_backend/public/app/store_metadata.ts
  • supabase/functions/private/index.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

Comment thread src/pages/onboarding/organization.vue
Comment thread supabase/functions/_backend/public/app/store_metadata.ts Outdated
@riderx riderx force-pushed the codex/onboarding-store-import-shortcut branch from edb5c9d to e1bdb93 Compare June 15, 2026 16:07
@riderx riderx force-pushed the codex/onboarding-store-import-shortcut branch from e1bdb93 to 7bd8d05 Compare June 15, 2026 16:20

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7bd8d05a85

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/pages/onboarding/organization.vue

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/dashboard/AppOnboardingFlow.vue (1)

967-973: 🧹 Nitpick | 🔵 Trivial

Switch CLI command to use --apikey flag instead of positional API key argument.

The command currently passes the API key as a positional argument (npx @capgo/cli@latest i [APIKEY]), but the capgo/cli documentation explicitly recommends using the --apikey flag to override the default key. Update line 94 to construct the command as npx @capgo/cli@latest i --apikey ${apiKey.value ?? '[APIKEY]'}${localCommand} and update both template snippets (lines 967-973 and 1288-1294) accordingly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/dashboard/AppOnboardingFlow.vue` around lines 967 - 973, The
CLI command is currently passing the API key as a positional argument, but it
should use the --apikey flag instead. Update the command construction logic
(around line 94) to build the command as npx `@capgo/cli`@latest i --apikey
${apiKey.value ?? '[APIKEY]'}${localCommand} instead of the positional format.
Then update both template snippets that display this command (the one shown in
the diff with the cliCommandArgs loop around lines 967-973, and another similar
template snippet around lines 1288-1294) to reflect the new --apikey flag
format, removing the positional argument display and ensuring the flag is
properly shown in the command visualization.

Source: Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/dashboard/AppOnboardingFlow.vue`:
- Around line 959-963: Replace the custom Tailwind styling on the button element
with the class v-if="isCliCommandVisible" with DaisyUI button primitives (using
d- prefixed classes like d-btn) instead of the manual class attributes
containing bg-slate-950, ring-1, ring-white/10, and other custom styling. This
change should be applied to all similar copy-command buttons in the
AppOnboardingFlow.vue component to maintain consistency with the project's
button primitive conventions and ensure consistent behavior and spacing across
interactive elements.
- Around line 514-520: In the AppOnboardingFlow.vue file where the icon is being
fetched from a remote HTTPS URL, add validation after the fetch call to ensure
the response is successful and contains image data. Before calling
response.blob(), check that response.ok is true to ensure the HTTP request
succeeded, and verify that the response's content-type header indicates an image
format (check for headers like 'image/png', 'image/jpeg', etc.). Only proceed
with creating the File object if both validations pass; otherwise, handle the
invalid response appropriately by returning null or throwing an error with a
descriptive message.
- Around line 372-388: The applyImportedStoreMetadata function only
conditionally sets values but does not clear previously imported data, allowing
stale metadata from prior imports to persist. At the start of the
applyImportedStoreMetadata function, reset the store-derived fields
(importedStoreAppId, storeIconPreview, and storeScreenshotPreview) to empty or
null values before applying the new imported data. This ensures that if a
subsequent import returns partial metadata, old values from previous imports do
not bleed through.

In `@supabase/functions/_backend/public/app/store_metadata.ts`:
- Around line 177-206: The functions extractGooglePlayDeveloperName and
extractDeveloperUrl each independently call extractJsonLdAuthor, causing the
same JSON-LD parsing to occur twice when both functions are used together.
Refactor extractGooglePlayDeveloperName and extractDeveloperUrl to accept the
author object as a parameter instead of calling extractJsonLdAuthor internally.
Then, in the calling code where both functions are invoked (in
fetchStoreMetadata for Google Play pages), call extractJsonLdAuthor once and
pass the returned author object to both functions.

---

Outside diff comments:
In `@src/components/dashboard/AppOnboardingFlow.vue`:
- Around line 967-973: The CLI command is currently passing the API key as a
positional argument, but it should use the --apikey flag instead. Update the
command construction logic (around line 94) to build the command as npx
`@capgo/cli`@latest i --apikey ${apiKey.value ?? '[APIKEY]'}${localCommand}
instead of the positional format. Then update both template snippets that
display this command (the one shown in the diff with the cliCommandArgs loop
around lines 967-973, and another similar template snippet around lines
1288-1294) to reflect the new --apikey flag format, removing the positional
argument display and ensuring the flag is properly shown in the command
visualization.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 384f9952-4bf0-4731-86ea-115f86641482

📥 Commits

Reviewing files that changed from the base of the PR and between edb5c9d and 7bd8d05.

📒 Files selected for processing (6)
  • messages/en.json
  • src/components/dashboard/AppOnboardingFlow.vue
  • src/pages/onboarding/organization.vue
  • supabase/functions/_backend/private/store_metadata.ts
  • supabase/functions/_backend/public/app/store_metadata.ts
  • supabase/functions/private/index.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

Comment thread src/components/dashboard/AppOnboardingFlow.vue
Comment thread src/components/dashboard/AppOnboardingFlow.vue
Comment thread src/components/dashboard/AppOnboardingFlow.vue
Comment thread supabase/functions/_backend/public/app/store_metadata.ts
@riderx riderx force-pushed the codex/onboarding-store-import-shortcut branch from 7bd8d05 to 7e53dc8 Compare June 15, 2026 16:35

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7e53dc8455

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/pages/onboarding/organization.vue Outdated
@riderx riderx force-pushed the codex/onboarding-store-import-shortcut branch from 7e53dc8 to 2cfd0fe Compare June 15, 2026 16:55

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2cfd0fe95a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/components/dashboard/AppOnboardingFlow.vue Outdated
@riderx riderx force-pushed the codex/onboarding-store-import-shortcut branch from 2cfd0fe to 8c377b2 Compare June 15, 2026 17:07
@sonarqubecloud

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6a7a996fc7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +196 to +198
const importedLogoUrl = computed(() => {
const storeIcon = storeMetadata.value?.icon_data_url || storeMetadata.value?.icon_url || ''
return websitePreview.value?.icon || storeIcon

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Gate imported logo by active mode

If a website preview request finishes after the user switches to the name or store flow, fetchWebsitePreview() can still populate websitePreview; this computed value then remains truthy and is preferred over the store icon. Because the new create path auto-uses any importedLogoUrl, that stale website logo can be uploaded and the logo step skipped for a non-website organization. Only return the website icon when mode === 'website' and the store icon when mode === 'store'.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant