Skip to content

About

Android254 / Kotlin Kenya community app: events, Call for Speakers, community and profile. Kotlin Multiplatform + Compose Multiplatform.

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Android254

Android254: events, talks, jobs and people for Kenya's Android and Kotlin developers

Events, Call for Speakers, community and profile for Kenya's Kotlin & Android developers.

Android254 is the official app of the Android254 / Kotlin Kenya developer community. Members use it to find the next meetup and RSVP, submit talks, get into meetups on the day with a QR ticket, connect with other developers, browse jobs from community sponsors, and keep a speaker and member profile.

The app is built with Kotlin Multiplatform + Compose Multiplatform. It uses Material 3 chrome on Android and native-feeling chrome on iOS, and both platforms share the brand content (cards, chips, state messages, type and colour tokens).

🎨 Design source of truth: Android254 on Figma Design system v1.1: 131 components, Android + iOS, Oct 2026.


Table of contents


Product overview

Who it's for Kotlin & Android developers in Kenya and the region. Chapters: Nairobi, Mombasa, Kisumu, Kampala (Kotlin Uganda, a partner community) and online-only members.
Top member tasks See the next meetup and RSVP, get in on the day, find jobs, find people.
Secondary tasks Submit a talk, rate meetups, speaker feedback, mentorship, sponsored challenges, sharing a profile poster.
Platforms Android (Material 3), iOS (native chrome), plus a companion website for public pages and sponsor/speaker forms.
Sign-in GitHub. Guest mode is also available in one onboarding variant.
Languages English and Kiswahili (sw-KE).
Themes Light, Dark and System. Every screen is designed in both.

Release scope

The Figma file tags frames with milestones:

Tag Meaning
MVP (T2, accepted 2026-10-02) Phone layouts for the core flows. No navigation drawer in the MVP. Submit a talk, Code of conduct, About and Our sponsors become rows on Profile and Settings. The full drawer design is kept for later.
M1 · January scope Medium (600dp), Expanded (840dp) and Foldable (673×841 book-portrait) layouts for key flows (onboarding, ticket, check-in tabletop mode, submit a talk, event detail, settings). This targets the January 24, 2027 meetup.
M2 List-detail layouts at Expanded widths (Events ↔ Event detail, Jobs ↔ Job detail, People ↔ Member profile, Settings ↔ sub-pages).

Navigation & information architecture

Decision (Oct 2026), Option A: four root tabs.

┌────────┬────────┬────────────┬─────────┐
│  Home  │ Events │ Community  │ Profile │   ← NavigationBar (Android) / TabView (iOS)
└────────┴────────┴────────────┴─────────┘
                        │
                        └─ PrimaryTabRow: Content · Jobs · People
                           (iOS: segmented Picker)
  • Home: the next meetup, shortcuts, the current promo and trending topics.
  • Events: calendar and list of meetups, event and session detail.
  • Community: CommunityScreen with three tabs: ContentTab · JobsTab · PeopleTab. Quick connect is the FAB on People.
  • Profile: your profile, talks, badges, mentorship and settings.
  • Secondary destinations (no duplicates of tabs): Submit a talk, Code of conduct, About, Our sponsors, Settings. In the MVP these are rows on Profile/Settings. A drawer comes later.
  • At ≥600dp the NavigationBar becomes a NavigationRail. Secondary items appear there too: Submit, Conduct, About, Sponsors, Settings.
  • The NavigationBar shows on root tabs only. It is hidden on detail, form and onboarding screens.

Why not five tabs (Home · Events · Jobs · Community · Profile)? Five 72dp items crowd the labels. "Community" truncates at 200% font size, and longer Kiswahili labels wrap. Labels must stay readable at 360dp, 200% font and +30% Kiswahili length.


Features

1. Onboarding

Onboarding is a short setup that builds a personalised feed. It runs as an A/B test:

Variant Flow
B: Sign in first (control) Welcome + GitHub sign-in → Step 0 Your chapter → Step 1 Pick your stack → Step 2 How do you build? → Step 3 What's next for you? → Complete
A: Interests first Welcome → interest steps → Step 4 Save your feed (sign in or continue as guest) → Complete (signed in / guest)
  • Your chapter: we guess the chapter from approximate location (e.g. Nairobi: 1,240 members). Members can pick Nairobi, Mombasa, Kisumu, Kampala or Online only, and follow other chapters later.
  • Experiment: 50/50 split on first launch, sticky per install, new installs only.
    • Primary metric: onboarding completion, meaning the user reaches Home with ≥1 topic picked in the first session.
    • Secondary metrics: GitHub sign-in rate, topics picked, day-7 retention, first RSVP within 14 days.
    • Guardrails: guest share +≤10 pts in A, crash-free sessions, median time-to-Home +≤20%.
    • Analytics events: onboarding_viewed{variant, step}, interest_selected{topic}, onboarding_skipped{step}, sign_in_started / sign_in_succeeded / sign_in_failed{provider}, guest_continued, onboarding_completed{variant, topics, signed_in}.
    • Decision rule: run until each arm has ~1,000 installs (≈4 weeks), then ship the winner. On a tie, keep B.
  • States: sign-in failed, none selected, Dark, 412dp, plus tablet and foldable layouts.

2. Home

The member's daily dashboard.

  • Chapter switcher (e.g. "NAIROBI CHAPTER ▾") opens a chapters bottom sheet. There is also a single-chapter variant.
  • Greeting: "Good morning, Zawadi".
  • Your next meetup: the featured EventCard shows date, venue, RSVP status, attendees ("+42 going"), session count and View event & sessions.
  • Shortcut tiles: Jobs (48 open roles), People (184 members), Quick connect (scan a code), Submit a talk (closes 10 Feb).
  • Promo slot (one at a time): Call for Speakers, a ticket drop, a survey or a sponsored challenge (e.g. "Ship a Compose foldable layout", presented by Kasha Health).
  • Trending topics: chips with counts (Jetpack Compose, Coroutines, KMP, Architecture).
  • States: Default, Empty (new member), Loading (skeletons), Error, Dark, 200% font scale, Kiswahili.
  • Post-event variants: After the meetup (rate prompt, rating skipped) and First meetup · Celebration.

3. Notifications

  • Filter chips at the top. Items are grouped into Today and Earlier.
  • Example items: talk accepted, meetup in 3 days, speaker mentor assigned, recording available, trending topic.
  • Read and unread NotificationItem states.
  • States: Default, All caught up, Loading, Error, Dark, 412dp.

4. Event day mode, ticket & check-in

On meetup day, Home changes into event day mode:

  • "It's meetup day, Zawadi" with the doors-open time.
  • TicketCard: attendee name, entry type, hall/floor. Tap it for the full QR ticket.
  • Now and next: the live session (with "Live poll open") and the next session.
  • At the venue: Wi-Fi name and password with Copy, directions ("Lifts on the left after security · Bring an ID").
  • Today's host: the sponsor row.
  • Offline: the ticket and venue info stay available with an inline offline note.

Ticket screen: Default, Dark and Offline, plus phone, tablet and foldable layouts. After a successful scan, a Checked in · Welcome toast appears.

Check-in scanner (organiser):

  • Camera viewfinder with a result bottom sheet. Results: Checked in, Already checked in, Not on the list.
  • Tabletop mode (foldable, M1): the upright half shows the viewfinder, the checked-in count against capacity ("38 still to arrive") and the last person scanned. The flat half holds the controls: recent scans, a manual 6-character code field, torch toggle, undo last, and end session. Results auto-return after a short progress bar.

5. Events

  • Events tab: a month/week calendar (CalendarMonth / CalendarDay) plus the event list. States: empty day, loading, error, past events with a Rate the meetup prompt.
  • Event detail: agenda, speakers, venue, sponsor and RSVP.
    • RSVP states: RSVP'd, Cancel RSVP confirm, RSVP confirmed.
    • Capacity states: Few seats left (warning under 15% capacity), Full · Waitlist (error at 0), Waitlist promoted.
    • After the event: Ended · Rate and Ended · Rated.
  • Session detail: Upcoming and Live. Live sessions can carry a sponsor poll ("Poll by …").
  • Panel sessions (new): panel formats in the agenda, plus Upcoming and Live panel session detail.
  • Post-event loop: rate the meetup (1–5 rating faces), submitted state, first-meetup celebration.
  • Sponsor impact report: an A4 report (complete or partial data) and an organiser mobile preview.

6. Call for Speakers (Submit a talk)

A 4-step form for proposing a talk:

  1. The pitch: title, format (talk or panel), abstract. States: title missing, draft saved, returning speaker.
  2. Content: outline, level, topics.
  3. Experience: prior speaking. First-time speakers get a mentor.
  4. Materials: slides and links.

→ Submitted ("Talk submitted. We'll reply by 10 Feb.")

  • Panel discussions (new): add panel speakers and invite members through a search sheet (states: no results, invite failed). Invites can be Pending, Accepted, Declined, Expired, or Leave panel (confirm).
  • Speaking history: SpeakerHistoryCard shows a speaker's track record to organisers.
  • The same flow exists on the web (see Web companion).

7. Community

Content tab: talks, recordings and articles with filters. States: empty filter, loading, error.

Jobs tab (Job board):

  • Search and filters. Featured roles: at most 2 per list, always labelled "Featured · Community sponsor", always showing a salary range.
  • Job detail: save, apply, and an Applications closed state.
  • Role insights (poster): view stats for the people who posted a job.
  • States: no results, no matching roles, 200% font scale, Expanded list-detail.

People tab (Developer network):

  • Search the member directory, with an expandable map. A new-member state.
  • Member profile: Not connected / Connected / Remove connection.

Quick connect (the FAB on People):

  • Scan another member's QR → Member found → Connected (First connection celebration).
  • My code: show your QR, or reset it (with a confirm step).
  • Sponsor booths: scan a sponsor code → choose what to share → Shared with sponsor. A Sponsor code expired state.
  • Camera permission handling (Android rationale and iOS system alert). Not a member code state.

Sponsors: the Our sponsors list and Sponsor detail (open roles, no open roles, loading, error).

8. Profile & settings

  • Profile: your info, talks, badges (with a Badge unlocked motion), topics (edit via sheet) and Talk accepted state. States: new member, loading, error, 200% font scale.
  • Edit profile: link validation, discard-changes confirm, saved confirmation.
  • Public profile & Open to work: a public web profile (360) and a 1200×630 share card.
  • Mentorship: request a mentor (sheet), incoming requests (for mentors), Your mentorships, mentoring settings, and mentorship notifications.
  • Speaker feedback: attendee feedback on your talks. A No feedback yet state.
  • Sponsored challenge: Open, Submitted, Closed, plus promo and badge examples.
  • Settings:
    • Theme sheet (Light / Dark / System).
    • Notifications (including a system notifications off state).
    • Privacy (what you share; a Nothing shared state; stop-sharing confirm).
    • Open to work.
    • Delete account (confirm).
    • Rows for Submit a talk, Code of conduct, About and Our sponsors (MVP replacement for the drawer).

9. Meetup posters

The app generates share-ready speaker posters for each meetup edition.

  • MeetupPoster component. Poster variables switch theme per edition: Kotlin night, Savannah dawn, Lake teal.
  • Preview & share states: generating, no photo, offline, long name/title, Dark. Available on iOS too.
  • Sponsor logo treatment rules come with the poster.

10. Web companion

The companion website is responsive: Desktop 1280 and Mobile 360, Light and Dark.

  • W1 (public): About us, Sponsor pitch, Sponsor tiers, Terms of service, Privacy policy, Account deletion (required by the Play Store).
  • W2 (forms): Call for Speakers (sign in → 4 steps → submitted), Call for Sponsors (form, errors, success), Call for Donations.
  • Organizer: a sponsor submissions dashboard.
  • Web shell: top bar, footer, mobile menu, skip link, keyboard focus styles, theme toggle, photo gallery, organiser marquee, a Get the app CTA and an iOS coming soon notice.

Brand

The Android254 mark is the Kotlin K on a dark rounded tile. Use the AppLogo component in core/ui and never redraw it.

  • Mark: the K on a #2F3037 tile. Show it at 24dp or larger, and never stretch it.
  • Name: "Android254", one word, capital A. Not "Android 254" or "android254".
  • Tagline: ANDROID · KOTLIN · KENYA.
  • Gradient: accents only. Never put a gradient behind the mark or text.

Android254 lockup for light backgrounds

Full guidelines are in docs/brand.md. The feature graphic is at docs/assets/brand/feature-graphic.jpg.


Design system

All UI binds to semantic tokens, never to raw hex values or palette tones. The rule is "bind, never paste".

Colour (Material 3 roles, seeded from Kotlin purple #6633E5)

Role Light Dark
primary #6633E5 #CDBDFF
onPrimary #FFFFFF #370095
primaryContainer #E8DEFF #54348A
secondary #615B71 #CBC3DC
tertiary / success #006C47 #71DAA6
warning #904D03 #FFB77D
error #BA1B1A #FFB4AB
surface / background #FBF8FF #12131A
surfaceContainerLowest #FFFFFF #0D0E14
surfaceContainerLow #F4F2FD #1A1B22
surfaceContainer #EEEDF7 #1E1F26
surfaceContainerHigh #E9E7F1 #292931
onSurface #1A1B22 #E3E1EB
onSurfaceVariant #494455 #CBC3D8
  • The full set has 47 colour roles. Beyond the Material 3 roles it adds success and warning families.
  • Muted text uses onSurfaceVariant. outline (#7A7487, 4.3:1) is for borders only, never text.
  • The Kotlin gradient is for accents only (bars, title fills, illustrations). Don't put text on it: white on its pink end fails AA.

Typography

Style Font Size/line Letter spacing
Display L Space Grotesk Bold 48/56 −1
Display M Space Grotesk Bold 40/48 −0.5
Display S Space Grotesk Bold 32/40 −0.5
Headline L Space Grotesk Bold 28/36 −0.5
Headline M Space Grotesk Bold 26/34 −0.5
Headline S Space Grotesk Bold 24/32 −0.5
Title L Space Grotesk Bold 20/28 −0.3
Title M Inter Semi Bold 18/26 0
Title S Inter Semi Bold 16/24 0
Body L Inter Regular 16/24 0
Body M Inter Regular 14/22 0
Body S Inter Regular 12/18 0
Label L Inter Semi Bold 14/20 0
Label M Inter Semi Bold 12/16 0.2
Label S Inter Semi Bold 12/16 0.3
Mono/Meta JetBrains Mono Bold 12/16 0
Mono/Overline JetBrains Mono Bold 12/16 0.5
Mono/Code JetBrains Mono Medium 13/20 0

Sizes and letter spacing are in sp. The minimum size is 11sp. Each style maps to a MaterialTheme.typography slot and to an iOS Dynamic Type style. JetBrains Mono is for metadata only (e.g. JAN 24 · 09:30 AM EAT).

Spacing, shape, elevation

  • Spacing: 4dp base grid. Screens use layout aliases: screen-margin 16, card-padding 16, stack-gap 12, inline-gap 8, section-gap 32. The values 6, 10 and 14 are retired.
  • Shape: xs 4 · sm 8 · md 12 (inputs, images) · lg 16 · xl 24 (cards, sheets) · full (pill). Pill shape is only for buttons, chips and badges.
  • Elevation (Light theme only):
    • Level 1: cards at rest.
    • Level 2: FAB, menus, sticky headers.
    • Level 3: bottom sheets and bars.
    • Primary Glow: only on the single primary CTA per screen.
    • In Dark theme, there are no shadows. Raise surfaces with surfaceContainer tones instead.
  • Icons: Material Symbols (Android) and SF Symbols (iOS) at 16/20/24. No emoji in UI.
  • Other variable collections in Figma: Size, Motion, Breakpoint and Poster (per-edition themes).

Component library (Figma → Compose)

Group Components
Actions Button (Filled, Tonal, Outlined, Text, Inverse), IconButton, Chip (Assist, Filter, Topic), SelectionControl, SegmentedButton, ShortcutTile
Navigation NavigationBar(+Item), TopAppBar (Small, Home, Large), BottomActionBar, NavigationDrawerItem, TabRow, NavigationRail(+SecondaryItem)
Lists & inputs SectionHeader, ListItem (1–3 lines, icon/avatar), NotificationItem, TextField (single/multiline), SearchField, CalendarDay/Month, OptionCard, Switch, SettingsRow, RatingRow
Cards EventCard (Featured/Compact), PromoCard, TicketCard, JobCard, SponsorRow, StatTile, PanelSessionCard, SpeakerHistoryCard
Feedback & overlays StateMessage, Skeleton, InlineNote, Toast, BottomSheet / SheetContent, dialogs
Identity AppLogo, Avatar, StatusBadge
iOS chrome StatusBar, NavigationBar (Large/Inline), TabBar, GlassButton, ListRow, Toggle

All components have Enabled, Pressed, Focused and Disabled states where they apply.

Reusing core/ui

Before building any UI, read core/ui/README.md and reuse or extend an existing component. Add a new component to core/ui only when none fits, and update that README in the same commit as any component change.


Screen-building rules

  1. Screen skeleton: TopAppBar → scrolling content on a 16dp margin → NavigationBar (root tabs only). Design at 360×800, verify at 412×915.
  2. TopAppBar hierarchy: Home variant on root tabs (logo + actions). Small with back on detail screens. Large only for top-level lists that collapse on scroll.
  3. Sections open with a SectionHeader: an optional overline, a title, and at most one "See all".
  4. Cards hold one thing.
    • Card recipe: surfaceContainerLowest (Light) / surfaceContainerLow (Dark) fill, 1dp outlineVariant stroke, 24dp radius, 16dp padding.
    • Content order: Mono overline → title → meta → tags → one action.
    • The whole card is the tap target. Secondary actions are 48dp IconButtons.
    • One Featured card per screen. One PromoCard per screen at most.
    • No cards inside cards. Lists of more than 3 rows use ListItem rows.
    • From 600dp, cards go in a 2-column grid. Never stretch a card past 560dp.
  5. Status colour means status. StatTiles are neutral by default. Seats left turns warning under 15% capacity and error at 0.
  6. Sponsors back events, never single sessions. Use one sponsor surface per screen, always labelled ("Hosted by", "Supported by", "Presented by").

Copy voice & localisation

The voice is a friendly organiser at the meetup door: warm, direct and local.

  • Use sentence case everywhere. Caps appear only in Mono overlines (MEETUP #80, CALL FOR SPEAKERS).
  • Button labels say what happens: "Submit a talk", "Turn on reminders", "Try again". Never "OK", "Click here" or a bare "Submit".
  • Errors say what failed, then what to do next. ✅ "Couldn't load events. Check your connection and try again." ❌ "Error 500: Request failed."
  • Formats:
    • Dates: Sun, 24 Jan · 9:30 AM EAT
    • Money: KES 1,500
    • Places: iHub Nairobi, Senteu Plaza
  • Don't use "Oops!", "functionality", "utilize", or emoji in UI chrome.
  • Kiswahili (sw-KE):
    • Keep it warm, not formal ("Karibu", "Habari za asubuhi, Zawadi").
    • Tech terms stay in English (Compose, KMP, RSVP, CFP, Quick connect). Translate the verbs around them ("Fanya RSVP", "Wasilisha mada").
    • Dates and times: "Jumapili, 24 Jan 2027", "Saa 3:30 asubuhi". Leave EAT out.
    • Text runs 20–40% longer, so labels wrap and never truncate.
    • Nav labels: Nyumbani · Matukio · Jumuiya · Wasifu.

Android ↔ iOS mapping

Shared Compose code covers brand content. Platform chrome stays native.

Concern Android (Material 3) iOS
Root navigation NavigationBar + NavigationBarItem TabView / TabBar
Top bar TopAppBar (Small / Large / Home) NavigationStack title (inline / large)
Back arrow_back + predictive back Native back swipe
Sheets ModalBottomSheet .sheet with .medium / .large detents
Dialogs AlertDialog .alert / .confirmationDialog
Date/time DatePicker / TimePicker dialogs DatePicker (compact / graphical)
Community tabs PrimaryTabRow Segmented Picker
Shared Button, Chip, cards, StateMessage, Skeleton, InlineNote, type and colour tokens ← same Compose components

The Figma iOS page covers root tabs, key flows and parity flows (#19): submit a talk, Quick connect, notifications, session detail, edit profile, member profile, onboarding, and panel discussions.


Adaptive layouts

Window class Width Layout
Compact 360–412dp NavigationBar, single column
Medium 600dp NavigationRail, 2-column card grid
Expanded 840dp NavigationRail, list-detail panes (M2)
Foldable 673×841 book-portrait NavigationRail; tabletop posture for the check-in scanner (hinge-aware)

Every screen must also hold up at 200% font scale.


Screen state checklist

A screen isn't done until it has:

  • Default (designed at 360dp, verified at 412dp)
  • Loading (Skeleton)
  • Empty / Error / Offline (StateMessage / InlineNote)
  • Dark theme
  • 200% font scale
  • Kiswahili length check
  • Medium / Expanded / Foldable layouts, where the screen is in M1/M2 scope

Project structure

This is a Kotlin Multiplatform project built with the Kotlin Toolchain (project.yaml / module.yaml, not Gradle).

Android254/
├── project.yaml            # module list: androidApp, iosApp, shared
├── libs.versions.toml      # version catalog
├── kotlin / kotlin.bat     # self-bootstrapping toolchain wrappers
├── androidApp/             # Android app (namespace & applicationId: ke.kotlinke.android254)
│   ├── src/MainActivity.kt
│   └── res/
├── iosApp/                 # iOS app (SwiftUI entry → Compose ViewController)
│   └── src/
└── shared/                 # KMP library: Compose UI, business logic
    ├── src/                # common code
    ├── src@android/        # Android-only code
    ├── src@ios/            # iOS-only code
    ├── composeResources/   # shared resources (Res.*, package ke.kotlinke.android254.resources)
    └── test*/              # common and platform tests

Current stack: Kotlin Multiplatform, Compose Multiplatform (runtime, foundation, Material 3, resources, hot reload), AndroidX Lifecycle ViewModel and runtime-compose, and Activity Compose. Targets: Android, iosArm64, iosSimulatorArm64.


Getting started

The kotlin (macOS/Linux) and kotlin.bat (Windows) wrappers download the pinned toolchain on first use. You don't need to install anything separately.

./kotlin build                # build everything
./kotlin run -m androidApp    # run on Android
./kotlin run -m iosApp        # run on iOS (macOS + Xcode required)
./kotlin test                 # run all tests
./kotlin test -m shared       # test a single module

You can also use the run configurations in your IDE's toolbar.


Open decisions

  • Onboarding order: A/B test pending (see Onboarding).
  • Navigation drawer: designed, but out of the MVP.
  • Decisions are logged in docs/decisions.md. Create it as decisions are made.

Learn more: Kotlin Multiplatform · Compose Multiplatform · Kotlin Toolchain

About

Android254 / Kotlin Kenya community app: events, Call for Speakers, community and profile. Kotlin Multiplatform + Compose Multiplatform.

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages