কম্পিউটার টিউটোরিয়াল

Astro, Upstash এবং GitHub দিয়ে একটি ফ্রি, ওপেন-সোর্স LinkTree অ্যাল্টারনেটিভ তৈরি করা

এই পোস্টে, আমি আলোচনা করব কীভাবে itsmy.fyi (LinkTree-এর একটি ওপেন-সোর্স অ্যাল্টারনেটিভ) Upstash, Astro, GitHub এবং Edgio দিয়ে তৈরি হয়েছে। Upstash আমাকে সব ইউজারের ডেটা (CRUD) ম্যানেজ করতে সাহায্য করেছে, GitHub API-এর তুলনায় CRUD অপারেশনের জন্য অনেক বেশি উদার রেট লিমিটিং অফার করেছে, এবং গ্র্যানুলার রেট লিমিটিং ইমপ্লিমেন্ট করতে সাহায্য করেছে।

Astro, Upstash এবং GitHub দিয়ে একটি ফ্রি, ওপেন-সোর্স LinkTree অ্যাল্টারনেটিভ তৈরি করা

আমরা কী ব্যবহার করব

  • Astro (ফ্রন্ট-এন্ড এবং ব্যাক-এন্ড)
  • Upstash (রেট লিমিটিং এবং CRUD অপারেশন)
  • GitHub Issue এবং Webhooks (পাবলিক CMS ইউজার প্রোফাইল ম্যানেজ করার জন্য)
  • Tailwind CSS (স্টাইলিং)
  • Edgio (ডিপ্লয়মেন্ট)

আপনার কী কী লাগবে

  • একটি GitHub অ্যাকাউন্ট
  • একটি Upstash অ্যাকাউন্ট ডেটাবেস তৈরি করার জন্য

Upstash Redis সেট আপ করা

একবার আপনি Upstash অ্যাকাউন্ট তৈরি করে লগ ইন করলে, আপনি Redis ট্যাবে যাবেন এবং একটি ডেটাবেস তৈরি করবেন।

Astro, Upstash এবং GitHub দিয়ে একটি ফ্রি, ওপেন-সোর্স LinkTree অ্যাল্টারনেটিভ তৈরি করা Astro, Upstash এবং GitHub দিয়ে একটি ফ্রি, ওপেন-সোর্স LinkTree অ্যাল্টারনেটিভ তৈরি করা

আপনার ডেটাবেস তৈরি হলে, আপনি Details ট্যাবে যাবেন। নিচে স্ক্রোল করুন যতক্ষণ না Connect your database সেকশনটি পাওয়া যায়। কন্টেন্ট কপি করুন এবং কোথাও সুরক্ষিত জায়গায় সংরক্ষণ করুন।

Astro, Upstash এবং GitHub দিয়ে একটি ফ্রি, ওপেন-সোর্স LinkTree অ্যাল্টারনেটিভ তৈরি করা

এছাড়া, নিচে স্ক্রোল করুন যতক্ষণ না REST API সেকশনটি পাওয়া যায় এবং .env বাটনটি সিলেক্ট করুন। কন্টেন্ট কপি করুন এবং কোথাও সুরক্ষিত জায়গায় সংরক্ষণ করুন।

Astro, Upstash এবং GitHub দিয়ে একটি ফ্রি, ওপেন-সোর্স LinkTree অ্যাল্টারনেটিভ তৈরি করা

প্রজেক্ট সেট আপ করা

সেট আপ করতে, শুধু অ্যাপ রিপো ক্লোন করুন এবং এই টিউটোরিয়াল ফলো করুন সেটার সব কিছু শিখতে। প্রজেক্ট ফর্ক করতে, চালান:

git clone https://github.com/rishi-raj-jain/itsmy.fyi
cd itsmy.fyi
yarn install

রিপো ক্লোন করার পর, আপনি একটি .env ফাইল তৈরি করবেন। আপনি উপরের ধাপগুলো থেকে সংরক্ষণ করা আইটেমগুলো যোগ করবেন।

এটি কিছু এইরকম দেখাবে:

# .env
# আপনার GitHub রিপো থেকে প্রাপ্ত
GITHUB_API_TOKEN="to_create_and_update_github_comments"
GITHUB_WEBHOOK_SECRET="if_you_are_matching_github_webhooks_sha256"
# উপরের ধাপগুলো থেকে প্রাপ্ত
UPSTASH_DB="your_upstash_redis_from_above"
UPSTASH_REDIS_REST_URL="your_upstash_redis_rest__url_from_above"
UPSTASH_REDIS_REST_TOKEN="your_upstash_redis_rest__token_from_above"

এই ধাপগুলো পূরণ করার পর, আপনাকে নিচের কমান্ড ব্যবহার করে লোকাল এনভায়রনমেন্ট শুরু করতে পারবেন:

yarn run edgio:dev

রিপোজিটরি স্ট্রাকচার

এটি প্রজেক্টের মেইন ফোল্ডার স্ট্রাকচার। আমি লাল ঘेড়ে চিহ্নিত করেছি যে ফাইলগুলো এই পোস্টে আরও আলোচনা করা হবে যা CRUD অপারেশন, রেট লিমিটিং এবং সেগুলো যেখানে রেফারেন্স করা হয়েছে।

Astro, Upstash এবং GitHub দিয়ে একটি ফ্রি, ওপেন-সোর্স LinkTree অ্যাল্টারনেটিভ তৈরি করা

উচ্চ-স্তরের ডেটা ফ্লো

এটি ডেটা কীভাবে ফ্লো করছে তার একটি উচ্চ-স্তরের ডায়াগ্রাম।

  • যদি একজন ব্যবহারকারী itsmy.fyi/me/slug ভিজিট করে এবং এই পেজের রেসপন্স ক্যাশ না থাকে (অথবা রি-ভ্যালিডেট হচ্ছে), তবে এটি getUserInfo ফাংশন কল করে যা 루পে Upstash DB থেকে ইউজার JSON রিট্রিভ করে।
  • যদি একজন ব্যবহারকারী GitHub Issue তৈরি করে, আপডেট করে বা ডিলিট করে, GitHub একটি Webhook ট্রিগার করে যা একটি এন্ডপয়েন্টে POST করে। সে এন্ডপয়েন্টে, প্রথমে Upstash Rate Limiting ব্যবহার করে ইভ্যালুয়েট করা হয় অনুরোধ করা পরিবর্তনটি করা যায় কিনা, এবং তারপর Upstash ব্যবহার করে ইউজার JSON(গুলো) তৈরি, আপডেট বা ডিলিট করা হয়।
Astro, Upstash এবং GitHub দিয়ে একটি ফ্রি, ওপেন-সোর্স LinkTree অ্যাল্টারনেটিভ তৈরি করা

Upstash Redis দিয়ে User Profile(s) CRUD অপারেশন

এই সেকশনে, আমরা গভীরে যাব কীভাবে ইউজার প্রোফাইল(গুলো)র জন্য ডেটা ফেচিং, আপডেটিং এবং ডিলিশন করা হয়। আমরা Upstash (via ioredis) ব্যবহার করে ধারাবাহিকভাবে ডেটা ফেচ এবং ডিসপ্লে করি।

কেন আমি GitHub থেকে Upstash-এ চলে এলাম CRUD অপারেশনের জন্য?

যদিও আমি GitHub-কে ডেটা ম্যানেজমেন্টের সোর্স হিসেবে শুরু করেছিলাম: GitHub Issues ডেটা ফর্ম হিসেবে থেকে GitHub Webhooks ইউজার JSON CRUD করার জন্য রিপোজিটরির মধ্যে, GitHub REST API-এর লিমিটেশন: 1,000 requests per hour per repository ইন্টেনডেড ইউজেজকে রেস্ট্রিক্ট এবং রিগ্রেস করতে লাগলো।

Upstash অনেক ভালো দাড়াল কারণ এটি তাদের ফ্রি প্ল্যানে দৈনিক ১০K কমান্ড অফার করেছিল আমাকে শুরু করার জন্য, এবং আমার ইউজেজ স্কেল করলে খুব ন্যূনতম রেট। এই টাইপের অ্যাপ্রোচ আমাকে почти শূন্য খরচে বেশি ইউজার অ্যাকুইজিশন এবং ডেটাবেস স্কেলিং ও ম্যানেজ করার খরচের চিন্তা ছাড়া দ্রুত ইটারেট করতে দিয়েছিল।

getUserInfo: ইউজার প্রোফাইল ফেচ করার ফাংশন

getUserInfo ফাংশনটি ioredis-এর hget ব্যবহার করে slug কে কি হিসেবে ব্যবহার করে Upstash-এ একটি API রিকোয়েস্ট করে সম্পর্কিত ইউজার প্রোফাইল পেজের জন্য, যা একটি ইউনিক slug- দ্বারা আইডেন্টিফাইড। যদি সেই ইউজার প্রোফাইল উপস্থিত না থাকে (বা একটি এরর হয়), ফাংশনটি একটি অবজেক্ট রিটার্ন করতে সেট করা হয়েছে { code: 0 } 그와 সাথে যাতে ইউজারকে Astro-এর ডাইনামিক রুটে অটোমেটিক্যালি ৪০৪-এ রিডাইরেক্ট করা যায়।

// File: lib/Upstash/users/get.js
// Read User Profile Code
import redis from "../setup";
export async function getUserInfo(slug) {
  try {
    const userData = await redis.hget("profiles", slug);
    const parsedData = JSON.parse(userData);
    if (parsedData.slug === slug) { return { ...parsedData, code: 1 }; }
    return { code: 0, error: `slug doesn't match for the user.`, };
  } catch (e) {
    const error = e.message || e.toString();
    console.log(error);
    return { code: 0, error, };
  }
}

সাদৃশ্য, বাকি CRUD অপারেশনগুলো নিম্নরূপ:

import redis from "../setup";
// File: @/lib/Upstash/users/delete.js
// Delete User Profile Code
export async function deleteUserInfo(slug) {
  try { await redis.hdel("profiles", slug); return { code: 1 }; }
  catch (e) { console.log(e.message || e.toString()); return { code: 0, }; }
}
// File: @/lib/Upstash/users/post.js
// Create/Update User Profile Code
export async function postUserInfo(data) {
  try { await redis.hset("profiles", data.slug, JSON.stringify(data)); return { code: 1 }; }
  catch (e) { const error = e.message || e.toString(); console.log(error); return { code: 0, error, }; }
}

রেট লিমিটিং

Edgio-তে সার্ভারলেস এনভায়রনমেন্টে রেট-লিমিটিং ইমপ্লিমেন্ট করতে, আমরা Upstash Redis ডেটাবেস ক্লায়েন্ট এবং একটি রেট লিমিটার লাইব্রেরি @upstash/ratelimit ব্যবহার করি।

// রেটলিমিটিং রেফারেন্স ফাংশন
// @/lib/Upstash/ratelimit.js
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";
import { getENV } from "@/lib/env";
const url = getENV("UPSTASH_REDIS_REST_URL");
const token = getENV("UPSTASH_REDIS_REST_TOKEN");
export const ratelimit = (number, time) => {
  if (url && token) {
    return new Ratelimit({ redis: new Redis({ url, token, }), limiter: Ratelimit.fixedWindow(number, time), });
  }
  return; };}

রেট লিমিটিং ব্যবহার করে, আমি নিম্নলিখিতগুলো অর্জন করতে পেরেছি:

A. সার্ভিসের ব্যবহার - সম্পূর্ণ ফ্রি এবং অনলিমিটেড করা

রেট লিমিটিং ব্যবহার করে, আমি প্রোফাইল ক্রিয়েশন API পাবলিকলি এক্সপোজ করতে পেরেছি! এটি আমাকে সিস্টেমের সুবিধাগুলো শোकेস করতে দিয়েছিল অর্থাৎ GUI-এর মাধ্যমে প্রোফাইল সেটআপের সহজতা। কেউ সপ্তাহে ৩টি প্রোফাইল ওয়েবসাইটটিই (itsmy.fyi) থেকে তৈরি করতে পারে, এবং অনলিমিটেড ফিচার অ্যাক্সেসের জন্য যেমন প্রোফাইল এডিট, অনলিমিটেড প্রোফাইল তৈরি, ব্যবহারকারীদের GitHub পদ্ধতিতে স্যুইচ করতে হবে। আমরা IP অ্যাড্রেস কি হিসেবে ব্যবহার করে ৩টি প্রোফাইল প্রতি সপ্তাহের রেট লিমিট এনফোর্স করতে পারছি।

// রেট লিমিট: ওয়েবে একজন ইউজারের জন্য সপ্তাহে ৩টি প্রোফাইল
const ratelimitUser = ratelimit(3, 7 * 24 * 60 * 60 + " s");
if (rateLimiter) {
  // Edgio দ্বারা সার্ভারলেসে সেট করা x-0-client-ip দেখুন
  const result = await rateLimiter.limit("x-0-client-ip");
  limit = result.limit;
  remaining = result.remaining;
  if (!result.success) { // একটি মেসেজ রিটার্ন করুন }
}

B. ইউজারের এডিট সংখ্যার গ্র্যানুলার মডারেশন ইমপ্লিমেন্ট করা

রেট লিমিটিং-এর মাধ্যমে, আমরা একটি ইউজারের দ্বারা একটি মিনিটে করা এডিটের সংখ্যা মডারেট করতে পারছি তাদের GitHub ইউজারনেমের উপর ভিত্তি করে। বর্তমানে, আমরা তাদের একটি মিনিটে ৩টি পরিবর্তন করার অনুমতি দিই। এটি যেকোনো অপ্রত্যাশিত স্প্যাম কমাতে সাহায্য করবে।

// @/pages/github/hook/issue.js
const rateLimiter = ratelimit(3, "60 s");
if (rateLimiter) {
  const result = await rateLimiter.limit(context.sender.login);
  limit = result.limit;
  remaining = result.remaining;
  if (!result.success) {
    return { headers: { "X-RateLimit-Limit": limit, "X-RateLimit-Remaining": remaining, }, body: JSON.stringify({ message: "Too many updates in 1 minute. Please try again in a few minutes.", }), };
  }
}

সব ইউজার প্রোফাইলের জন্য এজ-এ stale-while-revalidate ইমপ্লিমেন্ট করা

নিচের কোড বর্ণনা করে কীভাবে Stale While Revalidate কনসেপ্ট ব্যবহার করে ক্যাশ হিট রেট উন্নত করতে হয়। কোডে ( routes.js-এ), router.match ফাংশনটি ব্যবহার করা হয়েছে সব ইউজার প্রোফাইল ম্যাচ করার জন্য (যা /me/ দিয়ে শুরু হয়)। ক্যাশ মেথডের ভিতরে, আমরা ব্রাউজারে পেজ ক্যাশ করা বন্ধ করি এবং শুধু এজ ক্যাশিং সক্ষম করি যাতে ব্যবহারকারীদের সবসময় দ্রুত এবং লেটেস্ট কন্টেন্ট সাথে সার্ভ করা হয়। edge অপশনটি maxAgeSeconds: 1 সেট করা হয়েছে যাতে ডেটা শুধু এক সেকেন্ডের জন্য ক্যাশ হয়। staleWhileRevalidateSeconds অপশনটি এক বছর সেট করা হয়েছে যাতে ক্যাশ রিফ্রেশ হয় থাকাকালীন ডেটা সরাসরি ক্যাশ থেকে সার্ভ করা যায়।

// User path(s)
router.match("/me/:path", ({ cache, removeUpstreamResponseHeader }) => {
  // Astro-এর স্ট্যান্ডঅ্যালোন সার্ভার থেকে cache-control হেডার সরান
  removeUpstreamResponseHeader("cache-control");
  // ব্রাউজার ক্যাশিং ডিসেবল করুন, এবং Edgio-এর এজ ব্যবহার করুন SWR-এর জন্য
  cache({ edge: { maxAgeSeconds: 1, staleWhileRevalidateSeconds: 60 * 60 * 24 * 365, }, browser: false, });
});

Stale While Revalidate ব্যবহার করে অ্যাপের পারফরম্যান্স উন্নত করা যায় সার্ভারের লোড কমিয়ে এবং ব্যবহারকারীদের দ্রুত রেসপন্স দিয়ে।

ডাইনামিক ইউজার প্রোফাইল অন-দ-ফ্লাই তৈরি করা

Astro ডাইনামিক রুট সেট আপ করা অত্যন্ত সহজ করে দেয়। অ্যাপে, আপনি src/pages/me/[slug].astro পাবেন, যা /me/ দিয়ে শুরু হওয়া পেজগুলো ম্যাপ করে। উদাহরণস্বরূপ /me/rishi-raj-jain এবং /me/some-other-user।

ইউজার প্রোফাইল ফেচ করা

আমরা Astro params থেকে এক্সট্র্যাক্ট করা slug কোয়ারী প্যারামিটার ব্যবহার করে বর্তমান ইউজারের ডেটা ফেচ করি, এবং getUserInfo ফাংশন কল করি (যে উপরে বর্ণনা করা হয়েছে) সব সম্পর্কিত ইউজার ডেটা পাওয়ার জন্য। না পাওয়া গেলে বা এরর হলে, আমরা ভিজিটরকে ৪০৪-এ রিডাইরেক্ট করি।

import { getUserInfo } from "@/lib/Upstash/users";
// Extract slug query
const { slug } = Astro.params;
// Get data from Upstash using the getUserInfo function
const { name: userName, image: userImage, links = [], socials = [], about = "", og = {}, background = {}, code = 1, } = await getUserInfo(userSlug);
// In case the code: 0 is recevied, redirect to a 404
if (code === 0) { return Astro.redirect("/404"); }

CLI থেকে ডিপ্লয় করা

আপনি আপনার অ্যাপের প্রোডাকশন বিল্ড করতে এবং লোকালি টেস্ট করতে পারেন:

yarn run edgio:build && yarn run edgio:production

ডিপ্লয় করার জন্য Edgio-এ একটি অ্যাকাউন্ট দরকার। এখানে ফ্রি সাইন আপ করুন। একবার অ্যাকাউন্ট হলে, আপনি আপনার প্রজেক্টের রুট ফোল্ডারে নিচের কমান্ড চালিয়ে Edgio-এ ডিপ্লয় করতে পারেন:

yarn run edgio:deploy

এখন আমরা ডিপ্লয়মেন্ট শেষ করেছি! হ্যাঁ, ততটুকুই ছিল।

উপসংহার

উপসংহারে, এই প্রজেক্টটি গ্র্যানুলার রেট লিমিটিং, সার্ভারলেসে CRUD ডেটা অপারেশন, GitHub Issues কে CMS হিসেবে ব্যবহার করা, এবং একটি সার্ভিস ব্যবহার করে MVP শিপ করার ভালো ডিসিশন নেওয়া যেটি আপনার প্রয়োজনের সাথে স্কেল করে, অর্থাৎ Upstash-এ একটি মূল্যবান অভিজ্ঞতা প্রদান করেছে।

  1. How can I use Marquee text in an android app?

  2. অ্যান্ড্রয়েডে বাটনের টেক্সট ফন্ট পরিবর্তন করা

  3. jQuery-তে বাটন ক্লিক করলে একাধিক চেকবক্স আনসিলেক্ট করা

  4. CSS display: none ব্যবহার