تمپلیت شروع

یک اپ Next.js کامل و آماده روی سیستم طراحی پرتو، با یک قالب برای هر نوع صفحه — کپی کنید و شروع کنید

معرفی

تمپلیت شروع (apps/starter در ریپوی سیستم طراحی) یک اپ Next.js کامل است که همه‌ی سیم‌کشی مصرف پرتو در آن از قبل و به روش رسمی انجام شده است. به‌جای آنکه برای هر اپ جدید از صفر تصمیم بگیرید «کدام import، کدام تنظیم، فونت چطور، شل چطور»، این پوشه را کپی می‌کنید و مستقیم سراغ ساختن محصول می‌روید.

آنچه از پیش آماده است:

  • تم تاریک + RTL + فونت یکان بخ (فونت داخل خود پکیج است — هیچ تنظیم اضافه‌ای لازم نیست)
  • رسپی رسمی مصرف: فقط @import '@partodata/ui/tailwind.css' بعد از tailwindcss (راهنمای نصب)
  • قاب محصول ProductFrame، یک بار در لایهٔ گروه مسیر (app) (app/(app)/layout.tsx، از طریق app/frame.tsx) دور همهٔ صفحه‌های محصول — صفحهٔ ورود در گروه (auth) بیرون از آن است — با منوی داده‌محور (lib/nav.tsx)، مقصد فعال از pathname، پیوندهای next/link از راه linkComponent — بی سوییچر تم و منوی کاربر، چون این محصول آن‌ها را ندارد (هر دو فقط وقتی شرح محصول بخواهد)
  • هر نوع صفحه یک بار، هر کدام با یک قالب صفحه:
مسیرصفحهقالب
/داشبورد: بازهٔ زمانی، شاخص‌ها، نمودارها و جدول موضوع‌هاDashboardPage
/mentionsفهرست منشن‌ها: جست‌وجو، دو فیلتر، بازهٔ تاریخ، خروجی، صفحه‌بندی و همهٔ حالت‌هاListPage
/mentions/[id] · /mentions/[id]/commentsیک منشن در layout.tsx: بازگشت، برچسب‌ها، ستون کناری و دو زبانه که هر کدام نشانی خودشان را دارندDetailPage
/mentions/reportگزارش چاپی: خلاصه و همهٔ منشن‌های دوره؛ «چاپ» خود صفحه را، بدون نوار و منو، چاپ می‌کندDetailPage
/settings/alertsتنظیمات هشدار: یک فرم با اعتبارسنجی (react-hook-form و FormRow)FormPage
/searchجست‌وجوی پست‌ها: جست‌وجوی اول‌محور با ارسال و جست‌وجوی پیشرفته، فید پست‌ها در عرض خواندن، ستون کناری خلاصه، دو نمای «نتایج» و «تحلیل»، «نمایش بیشتر»ListPage (query، content="feed")
/sources · /sources/active · /sources/paused · /sources/errorمنبع‌ها: زبانه‌های وضعیت با شمار، نوار خلاصه، «نمایش بیشتر» برای API بی‌شمارشListPage (tabs، summary، loadMore)
/sources/[id] · /sources/[id]/postsگزارش یک منبع در layout.tsx: بازهٔ زمانی، زبانهٔ پست‌ها با جست‌وجو، فیلتر و صفحه‌بندی خودشDetailPage (period)
/liveپخش زنده: تازه‌شدن خودکار هر 15 ثانیه بی اسکلت، «آخرین به‌روزرسانی»، تازه‌شدن ناموفق با اعلان و دادهٔ حفظ‌شده، یک کانال در کشوی متصل به نشانی (?channel=)ListPage + EntityDrawer
/reportsبخشی که هنوز خالی استUtilityPage
/loginورود، بیرون از قاب (گروه مسیر (auth))AuthPage
هر نشانی دیگر (not-found)صفحهٔ 404، داخل قابUtilityPage
  • دادهٔ نمونه پشت یک API ساختگی با تأخیر کوتاه (lib/data.ts)، تا حالت بارگذاری هر صفحه‌ای که داده می‌خواند دیده شود؛ جست‌وجوی «خطا» در منشن‌ها یا پست‌ها حالت خطا و «تلاش مجدد» را نشان می‌دهد، فیلتری که نتیجه ندارد حالت «نتیجه‌ای یافت نشد»، هر چهارمین تازه‌شدن پخش زنده شکست می‌خورد (داده می‌ماند و اعلان «تلاش مجدد» می‌آید)، و ورود با گذرواژهٔ parto انجام می‌شود.
  • یک قاعدهٔ import برای همهٔ کد اپ: همه‌چیز از @partodata/ui، و ورودی‌هایی که فقط subpath دارند (templates، product-frame، form، theme-toggle، icons) از subpath خودشان — هیچ subpath دیگری حدس زده نمی‌شود
  • عنوان سند هر صفحه: title.template در app/layout.tsx و metadata (یا generateMetadata برای یک منشن یا منبع) در هر مسیر
  • AGENTS.md (و CLAUDE.md) که ایجنت کدنویسی را به راهنمای داخل پکیج (node_modules/@partodata/ui/AGENTS.md) می‌فرستد
  • قاعده‌های ESLint خود سیستم طراحی (configs.recommended از @partodata/ui/eslint-plugin، از جمله parto/page-primary-action، parto/page-template و parto/form-row) در eslint.config.mjs، با پارسر typescript-eslint روی همهٔ فایل‌های .ts/.tsx (از جمله app/)

پیش‌نمایش زنده

پیش‌نمایش، خودِ اپ است — همان فایل‌های screens/ و lib/nav.tsx، نه نسخه‌ای از آن‌ها — تمام‌صفحه و در یک برگه‌ی جدا باز می‌شود تا تجربه‌ی واقعی قاب و ناوبری را ببینید. از منوی قاب بین صفحه‌ها جابه‌جا شوید، روی نام نویسندهٔ یک منشن بزنید تا صفحهٔ جزئیات و زبانه‌هایش باز شود، و در فرم تنظیمات هشدار نام هشدار را پاک و ذخیره کنید تا خطای اعتبارسنجی را ببینید. در «پخش زنده» روی نام یک کانال بزنید تا کشوی آن باز شود و با J و K بین کانال‌ها بروید، و در «منبع‌ها» بین زبانه‌های وضعیت جابه‌جا شوید و «نمایش بیشتر» را بزنید.

مشاهده پیش‌نمایش در برگه جدید

چرا در برگه جدید؟

این پیش‌نمایش یک اپ کامل با قاب تمام‌صفحه است. رندر آن داخل صفحه‌ی مستندات، هم پیش‌نمایش را کوچک و ناخوانا می‌کند و هم با لی‌آوت مستندات تداخل دارد — پس همیشه در صفحه‌ی مستقل خودش باز می‌شود.

اجرا داخل مونوریپو

pnpm install
pnpm --filter @partodata/ui build       # اول پکیج DS ساخته شود
pnpm --filter @partodata/starter dev    # http://localhost:4300

pnpm dev در ریشه‌ی مونوریپو عمداً starter را اجرا نمی‌کند (فقط docs + ui) تا محیط توسعه سبک بماند. starter را همیشه با فیلتر بالا اجرا کنید.

ساخت اپ جدید از روی تمپلیت

  1. پوشه را به بیرون از ریپو کپی کنید:
cp -r apps/starter ~/my-new-app && cd ~/my-new-app
  1. در package.json وابستگی workspace را به نسخهٔ منتشرشده تغییر دهید:
- "@partodata/ui": "workspace:*",
+ "@partodata/ui": "^7.13.0",
  1. نصب و اجرا:
npm install
npm run dev

ساختار فایل‌ها

app/
  globals.css                   ← رسپی مصرف (دو @import)
  layout.tsx                    ← html با lang="fa" dir="rtl"، هر دو نشانگر تیره، Toaster یک بار
  frame.tsx                     ← ProductFrame (Client Component با usePathname، linkComponent={Link})
  not-found.tsx                 ← هر نشانی دیگر، داخل قاب  → screens/not-found.tsx
  (app)/layout.tsx              ← <Frame> یک بار دور همهٔ صفحه‌های محصول (گروه مسیر: بخشی از نشانی نیست)
  (app)/page.tsx                ← /                         → screens/dashboard.tsx
  (app)/mentions/page.tsx       ← /mentions                 → screens/mentions.tsx
  (app)/mentions/[id]/layout.tsx ← صفحهٔ یک منشن (سربرگ، زبانه‌ها، ستون کناری) → screens/mention.tsx
  (app)/mentions/[id]/page.tsx  ← /mentions/[id]            → زبانهٔ «پست»
  (app)/mentions/[id]/comments/page.tsx ← /mentions/[id]/comments → زبانهٔ «نظرات»
  (app)/mentions/report/page.tsx ← /mentions/report         → screens/mentions-report.tsx (گزارش چاپی)
  (app)/search/page.tsx         ← /search                   → screens/post-search.tsx
  (app)/sources/page.tsx        ← /sources (و active/، paused/، error/ برای زبانه‌های وضعیت) → screens/sources.tsx
  (app)/sources/[id]/layout.tsx ← گزارش یک منبع (سربرگ، بازهٔ زمانی، زبانه‌ها) → screens/source.tsx
  (app)/sources/[id]/page.tsx   ← /sources/[id]             → زبانهٔ «نمای کلی»
  (app)/sources/[id]/posts/page.tsx ← /sources/[id]/posts   → زبانهٔ «پست‌ها»
  (app)/live/page.tsx           ← /live                     → screens/live.tsx
  (app)/settings/alerts/page.tsx ← /settings/alerts         → screens/alert-settings.tsx
  (app)/reports/page.tsx        ← /reports                  → screens/reports.tsx
  (auth)/login/page.tsx         ← /login، بیرون از قاب       → login.tsx (پس از ورود، router.push) → screens/login.tsx
  icon.svg                      ← favicon برند
screens/                        ← هر صفحه: یک قالب از @partodata/ui/templates که جایگاه‌هایش پر شده است
lib/
  nav.tsx                       ← منوی قاب به‌صورت داده، نام محصول و منوی کاربر
  data.ts                       ← API ساختگی؛ با API محصول جایگزین کنید
next.config.mjs                 ← transpilePackages: ['@partodata/ui'] (اجباری)
postcss.config.js               ← @tailwindcss/postcss
eslint.config.mjs               ← قاعده‌های ESLint سیستم طراحی برای کد خود اپ (pnpm lint)
AGENTS.md، CLAUDE.md            ← ایجنت کدنویسی را به راهنمای داخل پکیج می‌فرستد

هر page.tsx فقط صفحهٔ خودش را از screens/ رندر می‌کند؛ صفحه‌ها در screens/ اند تا پیش‌نمایش همین مستندات هم همان‌ها را رندر کند. در اپ خودتان صفحه را می‌توانید مستقیم در page.tsx بنویسید.

قاب محصول لایهٔ گروه مسیر (app) است، نه لایهٔ ریشه: صفحه‌ای که بیرون از محصول است — ورود، کد یک‌بارمصرف، بازیابی گذرواژه — در گروه (auth) می‌نشیند و قالب AuthPage را پر می‌کند. نام گروه در نشانی نمی‌آید: app/(auth)/login/page.tsx همان /login است.

صفحه‌ای که زبانه دارد، مثل یک منشن، قالبش را در layout.tsx همان بخش می‌گذارد و هر زبانه یک page.tsx زیر آن است که فقط بخش‌های خودش را رندر می‌کند. این‌طور با رفتن از یک زبانه به دیگری سربرگ، زبانه‌ها و دادهٔ صفحه سر جایشان می‌مانند و تمرکز صفحه‌کلید روی زبانه‌ای که انتخاب شده باقی می‌ماند.

صفحهٔ تازه یک پوشه با page.tsx است که یک قالب را پر می‌کند (قالب را با جدول انتخاب پیدا کنید) و یک آیتم در منوی lib/nav.tsx؛ قاب را در صفحه دوباره نسازید و صفحه را از PageContainer و PageHeader دستی نسازید.

بهترین روش‌ها

بکنید

  • از همین تمپلیت برای هر اپ جدید شروع کنید — سیم‌کشی آن همان «مسیر طلایی» مستندات است. - importها را همان‌طور نگه دارید: همه‌چیز از @partodata/ui، و فقط ورودی‌هایی که در بارل نیستند از subpath خودشان؛ subpath حدس نزنید. - توابع lib/data.ts را با API محصول جایگزین کنید؛ ساختار صفحه‌ها (قاب در layout، یک قالب در هر صفحه، حالت‌ها با pageState، یک اقدام اصلی در primaryAction) را نگه دارید. - eslint.config.mjs (پیکربندی recommended از @partodata/ui/eslint-plugin) را نگه دارید و pnpm lint را در CI محصول اجرا کنید تا قاعده‌های سیستم طراحی، از جمله یک اقدام اصلی در هر صفحه، روی کد خود اپ چک شوند.

نکنید

  • فونت را جداگانه self-host نکنید — یکان بخ داخل پکیج است و خودکار بارگذاری می‌شود. - transpilePackages را حذف نکنید — بدون آن build با SyntaxError شکست می‌خورد. - رنگ hardcode نکنید — همه‌ی رنگ‌ها از توکن‌های معنایی (رنگ‌ها).

صفحات مرتبط