A dynamic, multi-tenant REST API built with Node.js, Express, and Firebase.
Build frontend applications without configuring a backend or database. Every student gets an isolated Firestore workspace automatically.
- Overview
- Quick Start
- Student Guide
- API Reference
- Frontend Examples
- Error Responses
- Admin Deployment Guide
- Project Structure
- Security
- FAQ
VibeWQuest Workshop API is designed for workshops, bootcamps and hackathons.
Instead of asking every student to install Firebase or MongoDB, each student receives a unique workspace where all data is stored automatically.
- ✅ Zero backend setup
- ✅ Automatic database provisioning
- ✅ Multi-tenant architecture
- ✅ Dynamic Firestore collections
- ✅ REST API
- ✅ Firebase Firestore
- ✅ Render ready
- Call
/api/v1/init - Save the returned
studentId - POST data to
/api/v1/{studentId}/{collectionName} - GET data from the same endpoint
That's it.
GET https://vibewquest-be.onrender.com/api/v1/initResponse
{
"studentId":"a1b2c3d4",
"apiUrl":"https://vibewquest-be.onrender.com/api/v1/a1b2c3d4"
}Save the studentId or apiUrl in localStorage.
POST https://vibewquest-be.onrender.com/api/v1/{studentId}/{collectionName}
Content-Type: application/json{
"task":"Learn React",
"completed":false
}GET https://vibewquest-be.onrender.com/api/v1/{studentId}/{collectionName}{
"success":true,
"data":[
{
"id":"7xYz9AbC123",
"task":"Learn React",
"completed":false
}
]
}PUT https://vibewquest-be.onrender.com/api/v1/{studentId}/{collectionName}/{documentId}
Content-Type: application/json{
"completed":true
}DELETE https://vibewquest-be.onrender.com/api/v1/{studentId}/{collectionName}/{documentId}| Method | Endpoint | Description | Request Body | Response |
|---|---|---|---|---|
| GET | /api/v1/init |
Creates a new student workspace | None | studentId, apiUrl |
| POST | /api/v1/{studentId}/{collection} |
Creates a document | Any JSON | Created document |
| GET | /api/v1/{studentId}/{collection} |
Retrieves all documents | None | Array of documents |
| PUT | /api/v1/{studentId}/{collection}/{documentId} |
Updates a specific document | Any JSON | Success message |
| DELETE | /api/v1/{studentId}/{collection}/{documentId} |
Deletes a specific document | None | Success message |
| Code | Meaning |
|---|---|
| 200 | Success |
| 201 | Created |
| 400 | Bad Request |
| 404 | Collection Not Found |
| 500 | Internal Server Error |
const res = await fetch("https://vibewquest-be.onrender.com/api/v1/init");
const data = await res.json();
localStorage.setItem("studentId", data.studentId);const studentId = localStorage.getItem("studentId");
await fetch(
`https://vibewquest-be.onrender.com/api/v1/${studentId}/todos`,
{
method:"POST",
headers:{
"Content-Type":"application/json"
},
body:JSON.stringify({
task:"Learn React",
completed:false
})
});const studentId = localStorage.getItem("studentId");
const res = await fetch(
`https://vibewquest-be.onrender.com/api/v1/${studentId}/todos`
);
const data = await res.json();
console.log(data.data);npm install axiosimport axios from "axios";
const {data:init} = await axios.get(
"https://vibewquest-be.onrender.com/api/v1/init"
);
localStorage.setItem("studentId",init.studentId);await axios.post(
`https://vibewquest-be.onrender.com/api/v1/${studentId}/todos`,
{
task:"Learn React",
completed:false
});const {data}=await axios.get(
`https://vibewquest-be.onrender.com/api/v1/${studentId}/todos`
);
console.log(data.data);import {useEffect,useState} from "react";
export default function App(){
const [todos,setTodos]=useState([]);
useEffect(()=>{
async function load(){
let studentId=localStorage.getItem("studentId");
if(!studentId){
const res=await fetch("https://vibewquest-be.onrender.com/api/v1/init");
const init=await res.json();
studentId=init.studentId;
localStorage.setItem("studentId",studentId);
}
const response=await fetch(
`https://vibewquest-be.onrender.com/api/v1/${studentId}/todos`
);
const data=await response.json();
setTodos(data.data);
}
load();
},[]);
return(
<ul>
{todos.map(todo=>(
<li key={todo.id}>{todo.task}</li>
))}
</ul>
);
}{
"success": false,
"message": "Collection not found"
}{
"success": false,
"message": "Invalid request"
}{
"success": false,
"message": "Internal server error"
}git clone https://github.com/QuestIT-Cell/VibeWQuest-BE.git
cd VibeWQuest-BE
npm install- Open Firebase Console
- Project Settings
- Service Accounts
- Generate New Private Key
- Rename to
serviceAccountKey.json
- Place inside
src/secrets/serviceAccountKey.json
Security Warning
Ensure
.gitignorecontains:src/secrets/Never commit your Firebase Admin SDK key.
node -e "console.log(require('fs').readFileSync('./src/secrets/serviceAccountKey.json').toString('base64'))"Copy the output.
| Setting | Value |
|---|---|
| Runtime | Node |
| Build Command | npm install |
| Start Command | node server.js |
Environment Variable
| Key | Value |
|---|---|
| FIREBASE_SERVICE_ACCOUNT_BASE64 | Base64 Firebase Key |
Deploy.
.
├── src
│ ├── routes
│ ├── controllers
│ ├── middleware
│ ├── secrets
│ └── utils
├── server.js
├── package.json
└── README.md
- Never expose your Firebase Admin SDK.
- Use environment variables in production.
- Do not commit secrets.
- Restrict Firestore permissions where applicable.
No.
No.
Yes.
No.
localStorage.
Made with ❤️ by QUEST IT Cell.