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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,6 @@ seo-report.sarif

# Generated local D1 fixture for builder-data screenshots
apps/web/test/fixtures/builder-metrics-d1-seed.sql

# Local Playwright MCP session logs
.playwright-mcp/
2 changes: 2 additions & 0 deletions _typos.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ extend-ignore-re = [
"https?://\\S+",
# Cloudflare data center (IATA airport) codes in the hero world map config
"colo: '[A-Z]{3}'",
# ISO 3166 country code for the Faroe Islands in the pricing currency map
"FO: 'DKK'",
# IndexNow verification key
"ue6dw2uu67eum6y2m8en775jjf1qhe1r",
]
Expand Down
5 changes: 5 additions & 0 deletions apps/shared/copy/messageContexts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3366,6 +3366,11 @@ export const messageContexts = {
pricing_credits_cover_usage: 'Page/area: Pricing page or plan calculator UI. Role: Website copy sentence. Seen in: component pricing/CreditPricing.astro. Message key `pricing_credits_cover_usage` (Pricing Credits Cover Usage).',
pricing_credits_cta_desktop: 'Page/area: Pricing page or plan calculator UI. Role: Website copy sentence. Message key `pricing_credits_cta_desktop` (Pricing Credits CTA Desktop).',
pricing_credits_cta_mobile: 'Page/area: Pricing page or plan calculator UI. Role: Website copy sentence. Message key `pricing_credits_cta_mobile` (Pricing Credits CTA Mobile).',
pricing_currency_auto: 'Page/area: Pricing page or plan calculator UI. Role: Short UI label or navigation item. Seen in: component pricing/CurrencySelector.astro. Message key `pricing_currency_auto` (Pricing Currency Auto).',
pricing_currency_change: 'Page/area: Pricing page or plan calculator UI. Role: Short UI label or navigation item. Seen in: component pricing/Plans.astro. Message key `pricing_currency_change` (Pricing Currency Change).',
pricing_currency_estimate_note: 'Page/area: Pricing page or plan calculator UI. Role: Supporting note or footnote. Seen in: component pricing/Plans.astro. Message key `pricing_currency_estimate_note` (Pricing Currency Estimate Note).',
pricing_currency_hint: 'Page/area: Pricing page or plan calculator UI. Role: Website copy sentence. Seen in: component pricing/CurrencySelector.astro. Preserve Capgo product/brand and developer terms exactly. Message key `pricing_currency_hint` (Pricing Currency Hint).',
pricing_currency_label: 'Page/area: Pricing page or plan calculator UI. Role: UI label. Seen in: component pricing/CurrencySelector.astro. Message key `pricing_currency_label` (Pricing Currency Label).',
pricing_description: 'Page/area: Pricing page or plan calculator UI. Role: Supporting description paragraph or meta description. Seen in: page pricing.astro. Preserve Capgo product/brand and developer terms exactly. Message key `pricing_description` (Pricing Description).',
pricing_explainer_bandwidth_body: 'Page/area: Pricing page or plan calculator UI. Role: Long marketing or legal paragraph. Seen in: component pricing/PricingExplainer.astro. Message key `pricing_explainer_bandwidth_body` (Pricing Explainer Bandwidth Body).',
pricing_explainer_bandwidth_title: 'Page/area: Pricing page or plan calculator UI. Role: Section or page heading. Seen in: component pricing/PricingExplainer.astro. Message key `pricing_explainer_bandwidth_title` (Pricing Explainer Bandwidth Title).',
Expand Down
5 changes: 5 additions & 0 deletions apps/shared/copy/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1376,6 +1376,11 @@ const messages = {
'EAS prices from expo.dev/pricing, checked September 2026: cheapest plan plus $0.005 per extra MAU. Compares MAU cost only; bandwidth, storage, and native builds are not included. Capgo prices are per month, billed yearly.',
pricing_compare_plan_suffix: 'plan',
pricing_compare_title: 'What live updates cost at your scale',
pricing_currency_auto: 'Based on your location',
pricing_currency_change: 'Change currency',
pricing_currency_estimate_note: 'Prices converted from USD at daily exchange rates. You are billed in USD.',
pricing_currency_hint: 'Capgo bills in USD. Other currencies are estimates based on daily European Central Bank exchange rates.',
pricing_currency_label: 'Display prices in',
pricing_credits_cta_desktop: "Don't want a plan? Buy credits instead.",
pricing_credits_cta_mobile: 'Buy credits instead.',
pricing_calculator_cta: 'Calculate your price',
Expand Down
5 changes: 5 additions & 0 deletions apps/shared/copy/translationContextByText.ts
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,7 @@ export const translationContextByText: Record<string, string> = {
'Banking app with account, payment, loan, and offer flows that need controlled rollout.': 'Page/area: Solution page app examples section. Role: Supporting note or footnote. Message key `solution_app_examples_fintech_app_1_note` (Solution App Examples Fintech App 1 Note).',
'Banking apps need safe, staged interface fixes': 'Page/area: Solution page app examples section. Role: Section or page heading. Message key `solution_app_examples_fintech_headline` (Solution App Examples Fintech Headline).',
'Based on public competitor cloud docs and pricing, plus GitHub Actions macOS rates.': 'Page/area: Capgo Builder / native cloud build product page. Role: Supporting note or footnote. Seen in: page native-build.astro. Preserve Capgo product/brand and developer terms exactly. Message key `native_build_v2_comp_footnote` (Native Build V2 Comp Footnote).',
'Based on your location': 'Page/area: Pricing page or plan calculator UI. Role: Short UI label or navigation item. Seen in: component pricing/CurrencySelector.astro. Message key `pricing_currency_auto` (Pricing Currency Auto).',
'Basic automatic updates are well documented. But Capgo has many options (manual, half-manual, channel_default, etc.) that aren\'t always easy to understand for every use case yet. We\'re actively improving this.': 'Page/area: Capacitor live-update alternatives comparison page. Role: Long marketing or legal paragraph. Seen in: page alternatives.astro. Preserve Capgo product/brand and developer terms exactly. Message key `alternatives_not_good_at_docs` (Alternatives Not Good At Docs).',
'Basic bundle checks.': 'Page/area: Live updates product page. Role: Website copy sentence. Seen in: page live-update.astro. Preserve Capgo product/brand and developer terms exactly. Message key `live_update_v2_comp_validate_capa` (Live Update V2 Comp Validate Capa).',
'Basic bundle validation. Native drift is easy to miss.': 'Page/area: CLI product or documentation marketing copy. Role: Website copy sentence. Seen in: page capgo-cli.astro. Preserve Capgo product/brand and developer terms exactly. Message key `cli_v2_comp_compat_capa` (CLI V2 Comp Compat Capa).',
Expand Down Expand Up @@ -1110,6 +1111,7 @@ export const translationContextByText: Record<string, string> = {
'Capgo Backend & Landing': 'Page/area: Bug bounty program page. Role: Short UI label or navigation item. Seen in: page bug-bounty.astro. Preserve Capgo product/brand and developer terms exactly. Message key `bug_bounty_repo_landing` (Bug Bounty Repo Landing).',
'Capgo backend and product repository (capgo.app API, dashboard, and related services)': 'Page/area: Bug bounty program page. Role: Website copy sentence. Seen in: page bug-bounty.astro. Preserve Capgo product/brand and developer terms exactly. Message key `bug_bounty_repo_landing_desc` (Bug Bounty Repo Landing Desc).',
'Capgo beta channel': 'Page/area: Capgo solutions marketing page. Role: Short UI label or navigation item. Seen in: page solutions/beta-testing.astro. Preserve Capgo product/brand and developer terms exactly. Message key `solutions_beta_testing_compare_capgo` (Solutions Beta Testing Compare Capgo).',
'Capgo bills in USD. Other currencies are estimates based on daily European Central Bank exchange rates.': 'Page/area: Pricing page or plan calculator UI. Role: Website copy sentence. Seen in: component pricing/CurrencySelector.astro. Preserve Capgo product/brand and developer terms exactly. Message key `pricing_currency_hint` (Pricing Currency Hint).',
'Capgo brand resources': 'Page/area: Capgo marketing website. Role: Section or page heading. Seen in: page brand.astro. Preserve Capgo product/brand and developer terms exactly. Message key `brand_hero_title` (Brand Hero Title).',
'Capgo Build': 'Page/area: Capgo solutions marketing page. Role: Short UI label or navigation item. Seen in: page solutions/white-label.astro. Preserve Capgo product/brand and developer terms exactly. Message key `solutions_white_label_visual_cell3_value` (Solutions White Label Visual Cell3 Value).',
'Capgo Build compiles and signs': 'Page/area: Capgo solutions marketing page. Role: Section or page heading. Preserve Capgo product/brand and developer terms exactly. Message key `solutions_webapp_to_mobile_cap2_title` (Solutions Webapp To Mobile Cap2 Title).',
Expand Down Expand Up @@ -1317,6 +1319,7 @@ export const translationContextByText: Record<string, string> = {
'Certificates and profiles are used in memory during the build and deleted when it finishes. Each build runs in an isolated environment that is destroyed afterwards.': 'Page/area: Capgo solutions marketing page. Role: Long marketing or legal paragraph. Message key `solutions_build_without_mac_trust3_desc` (Solutions Build Without Mac Trust3 Desc).',
'Certificates and profiles often sit on one person\'s Mac. When that person is away or a profile expires, the release waits.': 'Page/area: Capgo solutions marketing page. Role: Website copy sentence. Message key `solutions_build_without_mac_pain2_desc` (Solutions Build Without Mac Pain2 Desc).',
'Certificates, provisioning profiles, and keystores are supplied at build time from local env vars or CI secrets.': 'Page/area: Capgo Builder / native cloud build product page. Role: Website copy sentence. Message key `native_build_builder_feature_signing_text` (Native Build Builder Feature Signing Text).',
'Change currency': 'Page/area: Pricing page or plan calculator UI. Role: Short UI label or navigation item. Seen in: component pricing/Plans.astro. Message key `pricing_currency_change` (Pricing Currency Change).',
'Change language': 'Page/area: Site footer navigation or footer blurb. Role: UI label. Seen in: site footer. Message key `footer_language_label` (Footer Language Label).',
'Change promo and checkout screens during a campaign': 'Page/area: Capgo solutions marketing page. Role: Section or page heading. Seen in: page solutions/ecommerce.astro. Message key `solutions_ecommerce_hero_title` (Solutions Ecommerce Hero Title).',
'Change promo, product, and checkout screens in your Capacitor shopping app during a campaign. Stage on a channel, roll out by percentage, and roll back without a store release.': 'Page/area: Capgo solutions marketing page. Role: Supporting description paragraph or meta description. Seen in: page solutions/ecommerce.astro. Preserve Capgo product/brand and developer terms exactly. Message key `solutions_ecommerce_description` (Solutions Ecommerce Description).',
Expand Down Expand Up @@ -1812,6 +1815,7 @@ export const translationContextByText: Record<string, string> = {
'Discord community, support@capgo.app, and the contact page': 'Page/area: About Capgo page. Role: Website copy sentence. Seen in: page about.astro. Preserve Capgo product/brand and developer terms exactly. Message key `about_facts_communication_value` (About Facts Communication Value).',
'Discord support': 'Page/area: Enterprise product/pricing page. Role: Short UI label or navigation item. Seen in: page enterprise.astro. Preserve Capgo product/brand and developer terms exactly. Message key `enterprise_discord_support` (Enterprise Discord Support).',
'Discover how Capgo safeguards over-the-air updates with layered security, transparent monitoring, and privacy-first operations.': 'Page/area: Trust / security / compliance page. Role: SEO meta description. Seen in: page trust.astro. Preserve Capgo product/brand and developer terms exactly. Message key `trust_meta_description` (Trust Meta Description).',
'Display prices in': 'Page/area: Pricing page or plan calculator UI. Role: UI label. Seen in: component pricing/CurrencySelector.astro. Message key `pricing_currency_label` (Pricing Currency Label).',
'Disputes Resolution': 'Page/area: Terms of Service legal page. Role: Section or page heading. Seen in: page tos.astro. Message key `tos_disputes_resolution_title` (Terms of Service Disputes Resolution Title).',
'dist': 'HTML text fragment from a longer Capgo UI string (parent key `solutions_cordova_to_capacitor_ai_step2_body`). Page/area: Capgo solutions marketing page. Role: Website copy sentence. Seen in: page solutions/cordova-to-capacitor-ai.astro. Message key `solutions_cordova_to_capacitor_ai_step2_body` (Solutions Cordova To Capacitor Ai Step2 Body).',
'Distribution certificate': 'Page/area: Capgo Builder / native cloud build product page. Role: Short UI label or navigation item. Seen in: page native-build.astro. Message key `native_build_v2_wiz_ios_s2_l` (Native Build V2 Wiz Ios S2 L).',
Expand Down Expand Up @@ -3861,6 +3865,7 @@ export const translationContextByText: Record<string, string> = {
'Preview each lockup, then download SVG or PNG. Files are production ready and match the vectors used on capgo.app.': 'Page/area: Capgo marketing website. Role: Website copy sentence. Seen in: page brand.astro. Message key `brand_logos_intro` (Brand Logos Intro).',
'Preview every pull request on device': 'Page/area: Solution page app examples section. Role: Bullet list item. Message key `solution_app_examples_pr_preview_play_1` (Solution App Examples Pr Preview Play 1).',
'Preview your next pull request on a phone': 'Page/area: Capgo solutions marketing page. Role: Section or page heading. Seen in: page solutions/pr-preview.astro. Message key `solutions_pr_final_cta_title` (Solutions Pr Final CTA Title).',
'Prices converted from USD at daily exchange rates. You are billed in USD.': 'Page/area: Pricing page or plan calculator UI. Role: Supporting note or footnote. Seen in: component pricing/Plans.astro. Message key `pricing_currency_estimate_note` (Pricing Currency Estimate Note).',
'Prices usually come from your backend or POS integration, so change them there. A live update changes the web screens that display the menu and prices. Native plugins, payment SDKs, and Capacitor upgrades need a store release.': 'Page/area: Capgo solutions marketing page. Role: Long marketing or legal paragraph. Seen in: page solutions/qsr.astro. Preserve Capgo product/brand and developer terms exactly. Message key `solutions_qsr_faq5_a` (Solutions Qsr Faq5 A).',
'Prices usually come from your backend, so change them there. A live update changes the web code and assets that display them: promo banners, product pages, cart and checkout screens. Changes to native payment SDKs or plugins need a store release.': 'Page/area: Capgo solutions marketing page. Role: Long marketing or legal paragraph. Seen in: page solutions/ecommerce.astro. Preserve Capgo product/brand and developer terms exactly. Message key `solutions_ecommerce_faq1_a` (Solutions Ecommerce Faq1 A).',
'Pricing': 'Navigation/label for the Pricing page. Page/area: About Capgo page. Role: Short UI label or navigation item. Seen in: page about.astro. Message key `about_facts_pricing` (About Facts Pricing). | Navigation/label for the Pricing page. Page/area: Capgo Builder / native cloud build product page. Role: Section subtitle or tagline. Seen in: page native-build.astro. Message key `native_build_builder_pricing_eyebrow` (Native Build Builder Pricing Eyebrow). | Navigation/label for the Pricing page. Page/area: Capgo marketing website. Role: Call-to-action button or link label. Seen in: component BlogMidArticleCta.astro. Message key `blog_mid_article_china_cta_pricing_button` (Blog Mid Article China CTA Pricing Button). | Navigation/label for the Pricing page. Page/area: Capgo marketing website. Role: Short UI label or navigation item. Seen in: component comparison/ComparisonPage.astro. Message key `compare_row_pricing` (Compare Row Pricing). | Navigation/label for the Pricing page. Page/area: Capgo marketing website. Role: Short UI label or navigation item. Seen in: site footer, site header, page agents/[slug].astro. Message key `pricing` (Pricing).',
Expand Down
1 change: 1 addition & 0 deletions apps/web/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export default defineConfig({
proxy: {
'/live-update-metrics.json': { target: 'https://capgo.app', changeOrigin: true },
'/builder-metrics.json': { target: 'https://capgo.app', changeOrigin: true },
'/currency.json': { target: 'https://capgo.app', changeOrigin: true },
},
},
},
Expand Down
17 changes: 12 additions & 5 deletions apps/web/src/components/pricing/ComparePlans.astro
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,12 @@ function buildTimeDisplay(buildTimeSeconds: number) {
return `${buildTimeMinutes} ${m.build_minutes({}, { locale: Astro.locals.locale })}`
}

function priceDisplay(plan: Database['public']['Tables']['plans']['Row']) {
const yearlyMonthly = (plan.price_y / 12).toFixed(0)
const suffix = plan.name === 'Enterprise' ? '+' : ''
return `$${yearlyMonthly}${suffix}/mo yearly or $${plan.price_m}${suffix}/mo monthly`
function priceParts(plan: Database['public']['Tables']['plans']['Row']) {
return {
yearlyMonthly: Math.round(plan.price_y / 12),
monthly: plan.price_m,
suffix: plan.name === 'Enterprise' ? '+' : '',
}
}

function included(planName: string, names: string[]) {
Expand Down Expand Up @@ -369,7 +371,12 @@ const rows: CompareSection[] = [
<span class="rounded-full bg-blue-600 px-2 py-0.5 text-xs font-semibold text-white">{m.most_popular({}, { locale: Astro.locals.locale })}</span>
)}
</div>
<p class="mt-2 text-xs leading-5 font-medium text-gray-600">{priceDisplay(plan)}</p>
<p class="mt-2 text-xs leading-5 font-medium text-gray-600">
<span data-price-amount={priceParts(plan).yearlyMonthly} data-price-suffix={priceParts(plan).suffix}>{`$${priceParts(plan).yearlyMonthly}${priceParts(plan).suffix}`}</span>/mo
yearly or
<span data-price-amount={priceParts(plan).monthly} data-price-suffix={priceParts(plan).suffix}>{`$${priceParts(plan).monthly}${priceParts(plan).suffix}`}</span>/mo
monthly
</p>
</th>
))}
</tr>
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/pricing/CreditPricing.astro
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ function formatPrice(price: number): string {
: `${m.next({}, { locale: Astro.locals.locale })} ${formatNumber(credit.step_max - credit.step_min, type, credit.unit_factor)}`}
</div>
<div class="text-right text-sm leading-6 font-semibold text-gray-950">
${formatPrice(credit.price_per_unit)} {getUnitLabel(type)}
<span data-price-amount={credit.price_per_unit} data-price-format="unit">${formatPrice(credit.price_per_unit)}</span> {getUnitLabel(type)}
</div>
</div>
))}
Expand Down
Loading
Loading