UNPKG

quickstart-react-native

Version:

quickstart-react-native is a starter template designed to help developers set up and launch React Native projects faster. It comes pre-configured with essential dependencies, folder structure, and best practices, so you can focus on building features inst

313 lines (266 loc) 7.42 kB
#!/usr/bin/env node import inquirer from "inquirer"; import chalk from "chalk"; import { execa } from "execa"; import fs from "fs"; import path from "path"; async function run() { console.log(chalk.green("🚀 Welcome to Quickstart React Native ⚛️")); // Step 1: Ask project name const { projectName } = await inquirer.prompt([ { type: "input", name: "projectName", message: "Enter project name:", default: "MyApp", }, ]); // Step 2: Initialize RN app console.log(chalk.blue("📦 Creating React Native project...")); await execa( "npx", ["@react-native-community/cli@latest", "init", projectName], { stdio: "inherit", } ); // Move into project process.chdir(projectName); // Step 3: Install essential packages console.log(chalk.blue("🔗 Installing essential packages...")); await execa( "npm", [ "install", "axios", "@react-navigation/native", "@react-navigation/native-stack", "@react-navigation/bottom-tabs", "react-native-screens", "react-native-safe-area-context", ], { stdio: "inherit" } ); // Step 4: Ask for optional Paper const { withPaper } = await inquirer.prompt([ { type: "confirm", name: "withPaper", message: "Do you want to install react-native-paper?", default: false, }, ]); if (withPaper) { console.log(chalk.blue("🎨 Installing react-native-paper...")); await execa( "npm", [ "install", "react-native-paper", "@react-native-vector-icons/material-design-icons", ], { stdio: "inherit" } ); } // Step 5: Create folder structure console.log(chalk.blue("📂 Setting up folder structure...")); const folders = [ "src/api", "src/assets", "src/navigation", "src/screens", "src/components", "src/theme", "src/utils", ]; folders.forEach((dir) => fs.mkdirSync(dir, { recursive: true })); // Utility to write files const writeFile = (filePath, content) => { fs.writeFileSync(path.join(process.cwd(), filePath), content, "utf8"); }; // Write boilerplate files writeFile( "src/api/axiosConfig.js", ` import axios from "axios"; const axiosInstance = axios.create({ baseURL: "https://api.example.com", // change later timeout: 5000, }); export default axiosInstance; ` ); writeFile( "src/navigation/RootNavigator.js", ` import React from "react"; import { NavigationContainer } from "@react-navigation/native"; import AppNavigator from "./AppNavigator"; export default function RootNavigator() { return ( <NavigationContainer> <AppNavigator /> </NavigationContainer> ); } ` ); writeFile( "src/navigation/AppNavigator.js", ` import React from "react"; import { createBottomTabNavigator } from "@react-navigation/bottom-tabs"; import { createNativeStackNavigator } from "@react-navigation/native-stack"; import HomeScreen from "../screens/HomeScreen"; import DetailsScreen from "../screens/DetailsScreen"; const Tab = createBottomTabNavigator(); const Stack = createNativeStackNavigator(); function HomeStack() { return ( <Stack.Navigator> <Stack.Screen name="Home" component={HomeScreen}/> <Stack.Screen name="Details" component={DetailsScreen} /> </Stack.Navigator> ); } export default function AppNavigator() { return ( <Tab.Navigator screenOptions={{ headerShown: false }}> <Tab.Screen name="HomeTab" component={HomeStack} options={{ title: "Home" }} /> </Tab.Navigator> ); } ` ); writeFile( "src/screens/HomeScreen.js", ` import React from "react"; import { View, Text, Button } from "react-native"; export default function HomeScreen({ navigation }) { return ( <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}> <Text>🏠 Home Screen</Text> <Button title="Go to Details" onPress={() => navigation.navigate("Details")} /> </View> ); } ` ); writeFile( "src/screens/DetailsScreen.js", ` import React from "react"; import { View, Text } from "react-native"; export default function DetailsScreen() { return ( <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}> <Text>📄 Details Screen</Text> </View> ); } ` ); if (withPaper) { writeFile( "src/theme/theme.js", ` import { MD3LightTheme as DefaultTheme } from "react-native-paper"; const theme = { ...DefaultTheme, colors: { ...DefaultTheme.colors, primary: "#6200ee", secondary: "#03dac6", }, }; export default theme; ` ); writeFile( "babel.config.js", `module.exports = { presets: ['module:metro-react-native-babel-preset'], env: { production: { plugins: ['react-native-paper/babel'], }, }, }; ` ); } writeFile( "App.js", ` import React from "react"; import RootNavigator from "./src/navigation/RootNavigator"; ${ withPaper ? `import { Provider as PaperProvider } from "react-native-paper"; import theme from "./src/theme/theme";` : "" } let AppWrapper = ({ children }) => children; ${ withPaper ? `AppWrapper = ({ children }) => <PaperProvider theme={theme}>{children}</PaperProvider>;` : "" } export default function App() { return ( <AppWrapper> <RootNavigator /> </AppWrapper> ); } ` ); // Step 6: Patch MainActivity.kt patchMainActivity(projectName); console.log( chalk.green( `✅ Setup complete! Run:\n\ncd ${projectName}\nnpm run android\n` ) ); } // --- PATCH MAINACTIVITY.KT --- function patchMainActivity(appName = "") { const mainActivityPath = path.join( process.cwd(), "android/app/src/main/java/com/", appName.toLowerCase(), "MainActivity.kt" ); if (!fs.existsSync(mainActivityPath)) { console.log("⚠️ MainActivity.kt not found, skipping patch."); return; } let finalContent = ` package com.${appName.toLowerCase()} import android.os.Bundle; import com.facebook.react.ReactActivity import com.facebook.react.ReactActivityDelegate import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled import com.facebook.react.defaults.DefaultReactActivityDelegate class MainActivity : ReactActivity() { /** * Returns the name of the main component registered from JavaScript. This is used to schedule * rendering of the component. */ override fun getMainComponentName(): String = "${appName}" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(null) } /** * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] */ override fun createReactActivityDelegate(): ReactActivityDelegate = DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) } `; fs.writeFileSync(mainActivityPath, finalContent, "utf8"); console.log("✅ Patched MainActivity.kt successfully!"); } run();