A few years ago, “cross-platform” meant an iPhone app and an Android app that looked almost the same. One of the apps our team built, a speed reading app for an Australian company, runs on iPhone, Android, iPad, Mac and Apple Vision Pro, in 24 languages, from one Flutter codebase.

Sharing the code is the easy part. Sharing the design is harder. A layout that feels right on a 6-inch phone feels empty on a desktop window and strange when it floats in front of you in a headset.

Start with the widest and the narrowest screen, not the phone

Most teams design the phone screens first and “stretch” them later. A better order is to sketch every key screen at both ends at the same time: the narrowest phone and the widest desktop window, side by side.

Designing both ends early forces the real questions. Where does the navigation live when there is room for a sidebar? What happens to a single column of cards when there is space for three? Which elements should grow, and which should stay at a fixed, comfortable size? Once those answers exist for the two extremes, the in-between sizes mostly fall into place, and the developers can build one responsive layout instead of four separate ones.

In Flutter terms, that means deciding breakpoints and layout rules before anyone writes a widget, so the code reflects a design decision rather than a guess.

Treat translated text as a design input

With 24 languages, translated text becomes as big a layout factor as screen size. A button label that fits neatly in English can run much longer in German or Finnish, and some languages need more line height to stay readable.

So design with real long strings instead of English placeholder text. Give every key screen a “long language” version in the design file before sign-off. Let buttons wrap or grow, give headings room for a second line, and make sure nothing important depends on text staying short. It is a small habit, and it prevents a long list of layout bugs after translation.

Some UI elements are really timing problems

The heart of a speed reading app is the pacer: a moving guide that walks the reader through the text at a speed they set. Under the animated highlight is a timing engine with states: ready, running, paused, finished, and “the user just changed the speed mid-paragraph.”

Design those states before the visuals. Each state needs its own look and its own behavior on every screen size. On a large display the pacer has more room, so the reader’s eyes travel further, and that changes how fast a “comfortable” speed feels. Test speeds on real devices of each size instead of signing off a static mockup.

Content-heavy apps need a content model before screens

Another app we built, a wellness and diet planner, holds a library of 2,000+ vegetarian recipes and more than 1,000 food profiles, plus over 100 yoga and meditation sessions. With that much content, the screens are the last thing to design.

Start with the content model: what a recipe is, which fields every recipe has, which ones are optional, and how a recipe connects to a food profile or a wellness program. Only then design the cards, filters and detail pages. That order matters most for the easily forgotten states: the empty search result, the recipe with no photo, the program a user hasn’t unlocked yet. If the content model is clear, those states can be designed once and reused everywhere.

Paid tiers shape the layout

Both apps earn through subscriptions with more than one tier. That has a direct design cost. Every screen needs a clear answer to three questions: what a free user sees, what a paying user sees, and how a locked item looks without feeling like a dead end.

A pattern that works well is to give locked content the same card layout as unlocked content, with a light visual cue and one line explaining what unlocks it. Users can see the value of a tier without hitting a wall on every tap. It also keeps the design system small, because a locked card is a variant of an existing component.

Make the hand-off boring

The biggest speed gain comes from making the path from design to code predictable:

  • Every component in the design file maps to one widget in the codebase, with the same name.
  • Colors, spacing and type sizes live as tokens in both places, so a change in one is a change in the other.
  • Designers review builds on real devices, not screenshots.

For screens that need fast iteration, a team can build first in FlutterFlow and continue in Flutter code when the logic grows. FlutterFlow produces Flutter code, so designers can review something real early, and the work carries forward instead of being thrown away.

What this means if you are building or hiring

If you are planning an app for more than one kind of screen, test these early: one layout across the narrowest and widest screens, your longest translated strings, every state of anything that moves, and how locked content looks.

If you are hiring, ask a Flutter developer to show you one screen they adapted from phone to desktop and how they handled long translated text. The answer tells you more than a portfolio of phone screenshots. Ask the same of any team you consider, including ours if you are looking at remote Flutter developers.

One codebase can serve five kinds of screens if the design plans for all of them from the first sketch.

Bogdan Sandu
Share
Written by Bogdan Sandu

Bogdan Sandu is a seasoned designer who has been designing websites since 2008. Renowned for his expertise in logo design and visual branding, Bogdan has developed a multitude of logos for various clients. His skills extend to creating posters, vector illustrations, business cards, and brochures. Additionally, Bogdan's UI kits were featured on marketplaces like Visual Hierarchy and UI8. He also wrote in the past years on sites like Design Your Way, WebDesignerDepot, WPDean, Designmodo, Speckyboy, Slider Revolution, and more.