A lightweight React Native mobile app that lets users capture and share one dual-photo post (back then front camera) per day during a randomized time of day for a notification saying "Time to BeReal", which indicates when a user has 2 minutes to submit their daily "BeReal" photo. Friends can view each other's posts, and manage friend connections.
- Authentication: Sign up/login with email using JWT-based auth
- Dual Camera Capture: Capture both front and back camera photos and stitch them together
- Daily Posts: One post per user per day with daily prompts
- Friends System: Search, request, accept/decline, remove friends
- Feed: Friends-only feed of posts for the day
- Profile Management: Update profile information and view your posts
- Notifications: Local push notifications for daily prompts
- Reactions: Like posts and report inappropriate content
[React Native App]
- Camera, Feed, Friends, Notifications
- JWT Auth
- Local image stitch
|
|
V
[Node.js Express Server (server.js)]
- Auth (JWT, bcrypt)
- API Routes (/auth, /users, /friends, /posts, /feed, /reactions, /reports)
- SQLite DB (users, friends, posts, reactions, reports, meta)
- File Storage (uploads/)
- Scheduler (daily prompt with node-cron)
|
|
V
[SQLite + File System]
- SQLite: user/friend/post metadata
- File system: stored post images
- Node.js 18 or newer (Node 16 works but 18+ is recommended for Expo tooling)
- npm (bundled with Node)
- Optional: Expo CLI (
npm install -g expo-cli) for extra commands - Optional: iOS Simulator (requires Xcode) or Android Studio/Emulators if you plan to test natively
The repository includes a helper script that installs dependencies, prepares the database, and runs either the automated test suite or the dev servers.
./run.shBy default this will perform a non-interactive CI-style run:
- install/update dependencies
- run
npm run setup - execute the full Jest test suite with coverage reporting
To launch the development servers instead, pass the dev flag:
./run.sh devThe first run may take a few minutes while npm install completes. The Expo CLI output will show a QR code if you want to connect an Expo Go client. This project currently targets Expo SDK 49, so you must use a matching Expo Go build (or run the Expo web build in your browser).
-
Install dependencies:
npm install
-
Set up environment variables (optional – defaults work out of the box):
cp env.example .env
Edit
.envfile with your configuration:JWT_SECRET=your-super-secret-jwt-key-here PORT=3000 DB_PATH=./database.sqlite UPLOAD_PATH=./uploads -
Initialize database:
npm run setup
-
Start the server:
npm start
The server will run on
http://localhost:3000 -
Start the Expo dev server (new terminal):
npm run expo:start
-
Run on device/simulator:
- Web (default): open the browser tab Expo launches or run
npm run expo:web - iOS simulator:
npm run expo:ios - Android emulator:
npm run expo:android
Note: Using a physical device with Expo Go requires the Expo Go build that matches SDK 49. Newer App Store/Play Store versions (e.g., SDK 54) will refuse to load this project.
- Web (default): open the browser tab Expo launches or run
POST /auth/register- Register new userPOST /auth/login- Login user
GET /users/profile- Get user profilePUT /users/profile- Update user profile
GET /friends- Get friends listGET /friends/requests- Get friend requestsPOST /friends/search- Search usersPOST /friends/request- Send friend requestPUT /friends/respond- Accept/decline friend requestDELETE /friends/:friend_id- Remove friend
POST /posts- Create new post (with image upload)GET /posts/my- Get user's posts
GET /feed- Get friends' posts for today
POST /reactions- Add reaction to postDELETE /reactions/:post_id- Remove reaction
POST /reports- Report a post
GET /meta/daily-prompt- Get daily promptPUT /meta/daily-prompt- Update daily prompt
id(INTEGER PRIMARY KEY)email(TEXT UNIQUE)phone(TEXT UNIQUE)username(TEXT UNIQUE)display_name(TEXT)avatar_url(TEXT)password_hash(TEXT)created_at(DATETIME)updated_at(DATETIME)
id(INTEGER PRIMARY KEY)user_id(INTEGER)friend_id(INTEGER)status(TEXT) - 'pending', 'accepted', 'declined'created_at(DATETIME)updated_at(DATETIME)
This project now ships with a Jest + Expo testing harness that exercises the major user flows (authentication, feed interactions, friends management, camera capture/upload, and profile updates) in a fully isolated environment.
- Run the suite once (collects coverage by default):
npm test -- --coverage - Watch mode for TDD:
npm run test:watch
- Turnkey CI run (installs deps, seeds DB, runs coverage):
./run.sh
Key pieces of the scaffolding:
jest.config.jsdisables Watchman (no macOS permissions needed), wires thejest-expopreset, and enables HTML/LCOV coverage reports.jest.setup.jswires up native mocks (expo-camera,expo-notifications, AsyncStorage, vector icons, etc.) and fetch polyfills so tests run without real native services.- Manual mocks in
__mocks__/provide predictable behavior for axios,expo-camera, and static assets.
If you introduce new native dependencies, add lightweight mocks in jest.setup.js or __mocks__/ to keep the environment hermetic. When debugging odd watcher behaviour, you can always append USE_WATCHMAN=0 to npm test, though it should no longer be necessary.
id(INTEGER PRIMARY KEY)user_id(INTEGER)front_image_url(TEXT)back_image_url(TEXT)stitched_image_url(TEXT)caption(TEXT)created_at(DATETIME)
id(INTEGER PRIMARY KEY)post_id(INTEGER)user_id(INTEGER)reaction_type(TEXT)created_at(DATETIME)
id(INTEGER PRIMARY KEY)post_id(INTEGER)reporter_id(INTEGER)reason(TEXT)created_at(DATETIME)
id(INTEGER PRIMARY KEY)key(TEXT UNIQUE)value(TEXT)created_at(DATETIME)updated_at(DATETIME)
-
Backend with auto-reload:
npm run dev
-
Frontend with Expo:
npm run expo:start
- Set up a production server (AWS, DigitalOcean, etc.)
- Install Node.js and dependencies
- Set up environment variables
- Initialize database
- Use PM2 or similar for process management
- Set up reverse proxy (nginx)
- Build the app for production:
expo build:android expo build:ios
- Deploy to app stores or distribute APK/IPA files
- JWT tokens are used for authentication
- Passwords are hashed with bcrypt
- Posts are only visible to friends
- Input validation on all endpoints
- File upload restrictions (size, type)
- App launch target: under 2 seconds
- Capture-to-post target: under 3 seconds
- Supports small groups (tens to hundreds of users)
- SQLite database for fast local queries
- Image stitching handled server-side
MIT License