موتور تیغ ۰.۰.۱-beta • متریک‌های این صفحه زنده هستند

مستندات API اشعار فارسی

مرجع کامل برای API داده، موتور تیغ، فورک و توسعه، و پرامپت‌های آماده برای دستیارهای کدنویسی.

یا فشار دهید / در هر صفحه‌ای

معرفی کلی

API رایگان و متن‌باز برای دسترسی به مجموعه‌ای از اشعار و سخنان فارسی. تعداد دقیق اسناد، شاعران و دسته‌بندی‌ها در بخش متریک زنده از دادهٔ واقعی مخزن خوانده می‌شود.

زنده
تعداد اسناد
زنده
تعداد شاعران
TypeScript
پیاده‌سازی

متریک زنده موتور

مشاهده کامل
در حال دریافت متریک زنده از موتور...

شروع سریع

اولین درخواست در کمتر از ۳۰ ثانیه. هیچ مرحله نصبی لازم نیست — فقط یک درخواست HTTP ارسال کنید.

TERMINAL
bash
# دریافت یک شعر تصادفی
curl "https://pq.arsamadineh.ir/api/quotes?random=true&limit=1"

# دریافت ۵ شعر از حافظ
curl "https://pq.arsamadineh.ir/api/quotes/hafez?limit=5"

# فال حافظ (یک غزل تصادفی)
curl "https://pq.arsamadineh.ir/api/quotes/hafez?random=true&limit=1"

# جستجوی کلمه «عشق»
curl "https://pq.arsamadineh.ir/api/quotes/search?q=%D8%B9%D8%B4%D9%82&limit=5"

پنج اندپوینت برتر برای شروع

  • GET /api/quotes?random=true&limit=1
  • GET /api/quotes/hafez?random=true&limit=1
  • GET /api/quotes/search?q=عشق
  • GET /api/poets?stats=true
  • GET /api/engine/stats

احراز هویت

احراز هویت لازم نیست

تمام اندپوینت‌ها کاملاً عمومی هستند. هیچ کلید API، توکن، یا ثبت‌نامی نیاز نیست. فقط کافی است درخواست HTTP ارسال کنید. هدر Accept: application/json اختیاری است.

نرخ درخواست منصفانه

موتور تیغ به‌طور پیش‌فرض ۱۲۰ درخواست در دقیقه برای هر IP مجاز می‌کند. اگر به بیشتر نیاز دارید، صفحه محدودساز نرخ را ببینید.

CORS باز

تمام اندپوینت‌ها برای استفاده از مرورگر و فرانت‌اند پاسخ‌گو هستند. می‌توانید مستقیماً از دامنه خودتان fetch کنید.

مرجع اندپوینت‌ها

تمام روش‌ها GET هستند. پاسخ‌ها همگی JSON با ساختار یکپارچه{ success, data, count, meta }.

دریافت اشعار
GET
لیست اشعار با فیلتر اختیاری بر اساس شاعر، دسته‌بندی، و انتخاب تصادفی. تمام خروجی‌ها به فارسی و انگلیسی موجود است.

مسیرها

GET /api/quotes
GET /api/quotes/[poet]
GET /api/quotes/category/[category]

پارامترها

نامنوعپیش‌فرضتوضیح
limitnumber10تعداد اشعار بازگشتی (حداکثر 100)
randombooleanfalseانتخاب تصادفی اشعار
poetstringفیلتر بر اساس نام شاعر (مثلاً: مولانا)
categorystringفیلتر بر اساس دسته‌بندی (مثلاً: عشق)

نمونه درخواست

TERMINAL
bash
# پنج شعر تصادفی
curl "https://pq.arsamadineh.ir/api/quotes?random=true&limit=5"

# تمام اشعار حافظ
curl "https://pq.arsamadineh.ir/api/quotes/%D9%85%D9%88%D9%84%D8%A7%D9%86%D8%A7"

# اشعار عاشقانه
curl "https://pq.arsamadineh.ir/api/quotes/category/%D8%B9%D8%B4%D9%82"

نمونه پاسخ

RESPONSE.JSON
json
{
  "success": true,
  "data": [
    {
      "id": 1,
      "text_persian": "عاشقان مرده‌اند در عشق زنده\nتا ابد در دل جانان پاینده",
      "text_english": "Lovers are dead in love, yet alive...",
      "poet": "مولانا جلال‌الدین رومی",
      "poet_english": "Rumi",
      "source": "دیوان شمس",
      "category": "عشق",
      "tags": ["عشق", "زندگی", "جاودانگی"]
    }
  ],
  "count": 1,
  "meta": { "limit": 1, "random": true }
}
دیوان حافظ
نمونه پاسخ: ۴۹۷ غزل
GET
دسترسی کامل به تمام غزلیات خواجه شمس‌الدین حافظ شیرازی با ساختار بیتی (مصرع اول و دوم). پارامتر q جستجوی متنی اختصاصی دارد.

مسیرها

GET /api/quotes/hafez

پارامترها

نامنوعپیش‌فرضتوضیح
idnumberدریافت غزل با شماره موجود در مجموعه
qstringجستجو در بین مصرع‌های دیوان
limitnumber10تعداد غزل‌ها (حداکثر 100)
randombooleanfalseدریافت تصادفی (فال حافظ)

نمونه درخواست

TERMINAL
bash
# فال حافظ — یک غزل تصادفی
curl "https://pq.arsamadineh.ir/api/quotes/hafez?random=true&limit=1"

# غزل شماره ۱
curl "https://pq.arsamadineh.ir/api/quotes/hafez?id=1"

# جستجوی کلمه «رند»
curl "https://pq.arsamadineh.ir/api/quotes/hafez?q=%D8%B1%D9%86%D8%AF"

نمونه پاسخ

RESPONSE.JSON
json
{
  "success": true,
  "data": [
    {
      "id": 1,
      "verses": [
        ["الا یا ایها الساقی ادر کاسا و ناولها", "که عشق آسان نمود اول ولی افتاد مشکل‌ها"],
        ["به بوی نافه کاخر صبا زان طره بگشاید", "ز تاب جعد مشکینش چه خون افتاد در دل‌ها"]
      ],
      "poet": "حافظ شیرازی",
      "source": "دیوان حافظ"
    }
  ],
  "count": 1,
  "total": "نمونه؛ مقدار واقعی از API خوانده می‌شود"
}
شعر نو معاصر
نمونه پاسخ: ۴۴۰۰ اثر
GET
اشعار نو از پیشگامان شعر نو فارسی شامل نیما یوشیج، سهراب سپهری، و دیگر شاعران معاصر.

مسیرها

GET /api/quotes/shereno

پارامترها

نامنوعپیش‌فرضتوضیح
poetstringنام شاعر (مثلاً: نیما یوشیج، سهراب سپهری)
titlestringجستجو در عنوان شعر
limitnumber10تعداد اشعار (حداکثر 100)
randombooleanfalseانتخاب تصادفی

نمونه درخواست

TERMINAL
bash
# یک شعر نو تصادفی
curl "https://pq.arsamadineh.ir/api/quotes/shereno?random=true&limit=1"

# فقط اشعار نیما یوشیج
curl "https://pq.arsamadineh.ir/api/quotes/shereno?poet=%D9%86%DB%8C%D9%85%D8%A7"

نمونه پاسخ

RESPONSE.JSON
json
{
  "success": true,
  "data": [
    {
      "id": 2,
      "title": "قایق",
      "poem": "من چهره‌ام گرفته / من قایقم نشسته به خشکی...",
      "poet": "نیما یوشیج",
      "book": "مجموعه اشعار"
    }
  ],
  "count": 1,
  "total": "نمونه؛ مقدار واقعی از API خوانده می‌شود"
}
سخنان بزرگان
غیرشعری
GET
نقل‌قول‌های ارزشمند و الهام‌بخش از بزرگ‌ترین اندیشمندان تاریخ جهان — به زبان فارسی.

مسیرها

GET /api/quotes/non-poetry

پارامترها

نامنوعپیش‌فرضتوضیح
authorstringنام گوینده (مثلاً: انیشتین)
limitnumber10تعداد نقل‌قول‌ها (حداکثر 100)
randombooleanfalseانتخاب تصادفی

نمونه درخواست

TERMINAL
bash
# یک نقل‌قول تصادفی
curl "https://pq.arsamadineh.ir/api/quotes/non-poetry?random=true&limit=1"

# فقط سخنان ایلان ماسک
curl "https://pq.arsamadineh.ir/api/quotes/non-poetry?author=%D8%A7%DB%8C%D9%84%D8%A7%D9%86"

نمونه پاسخ

RESPONSE.JSON
json
{
  "success": true,
  "data": [
    {
      "id": 2,
      "body": "راه حل موفقیت این است که اشتیاق شما به پیروزی بیشتر از ترس شما از شکست باشد.",
      "author": "آلبرت انیشتین"
    }
  ],
  "count": 1,
  "total": "نمونه؛ مقدار واقعی از API خوانده می‌شود"
}
فهرست شاعران
GET
دریافت اطلاعات شاعران شامل نام فارسی، نام لاتین، و آمار اشعار.

مسیرها

GET /api/poets

پارامترها

نامنوعپیش‌فرضتوضیح
statsbooleanfalseافزودن فیلد quote_count به هر شاعر

نمونه درخواست

TERMINAL
bash
curl "https://pq.arsamadineh.ir/api/poets?stats=true"
دسته‌بندی‌ها
GET
لیست دسته‌بندی‌های موضوعی شامل عشق، عرفان، حکمت، طبیعت، اخلاق، و زندگی.

مسیرها

GET /api/categories

پارامترها

نامنوعپیش‌فرضتوضیح
statsbooleanfalseافزودن فیلد quote_count

نمونه درخواست

TERMINAL
bash
curl "https://pq.arsamadineh.ir/api/categories?stats=true"
آمار پایگاه داده
GET
تعداد کل اشعار، شاعران، و منابع داده.

مسیرها

GET /api/stats

نمونه درخواست

TERMINAL
bash
curl "https://pq.arsamadineh.ir/api/stats"
ویجت قابل تعبیه
HTML + iframe
GET
تولید HTML برای نمایش اشعار در سایت شخص ثالث. پنج قالب ظاهری، سه اندازه، و دو حالت تازه‌سازی خودکار.

مسیرها

GET /api/embed

پارامترها

نامنوعپیش‌فرضتوضیح
themestringdefaultdefault | elegant | minimal | classic | modern
sizestringmediumsmall | medium | large
poetstringفیلتر شاعر خاص
categorystringفیلتر دسته‌بندی خاص
auto_refreshbooleanfalseتازه‌سازی خودکار هر ۳۰ ثانیه

نمونه درخواست

HTML
html
<iframe
  src="https://pq.arsamadineh.ir/api/embed?theme=classic&poet=rumi"
  width="100%"
  height="300"
  frameborder="0"
></iframe>
CORE

موتور تیغ

یک موتور API نوشته‌شده در TypeScript خالص؛ ماژول‌های موتور به وابستگی خارجی نیاز ندارند. مناسب برای هر پروژه‌ای که به مسیریابی سریع، کش هوشمند، و متریک زنده نیاز دارد.

۹
فایل‌های TS
وابسته به build
اندازه bundle
۰
وابستگی
MIT
مجوز
lib/engine/
index.tsنقطه export
types.tsاینترفیس‌ها
engine.tsTigh — orchestrator
router.tsTrie matcher
cache.tsLRU + TTL
middleware.tsCORS + timing + compress
rate-limiter.ts۳ استراتژی
circuit-breaker.ts۳ حالت
metrics.tsPercentile + counter
adapter-next.tscreateNextHandler
instance.tssingleton
app/api/
engine/stats/route.ts
engine/benchmark/route.ts

مسیریاب Trie

TighRouter از ساختار Trie برای matching استفاده می‌کند. به جای جستجوی خطی O(n) در لیست مسیرها، مسیر ورودی به segment تقسیم می‌شود و در هر گره درخت Trie تنها یک شاخه پیمایش می‌شود.

پارامتر داینامیک

text
/api/quotes/[poet]
/api/quotes/hafez
→ { poet: "hafez" }

Wildcard

text
/api/static/*
/api/static/css/style.css
→ { wildcard: "css/style.css" }

ترکیبی

text
/api/[version]/users/[id]
/api/v2/users/42
→ { version: "v2", id: "42" }

کش LRU + TTL

TighCache با دو مکانیزم Eviction:

  • LRU (Least Recently Used): وقتی اندازه به سقف می‌رسد، کم‌استفاده‌ترین کلید حذف می‌شود.
  • TTL (Time To Live): هر کلید پس از انقضا به‌طور خودکار از کش خارج می‌شود.
  • invalidatePattern: حذف گروهی کلیدها بر اساس الگوی regex.
routes/quotes-popular.ts
typescript
// استفاده در یک route
engine.get("/api/quotes/popular", async () => {
  const top = await db.quotes
    .orderBy("likes", "desc")
    .limit(20)
  return {
    status: 200,
    headers: { "Content-Type": "application/json" },
    body: top,
  }
}, {
  cache: {
    ttl: 5 * 60_000,             // ۵ دقیقه
    key: (req) => `popular:${req.ip}`,
  },
})

محدودساز نرخ

TighRateLimiter سه استراتژی برای کنترل نرخ درخواست دارد:

Token Bucket

پیش‌فرض. درخواست‌ها با سرعت ثابت جایگزین می‌شوند.

ترافیک متغیر و burst-پذیر

Sliding Window

شمارش دقیق درخواست‌ها در پنجره زمانی شناور.

ترافیک یکنواخت

Fixed Window

شمارش ساده در هر پنجره زمانی ثابت.

ترافیک قابل پیش‌بینی

RESPONSE HEADERS
http
// هدرهای پاسخ
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1751640000
Retry-After: 30    // فقط در حالت 429

مدار شکن

TighCircuitBreaker از الگوی سه‌حالته پیروی می‌کند تا از فراخوانی بیش از حد یک endpoint ناپایدار جلوگیری کند.

CLOSED

حالت عادی. درخواست‌ها عبور می‌کنند. خطاها شمارش می‌شوند.

OPEN

پس از رسیدن به آستانه خطا، درخواست‌ها بلاک می‌شوند (۵۰۳). پس از recoveryTimeout به half-open می‌رود.

HALF-OPEN

تعداد محدودی درخواست آزمایشی ارسال می‌شود. موفقیت → closed، شکست → open.

پایپلاین Middleware

TighMiddleware هر درخواست را از طریق زنجیره‌ای از middlewareها عبور می‌دهد. دو middleware پیش‌فرض فعال هستند و فشرده‌سازی به‌صورت اختیاری در دسترس است:

corsMiddleware

تزریق هدرهای CORS و پاسخ ۲۰۴ به OPTIONS

timingMiddleware

اندازه‌گیری پاسخ + تزریق X-Request-Id

compressMiddleware

فشرده‌سازی gzip اختیاری در پاسخ‌های بزرگ

middleware/logger.ts
typescript
// افزودن middleware سفارشی
engine.use(async (req, next) => {
  const start = Date.now()
  const res = await next()
  console.log(`${req.method} ${req.path} → ${res.status} (${Date.now() - start}ms)`)
  return res
})

متریک‌ها

TighMetrics به‌طور خودکار برای هر درخواست latency، method، path و status code را ثبت می‌کند. percentileها به‌صورت بلادرنگ محاسبه می‌شوند.

P50 latency~20ms
P90 latency~20ms
P95 latency~20ms
P99 latency~20ms
AVG latency~12ms

اداپتور Next.js

createNextHandler(engine) یک NextRequest می‌گیرد و آن را به TighRequest تبدیل می‌کند، در موتور اجرا می‌کند، و پاسخ را به‌صورت Response استاندارد Web برمی‌گرداند.

app/api/(proxy)/route.ts
typescript
import { createNextHandler } from "@/lib/engine"
import { engine } from "@/lib/engine/instance"

export const dynamic = "force-dynamic"

export const GET = createNextHandler(engine)
// به همین سادگی تمام handlerهای شما از موتور عبور می‌کنند
// و از کش، rate limit، circuit breaker، و متریک بهره می‌برند.
LIVE

اندپوینت‌های موتور

دو اندپوینت برای مشاهده وضعیت داخلی موتور — بدون احراز هویت:

متریک زنده

GET

latency p50-p99، hit rate کش، وضعیت مدار شکن، و uptime.

/api/engine/stats

بنچمارک

GET

اندازه‌گیری ns/op برای روتر، کش، و متریک با تعداد تکرار قابل تنظیم (پیش‌فرض ۱۰۰۰).

/api/engine/benchmark?iterations=5000
مشاهده صفحه ساختار با متریک کامل
STEP-BY-STEP

فورک کردن و توسعه موتور

موتور تیغ طوری طراحی شده که به‌راحتی در پروژه شما قابل استفاده و گسترش باشد. این راهنما شما را از صفر تا استقرار یک نمونه سفارشی همراهی می‌کند.

۰۱

فورک کردن مخزن

روی صفحه گیت‌هاب، دکمه Fork را بزنید. مخزن به حساب شما کپی می‌شود.

step-۰۱.sh
bash
git clone https://github.com/YOUR-USER/Persian-Quote-API.git
cd Persian-Quote-API
bun install

نکته: پس از نصب، پروژه آماده اجرا است. دستور bun run dev سرور توسعه را روی پورت ۳۰۰۰ بالا می‌آورد.

۰۲

آشنایی با ساختار موتور

تمام منطق موتور در lib/engine/ است. مهم‌ترین فایل برای ویرایش instance.ts است که پیکربندی سراسری موتور را نگه می‌دارد.

step-۰۲.sh
bash
// lib/engine/instance.ts
import { Tigh } from "./engine"

export const engine = new Tigh({
  enableCache: true,           // کش LRU داخلی
  enableRateLimit: true,       // محدودسازی نرخ
  enableCircuitBreaker: true,  // مدار شکن خودترمیم
  cache: {
    maxSize: 5000,             // حداکثر کلید
    defaultTTL: 30_000,        // ۳۰ ثانیه
  },
  rateLimit: {
    windowMs: 60_000,          // ۶۰ ثانیه
    maxRequests: 120,          // ۱۲۰ درخواست
    strategy: "token-bucket",
  },
})

نکته: تغییر این مقادیر بلافاصله روی رفتار تمام اندپوینت‌های موتور اعمال می‌شود.

۰۳

افزودن اندپوینت سفارشی

هر فایل در app/api/*/route.ts می‌تواند از موتور استفاده کند یا مستقل باشد. الگوی کنونی: route ها مستقیماً NextResponse برمی‌گردانند — برای استفاده از موتور، ساختار را به handler-based تغییر دهید.

step-۰۳.sh
bash
// app/api/hello/route.ts
import { createNextHandler } from "@/lib/engine"
import { engine } from "@/lib/engine/instance"

engine.get("/api/hello", async (req) => {
  return {
    status: 200,
    headers: { "Content-Type": "application/json" },
    body: { greeting: "سلام", lang: req.headers["accept-language"] },
  }
}, {
  cache: { ttl: 60_000 },
})

export const GET = createNextHandler(engine)

نکته: نکته: route.register در زمان import اجرا می‌شود، پس فایل را در hot reload لازم نیست دوباره import کنید.

۰۴

سفارشی‌سازی ماژول‌ها

تمام ماژول‌ها قابل جایگزینی هستند: TighRouter، TighCache، TighRateLimiter، TighCircuitBreaker، TighMiddleware.

step-۰۴.sh
bash
// نمونه: جایگزینی کش با نسخه ردیس-مانند
import { Tigh } from "./engine"
import { MyRedisCache } from "./my-redis-cache"

const engine = new Tigh({
  cache: { maxSize: 100_000, defaultTTL: 300_000 }
})
engine.cache = new MyRedisCache({ url: process.env.REDIS_URL! })

نکته: کافی است اینترفیس عمومی هر ماژول را پیاده کنید و در سازنده Tigh جایگزین کنید.

۰۵

نوشتن تست با Bun Test

چون موتور صفر وابستگی دارد، تست‌نویسی بسیار ساده است.

step-۰۵.sh
bash
// tests/cache.test.ts
import { test, expect } from "bun:test"
import { TighCache } from "../lib/engine/cache"

test("TighCache respects TTL", () => {
  const c = new TighCache({ maxSize: 10, defaultTTL: 50 })
  c.set("k", "v")
  expect(c.get("k")).toBe("v")
  Bun.sleep(60)
  expect(c.get("k")).toBeNull()
})

test("TighCache evicts LRU", () => {
  const c = new TighCache({ maxSize: 2 })
  c.set("a", 1); c.set("b", 2); c.get("a"); c.set("c", 3)
  expect(c.has("a")).toBe(false)
})

نکته: bun test تمام تست‌ها را اجرا می‌کند. CI از bun test bun.lock استفاده می‌کند.

۰۶

استقرار

پروژه استاندارد Next.js است — Vercel به‌طور خودکار آن را تشخیص می‌دهد.

step-۰۶.sh
bash
# روی Vercel
vercel deploy

# یا با GitHub Actions
git push origin main   # در Vercel فعال باشد، خودکار deploy می‌شود

نکته: پس از deploy، به /sakhtar بروید و متریک زنده موتور را در production ببینید.

پس از فورک

اگر بهبودی در موتور اعمال کردید که به نفع همه است، یک Pull Request به مخزن اصلی بفرستید. راهنمای مشارکت در AGENTS.md توضیح داده شده است — به‌ویژه قاعده ثبت در changelog و لحن رسمی-دوستانه.

AUTOMATE

پرامپت‌های آماده برای دستیارها

اگر با Cursor، Claude Code یا Codex کار می‌کنید، کافی است یکی از پرامپت‌های زیر را کپی کنید و در دستیار خود paste کنید. پاسخ را به فارسی یا انگلیسی تنظیم کرده‌ایم.

توضیح کامل معماری موتور

از دستیار بخواهید ساختار lib/engine را به فارسی توضیح دهد و رابطه بین ماژول‌ها را بنویسد.

شناختCursorClaude Codeهمه
You are inside /home/arsam/Documents/work/Website/Webdev/Persian-Quote-API. Read every file under lib/engine/*.ts. Produce a written map (under 400 words) of every module: name, exports, role, and how it wires to engine.ts. Reply in Persian with code snippet citations.

ساخت اندپوینت جدید با موتور

یک اندپوینت GET که با موتور تیغ اجرا می‌شود، کش دارد، و از circuit breaker پیروی می‌کند.

توسعهCursorClaude CodeCodex
Create app/api/quotes/by-tag/[tag]/route.ts that uses Tigh from lib/engine. The handler must: import sampleQuotes from lib/data/poetry-quotes.json, filter where tags contains the [tag] param, return at most 50 results, attach cache { ttl: 60_000, key }, and surface non-200 status via the engine's circuit breaker. Show the full file and explain each engine call.

تنظیم TTL هر مسیر

بررسی الگوی ترافیک هر اندپوینت و پیشنهاد TTL اختصاصی — با قطعه کد.

بهینه‌سازیCursorClaude Codeهمه
Open lib/engine/instance.ts and lib/engine/cache.ts. Scan app/api/**/route.ts and propose: a per-route defaultTTL (short 10s for /search, medium 60s for /quotes/*, long 24h for /hafez, /shereno). Produce a diff for instance.ts plus a snippet showing engine.route({ cache: { ttl, key } }) for one route. Quantify expected hit-rate improvement.

اشکال‌زدایی Latency

تحلیل داده‌های زنده و ارائه دو پیشنهاد برای رساندن P99 به زیر ۵۰ms.

اشکال‌زداییCursorClaude Codeهمه
Hit GET /api/engine/stats and parse latency.p50/p90/p95/p99 plus cache.hitRate. Identify the top 3 slowest paths from topPaths. Suggest two concrete optimizations (cache key rewrite, eager prewarm, or middleware reorder) that should bring p99 below 50ms. Show diffs and explain trade-offs.

استقرار روی Vercel

راهنمای کامل env vars، build command، و تنظیمات لبه.

استقرارCursorClaude CodeCodex
Walk me through a full Vercel deployment of /home/arsam/Documents/work/Website/Webdev/Persian-Quote-API. Provide: the exact env vars (none required, but list any optional for future use), build/dev commands, a minimal vercel.json that pins Node.js 20 and maximizes the cron quota, and a check that the JSON imports in lib/data/*.json remain valid on the Edge runtime.

افزودن تست‌های موتور

ساخت تست واحد برای هر ماژول با Bun Test.

توسعهCursorClaude CodeCodex
Create tests/ folder with bun:test unit tests for every module in lib/engine: TighRouter (param + wildcard match), TighCache (LRU eviction, TTL expiration), TighRateLimiter (each strategy), TighCircuitBreaker (state transitions), TighMetrics (percentile accuracy). Group tests by module. No external libraries; pure assertions.

خلاصه PR برای بازبینی

از تغییرات فعلی یک توصیف کوتاه و حرفه‌ای برای ارسال به GitHub PR بساز.

شناختCursorClaude Codeهمه
Look at the currently changed files (git status / git diff --staged). Write a Persian PR description under 250 words: a one-line summary, a section of files changed, and a checklist of what to verify before merging. Keep language formal and direct — no marketing adjectives.

Refactor یک اندپوینت موجود

تبدیل یکی از route.tsهای موجود به استفاده کامل از موتور (به‌جای NextResponse مستقیم).

توسعهCursorClaude Codeهمه
Pick app/api/quotes/route.ts. Refactor it to delegate to engine via createNextHandler(engine) from lib/engine/adapter-next.ts. Register the route inside instance.ts via engine.get("/api/quotes", ...), wire cache { ttl, key } and rateLimit config. Provide a step-by-step diff and explain how NextRequest becomes the engine Request shape.

نحوه استفاده

  1. روی یکی از کارت‌ها دکمه «کپی» را بزنید.
  2. در پنل دستیار، متن کپی‌شده را paste کنید.
  3. پاسخ را بخوانید، تغییرات را مرور کنید، و در صورت نیاز PR ثبت کنید.

در مستندات بیشتر درباره هر پرامپت، روی عنوان کارت کلیک کنید تا به بخش مربوط به آن هدایت شوید.

نمونه‌های کاربردی

چهار سناریوی واقعی برای استفاده از API — از ساده‌ترین تا یکپارچه‌سازی کامل در رابط کاربری.

نمایش شعر روز در سایت

هر روز یک شعر جدید به بازدیدکنندگان نشان دهید.

javascript
const today = new Date().toISOString().slice(0, 10)
const res = await fetch(
  `https://pq.arsamadineh.ir/api/quotes?random=true&limit=1&cacheBust=${today}`
)
const { data } = await res.json()
// data[0].text_persian

ویجت فال حافظ

یک iframe ساده برای نمایش فال حافظ در سایت شخص ثالث.

html
<iframe
  src="https://pq.arsamadineh.ir/api/embed?theme=classic&poet=hafez&auto_refresh=true"
  width="400"
  height="280"
  style="border: 0; border-radius: 12px;"
  loading="lazy"
></iframe>

تست بار (Load Test)

اندازه‌گیری latency واقعی از سمت کاربر.

python
import asyncio, aiohttp, time

async def hit(session, url):
    async with session.get(url) as r:
        return r.status, await r.json()

async def main():
    url = "https://pq.arsamadineh.ir/api/quotes?random=true"
    async with aiohttp.ClientSession() as s:
        start = time.time()
        results = await asyncio.gather(*[hit(s, url) for _ in range(100)])
        print(f"100 reqs in {time.time() - start:.2f}s")

asyncio.run(main())

اپ موبایل (React Native)

یک اپ ساده برای مرور اشعار، با کش محلی برای آفلاین.

tsx
import { useEffect, useState } from "react"
import AsyncStorage from "@react-native-async-storage/async-storage"

export function QuoteScreen() {
  const [quote, setQuote] = useState(null)
  useEffect(() => {
    AsyncStorage.getItem("quote").then(setQuote)
  }, [])
  const refresh = async () => {
    const r = await fetch("/api/quotes?random=true&limit=1")
    const j = await r.json()
    setQuote(j.data[0])
    AsyncStorage.setItem("quote", JSON.stringify(j.data[0]))
  }
  return /* ... */
}

استقرار و خودمیزبانی

سه روش برای راه‌اندازی یک نمونه شخصی — از ساده‌ترین (Vercel) تا کنترل کامل (Docker).

  1. مخزن را به حساب گیت‌هاب خود fork کنید.
  2. به vercel.com بروید و «New Project» را بزنید.
  3. مخزن fork شده را انتخاب کنید. Vercel به‌طور خودکار Next.js را تشخیص می‌دهد.
  4. روی «Deploy» کلیک کنید. در کمتر از یک دقیقه نمونه شما فعال می‌شود.
  5. برای custom domain، از تنظیمات پروژه دامنه را اضافه کنید.

هیچ متغیر محیطی لازم نیست — تمام داده‌ها فایل‌های JSON محلی هستند.

پشتیبان‌گیری از داده‌ها

فایل‌های JSON در lib/data/ منبع حقیقتی هستند. برای افزودن شعر جدید، یا فایل JSON را ویرایش کنید، یا از فرم /contribute استفاده کنید تا یک PR خودکار ساخته شود.

عیب‌یابی

رایج‌ترین مشکلات و راه‌حل‌های آن‌ها.

CORS بلاک می‌کند

علائم: در مرورگر خطای «blocked by CORS policy» می‌بینید.
علت: معمولاً به دلیل استفاده از endpoint قدیمی یا فراخوانی مستقیم بدون HTTPS.
رفع: مطمئن شوید URL با https شروع می‌شود و /api/embed?… در iframe همیشه موفق است.

کش stale شده

علائم: تغییرات در lib/data/*.json بلافاصله دیده نمی‌شود.
علت: موتور کش داخلی دارد که برای ۳۰ ثانیه تا ۵ دقیقه نگه می‌دارد.
رفع: یا صبر کنید، یا کش را با ?cacheBust=<timestamp> در URL بشکنید، یا در production: curl /api/engine/stats | grep cache.hitRate برای بررسی وضعیت.

دریافت ۴۲۹ (Too Many Requests)

علائم: تعداد بالای درخواست در کمتر از یک دقیقه.
علت: Rate limit پیش‌فرض ۱۲۰ درخواست در دقیقه به ازای هر IP است.
رفع: صبر کنید تا پنجره زمانی ریست شود، یا اگر نمونه خودتان است، maxRequests در lib/engine/instance.ts را افزایش دهید.

مدار شکن باز است (۵۰۳)

علائم: بعضی درخواست‌ها خیلی سریع با 503 پاسخ می‌گیرند.
علت: تعداد خطاها به آستانه (failureThreshold پیش‌فرض ۵) رسیده است.
رفع: recoveryTimeout پیش‌فرض ۳۰ ثانیه است. موتور خودکار بهبود می‌یابد. در نمونه سفارشی، recoveryTimeout را تنظیم کنید.

P99 بالا (بیش از ۲۰۰ms)

علائم: بعضی درخواست‌ها کند هستند.
علت: عدم کش، یا cache key نادقیق، یا I/O در handler.
رفع: از /api/engine/stats مقدار p99 را بخوانید، سپس در lib/engine/instance.ts برای route های پرکاربرد cache.ttl اختصاصی تعریف کنید.

مدیریت خطاها

کدهای HTTP استاندارد و ساختار پاسخ‌های خطا.

200درخواست موفقموفقیت
400پارامتر نامعتبرهشدار
404منبع یافت نشدهشدار
429تعداد درخواست بیش از حدهشدار
503سرویس موقتاً در دسترس نیست (مدار شکن)خطا

نمونه پاسخ خطا

RESPONSE.JSON
json
{
  "error": "No quotes found for this poet",
  "poet": "شاعر نامعلوم",
  "suggestion": "Available poets: مولانا, حافظ, سعدی, فردوسی"
}

آماده‌اید موتور را امتحان کنید؟

به صفحه متریک زنده بروید و عملکرد موتور را در زمان واقعی ببینید. یا فورک کنید و برای پروژه خودتان سفارشی‌سازی کنید.