Web Development/3 min read
Trendzy, a video-sharing app with React Native and Appwrite
How I built Trendzy, a React Native and Expo app for sharing short videos, with file-based routing, an Appwrite backend, NativeWind styling and a separate admin area.
Trendzy was my first real mobile app: a place to share short videos, find trending posts, save the ones you like and manage your profile. I built it with React Native and Expo, and used Appwrite as the backend so I could focus on the app instead of writing a server.
What it does
- Sign up and sign in, with the session kept between launches.
- A home feed with a horizontal trending row at the top.
- Video posts that play inline.
- Create: pick a video and a thumbnail from the phone and publish a post.
- Search, with its own results page.
- Bookmarks for posts you want to keep.
- A profile with your own posts and stats.
- An admin area for managing users and posts.
Expo Router and route groups
Expo Router gives React Native file-based routing, like Next.js. The folder structure is the navigation:
app/
├── (auth)/ sign-in, sign-up
├── (tabs)/ home, create, bookmark, profile
├── (admintabs)/ users, posts
├── search/[query].jsx
└── _layout.jsxThe folders in parentheses are route groups: they organise screens and give each group its own layout (the (tabs) group gets a tab bar) without adding anything to the URL. search/[query].jsx is a dynamic route, so searching for "music" opens /search/music.
The nice part is how cleanly this separates the three kinds of users: logged out, regular user and admin. Each one lives in its own group with its own layout.
Appwrite as the backend
Appwrite is an open-source backend-as-a-service. It gave me three things out of the box:
- Accounts: email sign-up, login and sessions.
- Databases: collections for users and posts.
- Storage: buckets for the uploaded videos and thumbnails.
Creating a post follows the usual Appwrite pattern: upload the video and the thumbnail to a storage bucket, then create a document in the posts collection that points to those files, with the title and the creator. The feed, trending row, search and profile are all queries on that one collection.
Global state and styling
A small GlobalProvider using React Context holds the logged-in user and the loading state, so any screen can check who's signed in. On launch, the app asks Appwrite for the current session and sends the user to the right group: auth, tabs or admin tabs.
For styling I used NativeWind, which brings Tailwind CSS class names to React Native. Coming from web development, being able to write className="flex-1 bg-primary px-4" instead of style objects made building screens much faster.
Video playback uses expo-av, and creating a post uses expo-image-picker and expo-document-picker to choose files from the device. The project is set up for EAS Build, Expo's cloud build service, to produce installable Android and iOS builds.
Looking back
- Watch operator precedence. The admin redirect checked
!user.Role === "admin", which is always false:!user.Roleturns into a boolean first, and a boolean is never equal to"admin". It should beuser.Role !== "admin". A one-character habit that's worth a linter rule. - Don't rely on the client for permissions. Hiding the admin screens in the app isn't security. The real checks belong in Appwrite's collection and bucket permissions.
- Keep editor files out of git. The repo still has a
.vsfolder that should be in.gitignore.
Trendzy taught me how much a good backend-as-a-service speeds things up, and how routing by folder makes a growing app easier to reason about.
Blog / Keep reading
Related articles.
Web Development/4 min read
CourseCraft, a course website from a folder of videos
A zero-dependency Node.js app that turns course folders into a website.
Decentralized Web/6 min read
Storing wallet credentials in Solid Pods
Moving verifiable credentials out of an e-wallet and into the user's Pod.