The shared design system the app is built on — and, just as importantly, the composite-build setup you need before the main app will even compile.
If you just tried to sync the main app and it failed — or you can’t find StcPayTheme anywhere in the codebase — you’re in the right place.
The stc pay app is built on a shared UI Kit: the theme, the brand colours, the language engine and a library of Compose components all live in a separate repo (stcpay-bh-android-ui-kit). The main app pulls it in as a composite build — and until you set that up, the app won’t even sync. This short guide gets you past that and explains what the kit gives you.
This guide pairs with the main Developer Knowledge Transfer; keep both open, and walk through the setup with your lead the first time.
The UI Kit is stc pay’s shared design system and component library, packaged as the Gradle module :stcpay-ui-kit (namespace com.stcpay.uikit). It’s bigger than it sounds — it holds almost everything the app is built from:
StcPayTheme, the colour palette, typography, dimensions (§07).LocaleManager / LocaleWrapper (English, Arabic + 5 more, RTL) (§09).Put simply: if you’ve tapped a button, typed in a field, or seen a bottom sheet in the app, it came from here.
The main app depends on it as the artifact com.stcpay:stcpay-ui-kit (declared once in the :util module). That artifact isn’t published to a repository you can reach, so you supply it from source via a composite build.
stcPayUiKitProjectPath isn’t set (§05), Gradle can’t resolve com.stcpay:stcpay-ui-kit and the app fails to sync. Setting it up is part of first-time setup, not an extra.
So the first job is simply to point the app at a local copy of this repo. Here’s the kit itself, then how to link it.
It’s a single Gradle module — a Compose Android library on JDK 17 (compileSdk 36, minSdk 23, Hilt) — but don’t mistake “one module” for “small”: it’s around 90 source files plus the fonts, strings and icons. The module is :stcpay-ui-kit under rootProject.name = "stcpay_ui_kit" (that name matters in §06).
com.stcpay.uikit)| Package | What’s inside |
|---|---|
theme | StcPayTheme, the colour palette (Color.kt), CustomColorsScheme, typography (STC Forward), Dimensions. (§07) |
views | The bulk of the component library — ~50 files: buttons, text, text fields, app bars, OTP, lists, cards & more. (§08) |
bottomsheet | The bottom-sheet system: BottomSheetHost, the global BottomSheetManager, standard / menu / list sheets. (§08) |
pickers | Date & date-range pickers. (§08) |
language | The locale engine: LocaleManager, LocaleWrapper, LanguageViewModel. (§09) |
utils | Formatting, dates, validation, QR, copy & screen-capture helpers. (§09) |
keyboardguard | Secure-keyboard guard. (§09) |
cashbackplus · data | Cashback-plus UI, plus shared models & enums (incl. the Language enum). |
values, -ar, -bn, -hi, -ml, -tl, -ur) and a large shared icon set. So shared strings and the brand fonts live here, not in the app repo.
| Repo | stcpay-bh-android-ui-kit |
| Module | :stcpay-ui-kit · namespace com.stcpay.uikit |
| Consumed as | com.stcpay:stcpay-ui-kit |
| Published as | com.github.stcpay:stcpay-uikit-android |
This is the step that makes the main app sync. You’re telling the app “use this local folder as the UI Kit”.
stcpay-bh-android-ui-kit somewhere on your machine.local.properties, add the path to that clone:stcPayUiKitProjectPath=/Users/you/claude/stcpay-bh-android-ui-kit
That’s it. The app’s settings.gradle.kts picks up the key and wires the kit in as a composite build — includeBuild pulls in your local source, and dependencySubstitution swaps the published artifact for it:
localProperties?.getProperty("stcPayUiKitProjectPath")?.let { path -> includeBuild(path) { name = "stcpay-uikit" dependencySubstitution { substitute(module("com.stcpay:stcpay-ui-kit")).using(project(":stcpay-ui-kit")) } } }
stcPayUiKitProjectPath must be the folder that contains the kit’s settings.gradle.kts — the repo root, not the inner stcpay-ui-kit/ module.
Sync now. If it works — great. If you hit a duplicate-class error, that’s the next section (and it’s expected).
Almost everyone hits this on first sync after linking the kit: a duplicate-class / “class already exists” error. It happens because the composite build’s name and the kit’s own project name don’t line up. The fix is quick.
By default the names differ — the kit calls itself stcpay_ui_kit, while the app includes it as stcpay-uikit:
| File | Default value |
|---|---|
UI Kit — settings.gradle.kts | rootProject.name = "stcpay_ui_kit" |
App — settings.gradle.kts (includeBuild) | name = "stcpay-uikit" |
"stcpay-uikit").Once you’re synced, the rest is just knowing what the kit offers.
This is the app’s visual language in one place — and the reason StcPayTheme isn’t in the app repo.
| Piece | What it is |
|---|---|
StcPayTheme { } | The theme wrapper. Handles light/dark (and Material You dynamic colour) and provides the typography + custom colours to everything inside it. (theme/Theme.kt) |
customColorsScheme | The brand semantic colours beyond Material — e.g. textColorPrimary, primaryToWhite — read via MaterialTheme.customColorsScheme (a CustomColorsScheme). |
Color.kt | The raw palette: PrimaryColor #4F008C, SecondaryColor #00C48C, eKeyColor, plus text / border / background tokens (light & dark). |
| Typography | stcPayTypography() on the STC Forward font family (shipped by the kit), with an Urdu fallback. (theme/Type.kt) |
Dimensions | Shared spacing / size tokens. (theme/Dimensions.kt) |
| Status bar | SetStatusBarColor + LocalStatusBarColor for per-screen status-bar colour. |
MaterialTheme.customColorsScheme and the typography styles instead of literal colours or text styles — that’s what keeps light/dark and Arabic looking right.
This is the heart of the kit and what you’ll use every day. Nearly every shared UI building block in the app lives here — reach for these before writing your own.
| Category | Components (& file) |
|---|---|
| Buttons | PrimaryButton, PrimaryButtonSmall, SecondaryButton, FullWidthButtonBordered, DoubleTextWithArrowButton, IconAndTextBorderButton — views/ButtonComponents.kt |
| Text | TitleSubtitle, OutlinedTextRow, CopyableTextRow, ResponsiveText, DateText — views/TextComponents.kt |
| Text fields & inputs | TextFieldComponents, NumberInputField, CurrencyLabelInputField, SearchViewField, ClickableSearchView |
| Selection controls | CheckboxComponents, RadioButtonComponents, SwitchComponents, DropdownComponents |
| App bars | BaseAppBar, CommonAppBar, LoginAppBar, HistoryAppBar, RemittanceAppBar & more — views/AppBarComponents.kt |
| OTP | OtpView, OtpTimerButtonsView |
| Bottom sheets | BottomSheetHost, StandardBottomSheet, MenuBottomSheet, ListBottomSheet — raised via the global BottomSheetManager |
| Pickers | DatePickerSheet, DateRangePickerSheet, DateRangeRowWithPicker |
| Feedback & state | CustomLoadingIndicator, Shimmer, EmptyListView, HomeErrorView, StepProgressIndicator, PagerComponents |
| Lists, rows & cards | ListItemComponents, LabeledActionRow, AccountOverviewCard, ReviewTansactionView, Note, image & gradient helpers |
| Layout helpers | BaseScreen (screen scaffold), CustomModifiers, CustomEdgeToEdge, LtrLayout |
The kit owns the whole localization engine: LocaleManager (init, setLocale, localizedString, getPersistedLanguage), the LocaleWrapper composable that provides language context, LanguageViewModel, and the Language enum (which carries each language’s LayoutDirection for RTL). It also ships the app’s strings in 7 languages and the STC Forward fonts.
utils/ holds shared helpers you’ll reuse constantly: FormattingUtils (prices / currency), DateTimeUtils, Validations, QRCodeUtils, CopyUtils, SendMessageUtils, ContextUtil.
KeyboardSecurityManager (a secure-keyboard guard) and ScreenCaptureUtils (screenshot control) — small but important for a banking app.
strings.xml (en + ar / bn / hi / ml / tl / ur) and the brand fonts are in the kit, not the app. Adding a shared string, or can’t find one? Look here.
You almost never add the dependency yourself — it’s declared once and flows everywhere. The :util module pulls it in with api(...), and because :util sits low in the dependency chain, the whole app gets the kit transitively.
The main app wires the kit’s big pieces in at startup (see the main guide’s §12 and §16):
StcPayTheme wraps the app’s content in MainActivity.LocaleManager.init(...) runs in StcApplication at startup.BottomSheetHost is mounted once; any screen raises a sheet through BottomSheetManager.| Repo | stcpay-bh-android-ui-kit |
| Module · namespace | :stcpay-ui-kit · com.stcpay.uikit |
| Consumed as | com.stcpay:stcpay-ui-kit |
Link key (local.properties) | stcPayUiKitProjectPath |
| Kit project name | stcpay_ui_kit |
App includeBuild name | stcpay-uikit |
| Also ships | STC Forward fonts · strings ×7 languages · shared icons |
stcPayUiKitProjectPath in the app’s local.properties (§05).