Tutorial
Providers & Deployment
A complete walkthrough of every external service OCM depends on, followed by deploying the frontend to Vercel and the backend to Render. Start here after completing Getting Started.
How OCM's Auth Works
Understanding the auth flow makes every other setup step clearer.
- 1
User signs in
Firebase SDK handles sign-in (email/password or social). Firebase issues a short-lived ID token.
- 2
Token attached to every API call
The Axios interceptor in frontend/src/api/axiosInstance.js automatically fetches the current Firebase token and adds it as Authorization: Bearer <token>.
- 3
Django verifies the token
FirebaseAuthentication in backend/userapp/authentication.py calls firebase_admin.auth.verify_id_token(). If valid, it looks up or creates a matching CustomUser row.
- 4
Request proceeds normally
DRF sees an authenticated request. Role/group checks (IsLeaderOrReadOnly, IsAuthorOrPastor) run on top of this.
This means Firebase is the only auth dependency you can't skip. Cloudinary, Paystack, and YouTube are optional for basic functionality.
Firebase — Auth & Firestore
Firebase handles two things in OCM: user authentication (sign up, sign in, token refresh) and Firestore (real-time group chat). You need one Firebase project for both.
Create the Firebase project
- 1. Go to console.firebase.google.com and create a new project.
- 2. Enable Google Analytics if you want it — it's not required by OCM.
- 3. In the left sidebar go to Build → Authentication → Get started.
- 4. Enable the Email/Password sign-in provider (and any others you want, e.g. Google).
- 5. Go to Build → Firestore Database → Create database. Start in production mode — you'll add Security Rules next.
Get the Web SDK config (frontend)
- 1. In Firebase Console go to Project Settings (gear icon) → General → Your apps.
- 2. Click Add app → Web. Register it (no Firebase Hosting needed).
- 3. Copy the firebaseConfig object. Each field maps to a VITE_ env var in frontend/.env.local.
// Firebase gives you this:
const firebaseConfig = {
apiKey: "...", // → VITE_FIREBASE_API_KEY
authDomain: "...", // → VITE_FIREBASE_AUTH_DOMAIN
projectId: "...", // → VITE_FIREBASE_PROJECT_ID
storageBucket: "...", // → VITE_FIREBASE_STORAGE_BUCKET
messagingSenderId: "...", // → VITE_FIREBASE_MESSAGING_SENDER_ID
appId: "...", // → VITE_FIREBASE_APP_ID
}; Get the service account key (backend)
- 1. In Project Settings go to the Service Accounts tab.
- 2. Click "Generate new private key" and confirm.
- 3. Download the JSON file and save it as backend/firebase-key.json.
- 4. Never commit this file. It's already in .gitignore.
Firestore Security Rules
OCM uses Firestore directly from the frontend for chat. Paste these rules in Firestore → Rules to restrict reads/writes to authenticated users only:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Chat rooms: any authenticated user can read
match /rooms/{roomId} {
allow read: if request.auth != null;
allow write: if request.auth != null;
// Messages inside a room
match /messages/{messageId} {
allow read: if request.auth != null;
allow create: if request.auth != null
&& request.resource.data.uid == request.auth.uid;
allow delete: if request.auth != null
&& resource.data.uid == request.auth.uid;
}
}
}
} Cloudinary — Media Storage
Django uses Cloudinary as the default file storage backend
(DEFAULT_FILE_STORAGE = 'cloudinary_storage.storage.MediaCloudinaryStorage').
All profile pictures, post images, and uploaded media go here.
- 1. Create a free account at cloudinary.com.
- 2. From the Dashboard copy your Cloud Name, API Key, and API Secret.
- 3. Add them to backend/.env:
CLOUDINARY_CLOUD_NAME=your-cloud-name
CLOUDINARY_API_KEY=your-api-key
CLOUDINARY_API_SECRET=your-api-secret Paystack — Payments
Paystack is used for charity organisation donations. The backend verifies payment
via backend/mainapp/views.py → VerifyPaymentView using the secret key.
The frontend initiates payment using the public key.
- 1. Create an account at paystack.com (available in Nigeria, Ghana, Kenya, South Africa, and more).
- 2. From Settings → API Keys & Webhooks copy your Test Secret Key and Test Public Key.
- 3. For local development always use the test keys — no real money moves.
- 4. Add the keys to your env files:
# backend/.env
PAYSTACK_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxx
# frontend/.env.local
VITE_PAYSTACK_PUBLIC_KEY=pk_test_xxxxxxxxxxxxxxxxxxxx sk_test_ → sk_live_ and
pk_test_ → pk_live_. Live keys require a verified Paystack business account.
YouTube Data API
The streaming page uses the YouTube Data API v3 to fetch live streams and videos. This key lives only in the frontend — the backend never touches it.
- 1. Go to console.cloud.google.com and create (or select) a project.
- 2. In the sidebar go to APIs & Services → Library. Search for YouTube Data API v3 and enable it.
- 3. Go to APIs & Services → Credentials → Create Credentials → API Key.
- 4. Copy the key and optionally restrict it to the YouTube Data API and your domain.
- 5. Add it to frontend/.env.local:
VITE_YOUTUBE_API_KEY=AIzaSy... PostgreSQL
The backend reads the database connection from a single DATABASE_URL
environment variable (via dj-database-url), or from individual
POSTGRES_* variables as a fallback.
Local development
Use a local PostgreSQL instance. Create the database then set the variables in backend/.env:
POSTGRES_DB=ocm
POSTGRES_USER=postgres
POSTGRES_PASSWORD=yourpassword
POSTGRES_HOST=localhost
POSTGRES_PORT=5432 Cloud database (any provider)
Set a single DATABASE_URL and it takes precedence:
DATABASE_URL=postgresql://user:pass@host:5432/db Works with Render (auto-injected), Supabase, Railway, Neon, or any pg host.
Deploy: Frontend to Vercel
The frontend is a static Vite SPA. frontend/vercel.json already includes the
SPA rewrite rule so all routes resolve to index.html.
Deploy via Vercel CLI
npm i -g vercel
cd frontend
vercel
Vercel auto-detects Vite. Set the root directory to frontend when prompted.
Or deploy via the Vercel dashboard
- 1. Go to vercel.com and import your GitHub repository.
- 2. Set the Root Directory to "frontend" in the project settings.
- 3. Framework will be detected as Vite automatically.
- 4. Add all VITE_ environment variables from your .env.local in Project Settings → Environment Variables.
- 5. Deploy. Every push to main triggers a new deployment.
Point VITE_API_URL at your live backend
Once the backend is deployed (next step), update the environment variable in Vercel's dashboard:
VITE_API_URL=https://your-service.onrender.com/api/ Deploy: Backend to Render
The repo includes backend/render.yaml which provisions a Python web service
and a free PostgreSQL database in one step. Render reads this file automatically when
you connect the repo.
1. Connect the repo
- 1. Go to dashboard.render.com → New → Blueprint.
- 2. Connect your GitHub account and select this repository.
- 3. Render finds render.yaml and shows you the services it will create: "opencms" (web) and "cmsdb-service" (PostgreSQL).
- 4. Click Apply — Render creates both services.
2. Set environment variables
DATABASE_URL and SECRET_KEY are handled automatically by
render.yaml. You need to set the rest manually in the web service's
Environment tab:
ALLOWED_HOSTS=your-service.onrender.com
CLOUDINARY_CLOUD_NAME=
CLOUDINARY_API_KEY=
CLOUDINARY_API_SECRET=
PAYSTACK_SECRET_KEY=
BACKEND_ADMIN_EMAIL=
BACKEND_ADMIN_PASSWORD= 3. Upload firebase-key.json
Render doesn't support file uploads directly, so you have two options:
Option A — Secret file (recommended)
In Render, go to the service → Environment → Secret Files.
Add a file named firebase-key.json with the contents of your service account JSON.
Render mounts it at /etc/secrets/firebase-key.json.
Update FIREBASE_PATH in settings.py to that path for production.
Option B — Env variable
Base64-encode the JSON file, store it as an env var
(FIREBASE_KEY_B64), then decode it at startup in
settings.py before calling firebase_admin.initialize_app().
4. What happens on deploy
Render runs build.sh which:
pip install -r requirements.txt
python manage.py collectstatic --no-input
python manage.py migrate Then starts the server with:
python -m gunicorn church.asgi:application -k uvicorn.workers.UvicornWorker Post-Deployment Checklist
After both services are live, there are a few cross-service wires to connect.
-
Add your Vercel URL to Django CORS
In backend/church/settings.py, add your production Vercel URL to CORS_ALLOWED_ORIGINS. Then redeploy the backend.
CORS_ALLOWED_ORIGINS = [ "https://your-app.vercel.app", ... ] -
Add your Render URL to Firebase authorised domains
In Firebase Console → Authentication → Settings → Authorised domains, add your Render backend domain (e.g. your-service.onrender.com). This prevents token errors.
-
Update VITE_API_URL in Vercel
Set VITE_API_URL to your Render service URL in Vercel's Environment Variables, then trigger a redeployment.
VITE_API_URL=https://your-service.onrender.com/api/ -
Restrict your YouTube API key
In Google Cloud Console, restrict the key to HTTP referrers and add your Vercel domain. This prevents quota abuse.
-
Switch Paystack to live keys
When you're ready to accept real payments, replace the sk_test_ / pk_test_ keys with your live keys in both services.
You're done
OCM is live.
View the source, open issues, or contribute on GitHub.