Set up your social network app's foundation by cleaning the structure, integrating NativeWind, and handling safe area boundaries.
In Part 1, we set the stage for our journey into building a social network app, discussing what lies ahead and the tools we’ll use. Now it’s time to roll up our sleeves and get to work. In this chapter, we’ll focus on setting up the foundation for our project. By the end of this section, you’ll have an Expo repository ready to go, equipped with TypeScript and NativeWind (Tailwind CSS for React Native), and a clean structure prepared for our app’s screens.
Let’s dive in!
Part 1 completed repo on GitHub for reference
To begin, navigate to the directory where you want to create your repository. Open your terminal and run the following command:
npx create-expo-app@latest
Follow the prompts to configure your project. Once the setup is complete, navigate into the newly created repository:
cd <your-repo-name>
Open the project in your IDE of choice, such as Visual Studio Code.
We want to start with a clean slate, so let’s tidy up the default files and folders created by Expo.
components
, constants
, and hooks
folders.scripts
folder located at the root of your project (which contains reset-project.js
).app
Folderapp
folder, remove screens you won’t be using.After this cleanup, your project structure should look like this:
.gitignore
app
└─ (tabs)
├─ index.tsx
└─ _layout.tsx
└─ _layout.tsx
app.json
assets
├─ fonts
│ └─ SpaceMono-Regular.ttf
└─ images
├─ adaptive-icon.png
├─ icon.png
└─ splash-icon.png
components
constants
hooks
package-lock.json
package.json
README.md
tsconfig.json
This streamlined setup ensures we stay focused and keep our project organized as we build out the app.
Here are the cleaned-up contents of the key files:
app/_layout.tsx
import { useFonts } from "expo-font";
import { Stack } from "expo-router";
import * as SplashScreen from "expo-splash-screen";
import { StatusBar } from "expo-status-bar";
import { useEffect } from "react";
import { View } from "react-native";
import "react-native-reanimated";
// Prevent the splash screen from auto-hiding before asset loading is complete.
SplashScreen.preventAutoHideAsync();
export default function RootLayout() {
const [loaded] = useFonts({
SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"),
});
useEffect(() => {
if (loaded) {
SplashScreen.hideAsync();
}
}, [loaded]);
if (!loaded) {
return null;
}
return (
<View>
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
</Stack>
<StatusBar style="auto" />
</View>
);
}
app/(tabs)/_layout.tsx
import { Tabs } from "expo-router";
import React from "react";
export default function TabLayout() {
return (
<Tabs
screenOptions={{
headerShown: false,
}}
>
<Tabs.Screen name="index" />
</Tabs>
);
}
app/(tabs)/index.tsx
import { View } from "react-native";
export default function HomeScreen() {
return <View></View>;
}
This streamlined setup ensures we stay focused and keep our project organized as we build out the app.
NativeWind is a library that brings the simplicity and power of Tailwind CSS to React Native. Tailwind CSS is a utility-first CSS framework that allows you to rapidly build modern and responsive designs by applying pre-defined utility classes directly to your components. NativeWind adapts this for React Native, enabling you to style your app with ease and consistency.
tailwind.config.js
includes the components
folder in addition to the app
folder
/** @type {import('tailwindcss').Config} */
module.exports = {
// NOTE: Update this to include the paths to all of your component files.
content: ["./app/**/*.{js,jsx,ts,tsx}", "./components/**/*.{js,jsx,ts,tsx}"],
presets: [require("nativewind/preset")],
theme: {
extend: {},
},
plugins: [],
};
package.json
), create a file named globals.css
. Copy the content from the NativeWind guide into this file. Then, import it at the top of app/_layout.tsx
:import "../globals.css";
babel.config.js
file (as Expo hides it by default), generate one by running:npx expo customize
babel.config.js
option using the space bar and hit Enter. Once generated, copy the content from the NativeWind guide into this file.metro.config.js
file, generate it using the same steps. Copy the content from the NativeWind guide into this file as well.
{
"expo": {
// other configurations here
}
}
nativewind-env.d.ts
at the root of your project with the following content (This step is required for proper type support in our TypeScript-based app):/// <reference types="nativewind/types" />
Before running your app, ensure you’ve updated the screen files to the following:
app/_layout.tsx
<View className="flex-1">
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
</Stack>
<StatusBar style="auto" />
</View
app/(tabs)/index.tsx
<View className="bg-red-500 flex-1">
<Text>Hello World</Text>
</View>
Once these steps are complete, start your app with the following command:
npx expo start
You should now see an ugly red screen with a Hello World
text in the top left corner (it will be behind the status bar as it’s outside the safe area), and a tab navigation bar at the bottom with a single tab. At this point, we’re almost done!
Lastly, we will incorporate the SafeAreaProvider
and SafeAreaView
components into our app, which are part of the react-native-safe-area-context
library. These components help ensure that your content is displayed within the safe area boundaries of a device, avoiding overlaps with the status bar, notch, or other UI elements.
For simplicity, in this tutorial, we’ll wrap the entire app with SafeAreaView
. Here's how to integrate it:
SafeAreaProvider
and SafeAreaView
into app/_layout.tsx
:import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context";
app/_layout.tsx
file to wrap your app as follows:<SafeAreaProvider>
<SafeAreaView className="flex-1">
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
</Stack>
</SafeAreaView>
<StatusBar style="auto" />
</SafeAreaProvider>
By wrapping the app with SafeAreaProvider
and SafeAreaView
, we ensure all screens respect the safe area. While it’s possible to use SafeAreaView
selectively for specific screens, we are keeping it simple by applying it globally in this tutorial.
Once you’ve made these updates, update your app or simply re-run it using:
npx expo start
You should now see the red screen with a Hello World
message, properly contained within the safe area and a tab navigation bar at the bottom.
With this setup complete, your app is now ready to be built! We’ve laid the foundation by setting up the project structure, integrating NativeWind, and ensuring our app respects the device’s safe area boundaries.
In the next part of this tutorial, we’ll focus on authenticating users. Stay tuned, as this is where your social network starts coming to life!
Don’t forget to join the Discord server where I post free boilerplate code repos for different types of social networks. Updates about the next article and additional resources will also be shared there. Lastly, follow me for updates here and on X/Twitter & BlueSky.
Powerful, self-serve product and growth analytics to help you convert, engage.
Dive into the heart of innovation with our 'Coding Chronicles' blog section. Explore a rich tapestry of articles, tutorials, and insights that unravel.