One Codebase, Two Products, Two Markets

8 min read
indie-hackingbuild-in-publicstrategynext-js

Two phones side by side — Falavra for Brazil, DropVox for the world

Falavra launched in Brazil. WhatsApp voice message transcription. Connect your WhatsApp, every audio gets transcribed and sent back as text. Portuguese UI, BRL pricing, built for Brazilians who are drowning in 3-minute voice notes from their tia.

Three days later, I shipped DropVox — the same product, for everyone else.

Same codebase. Same architecture. Same Supabase-and-Stripe stack. Different brand, different language, different pricing, different market. Two products from one afternoon of work.

This is not a story about internationalization. I did not add a language toggle. I forked my own product. Here is why, and how.

Why Not Just Add i18n?

The obvious move is next-intl or some i18n library, a locale switcher in the nav, and a single deployment serving both languages. I have done this before — I wrote a whole post about internationalizing BookBit.

I did not do it here. Three reasons.

Why not i18n — pricing, brand, and SEO all break

Pricing. Falavra charges R$19/month for the Basico plan. That is roughly $3.50 USD. If I put a language toggle on the same site, international users see $3.50/month and think "cheap product, probably bad." Brazilians see $4.99/month in USD and think "too expensive for what it does." Same product, same value, same cost to run — but the number on the screen means completely different things depending on who is reading it.

The fix is not a currency converter. It is separate pricing strategies. Falavra charges R$19, R$49, R$99 in BRL. DropVox charges $4.99, $9.99, $19.99 in USD. Different Stripe accounts. Different price anchors. Different conversion psychology.

Brand positioning. "Falavra" means something in Portuguese — it is a play on "fala" (speech) and "palavra" (word). To an English speaker, it is just a string of letters. DropVox already existed as a brand — I had built a native macOS transcription app under that name. The brand had recognition, a domain, an existing audience. Putting English users on falavra.com would waste all of that.

SEO and distribution. Two separate domains means two separate SEO profiles. falavra.com targets Portuguese-language queries. dropvox.app targets English-language queries. Google treats these as different sites because they are different sites. One bilingual domain would compete with itself across languages.

The Fork

The actual execution was one commit. Literally one commit: "feat: repurpose DropVox as international Falavra."

The fork — Falavra routes and pricing on the left, DropVox on the right, connected by one commit

Here is what changed:

WhatFalavraDropVox
LanguagePortuguese (PT-BR)English
CurrencyBRLUSD
PlansGratis / Basico / Pro / EnterpriseFree / Starter / Pro / Business
Free tier30 min30 min
Entry priceR$19/mo$4.99/mo
Mid tierR$49/mo$9.99/mo
Top tierR$99/mo$19.99/mo
Domainfalavra.comdropvox.app
Contactola@falavra.comhello@dropvox.app
Routes/conta, /transcricoes/account, /transcriptions
Anchors#como-funciona, #precos#how-it-works, #pricing
LogoWave mark + "falavra"Sound bars mark + "DropVox"

Everything else — the color system, the component structure, the worker architecture, the Supabase schema, the Baileys integration, the Stripe webhook handling — is identical.

How the Fork Works in Practice

DropVox is not a fork in the git sense. It is a full copy of the Falavra codebase in its own directory with its own git history. This is intentional.

I considered a monorepo with shared packages. I considered environment variables for branding. I considered a white-label approach with a config file. All of these optimize for code reuse at the cost of deployment independence.

What I actually need is the opposite: deployment independence at the cost of some code duplication.

  • Falavra deploys to Vercel, connected to its own Supabase project, its own Stripe account, its own Railway worker.
  • DropVox deploys to a separate Vercel project, separate Supabase, separate Stripe, separate worker.
  • If I need to test a new pricing model in Brazil, I change Falavra. DropVox is untouched.
  • If DropVox needs a feature that does not make sense for the Brazilian market, I add it to DropVox only.

The codebases will diverge over time. That is the point.

Deployment independence — two parallel pipelines, zero shared infrastructure

The Translation

The translation itself was mechanical. Every UI string, every error message, every legal page, every email template — PT-BR to English. The route structure changed: /dashboard/conta became /dashboard/account, /dashboard/transcricoes became /dashboard/transcriptions. Redirects were added for the old Portuguese routes in case any links survived:

// next.config.ts
{
  source: '/dashboard/conta',
  destination: '/dashboard/account',
  permanent: true,
},
{
  source: '/dashboard/transcricoes',
  destination: '/dashboard/transcriptions',
  permanent: true,
}

The hero copy went from "Cansado de ouvir notas de voz de 5 minutos?" to "Done listening to 5-minute voice notes." Same energy, not a literal translation. Marketing copy should never be literally translated — it should be re-written for the target audience.

Plan names were localized too. "Basico" became "Starter" (not "Basic" — "Starter" sounds more inviting). "Enterprise" became "Business" (enterprise sounds too corporate for indie pricing).

The Pricing Math

Pricing comparison — Falavra in BRL vs DropVox in USD

This is the part most people skip. Let me not skip it.

Falavra's Pro plan is R$49/month. At current exchange rates, that is about $8.50 USD. DropVox's Pro plan is $9.99/month. The difference is less than two dollars.

But the perception is completely different. R$49 in Brazil is a real monthly expense — it is comparable to a Netflix subscription. $9.99 in the US is a rounding error. Same value delivered, same infrastructure cost, but the willingness to pay shifts dramatically based on local purchasing power and price anchoring.

If I had used a single site with a currency converter, I would have to pick one anchor point. Either the Brazilian user sees cheap dollar pricing and wonders why it is so cheap (is this product not serious?), or the American user converts BRL to USD and thinks "wait, this is only $3.50 — I'll pay that, but I would not have paid $9.99." You lose either way.

Two brands, two price sheets. The same product is "premium" in both markets.

The Native App Question

DropVox used to be something else entirely. It was a native macOS menu bar app — Swift, WhisperKit, on-device transcription. I shipped it. I wrote multiple blog posts about it. It was my poster child for "frontend dev ships native apps."

I archived the entire native codebase to a git branch (archive/native-app-v1) and replaced it with the Falavra SaaS codebase. The domain, the brand equity, the audience — all repurposed.

This might sound wasteful. It is not. The native app was a technical achievement but not a business. It had no recurring revenue, no network effects, no organic growth loop. The WhatsApp SaaS version has all three. The brand name is worth more than the code.

If you have a product that is not working, the brand might still be valuable. Do not throw it away. Redirect it.

When This Strategy Makes Sense

Not every product should be forked into two brands. This works when:

  1. Pricing needs to differ by more than exchange rates. If a simple currency conversion works, just use Stripe's multi-currency support. If the price strategy differs (different tiers, different anchors, different positioning), you need separate products.

  2. The brand does not translate. "Falavra" is a Portuguese pun. "DropVox" is a global brand. If your name works in both markets, a single site with i18n might be fine.

  3. You need SEO in both languages. A .com with English and Portuguese content will rank worse in both languages than two dedicated domains. Google is explicit about this.

  4. Deployment independence matters. If you want to experiment differently in each market — different features, different pricing, different marketing — separate codebases give you freedom that shared infrastructure does not.

The Cost of Duplication

Yes, I now maintain two codebases that are 95% identical. Yes, a bug fix in Falavra's pipeline needs to be manually ported to DropVox. Yes, this is theoretically worse than a shared codebase.

In practice, the products are four days old. The duplication cost is near zero because there has been almost nothing to duplicate yet. If both products survive and grow, I will extract the shared core into a package. If one dies, I delete it and move on without untangling a shared codebase.

Expanding brain meme — from i18n library to just copying the folder

Premature abstraction is more expensive than temporary duplication. Every time.

The Result

Two products. Two markets. Two brands. Two revenue streams. One afternoon of work — because the hard part (building the product) was already done.

Falavra serves Brazil. DropVox serves everyone else. Same voice transcription, same WhatsApp integration, same AI pipeline. Different wrappers. Different prices. Different growth trajectories.

The lesson is not "fork your product." The lesson is: your code is not your product. Your product is the value delivered to a specific person in a specific context. Change the context, change the wrapper, and you have a new product.

Same engine. Different car.