Skip to content

Repository files navigation

SamePage - Relationship Needs Tracker

A web application that helps people communicate expectations and track relationship health through transparent, mutual rating systems.

Features

  • Magic Link Authentication - Password-free sign in via email
  • Relationship Creation - Define what matters to you with customizable aspects
  • Mutual Ratings - Rate each other privately until both submit
  • Table Stakes - Mark must-have aspects with minimum requirements
  • Transparent Communication - Share expectations clearly
  • Privacy-Focused - No PII storage, email hashing, anonymous nicknames

Tech Stack

Backend

  • Node.js + Express + TypeScript
  • PostgreSQL database
  • JWT authentication
  • Magic link email flow

Frontend

  • React 18 + TypeScript
  • Tailwind CSS for styling
  • React Router for navigation
  • Axios for API calls
  • Recharts for data visualization

Deployment

  • Monorepo - Single deployment for both frontend and backend
  • Backend serves frontend static files in production
  • Railway for hosting (backend + frontend + database)

Getting Started

Prerequisites

  • Node.js 18+
  • PostgreSQL 14+
  • npm

Installation

  1. Clone the repository
git clone <your-repo-url>
cd samepage-app
  1. Install dependencies
# Install backend dependencies
cd backend
npm install

# Install frontend dependencies
cd ../frontend
npm install
  1. Set up environment variables

Backend (.env in backend folder):

cp backend/.env.example backend/.env
# Edit backend/.env with your configuration

Key environment variables:

  • DATABASE_URL - PostgreSQL connection string
  • JWT_SECRET - Secret key for JWT tokens (generate with: openssl rand -base64 32)
  • EMAIL_HASH_SALT - Salt for email hashing (generate with: openssl rand -base64 32)
  • EMAIL_API_KEY - Email service API key (optional for dev)
  • NODE_ENV - Set to production for Railway deployment
  1. Set up the database
# Create database
createdb samepage

# Run migrations
cd backend
psql -d samepage -f migrations/001_initial_schema.sql
psql -d samepage -f migrations/002_seed_data.sql

Development

Run backend and frontend in separate terminals:

# Terminal 1 - Backend
cd backend
npm run dev
# Runs on http://localhost:3000

# Terminal 2 - Frontend
cd frontend
npm run dev
# Runs on http://localhost:5173 (with proxy to backend)

The app will be available at:

Deployment (Monorepo on Railway)

This app uses a monorepo architecture - one Railway service deploys both frontend and backend together.

How It Works

  1. Build Phase: Railway builds both backend TypeScript and frontend React app
  2. Runtime: Backend Express server serves:
    • API endpoints at /api/*
    • Frontend static files at all other routes
  3. One URL: Everything runs on a single domain (e.g., https://thesamepage.up.railway.app)

Deploy to Railway

1. Create Railway Project

  • Go to Railway
  • Click "New Project"
  • Select "Deploy from GitHub repo"
  • Connect your repository
  • Set Root Directory to / (root of repo)

2. Add PostgreSQL Database

  • Click "New" → "Database" → "PostgreSQL"
  • Railway automatically provisions database and sets DATABASE_URL

3. Configure Environment Variables

Add these in Railway → Variables:

DATABASE_URL=${DATABASE_URL}  # Auto-populated by Railway
JWT_SECRET=<generate-with-openssl-rand-base64-32>
EMAIL_HASH_SALT=<generate-with-openssl-rand-base64-32>
NODE_ENV=production
# Optional (for email in production):
EMAIL_API_KEY=your-email-service-api-key
EMAIL_FROM=noreply@yourdomain.com

4. Run Database Migrations

In Railway's terminal or locally:

railway run psql $DATABASE_URL -f backend/migrations/001_initial_schema.sql
railway run psql $DATABASE_URL -f backend/migrations/002_seed_data.sql

5. Generate Domain

  • Railway → Service → Settings → Networking
  • Click "Generate Domain"
  • You'll get: https://your-app.up.railway.app

6. Deploy

  • Push to GitHub main branch
  • Railway automatically builds and deploys
  • Wait 2-3 minutes for build to complete
  • Visit your Railway URL to see the app!

Deployment Configuration

The project includes:

  • railway.json - Builds both backend and frontend, starts with NODE_ENV=production
  • backend/src/index.ts - Serves frontend static files when NODE_ENV=production
  • frontend/.env - Uses relative /api URLs (works in both dev and production)

Project Structure

samepage-app/
├── backend/
│   ├── src/
│   │   ├── config/         # Database config
│   │   ├── controllers/    # Route handlers
│   │   ├── middleware/     # Auth middleware
│   │   ├── routes/         # API routes
│   │   ├── services/       # Business logic
│   │   ├── utils/          # Helper functions
│   │   └── index.ts        # Entry point (serves frontend in production)
│   ├── migrations/         # SQL migrations
│   └── package.json
│
├── frontend/
│   ├── src/
│   │   ├── components/     # React components
│   │   ├── context/        # React context (auth)
│   │   ├── pages/          # Page components
│   │   ├── services/       # API calls
│   │   ├── types/          # TypeScript types
│   │   ├── App.tsx         # Main app component
│   │   └── vite-env.d.ts   # Vite TypeScript definitions
│   ├── dist/              # Built frontend (created during build)
│   └── package.json
│
├── railway.json           # Railway monorepo deployment config
├── package.json           # Root package.json with workspace scripts
└── README.md

Environment Variables Reference

Backend

Variable Description Required Default
DATABASE_URL PostgreSQL connection string Yes -
JWT_SECRET Secret for JWT signing Yes -
EMAIL_HASH_SALT Salt for email hashing Yes -
NODE_ENV Environment (production/development) No development
PORT Port for server (Railway sets this) No 3000
EMAIL_API_KEY Email service API key No* -
EMAIL_FROM Sender email address No* -
CORS_ORIGIN Allowed CORS origin No http://localhost:5173

*Required in production for magic link emails to work

Frontend

Variable Description Default
VITE_API_URL API base URL /api

In development, Vite proxies /api to http://localhost:3000 In production, backend serves frontend, so /api works directly

API Documentation

Public Endpoints

  • GET /api/health - Health check
  • GET /api/reference/relationship-types - Get relationship types
  • GET /api/reference/aspects - Get default aspects
  • GET /api/invite/:token - Get invite details (public)

Authentication

  • POST /api/auth/request-magic-link - Request magic link
    • Body: { "email": "user@example.com" }
  • GET /api/auth/verify?token=... - Verify magic link
    • Returns: JWT session token

Protected Endpoints (Require Auth Token)

User:

  • GET /api/user/profile - Get user profile
  • GET /api/user/relationships - Get user's relationships

Relationships:

  • POST /api/relationships/create - Create new relationship
  • GET /api/relationships/:id - Get relationship details

Invites:

  • POST /api/invite/:token/accept - Accept invite

Security Features

  • Email hashing (SHA-256) - emails never stored in plain text
  • Anonymous nicknames auto-generated
  • JWT-based authentication
  • Magic links with 15-minute expiry
  • Session tokens with 7-day expiry
  • Rate limiting on auth endpoints
  • CORS protection
  • Helmet.js security headers

Monorepo Benefits

One deployment instead of separate frontend/backend ✅ No CORS issues (same origin) ✅ Simpler configurationLower cost (one Railway service instead of two) ✅ Easier to manage and update

Troubleshooting

Railway Deployment

Build fails:

  • Check deploy logs in Railway dashboard
  • Ensure both backend and frontend build successfully
  • Verify all dependencies are in package.json files

Frontend shows API JSON instead of React app:

  • Ensure NODE_ENV=production is set in Railway variables
  • Check that frontend/dist folder was created during build
  • Verify railway.json builds both backend and frontend

API calls fail with 404:

  • Check that API routes use /api prefix
  • Ensure app.use('/api', routes) comes before static file serving in backend/src/index.ts

502 Error:

  • Check Railway logs for crashes
  • Verify DATABASE_URL is set
  • Ensure database migrations ran successfully

Local Development

Database connection error:

# Check if PostgreSQL is running
pg_isready

# Check if database exists
psql -l | grep samepage

# Verify DATABASE_URL in backend/.env

Port already in use:

# Find process using port 3000
lsof -i :3000

# Kill it or change PORT in backend/.env

Module not found:

# Reinstall dependencies
cd backend && rm -rf node_modules && npm install
cd ../frontend && rm -rf node_modules && npm install

Vite build fails:

  • Check for TypeScript errors: cd frontend && npm run build
  • Ensure vite-env.d.ts exists with proper types

Documentation Files

License

MIT

Support

For issues and questions, please open a GitHub issue.


Live Demo: Deployed on Railway at your generated URL Stack: React + TypeScript + Express + PostgreSQL Architecture: Monorepo with single-service deployment

About

Are we on the same page

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages