Starting from version 4.1, UI Kitten includes built-in support for web platforms using React Native Web . This allows you to run your mobile app in the browser with minimal configuration.
Web support is considered experimental and hasn’t been widely used in production. While functional, you may encounter edge cases. We encourage you to try it and report any issues.
Quick Start with Expo
The easiest way to start a new project with web support is using Expo.
Create New Project
Initialize a new Expo project: npx create-expo-app my-app
cd my-app
Run on Web
Start the web development server:
Expo handles all the React Native Web configuration automatically.
Existing Expo Applications
If you already have an Expo application, adding web support is straightforward.
Add Web Support
Expo projects created recently already include web support. If yours doesn’t, follow these steps:
Install Dependencies
Install React Native Web and related packages: npx expo install react-native-web react-dom @expo/webpack-config
For more details, read the Expo web documentation .
Regular React Native Applications
For bare React Native projects (created with react-native init), you’ll need to manually configure React Native Web.
Manual Configuration
Follow the React Native Web multi-platform guide for complete setup instructions.
Key Steps
Install Dependencies
npm install react-native-web react-dom
npm install --save-dev babel-plugin-react-native-web webpack webpack-cli webpack-dev-server
Configure Webpack
Create webpack.config.js in your project root: const path = require ( 'path' );
module . exports = {
entry: './index.web.js' ,
output: {
path: path . resolve ( __dirname , 'dist' ),
filename: 'bundle.js' ,
},
module: {
rules: [
{
test: / \. ( js | jsx | ts | tsx ) $ / ,
exclude: /node_modules/ ,
use: {
loader: 'babel-loader' ,
options: {
presets: [
'@babel/preset-react' ,
'@babel/preset-typescript' ,
],
plugins: [ 'react-native-web' ],
},
},
},
],
},
resolve: {
alias: {
'react-native$' : 'react-native-web' ,
},
extensions: [ '.web.js' , '.js' , '.web.ts' , '.ts' , '.web.tsx' , '.tsx' ],
},
devServer: {
static: {
directory: path . join ( __dirname , 'public' ),
},
compress: true ,
port: 3000 ,
},
};
Create Web Entry Point
Create index.web.js: import { AppRegistry } from 'react-native' ;
import App from './App' ;
import { name as appName } from './app.json' ;
AppRegistry . registerComponent ( appName , () => App );
AppRegistry . runApplication ( appName , {
rootTag: document . getElementById ( 'root' ),
});
Create HTML Template
Create public/index.html: <! DOCTYPE html >
< html >
< head >
< meta charset = "utf-8" />
< meta name = "viewport" content = "width=device-width, initial-scale=1" />
< title > My App </ title >
< style >
html , body , #root {
width : 100 % ;
height : 100 % ;
margin : 0 ;
padding : 0 ;
}
#root {
display : flex ;
flex-direction : column ;
}
</ style >
</ head >
< body >
< div id = "root" ></ div >
< script src = "../dist/bundle.js" ></ script >
</ body >
</ html >
Add NPM Scripts
Update package.json: {
"scripts" : {
"web" : "webpack serve --mode development" ,
"build:web" : "webpack --mode production"
}
}
UI Kitten Web Configuration
UI Kitten doesn’t require any special web-specific configuration. Once React Native Web is set up, UI Kitten components work out of the box.
import React from 'react' ;
import * as eva from '@eva-design/eva' ;
import { ApplicationProvider , Layout , Text , Button } from '@ui-kitten/components' ;
export default () => (
< ApplicationProvider { ... eva } theme = { eva . light } >
< Layout style = { { flex: 1 , justifyContent: 'center' , alignItems: 'center' } } >
< Text category = 'h1' > Hello Web! </ Text >
< Button > Click Me </ Button >
</ Layout >
</ ApplicationProvider >
) ;
Platform-Specific Code
Use React Native’s Platform module for platform-specific code:
import { Platform , StyleSheet } from 'react-native' ;
import { Layout , Text } from '@ui-kitten/components' ;
export const PlatformDemo = () => (
< Layout style = { styles . container } >
< Text > Running on: { Platform . OS } </ Text >
</ Layout >
);
const styles = StyleSheet . create ({
container: {
flex: 1 ,
padding: Platform . select ({
web: 32 ,
ios: 16 ,
android: 16 ,
}),
},
});
File Extensions
Create platform-specific files using extensions:
Component.web.tsx - Web only
Component.ios.tsx - iOS only
Component.android.tsx - Android only
Component.tsx - All platforms
React Native Web automatically picks the most specific file:
// Navigation.web.tsx - Web-specific navigation
import { BrowserRouter } from 'react-router-dom' ;
export const Navigation = () => (
< BrowserRouter >
{ /* Web navigation */ }
</ BrowserRouter >
);
// Navigation.tsx - Mobile navigation
import { NavigationContainer } from '@react-navigation/native' ;
export const Navigation = () => (
< NavigationContainer >
{ /* Mobile navigation */ }
</ NavigationContainer >
);
Web-Specific Considerations
Hover States
Web supports hover interactions that aren’t available on mobile:
import React , { useState } from 'react' ;
import { Button } from '@ui-kitten/components' ;
import { Platform } from 'react-native' ;
export const HoverButton = () => {
const [ hovered , setHovered ] = useState ( false );
const webProps = Platform . OS === 'web' ? {
onMouseEnter : () => setHovered ( true ),
onMouseLeave : () => setHovered ( false ),
} : {};
return (
< Button
{ ... webProps }
appearance = { hovered ? 'outline' : 'filled' }
>
Hover Me
</ Button >
);
};
Responsive Design
Use useWindowDimensions for responsive layouts:
import React from 'react' ;
import { useWindowDimensions } from 'react-native' ;
import { Layout , Card } from '@ui-kitten/components' ;
export const ResponsiveGrid = () => {
const { width } = useWindowDimensions ();
const columns = width > 1200 ? 3 : width > 768 ? 2 : 1 ;
return (
< Layout style = { { flexDirection: 'row' , flexWrap: 'wrap' } } >
{ items . map (( item ) => (
< Card
key = { item . id }
style = { { width: ` ${ 100 / columns } %` } }
>
{ /* Card content */ }
</ Card >
)) }
</ Layout >
);
};
SEO and Meta Tags
For web, add proper SEO tags using react-helmet or similar:
import React from 'react' ;
import { Helmet } from 'react-helmet' ;
import { Layout , Text } from '@ui-kitten/components' ;
export const HomePage = () => (
<>
< Helmet >
< title > My App - Home </ title >
< meta name = "description" content = "Welcome to my app" />
< meta property = "og:title" content = "My App" />
</ Helmet >
< Layout style = { { flex: 1 } } >
< Text category = 'h1' > Home </ Text >
</ Layout >
</>
);
Icons on Web
Eva Icons work seamlessly on web with react-native-svg-web:
import React from 'react' ;
import { Icon } from '@ui-kitten/components' ;
export const WebIcon = () => (
< Icon
name = 'star'
style = { { width: 32 , height: 32 } }
fill = '#FFD700'
/>
);
Building for Production
Expo
This creates an optimized production build in the web-build directory.
Bare React Native
Deploy the contents of the dist directory to your web host.
Performance Optimization
Use dynamic imports to split your bundle: const HeavyComponent = React . lazy (() => import ( './HeavyComponent' ));
< Suspense fallback = { < Spinner /> } >
< HeavyComponent />
</ Suspense >
Import only what you need from UI Kitten: // Good - tree shakeable
import { Button , Layout } from '@ui-kitten/components' ;
// Avoid - imports everything
import * as UIKitten from '@ui-kitten/components' ;
Use optimized image formats and lazy loading: import { Image } from 'react-native' ;
< Image
source = { { uri: 'image.webp' } }
style = { { width: 200 , height: 200 } }
loading = "lazy"
/>
Known Limitations
Animations : Some complex animations may not work identically on web
Native Modules : Platform-specific native modules won’t work on web
Navigation : React Navigation drawer may behave differently on web
Performance : Large lists may need web-specific optimizations
Troubleshooting
Ensure React Native Web is properly aliased in your webpack config
Check that all dependencies are web-compatible
Verify your entry point correctly registers the app
React Native Web doesn’t support all React Native styles
Test your components on web early in development
Use Platform.select() for platform-specific styles
Ensure react-native-svg is installed
Webpack may need configuration for SVG loading
Check that IconRegistry is properly configured
Next Steps
Branding Create custom themes that work across all platforms
Improving Performance Optimize your multi-platform app for production