Firebase এর হাতেখড়ি সিরিজের এটাই শেষ পর্ব। এতদিন Auth, Database, Storage, Security Rules, Emulator, Cloud Functions — সবকিছু আলাদাভাবে শিখেছি। আজ সব একসাথে জুড়ে একটা সম্পূর্ণ Todo App বানাব, আর শেষে সেটা Cloudflare Pages-এ Firebase backend সহ কীভাবে লাইভ করতে হয় তা দেখব — ঠিক যেভাবে ArifStack-এর অন্য প্রজেক্টগুলো ডেপ্লয় হয়।
প্রজেক্টের পরিকল্পনা
ফিচার তালিকা —
- ইউজার Email/Password দিয়ে লগইন করবে (পর্ব ২)
- লগইন করা ইউজার নিজের Todo যোগ, দেখা, এডিট, ডিলিট করতে পারবে (পর্ব ৩, ৬, ৭)
- প্রতিটা Todo শুধু তার মালিক দেখতে/বদলাতে পারবে (পর্ব ৮-এর Security Rules)
- Todo-র তালিকা লাইভ আপডেট হবে (পর্ব ৭-এর onValue)
JSON স্ট্রাকচার (পর্ব ৫-এর নিয়ম মেনে)
{
"todos": {
"-Nx1abc": {
"text": "Firebase সিরিজ শেষ করা",
"done": false,
"ownerId": "uid123",
"createdAt": 1700000000000
}
}
}
Security Rules (পর্ব ৮)
{
"rules": {
"todos": {
"$todoId": {
".read": "auth != null && data.child('ownerId').val() == auth.uid",
".write": "auth != null && (!data.exists() || data.child('ownerId').val() == auth.uid)",
"text": { ".validate": "newData.isString() && newData.val().length > 0" }
}
}
}
}
CRUD ফাংশনগুলো
আগের পর্বগুলোর সব ফাংশন একসাথে জুড়ে একটা todoService.js বানানো —
// todoService.js
import { ref, push, update, remove, onValue, query, orderByChild, equalTo } from "firebase/database";
import { db, auth } from "./firebase";
// Create (পর্ব ৬)
export async function addTodo(text) {
await push(ref(db, "todos"), {
text,
done: false,
ownerId: auth.currentUser.uid,
createdAt: Date.now(),
});
}
// Read — লাইভ (পর্ব ৭)
export function subscribeTodos(callback) {
const myTodos = query(ref(db, "todos"), orderByChild("ownerId"), equalTo(auth.currentUser.uid));
return onValue(myTodos, (snapshot) => {
callback(snapshot.val() || {});
});
}
// Update (পর্ব ৬)
export async function toggleTodo(todoId, done) {
await update(ref(db, `todos/${todoId}`), { done: !done });
}
// Delete
export async function deleteTodo(todoId) {
await remove(ref(db, `todos/${todoId}`));
}
React কম্পোনেন্টে ব্যবহার
function TodoApp() {
const [todos, setTodos] = React.useState({});
const [text, setText] = React.useState("");
React.useEffect(() => {
const unsubscribe = subscribeTodos(setTodos);
return () => unsubscribe();
}, []);
async function handleAdd() {
if (!text.trim()) return;
await addTodo(text);
setText("");
}
return (
<ProtectedPage> {/* পর্ব ৩-এর guard */}
<input value={text} onChange={(e) => setText(e.target.value)} />
<button onClick={handleAdd}>যোগ করো</button>
{Object.entries(todos).map(([id, todo]) => (
<div key={id}>
<input type="checkbox" checked={todo.done} onChange={() => toggleTodo(id, todo.done)} />
<span>{todo.text}</span>
<button onClick={() => deleteTodo(id)}>মুছো</button>
</div>
))}
</ProtectedPage>
);
}
লাইভ ডেমো — সম্পূর্ণ Todo App (সিমুলেটেড)
নিচে পুরো CRUD ফ্লো — যোগ করা, টগল করা, মুছে ফেলা — একসাথে দেখা যাচ্ছে।
এটাই সেই লজিক যা আসল Firebase দিয়ে push(), update(), remove() ব্যবহার করে করা হয়েছে — শুধু এখানে লোকাল state দিয়ে সিমুলেট করা।
এখন ডেপ্লয়মেন্ট — Cloudflare Pages
প্রজেক্ট রেডি, এবার লাইভ করার পালা। ধরে নিচ্ছি এটা একটা Vite + React প্রজেক্ট (npm-ভিত্তিক Firebase SDK, পর্ব ১ মনে আছে?)।
- বিল্ড কমান্ড ঠিক করা —
npm run buildচালালে একটাdist/ফোল্ডার তৈরি হবে - GitHub-এ পুশ করা — কোড GitHub রিপোজিটরিতে থাকতে হবে
- Cloudflare Pages-এ কানেক্ট করা — Cloudflare Dashboard-এ Workers & Pages → Create → Pages → Connect to Git
- Build settings — Framework preset: Vite, Build command:
npm run build, Output directory:dist - Environment variables — firebaseConfig-এর মানগুলো Cloudflare-এর Environment Variables সেকশনে যোগ করা (কোডে হার্ডকোড না করে)
- Save and Deploy — কয়েক মিনিটেই একটা লাইভ URL পাওয়া যাবে
// .env (Vite প্রজেক্টে)
VITE_FIREBASE_API_KEY=AIzaSy...
VITE_FIREBASE_AUTH_DOMAIN=my-first-app.firebaseapp.com
VITE_FIREBASE_DATABASE_URL=https://my-first-app-default-rtdb.firebasedatabase.app
// firebase.js-এ ব্যবহার
const firebaseConfig = {
apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
databaseURL: import.meta.env.VITE_FIREBASE_DATABASE_URL,
};
একটা গুরুত্বপূর্ণ শেষ ধাপ — Authorized Domains
ডেপ্লয়ের পর Google Sign-In (পর্ব ৩) কাজ নাও করতে পারে, কারণ Firebase Console জানে না নতুন Cloudflare Pages ডোমেইনটা বিশ্বস্ত। এটা ঠিক করতে —
- Firebase Console-এ Authentication → Settings → Authorized domains-এ যান
- Add domain চেপে Cloudflare-এর দেওয়া ডোমেইন (যেমন
my-app.pages.dev) যোগ করুন
Billing ও Blaze Plan সীমা
এই সিরিজে যা যা শিখেছি তার প্রায় সবই Spark plan (ফ্রি)-তেই চলে — Auth, RTDB, Storage-এর একটা যথেষ্ট বড় ফ্রি কোটা আছে। শুধু Cloud Functions (পর্ব ১১) ব্যবহার করতে হলে Blaze plan-এ যেতে হয়।
- Blaze মানেই বিল আসবে না — Blaze-এও একটা ফ্রি কোটা থাকে (Spark-এর মতোই), শুধু কোটা পার হলে টাকা কাটে
- Budget alert সেট করা যায় — Google Cloud Console-এ একটা নির্দিষ্ট খরচের সীমা পার হলে ইমেইল এলার্ট পাওয়া যায়, এটা সবসময় সেট করে রাখা ভালো অভ্যাস
- RTDB-এর ফ্রি কোটা — সাধারণত ১GB স্টোরেজ ও ১০GB/মাস ডাউনলোড, যা ছোট-মাঝারি প্রজেক্টে যথেষ্ট (হালনাগাদ সীমার জন্য সবসময় Firebase Pricing পেজ দেখে নেওয়া ভালো, কারণ এগুলো সময়ে সময়ে বদলায়)
সিরিজ জুড়ে যা শিখলাম
- পর্ব ১-৩: প্রজেক্ট সেটআপ ও Authentication (Email/Password, Google, Auth State)
- পর্ব ৪-৫: ডেটাবেজ বাছাই ও Realtime Database পরিচিতি
- পর্ব ৬-৭: Write ও Read অপারেশন, Query, Pagination
- পর্ব ৮-৯: Security Rules ও Storage
- পর্ব ১০-১১: Emulator, Error Handling, Cloud Functions
- পর্ব ১২: সব একসাথে জুড়ে একটা লাইভ প্রজেক্ট
নিজে চেষ্টা করো
Exercise:
- উপরের
todoService.jsনিজে বানাও, একটা সম্পূর্ণ Todo App বানিয়ে নিজের ডেটাবেজে টেস্ট করো। - Vite দিয়ে বিল্ড করে GitHub-এ পুশ করো, Cloudflare Pages-এ কানেক্ট করে লাইভ ডেপ্লয় করো।
- Environment variables Cloudflare-এ সেট করো, কোডে কোনো API key হার্ডকোড নেই তা নিশ্চিত করো।
- Authorized domains-এ নিজের Cloudflare ডোমেইন যোগ করে Google Sign-In টেস্ট করো।
- Google Cloud Console-এ একটা Budget alert সেট করে রাখো, যাতে ভবিষ্যতে খরচ নিয়ন্ত্রণে থাকে।