This document outlines the plan to add a React frontend with TypeScript to the existing Kotlin Multiplatform project alongside the current Compose Web frontend, with easy build target switching.
TypeScript is a programming language developed by Microsoft that builds on JavaScript by adding static type definitions. It provides:
- Static typing - Catch errors at compile time, not runtime
- Better IDE support - Autocomplete, refactoring, navigation
- Compiles to JavaScript - Runs anywhere JavaScript runs
- Gradual adoption - Can mix with existing JavaScript code
JavaScript React:
function LoginForm({ onSubmit }) {
const [email, setEmail] = useState('');
return <input value={email} onChange={e => setEmail(e.target.value)} />;
}TypeScript React:
interface LoginFormProps {
onSubmit: (email: string) => void;
}
function LoginForm({ onSubmit }: LoginFormProps) {
const [email, setEmail] = useState<string>('');
return <input value={email} onChange={e => setEmail(e.target.value)} />;
}web/- Compose Web frontend (Kotlin/JS)app/- Ktor servershared/- Shared code between platformsdb/- Database layer
- Create
react-web/directory with standard React + TypeScript structure - Set up
package.jsonwith React, TypeScript, Vite, and build dependencies - Create basic React components (LoginForm, App) matching existing Compose Web functionality
- Add Vite configuration for development and production builds
Directory Structure:
react-web/
├── package.json
├── tsconfig.json
├── vite.config.ts
├── build.gradle.kts
├── src/
│ ├── components/
│ │ ├── LoginForm.tsx
│ │ └── App.tsx
│ ├── services/
│ │ └── ApiClient.ts
│ ├── types/
│ │ └── index.ts
│ ├── main.tsx
│ └── index.html
└── public/
- React 18 - UI library
- TypeScript - Type safety and better developer experience
- Vite - Fast build tool and dev server
- Axios/Fetch - HTTP client for API calls
- Create
react-web/build.gradle.ktsthat uses Node.js plugin - Configure Gradle tasks to run
npm installandnpm run build - Set up proper dependency relationships between modules
- Ensure React build outputs to correct location for Ktor static serving
- Add Gradle property
frontend.typeto control which frontend to build - Modify root build configuration to conditionally include frontend packages
- Create convenience Gradle tasks:
./gradlew buildWithReact- builds with React frontend./gradlew buildWithCompose- builds with Compose Web frontend./gradlew run -Pfrontend=react- runs server with React frontend./gradlew run -Pfrontend=compose- runs server with Compose frontend
- Modify Ktor configuration to serve static files from appropriate build output
- Ensure both frontends output to locations the server can find
- Update
settings.gradle.ktsto include newreact-webmodule - Configure routing to serve appropriate index.html based on frontend choice
- Port existing
ApiClient.ktfunctionality to TypeScript - Ensure both frontends can communicate with the same Ktor backend APIs
- Implement authentication flow and session management
- Create TypeScript types matching Kotlin data classes from shared module
Create React equivalents of existing Compose Web components:
- LoginForm - User authentication interface
- App - Main application container
- Navigation - Route handling
- Error handling - User feedback for API errors
- Compose Web Development:
./gradlew :web:browserDevelopmentRun - React Development:
./gradlew :react-web:npmStart(Vite dev server) - Production Build:
./gradlew build -Pfrontend=react|compose
- Add new build commands and frontend switching instructions to CLAUDE.md
- Document development workflow for both frontends
- Include TypeScript setup and configuration details
Advantages:
- Type Safety - Similar to Kotlin's type system you're already using
- IDE Support - Excellent tooling and refactoring capabilities
- Professional Standard - Widely adopted in industry
- Ecosystem - Massive library ecosystem and community
- Team Familiarity - Coming from Kotlin, TypeScript will feel natural
Integration Benefits:
- Both frontends can share the same API contracts
- Type safety across the full stack (Kotlin backend, TypeScript frontend)
- Easy switching between frontends for comparison and testing
- Maintain single Ktor backend regardless of frontend choice
- Shared Types - Consider generating TypeScript types from Kotlin data classes
- Testing - Add Jest/Vitest for React component testing
- Styling - Choose between CSS modules, styled-components, or Tailwind
- State Management - Add Redux/Zustand if application grows complex
- Bundle Analysis - Monitor bundle size and optimize as needed
When ready to implement:
- Create the react-web module structure
- Set up package.json and dependencies
- Create basic React components
- Configure Gradle integration
- Test build target switching
- Update server configuration
- Test full stack integration