Skip to content
lemoncloud-ioPublic

About

A full-stack, cross-platform messaging & community app built with React, React Native, and Nx

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

4,713 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DoU Logo

DoU

A full-stack, cross-platform messaging & community app built with React, React Native, and Nx

React 19.2 React Native 0.83 TypeScript 5.9 Vite 7 Nx 22 Apache 2.0 License

Getting Started  ·  Architecture  ·  Contributing


Overview

DoU is an Nx monorepo powering a real-time messaging and community platform across 8 applications and 16 shared libraries — web, mobile, desktop, and admin interfaces from a single codebase.

App Description Stack
Web Main user-facing web app React 19 + Vite + Tailwind CSS
Admin V2 Admin dashboard React 19 + Vite + Tailwind CSS
Mobile iOS & Android native app — WebView shell around Web React Native 0.83 + WebView bridge
Landing Marketing site, policy pages & invite-link bounce page React 19 + Vite
Desktop Electron shell around Desktop Web Electron + electron-vite
Desktop Web Web client rendered inside the Desktop Electron shell React 19 + Vite + Tailwind CSS
Block Kit Builder Visual editor for @chatic/block-kit message blocks React 19 + Vite + Tailwind CSS
Testbed Experimental app for validating data/config/socket flows React 19 + Vite + Tailwind CSS
Table of Contents

Key Features

  • Real-time messaging via WebSocket with optimistic updates
  • Multi-provider auth — OAuth, Apple Sign-In, Google Sign-In
  • Push notifications — Firebase Cloud Messaging (iOS & Android)
  • In-App Purchases — iOS & Android subscription management
  • Places — Location-based community features
  • Deep linking — iOS Universal Links & Android App Links
  • Theming — Dark / light mode with system preference detection
  • i18n — Multi-language support with auto-detection
  • 29 UI components — Built on Radix UI primitives (shadcn/ui)

Tech Stack

Category Technology
Framework React 19.2, React Native 0.83
Language TypeScript 5.9 (strict mode)
Build Vite 7, Metro, Nx 22
Styling Tailwind CSS 3.4, Radix UI (shadcn/ui)
State Zustand 5, TanStack Query 5
Routing React Router 6, React Navigation 7
Forms React Hook Form 7
i18n i18next 25
Testing Vitest 4, Jest 30, Testing Library, Playwright
Code Quality ESLint 9, Prettier, Husky, Commitlint

Architecture

graph TB
    subgraph Apps
        WEB["apps/web<br/>React Web App<br/><i>:5003</i>"]
        ADMINV2["apps/admin-v2<br/>Admin Dashboard<br/><i>:5001</i>"]
        LANDING["apps/landing<br/>Landing Page<br/><i>:5004</i>"]
        DESKWEB["apps/desktop-web<br/>Desktop Web Client<br/><i>:5005</i>"]
        BKB["apps/block-kit-builder<br/>Block Kit Builder<br/><i>:5006</i>"]
        TESTBED["apps/testbed<br/>Experimental App"]
        MOBILE["apps/mobile<br/>React Native shell"]
        DESKTOP["apps/desktop<br/>Electron shell"]
    end

    subgraph Core["Core Libraries"]
        DATA["data<br/>Headless Data Layer"]
        HTTP["http<br/>Request Execution & Policy"]
        CONFIG["config<br/>Runtime Settings"]
        UIKIT["ui-kit<br/>29 Radix/shadcn Components"]
        SHARED["shared<br/>Utils & Hooks"]
        THEME["theme<br/>Dark / Light Mode"]
    end

    subgraph Native["Native Bridge Libraries"]
        RUNTIME["app-runtime<br/>Session & Runtime"]
        BRIDGES["bridges<br/>WebView Transport"]
        APPMSG["app-messages<br/>Bridge Message Vocabulary"]
        DEVICE["device-utils<br/>Injected Device Info"]
        DB["db<br/>Cache Storage Engines"]
        LOGGER["logger<br/>Cross-Platform Logging"]
        AUTHSIGN["auth-sign<br/>HMAC Request Signing"]
    end

    MOBILE --> BRIDGES & APPMSG
    DESKTOP --> DESKWEB
    WEB --> DATA & UIKIT & SHARED & THEME & CONFIG
    WEB --> RUNTIME & BRIDGES & DEVICE
    DESKWEB --> DATA & UIKIT & SHARED & THEME & RUNTIME
    ADMINV2 --> DATA & UIKIT & SHARED & THEME
    RUNTIME --> DATA & HTTP & AUTHSIGN
    DATA --> DB & HTTP
Loading

Project Structure

dou-app/
├── apps/
│   ├── web/                 # Main web application (port 5003)
│   ├── web-e2e/             # Playwright E2E of web inside a fake native shell
│   ├── shell-adapter/       # The app's side of the virtual mobile shell — `yarn local` (port 5007)
│   ├── admin-v2/            # Admin dashboard (port 5001)
│   ├── landing/             # Marketing site & policy pages (port 5004)
│   ├── desktop-web/         # Web client for the Desktop shell (port 5005)
│   ├── block-kit-builder/   # Block Kit visual editor (port 5006)
│   ├── testbed/             # Experimental app for data/config/socket flows
│   ├── mobile/              # React Native app (iOS + Android)
│   │   ├── android/
│   │   ├── ios/
│   │   └── src/
│   └── desktop/             # Electron shell (hosts desktop-web)
├── libs/
│   ├── data/                # Headless data layer (models, cache, repositories)
│   ├── db/                  # Cache storage engines (IndexedDB / native SQLite)
│   ├── http/                # Request execution, retry & logging policy
│   ├── config/              # Runtime settings facade
│   ├── app-runtime/         # Session, sockets, repositories, sync runtimes
│   ├── bridges/             # WebView transport between web and native shell
│   ├── app-messages/        # Bridge message vocabulary (web <-> native)
│   ├── fake-shell/          # Fake native shell core of web-e2e; its answers back the virtual shell's
│   ├── device-utils/        # Injected device info, reader hooks
│   ├── auth-sign/           # Lemon HMAC request signing
│   ├── logger/              # Cross-platform logging core
│   ├── policy-content/      # Legal text (terms, privacy, child safety)
│   ├── block-kit/           # Message block model consumed by block-kit-builder
│   ├── ui-kit/              # Generic UI components (shadcn/ui)
│   ├── web-ui-kit/          # Mobile-web design system components
│   ├── shared/              # Common utilities and hooks
│   └── theme/               # Theme provider (dark/light)
├── assets/                  # Shared images, logos, icons
├── scripts/                 # Build and deployment scripts
├── docs/                    # ADRs (docs/adr/) and infra config (docs/infra/)
└── .github/workflows/       # CI/CD pipelines

State Management Pattern

  • Server state — TanStack Query for caching, background refetching, and optimistic updates
  • Client state — Zustand stores for auth, theme, device info, and UI state
  • Local state — React useState / useReducer for component-scoped data

Mobile Architecture

The mobile app uses a WebView + Native Bridge pattern:

  1. React Native shell provides native capabilities (push notifications, IAP, contacts, camera)
  2. Web app runs inside a WebView
  3. A bridge layer enables bidirectional communication between native and web

Shared Library System

All apps share code through @chatic/* path aliases:

import { runtime } from '@chatic/app-runtime';
import { Button } from '@chatic/ui-kit';
import { config } from '@chatic/config';
import { ThemeProvider } from '@chatic/theme';

Before editing a lib, read its own README.md — each one documents what it owns and, where a decision's reasoning matters, links back to the ADR that made it (see docs/adr/).

Getting Started

Prerequisites

Tool Version Notes
Node.js v22.15.1 Use nvm use — .nvmrc is included
Yarn 1.x Classic Yarn
Xcode Latest For iOS development
Android Studio Latest For Android development
CocoaPods Latest For iOS dependencies
Ruby 3.2.9 For CocoaPods — .ruby-version is included

Installation

# Clone the repository
git clone https://github.com/lemoncloud-io/dou-app.git
cd dou-app

# Use the correct Node version
nvm use

# Install dependencies
yarn install

Environment Setup

Full checklist — which .env files, Firebase config, and (for release builds only) signing credentials a fresh checkout needs — lives in ONBOARDING.md.

Warning

Environment files (.env) must exist before building. The app will not start without them.

Development

# The app, locally — the web inside the virtual mobile shell, no simulator (apps/shell-adapter/README.md)
yarn local                    # http://localhost:5007/__shell/ · dev; --env prod (:5017), --mode web|native

# Web app
yarn web:start                # http://localhost:5003

# Admin dashboard
yarn admin-v2:start           # http://localhost:5001

# Landing page
yarn landing:start            # http://localhost:5004

# Desktop web client (served standalone, or hosted by the Desktop shell)
yarn desktop-web:start        # http://localhost:5005

# Block Kit Builder
yarn block-kit-builder:start  # http://localhost:5006

# Testbed (experimental app)
yarn testbed:start

# Desktop — Electron shell + its web client, in one command
yarn desktop:start            # deployed desktop-web build
yarn desktop:start:local      # local desktop-web dev server

# Mobile — Local run: web dev server + Metro + the app, in one command
yarn mobile:ios:local         # iOS Simulator, WebView -> http://localhost:5003
yarn mobile:android:local     # Android Emulator, same address via `adb reverse`

# Mobile — Start Metro bundler only
yarn mobile:start

# Mobile — Run against the deployed web (dev/prod)
yarn mobile:ios:dev           # iOS Simulator
yarn mobile:android:dev       # Android Emulator

# Mobile — A feature's device scenario in one command (opt-in; see apps/mobile/docs/release/device-verify.md)
yarn mobile:verify home/open-room --platform ios

Note

mobile:*:local needs apps/mobile/.env (the LOCAL env — same meaning as in web). Copy it once with cp apps/mobile/.env.example apps/mobile/.env. See apps/mobile/docs/release/local-run.md.

Tip

Run npx nx graph to visualize the dependency graph of all apps and libraries.

Building & Deployment

Build

# Build individual apps
yarn web:build:dev              # Development build
yarn web:build:prod             # Production build
yarn admin-v2:build:dev
yarn admin-v2:build:prod
yarn landing:build:dev
yarn landing:build:prod
yarn desktop-web:build:dev
yarn desktop-web:build:prod
yarn block-kit-builder:build:dev
yarn block-kit-builder:build:prod
yarn desktop:build               # Electron shell

# Build all apps at once
yarn build:all:dev
yarn build:all:prod

Deploy

Deployment uses AWS S3 + CloudFront. Required environment variables:

Variable Description
DEPLOY_BUCKET_NAME S3 bucket name
DEPLOY_DEV_CF_DISTRIBUTION_ID CloudFront distribution ID (dev)
DEPLOY_PROD_CF_DISTRIBUTION_ID CloudFront distribution ID (prod)
yarn web:deploy:dev              # Deploy web to dev
yarn web:deploy:prod             # Deploy web to prod
yarn admin-v2:deploy:dev
yarn admin-v2:deploy:prod
yarn landing:deploy:dev
yarn landing:deploy:prod
yarn desktop-web:deploy:dev
yarn desktop-web:deploy:prod
yarn block-kit-builder:deploy:dev
yarn block-kit-builder:deploy:prod

# Desktop is packaged, not deployed to S3/CloudFront
yarn desktop:package:mac:dev
yarn desktop:package:mac:prod:signed
yarn desktop:package:win:dev
yarn desktop:package:win:prod

Important

desktop-web only deploys automatically on push to develop/main — force-deploy.yml (manual redeploy/rollback) covers Web, Admin V2 and Landing only. The Desktop Electron shell loads desktop-web from a remote URL at runtime, so a desktop-web deploy reaches every running Desktop user immediately, and the only way back is a revert commit pushed through the same pipeline.

Mobile Development

iOS Commands
Command Description
yarn mobile:pod Install CocoaPods dependencies
yarn mobile:ios:local Local run against the web dev server
yarn mobile:ios:dev Run dev build on iPhone Simulator
yarn mobile:ios:prod Run prod build on iPhone Simulator
yarn mobile:ios:dev:device Run dev build on physical device
yarn mobile:ios:dev:release Release dev build on Simulator
yarn mobile:ios:dev:release:device Release dev build on device
yarn mobile:ios:prod:release Release prod build on Simulator
yarn mobile:ios:prod:release:device Release prod build on device
yarn mobile:ios:clean Clean iOS build artifacts
Android Commands
Command Description
yarn mobile:android:local Local run against the web dev server
yarn mobile:android:dev Run dev build on emulator
yarn mobile:android:prod Run prod build on emulator
yarn mobile:android:build:apk:dev Build dev APK
yarn mobile:android:build:apk:prod Build prod APK
yarn mobile:android:build:aab:dev Build dev AAB (Play Store)
yarn mobile:android:build:aab:prod Build prod AAB (Play Store)
yarn mobile:android:install:dev Install dev APK via ADB
yarn mobile:android:install:prod Install prod APK via ADB
yarn mobile:android:clean Clean Android build artifacts

Mobile Platform Support

Platform Min Version Target
Android SDK 24 (Android 7.0) SDK 36 (Android 15)
iOS See Xcode project Latest

Environment Variables

Web (apps/web/.env)
Variable Description
VITE_ENV Environment (LOCAL, DEV, PROD)
VITE_PROJECT Project identifier
VITE_HOST App host URL
VITE_OAUTH_ENDPOINT OAuth API endpoint
VITE_SOCIAL_OAUTH_ENDPOINT Social OAuth endpoint
VITE_IMAGE_API_ENDPOINT Image API endpoint
VITE_BACKEND_ENDPOINT Backend API endpoint
VITE_WS_ENDPOINT WebSocket endpoint
VITE_DOU_ENDPOINT DoU API endpoint
VITE_ARCHIVE_ENDPOINT Log archive endpoint (optional)
VITE_SOC_ENDPOINT Social API endpoint
Admin V2 (apps/admin-v2/.env)
Variable Description
VITE_ENV Environment (LOCAL, DEV, PROD)
VITE_PROJECT Project identifier
VITE_HOST App host URL
VITE_OAUTH_ENDPOINT OAuth API endpoint
VITE_SOCIAL_OAUTH_ENDPOINT Social OAuth endpoint
VITE_IMAGE_API_ENDPOINT Image API endpoint
VITE_BACKEND_ENDPOINT Backend API endpoint
VITE_WS_ENDPOINT WebSocket endpoint
VITE_DOU_ENDPOINT DoU API endpoint
VITE_ARCHIVE_ENDPOINT Log archive endpoint (optional)
VITE_FRONT_ENDPOINT Frontend URL for cross-linking
VITE_FIREBASE_* Firebase web config (7 keys)
Desktop Web / Testbed / Block Kit Builder

Same shape as Web's VITE_* variables (apps/desktop-web/.env, apps/testbed/.env, apps/block-kit-builder/.env — each has its own .env.example). desktop-web additionally reads VITE_SOC_ENDPOINT, VITE_IAP_ENDPOINT and VITE_DEBUG_CODE; testbed mirrors Admin V2's VITE_FRONT_ENDPOINT for cross-linking.

Mobile (apps/mobile/.env)

.env is the LOCAL env, .env.dev / .env.prod are the built ones — the same split web uses. Which file a build reads is decided by the build configuration (iOS ENVFILE build setting, Android envConfigFiles), not by the script. See apps/mobile/docs/release/local-run.md.

Variable Description
VITE_ENV Environment (LOCAL, DEV, PROD)
VITE_WEBVIEW_BASE_URL WebView base URL
VITE_WS_ENDPOINT Unused — no code reads it
VITE_SUBSCRIPTION_IAP_SKUS_IOS iOS IAP product SKUs
VITE_SUBSCRIPTION_IAP_SKUS_ANDROID Android IAP product SKUs
VITE_SUBSCRIPTION_IAP_PLANS_ANDROID Android IAP plan IDs
VIEW_APP_NAME Display app name
VITE_GOOGLE_WEB_CLIENT_ID Google OAuth web client ID
ANDROID_KEYSTORE_FILE Android keystore file path
ANDROID_KEYSTORE_PASSWORD Android keystore password
ANDROID_KEY_ALIAS Android key alias
ANDROID_KEY_PASSWORD Android key password

CI/CD

Workflow Trigger Description
verify.yml Pull requests, push to develop Doc links, doc language, code comment language, lint, typecheck & test — only the projects listed as covered; excluded projects are named at the bottom of the file with the reason
deploy-dev.yml Push to develop Auto-detect changed apps, build & deploy to dev
deploy-prod.yml Push to main Build, deploy to prod & create a GitHub release
force-deploy.yml Manual dispatch Force (re)deploy Web / Admin V2 / Landing to dev or prod — no other app
build-desktop.yml Manual dispatch Build unsigned macOS .dmg + Windows .exe installers, publish to a rolling desktop-dev / desktop-prod GitHub Release
build-desktop-win.yml Manual dispatch Windows-only variant of the above

deploy-dev/deploy-prod auto-detect which apps changed and only build/deploy the affected ones — this is the only path that ships desktop-web (see the note in Building & Deployment). verify.yml was added later than the rest; before it, nothing in CI ran a type check or a test. Its second job, e2e, runs the web app in a real browser inside a fake native shell (apps/web-e2e) when web-e2e is affected.

Code Quality

# Lint
yarn lint                   # Check for issues
yarn lint:fix               # Auto-fix issues
yarn check:undefined-names  # Fail on TS2304 — a name used but never imported; run after moving symbols
yarn check:doc-links        # Fail on a dead markdown link, or an ADR link whose label and target disagree
yarn check:doc-korean       # Fail on untranslated Korean prose in a markdown file (AGENTS.md's English policy)
yarn check:code-korean      # Fail on untranslated Korean prose in a source code comment (same policy)

# Format
yarn prettier               # Format all files
yarn prettier:staged        # Format staged files only

# Test
npx nx test web             # Test specific project
npx nx test                 # Run all tests
yarn web:e2e                # Web in a real browser, inside a fake native shell (apps/web-e2e/README.md)
yarn web:e2e:ui             # The same, in Playwright's UI mode (yarn web:e2e:install once first)
yarn desktop:test:sandbox   # Electron preload under sandbox — run when touching apps/desktop/src/preload

# Cache
yarn clean:cache            # Clear Vite/Nx caches

Pre-commit hooks (via Husky) automatically run linting and formatting on staged files. Commit messages are enforced with Conventional Commits via Commitlint.

yarn check:undefined-names is deliberately outside those hooks — it type-checks every buildable project (an app or lib with a tsconfig.app.json/tsconfig.lib.json, 23 today) and takes about 20 seconds, which is too slow per commit. Run it yourself after any change that moves or extracts a symbol. It catches what nothing else here can: ESLint disables no-undef on TypeScript files, Vite strips types without resolving free identifiers, and a test only sees the error if something renders that line. Pass a project name to narrow it (yarn check:undefined-names desktop-web).

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes using Conventional Commits (git commit -m 'feat: add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the Apache License 2.0. See the LICENSE file for details.

About

A full-stack, cross-platform messaging & community app built with React, React Native, and Nx

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages