Cross-Platform Mobile · React Native

Piko Social App

Production-grade cross-platform social application for iOS, Android, and web — built from inception with a single shared codebase, real-time messaging, and a 50+ component library.

50+Reusable components
3Platforms from 1 codebase
40%Dev cycle acceleration
2Languages (EN / ZH)
Piko social media app — cross-platform pet community interface on iOS, Android and web

Production-ready cross-platform app — iOS, Android, and web from a single codebase

Project typeCross-Platform Mobile App
RoleFrontend Developer
TimelineMay 2024 – Aug 2025
StatusProduction ready

Project Overview

Built a production-ready cross-platform social application for pet owners from the ground up. The platform lets pet parents share moments, connect with other families, discover local events, and build community — with a consistent experience across iOS, Android, and web from a single React Native codebase.

Greenfield development from inception

Joined at day zero, contributing to critical architecture decisions and establishing the patterns that made rapid, scalable development possible. Built 50+ reusable components, implemented real-time features with GraphQL subscriptions, and resolved 40+ cross-platform compatibility issues to ship a polished, production-quality app.

The Challenge

PetoLab needed a comprehensive social platform built from scratch — capable of handling real-time social interactions, media-heavy content, and consistent UX across three platforms simultaneously. The architecture had to support future scaling to thousands of concurrent users without performance degradation.

Cross-platform consistency

Identical UX and visual consistency across iOS, Android, and web — with platform-specific optimisations where they matter.

Real-time features

GraphQL subscriptions for instant messaging, live notifications, and dynamic feed updates — without polling.

Media performance

Image and video uploads, compression, thumbnail generation, and adaptive playback across platforms with varying hardware.

Internationalisation

English and Chinese language support with proper pluralisation, locale-aware formatting, and instant runtime switching.

System Architecture

Layer 1 — Presentation

React Native + Expo 52

50+ reusable components, platform adapters (.native.tsx / .web.tsx), responsive layouts

Layer 2 — State management

Redux Toolkit

Feature slices, async thunks, memoised selectors, normalised relational state

Layer 3 — Data layer

GraphQL + REST (Apollo Client)

Queries, mutations, WebSocket subscriptions, media uploads

Layer 4 — Platform services

Expo Modules + Firebase

Camera, location, push notifications (FCM), Firebase Auth, Google/Apple sign-in

Layer 5 — Native platforms

iOS · Android · Web

Platform-specific optimisations isolated behind file-extension adapters

// Cross-platform request flow Presentation (React Native / Web) → State (Redux Toolkit + async thunks) → API Layer (Apollo Client — queries / mutations / subscriptions) → Platform Services (Expo Modules / Firebase) → Native Platforms (iOS · Android · Web)

Key Technical Contributions

01

Comprehensive Component Library — 50+ Components

Cross-platform UI foundation that accelerated every feature built after it

Challenge: Build reusable components that behave identically on iOS, Android, and web while taking advantage of native performance where it matters — without duplicating logic.

Solution: Architected a library with platform file-extension adapters, a theming system, and responsive layouts from day one. Every component documented in Storybook.

Component categories

Core primitives

  • Avatar, Badge, Button, Icon, Image
  • Text, Chip, Divider, Modal, BottomSheet
  • LoadingIndicator, Carousel, Overlay

Input components

  • TextInput, PasswordInput, SearchInput
  • DatePicker, TimePicker, PickerInput
  • ImageInput, VideoEditor, CameraModule
  • LocationPicker, QRCodeScanner

Social components

  • PostItem, CommentItem, MessageListItem
  • UserProfileCard, PetProfileCard
  • ActivityFeed, NotificationCard
  • ChatMessage, GroupAvatar

Layout components

  • ScreenLayout, PagerScreen, StackScreen
  • ScrollList, VirtualizedList
  • Header, TabBar, NavigationDrawer
Platform adapter pattern
// Image.web.tsx — web renderer export const Image = ({ source, style, ...props }) => <img src={source.uri} style={style} {...props} />; // Image.native.tsx — iOS + Android (uses FastImage for caching) import FastImage from '@d11/react-native-fast-image'; export const Image = ({ source, style, ...props }) => <FastImage source={source} style={style} {...props} />; // Shared usage — same import on every platform import { Image } from '@/components/Image';
50+Reusable components
40%Dev acceleration
3Platforms, 1 codebase
Impact: Every feature built after the component library was 40% faster to ship. Visual consistency across all three platforms was maintained without separate platform design reviews.
02

Real-Time Social Features via GraphQL Subscriptions

Instant messaging, live notifications, and feed updates over WebSocket — zero polling

Challenge: Build a social platform where messages arrive instantly, notifications fire live, and feeds update without polling — matching what users expect from modern social apps.

Solution: Integrated Apollo Client's GraphQL subscriptions over WebSocket, with optimistic UI updates so interactions feel instant before server confirmation.

Instant messaging

  • Direct 1-on-1 chat
  • Group chat + typing indicators
  • Read receipts and message status
  • Image and video attachments

Live notifications

  • Push via Firebase Cloud Messaging
  • In-app notification centre
  • Friend requests and invitations
  • Activity feed with live updates

Feed updates

  • New post subscriptions
  • Live comment and like counters
  • Event RSVP updates
  • Optimistic UI for all mutations
GraphQL subscription hook
export const useChatSubscription = (chatId: string) => { return useSubscription(NEW_MESSAGE_SUBSCRIPTION, { variables: { chatId }, onData: ({ client, data }) => { // Write directly into Apollo cache — no refetch needed client.cache.modify({ id: client.cache.identify({ __typename: 'Chat', id: chatId }), fields: { messages: (existing) => [data.data.messageAdded, ...existing], }, }); }, }); };
Impact: Real-time social experience with instant message delivery, live notifications, and dynamic content updates — without a single polling request adding server load.
03

Redux Architecture for Complex State Management

Feature slices, async thunks, normalised state, and optimistic updates

Challenge: Managing user sessions, content feeds, chat history, real-time updates, and UI state across 20+ screens — without performance degradation or race conditions.

Solution: Feature-based Redux Toolkit architecture with normalised state, memoised selectors, and async thunks keeping all business logic out of components.

State slices

  • authSlice — sessions and tokens
  • postSlice — feed and post management
  • chatSlice — messaging and conversations
  • petProfileSlice — pets and relationships
  • eventSlice — events and attendance
  • notificationSlice — activities and alerts

Architecture patterns

  • Feature-based slice organisation
  • Memoised selectors (Reselect)
  • Async thunks for all API calls
  • Normalised state for relational data
  • Optimistic updates for likes and follows
  • AsyncStorage for offline persistence
Slice with optimistic update
const postSlice = createSlice({ name: 'post', initialState: { feed: [], loading: false, hasMore: true }, reducers: { // Flip like instantly — server confirms (or reverts) asynchronously optimisticToggleLike: (state, { payload: postId }) => { const post = state.feed.find(p => p.id === postId); if (post) post.isLiked = !post.isLiked; }, }, extraReducers: builder => { builder .addCase(fetchPostFeed.pending, s => { s.loading = true; }) .addCase(fetchPostFeed.fulfilled, (s, { payload }) => { s.feed = [...s.feed, ...payload.posts]; s.hasMore = payload.hasMore; s.loading = false; }); }, });
Impact: Predictable data flow and optimistic updates made every interaction feel instant. Normalised state prevented the duplicate-entity bugs that plague relational social data as feature count grows.
04

Multilingual Support with LinguiJS

English + Chinese, 1,000+ strings, zero runtime parsing overhead

Challenge: Support English and Mandarin Chinese with proper pluralisation, locale-aware formatting, and instant runtime language switching — without a performance hit from runtime string parsing.

Solution: LinguiJS 5 with automated message extraction, compiled PO catalogs (no parsing at runtime), and TypeScript integration for compile-time validation of missing keys.

Message management

Automated extraction from source, PO file management, compiled catalogs — zero parsing overhead at runtime.

Locale features

Pluralisation rules, number/date/currency formatting, time zone awareness, RTL layout preparation.

Dev experience

TypeScript autocomplete, compile-time validation, hot reload support, Storybook locale switcher.

LinguiJS in practice
import { Trans, t } from '@lingui/macro'; import { useLingui } from '@lingui/react'; export const NotificationBanner = ({ count }: { count: number }) => { const { i18n } = useLingui(); return ( <View> <Text><Trans>Welcome to PetoKingdom!</Trans></Text> <Text> {i18n._(t`You have ${count} new ${count === 1 ? 'notification' : 'notifications'}`)} </Text> </View> ); }; // zh.po catalog // msgid "Welcome to PetoKingdom!" // msgstr "欢迎来到宠物王国!"
2Languages supported
1,000+Translated strings
InstantRuntime switching
Impact: Expanded addressable user base to Chinese-speaking pet owners. Compiled catalogs mean i18n adds zero runtime overhead — switching languages is instantaneous with no re-render lag.
05

Cross-Platform Compatibility — 40+ Issues Resolved

Systematic debugging across iOS, Android, and web to ship production-quality UX

Challenge: Cross-platform development surfaces subtle but user-facing bugs — styling inconsistencies, keyboard handling, native module incompatibilities — that only appear on specific platforms.

Solution: Established a platform-testing discipline running every feature on a physical iOS device, Android emulator, and web before closing a ticket. Issues tracked and categorised by root cause.

Styling inconsistencies

  • Flexbox behaviour differences
  • Font rendering and line-height gaps
  • Shadow and elevation on Android
  • Border radius clipping issues

Responsive design

  • Keyboard avoidance and layout shift
  • Safe area insets (notch, home bar)
  • Tablet and foldable adaptation
  • Orientation change reflow

Native module issues

  • Camera permission flows per platform
  • Video playback performance (Android)
  • File system access differences
  • Deep linking and URL schemes

Performance fixes

  • List virtualisation for large feeds
  • FastImage LRU caching
  • Subscription memory leak prevention
  • Bundle size reduction via tree shaking
Impact: 40+ resolved compatibility issues translated directly into a polished app with no jarring platform-specific breaks — the standard users expect from any serious social platform.
06

Advanced Media Handling & Optimisation

Image and video pipelines from capture to CDN — 60–80% video size reduction

Challenge: A social app lives and dies by media quality and speed. Image and video uploads needed compression, thumbnail generation, HEIC conversion, and cross-platform playback without blocking the UI.

Solution: Built separate image and video pipelines using Expo Image Picker, Vision Camera 4, and FFmpegKit — with background upload, progress tracking, and adaptive quality by connection speed.

Image pipeline

Capture, gallery pick, crop, HEIC→JPEG, 70% quality compression, thumbnail generation, chunked CDN upload.

Video pipeline

Recording with time limits, trim editor, FFmpeg H.264 compression, poster frame extraction, background upload.

Playback optimisation

FastImage LRU cache, progressive JPEG, WebP on Android, lazy loading in virtualised lists, CDN integration.

FFmpeg video compression
import { FFmpegKit, ReturnCode } from 'ffmpeg-kit-react-native'; const compressVideo = async (inputPath: string): Promise<string> => { const output = `${FileSystem.cacheDirectory}v_${Date.now()}.mp4`; // H.264 · CRF 28 · fast preset · AAC audio · web-optimised moov atom const cmd = `-i ${inputPath} -c:v libx264 -crf 28 -preset fast ` + `-c:a aac -b:a 128k -movflags +faststart ${output}`; const session = await FFmpegKit.execute(cmd); if (ReturnCode.isSuccess(await session.getReturnCode())) return output; throw new Error(await session.getOutput()); // Typical result: 60–80% smaller file, imperceptible quality loss };
Impact: 60–80% video file size reduction cut upload times and CDN costs proportionally — without visible quality loss at typical mobile viewing sizes.

Core Application Features

Social networking

  • User profiles and pet profiles
  • Friend connections and family crews
  • Content feed with posts and media
  • Comments, likes, and shares
  • Hashtag discovery
  • QR code pet profile sharing

Messaging

  • Direct 1-on-1 chat
  • Group chat with multiple users
  • Real-time message delivery
  • Media sharing (images and videos)
  • Read receipts and typing indicators

Events and activities

  • Create and discover local pet events
  • Map-based event discovery
  • RSVP and attendance tracking
  • Event notifications and reminders
  • Lost pet alerts

Content creation

  • Photo and video capture and upload
  • AI-powered breed detection
  • Content editing and filters
  • Draft management
  • Multilingual caption support

Complete Technology Stack

Core framework

React Native 0.76Expo 52TypeScript 5.3React 18.3

State & data

Redux ToolkitGraphQL 16Apollo ClientGraphQL CodegenAxiosAsyncStorage

UI & animation

React Native ReanimatedGesture HandlerRN UnistylesRN SVGFastImage

Navigation

Expo Router 4React NavigationTab ViewPager View

Media

Vision Camera 4FFmpeg KitExpo Image PickerRN VideoImage CompressorVideo Thumbnails

Platform services

Firebase AuthFirebase Messaging (FCM)Google Sign-InApple AuthenticationExpo LocationReact Native Maps

Internationalisation

LinguiJS 5Expo LocalizationIntl Polyfills

Testing & tooling

Storybook 8Jest 29React Testing LibraryESLintPrettierHusky

Results & Business Impact

MetricAchievementImpact
Component library50+ reusable cross-platform components↑ 40% dev velocity
Platform reachiOS, Android, and web — 1 codebase3× platform coverage
Compatibility40+ platform bugs resolvedProduction-ready quality
Video compressionFFmpeg H.264 pipeline60–80% size reduction
InternationalisationEnglish + Chinese, 1,000+ stringsInstant runtime switch
Real-time featuresGraphQL subscriptions over WebSocketZero polling overhead

Engineering Learnings

Architecture decisions compound early

Building from inception taught that choosing cross-platform development and a modular component architecture at day zero either accelerates or constrains every week that follows. Upfront investment pays multiplicatively.

Performance must be designed in, not added later

Virtualisation, lazy loading, and image caching are orders of magnitude harder to retrofit. Building them in from the start meant the app stayed smooth even as the feature set grew to 20+ screens.

Component libraries pay forward

Every hour invested in the component library in month one saved two hours in every month after. The 40% acceleration wasn't a one-time gain — it compounded with every feature shipped.

Test on all platforms, every time

Cross-platform development looks identical in code and catastrophic in practice. The 40+ resolved bugs were almost all invisible on the development platform and immediately visible on the other two.

State architecture shapes the product

Redux Toolkit's slice pattern and async thunks kept business logic outside components. Without normalised state, the relational data (users, pets, posts, chats) would have become a maintenance burden at scale.

Real-time requires careful teardown

GraphQL subscriptions with optimistic updates created the responsiveness users expect — but reliability came from treating reconnection, error states, and subscription cleanup as first-class concerns, not edge cases.