Jeito

Brazilian Portuguese like it's spoken

Mobile

In Testing

The short version

Study for a year, land in São Paulo, get in an Uber, and the driver says something incomprehensible. That's spoken Portuguese. Brazilians fuse and drop the same small set of words constantly and courses teach a written, formal version. Jeito is a comprehension app built to hear what the textbooks leave out.

I formed the product strategy and designed it. I also wrote the scenes, produced the audio, and built the app. All with AI-assisted workflows.

A lot of that was new. I'd not gone deep into database architectures, done authentication or routing, or taken Xcode that far. What I came in with was the language and a clear view of the problem.

Where it stands. I learned Portuguese and found the apps taught a version of it nobody actually speaks, so I built the one I wanted to use. The reason it keeps moving is that I use it and enjoy evolving the product when I have time.

How it started

I've studied Portuguese for years, and it took real time in Brazil to see the problem. What people say and what the textbooks print are nearly two different languages.

Você becomes cê. Está becomes tá. Estou becomes tô. Para becomes pra. It happens constantly, in every register. None of the courses I'd used mentioned it. They teach a version that's correct but lacking in daily life.

So the product isn't a speaking app and it isn't for beginners. It's for somebody who has studied enough to read a menu and then discovers that the wall is comprehension.

The whole thing is scenes. A bakery, a pharmacy, an airport Uber, played at the speed a Brazilian actually says them, with the reductions marked in the transcript so you can see the word you already know hiding inside the sound you didn't recognize.

Making it

The transcript fades behind the audio so your ear gets the line before your eyes do. The recovery phrase waits before its note appears so it reads as dialogue before it reads as a lesson. Auto-scroll was refused. This is reading-while-listening rather than following, and surprise motion breaks it. Tapping a reduction never pauses the audio.

There's no quiz after it, no score, no streak credit. The PRD lists those as explicitly absent. What you leave with is the phrase, and the feeling the spec names as the goal. Not congratulated, not graded, just done and a little more capable than when the audio started.

Every scene ends in a recovery phrase for the same reason. When you stall in a conversation the natural move is to switch to English, and switching to English ends the practice. A phrase that keeps you in Portuguese while you ask for help keeps the whole thing compounding.

Most of the work you can't see is the audio. Each scene has a direction file that specifies, per turn, which voice speaks it and at what stability and style, with markup where a pause has to land in a particular place.

A script calls ElevenLabs turn by turn, caches each render so a re-run doesn't cost money twice, assembles them with ffmpeg, masters to a consistent loudness, writes a manifest, and uploads the individual turns rather than one track. A single line can replay without touching the rest and a bad take regenerates alone instead of forcing the whole scene to be redone. There are close to 500 audio turn files, about an hour of dialogue, across a 12-voice roster.

The scenes I draft myself, work up with AI, and take past 90% before native review with Brazilian friends of mine.

The rest of it

What I got wrong

I refused speed control on principle. Slowing the audio is the thing that lets you avoid the skill, so it wasn't going in. Testers asked for it anyway, repeatedly. It's back now, with full speed as the default and a slower pass available if you want it. Holding the default matters.

Then there was one scene that I messed up. Every reduction in a script carries a character offset so the app can highlight the exact span in the transcript. This scene went out with 15 of its 24 offsets wrong, under a changelog that said they'd been verified.

Nothing visibly broke. The highlight just quietly pointed at the wrong letters, which in a product about noticing small sounds is the worst possible failure, because the app was confidently teaching you the wrong thing.

So there's a gate now. It reads every script, slices the sentence at each offset, and asserts the result equals the token it claims to be. It runs before the linguist sees a scene and again before anything is seeded, and it fails the build.

What I learned

Refusing a feature is a position that has to survive the user's actual argument. The way to keep the principle was the default rather than the absence and I'd reach for that shape much earlier next time.

Chat is a fleeting interface. I built an AI companion you could ask anything about the language. It works, and whatever you learn in one evaporates unless the product gives you somewhere to put it. If it comes back it'll be built around saving phrases out of the conversation.

Where it landed

A small beta group is on it now and their main effect was playback bugs. The audio player rather than the language.

Some things got built and put down. Regional accents, because Brazil has many and ElevenLabs can't produce them convincingly, so everything is São Paulo for now and the others wait for native speakers in a room. Two whole content formats, “Sons do Brasil” and “Fala Real”, went the same way. The pipeline can produce them, and the product doesn't get them until plain listening is flawless.

Jeito

Brazilian Portuguese like it's spoken

Mobile

In Testing

The short version

Study for a year, land in São Paulo, get in an Uber, and the driver says something incomprehensible. That's spoken Portuguese. Brazilians fuse and drop the same small set of words constantly and courses teach a written, formal version. Jeito is a comprehension app built to hear what the textbooks leave out.

I formed the product strategy and designed it. I also wrote the scenes, produced the audio, and built the app. All with AI-assisted workflows.

A lot of that was new. I'd not gone deep into database architectures, done authentication or routing, or taken Xcode that far. What I came in with was the language and a clear view of the problem.

Where it stands. I learned Portuguese and found the apps taught a version of it nobody actually speaks, so I built the one I wanted to use. The reason it keeps moving is that I use it and enjoy evolving the product when I have time.

How it started

I've studied Portuguese for years, and it took real time in Brazil to see the problem. What people say and what the textbooks print are nearly two different languages.

Você becomes cê. Está becomes tá. Estou becomes tô. Para becomes pra. It happens constantly, in every register. None of the courses I'd used mentioned it. They teach a version that's correct but lacking in daily life.

So the product isn't a speaking app and it isn't for beginners. It's for somebody who has studied enough to read a menu and then discovers that the wall is comprehension.

The whole thing is scenes. A bakery, a pharmacy, an airport Uber, played at the speed a Brazilian actually says them, with the reductions marked in the transcript so you can see the word you already know hiding inside the sound you didn't recognize.

Making it

The transcript fades behind the audio so your ear gets the line before your eyes do. The recovery phrase waits before its note appears so it reads as dialogue before it reads as a lesson. Auto-scroll was refused. This is reading-while-listening rather than following, and surprise motion breaks it. Tapping a reduction never pauses the audio.

There's no quiz after it, no score, no streak credit. The PRD lists those as explicitly absent. What you leave with is the phrase, and the feeling the spec names as the goal. Not congratulated, not graded, just done and a little more capable than when the audio started.

Every scene ends in a recovery phrase for the same reason. When you stall in a conversation the natural move is to switch to English, and switching to English ends the practice. A phrase that keeps you in Portuguese while you ask for help keeps the whole thing compounding.

Most of the work you can't see is the audio. Each scene has a direction file that specifies, per turn, which voice speaks it and at what stability and style, with markup where a pause has to land in a particular place.

A script calls ElevenLabs turn by turn, caches each render so a re-run doesn't cost money twice, assembles them with ffmpeg, masters to a consistent loudness, writes a manifest, and uploads the individual turns rather than one track. A single line can replay without touching the rest and a bad take regenerates alone instead of forcing the whole scene to be redone. There are close to 500 audio turn files, about an hour of dialogue, across a 12-voice roster.

The scenes I draft myself, work up with AI, and take past 90% before native review with Brazilian friends of mine.

The rest of it

What I got wrong

I refused speed control on principle. Slowing the audio is the thing that lets you avoid the skill, so it wasn't going in. Testers asked for it anyway, repeatedly. It's back now, with full speed as the default and a slower pass available if you want it. Holding the default matters.

Then there was one scene that I messed up. Every reduction in a script carries a character offset so the app can highlight the exact span in the transcript. This scene went out with 15 of its 24 offsets wrong, under a changelog that said they'd been verified.

Nothing visibly broke. The highlight just quietly pointed at the wrong letters, which in a product about noticing small sounds is the worst possible failure, because the app was confidently teaching you the wrong thing.

So there's a gate now. It reads every script, slices the sentence at each offset, and asserts the result equals the token it claims to be. It runs before the linguist sees a scene and again before anything is seeded, and it fails the build.

What I learned

Refusing a feature is a position that has to survive the user's actual argument. The way to keep the principle was the default rather than the absence and I'd reach for that shape much earlier next time.

Chat is a fleeting interface. I built an AI companion you could ask anything about the language. It works, and whatever you learn in one evaporates unless the product gives you somewhere to put it. If it comes back it'll be built around saving phrases out of the conversation.

Where it landed

A small beta group is on it now and their main effect was playback bugs. The audio player rather than the language.

Some things got built and put down. Regional accents, because Brazil has many and ElevenLabs can't produce them convincingly, so everything is São Paulo for now and the others wait for native speakers in a room. Two whole content formats, “Sons do Brasil” and “Fala Real”, went the same way. The pipeline can produce them, and the product doesn't get them until plain listening is flawless.