Your design
Choose how the agent looks in the dashboard — the SDK draws it on your website and in every app, typeface included, with nothing in your code.
The brand decides how the agent looks, once, in the dashboard. Every surface draws that design: the website widget, and the React Native, Android, iOS and Flutter SDKs. That covers the launcher, the voice bar, the caption, the chat window and every component the agent shows. The app passes nothing about how the agent looks. There is no colour to set in code and no font to bundle, so a redesign reaches every phone the next time your app starts, with no app release.
In one line: pick a design under Agent → Embed & Widgets → Appearance and save. Websites change on their next page load, and apps on React Native 0.38.0 or Android, iOS and Flutter 0.3.0 the next time they start — within about 30 seconds of saving. Every design and knob is on The Garage.
Choosing a design
Appearance opens on the Garage: design philosophies you flip through like cars in a showroom, with the website and in-app previews redrawing as you go. Each design has a light and a dark version, and every text colour is checked for legibility.
Graine Classic · Signature · Chat Neutral · Material You · iOS Native · Minimal Mono · Fluent · Enterprise Grid · Fintech Clear · Liquid Glass · Soft & Playful · Desktop Buddy · Swiss Grid · Precision · Japandi Calm · Neo-Brutalist · Editorial · Black & Gold · Retro Terminal · Warm & Earthy · Bauhaus · Gamified · High Contrast
Each one comes from a real design tradition: the International Typographic Style for Swiss Grid, the Bauhaus primaries, Linear's dense dark interface for Precision, wabi-sabi and calm technology for Japandi Calm, Duolingo's chunky play for Gamified, and the navy-and-teal restraint of payment products for Fintech Clear, and Graine's own look — quiet greys, an indigo voice, the grain of the G mark — for Signature.
Then tune it — Paint, Body, Typeface, Rims, Lights and Interior: the accent, roundness, the launcher's shape and glyph, the fonts, motion and glass, the chat's bubbles and frame. Every knob and its values are on The Garage.
Save, and the design is live. The phone preview is drawn from the same tokens the SDKs draw, element by element, so what the brand approves there is what customers see.
Your logo
Upload it under Setup → Logo and pick it as the launcher glyph under Rims. Wherever it stands in for the glyph — the launcher, the voice bar's avatar, the chat header — it is drawn whole: fitted into the largest square the shape holds, proportions kept, never cropped. A wide wordmark shows end to end; a square logo keeps its corners.
It sits on one of two backgrounds, shown side by side under the upload so you can see both:
| Background | For |
|---|---|
| Brand colour | A white or light logo made for a coloured background |
| White | Anything else — a coloured or dark logo, or an image with its own background. A logo drawn in your brand colour would vanish on a button of the same colour |
The dashboard reads the logo when you upload it and picks one for you; change it any time. Empty transparent space around the logo is trimmed on upload, so it fills its button instead of floating small in the middle.
What the SDK draws
| Surface | Drawn from the design |
|---|---|
| Launcher | The accent, the launcher shape, the glyph or logo, the shadow or hard offset |
| Voice bar | The surface, outline, corners and shadow. Then the accent avatar, and the name and status in the design's typeface, with a meter that moves at the design's pace. Then the microphone and the hang-up |
| Caption | The line being said, on the design's card |
| Chat window | The page, a header with the heading in the heading font, bubbles in the chosen style, and the composer — and the window size, title, avatar, header, background, starters, placeholder and timestamps from the Garage's Chat window tab |
| Call screen | The ring and the call, from the Garage's Call screen tab: background, avatar, controls, captions, timer, end button, ringtone and the words for each state. A locked iPhone shows the system's call screen — The Garage → Every state of a call |
| Components | Cards, lists and choices in the design's corners, type and depth — a component's own look still wins where you set one |
| Loader | Your choice in Appearance → Loading, while connecting, reconnecting, thinking and while a component loads |
Typefaces
The system font, or one of 24 families — eleven with Devanagari:
Inter · Roboto · Geist · IBM Plex Sans · IBM Plex Sans Devanagari · DM Sans · Noto Sans · Noto Sans Devanagari · Noto Sans Tamil · Mukta · Hind · Anek Devanagari · Poppins · Baloo 2 · Nunito · Atkinson Hyperlegible Next · Source Serif 4 · Newsreader · Fraunces · Playfair Display · Tiro Devanagari Hindi · Noto Serif Devanagari · Martel · JetBrains Mono
The SDK loads the typeface itself. It fetches only the faces the design draws with: the body font at its regular and strong weights, and the heading font at its title weight. They come from Graine, never a third party, and are kept on the device so each is fetched once. Until a face arrives, and if it never does, the SDK draws the system font. A missing font never costs a call.
A family your app already ships wins over the download: name it in fonts on
the React Native provider, or in GraineConfig.fonts natively.
What your app does
React Native — mount the SDK's bar, and hand the provider the two platform abilities it cannot import itself: registering a font, and drawing a vector.
For a launcher of your own placement, GraineLauncherButton draws the design's
launcher and calls onPress. See React Native.
Android, iOS, Flutter — nothing beyond the bar you already mount
(GraineAgentBarView, GraineAgentBar). From 0.3.0 it is drawn in the design,
and the SDK downloads and registers the typeface natively — no module to add,
nothing to hand over. Pass onClose if your app shows the bar on demand.
Light, dark and motion
Auto follows each customer's device, and switches the moment they do. Light or dark pins it for everyone. Motion runs at the design's pace: the meter, the caption and chat arriving, the launcher appearing. It stops entirely when the design says none, or when the customer's phone asks for reduced motion.
Drawing your own UI
You rarely need to, and replacing the SDK's bar means the design chosen in the
dashboard stops reaching that part of your app. For anything you draw beside
the agent, the design is available as tokens: useGraineTheme() in React
Native, and the resolved tokens on GraineInApp natively. They cover colours,
type, corners, spacing, shadows and motion for the device's light or dark.
When the phone does not match
| Symptom | Check |
|---|---|
| The website changed, the app did not | The app draws its own bar instead of the SDK's — mount GraineVoiceBar (React Native) or the SDK's bar (native) — or the SDK is older than 0.38.0 / 0.3.0 |
| The app changed later than the website | The SDK reads the design once each time the app starts. Quit the app fully and open it again — coming back from the background is not a new start |
| The typeface did not change | React Native without loadFont; a family the app named in fonts wins; the phone was offline the first time — it draws the system font and tries again next session |
| Icons are plain glyphs | React Native without svg |
| No switch to the chat in a native app | The Android, iOS and Flutter SDKs carry the call, not the text chat. In Flutter, hand the bar your chat (chat:) and it offers the switch |

