Joe Gilmore

5 min read

Creating a Typescript, Tailwind and Expo Go App in 2 Minutes (Updated for 2025)

Updated for 2025 — build a fully configured Expo Go + Tailwind + NativeWind + TypeScript app in under 2 minutes using a single command.

Creating a Typescript, Tailwind and Expo Go App in 2 Minutes (Updated for 2025)

🚀 Creating a Typescript, Tailwind & Expo Go App in 2 Minutes (Updated for 2025)

This is the 2025 update of my long-running “fast Expo Go starter” article.

You can still read the previous versions here:

This updated guide uses:

  • Expo SDK 2025
  • TailwindCSS 3.4+
  • NativeWind v4+
  • Metro bundler (required for web + NativeWind)
  • Fully cross-platform JSON editing (no macOS-only sed)
  • One clean, modern Bash script

💡 Why Expo Go?

Expo Go remains the fastest way to:

  • Start a React Native project
  • Test instantly on real devices
  • Avoid native build complications
  • Use modern UI tooling like Tailwind & NativeWind seamlessly

This guide gets you from an empty folder → fully configured app in ~2 minutes.


🧙‍♂️ The 2025 One-Liner (macOS + Linux + WSL)

✔️ Fully cross-platform
✔️ Safe JSON editing
✔️ Modern NativeWind setup
✔️ Creates a working Tailwind UI screen automatically

APP_NAME="my-awesome-app"

# Create folder & project
mkdir $APP_NAME && cd $APP_NAME \
&& npx create-expo-app . --template blank --no-install \

# Install dependencies
&& npx expo install react-dom react-native-web @expo/metro-runtime react-native-screens react-native-safe-area-context react-native-reanimated \
&& yarn add @react-navigation/native @react-navigation/native-stack \
&& yarn add nativewind \
&& yarn add -D tailwindcss prettier prettier-plugin-tailwindcss \

# Convert to TS
&& yarn add -D typescript @types/react @types/react-native \
&& echo '{ "extends": "expo/tsconfig.base", "compilerOptions": {} }' > tsconfig.json \

# Tailwind init
&& npx tailwindcss init \

# Write Tailwind config (modern NativeWind preset)
&& node -e "const fs=require('fs'); fs.writeFileSync('tailwind.config.js', `
module.exports = {
  content: [
    './App.{js,jsx,ts,tsx}',
    './src/**/*.{js,jsx,ts,tsx}'
  ],
  presets: [require('nativewind/preset')],
};
`);" \

# Create global.css
&& echo '@tailwind base;\n@tailwind components;\n@tailwind utilities;' > global.css \

# Create metro.config.js for NativeWind
&& node -e "const fs=require('fs'); fs.writeFileSync('metro.config.js', `
const { getDefaultConfig } = require('expo/metro-config');
const { withNativeWind } = require('nativewind/metro');

const config = getDefaultConfig(__dirname);
module.exports = withNativeWind(config, { input: './global.css' });
`);" \

# Update app.json to include web bundler & new app name
&& node -e "const fs=require('fs'); const f='app.json'; const j=JSON.parse(fs.readFileSync(f)); j.expo=j.expo||{}; j.expo.name='$APP_NAME'; j.expo.slug='$APP_NAME'; j.expo.web={bundler:'metro'}; fs.writeFileSync(f, JSON.stringify(j,null,2));" \

# Add NativeWind types
&& echo '/// <reference types="nativewind/types" />' > my-app.d.ts \

# Replace App.js with App.tsx using Tailwind + Navigation
&& rm App.js \
&& cat > App.tsx << 'EOL'
import React from "react";
import { View, Text } from "react-native";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { StatusBar } from "expo-status-bar";

function HomeScreen() {
  return (
    <View className="flex-1 items-center justify-center bg-white">
      <View className="bg-cyan-100 py-2 px-7 rounded-xl border border-cyan-300">
        <Text className="text-cyan-700 text-lg font-semibold">
          I am a Tailwind Expo Go app!
        </Text>
      </View>
      <StatusBar style="auto" />
    </View>
  );
}

const Stack = createNativeStackNavigator();

export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="home" component={HomeScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}
EOL

# Open VS Code and run
&& code . --add \
&& npx expo start