Files
arsam e9cd12dda6 Import remaining project documentation and reference notes
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
2026-09-18 23:33:04 +03:30

26 KiB
Raw Permalink Blame History

PHASES.md

Completion log. Active work and future roadmap live in ARCH.md.

Current Production Baseline

Teknav is a Persian RTL Vite/React SPA backed by Fastify, Prisma, PostgreSQL, Redis, Argon2id sessions, CSRF, Persian search, SEO artifacts, admin CMS APIs, media uploads, scheduled publishing, SMTP email flows, and Kavenegar OTP. Production deployment is native Linux/systemd with nginx on https://www.teknav.ir; Docker is not the current deployment target.

Phase 1 - Frontend: Zero CDN + Vite

Shipped.

  • Vite 5 + React 18.3.1 with ES modules.
  • Removed unpkg, Google Fonts, and CDN scripts.
  • Local font loading from public/fonts/.
  • scripts/check-no-cdn.mjs runs on npm run build.
  • Dev/preview port is locked to 3009.

Phase 2 - Database + Seed

Shipped.

  • Backend workspace in backend/.
  • Prisma schema for users, authors, categories, tags, articles, reactions, saved articles, newsletter subscribers, activity logs, and media assets.
  • Persian FTS function/indexes are applied idempotently from backend/prisma/seed.ts.
  • Seed imports teknav-data.js, hashes credentials with Argon2id, and creates the three real Teknav authors.
  • Staff seed credentials live in backend/prisma/credentials.json; operator-facing credentials live in ignored ACCOUNTS.md.

Phase 3 - Auth

Shipped.

  • Redis-backed sessions with tek_sid and tek_csrf.
  • Login/logout/me APIs in backend/src/routes/auth.ts.
  • CSRF middleware for mutating routes.
  • Login/signup captcha and per-IP rate limiting.
  • Frontend AuthProvider uses /api/v1/auth/* on the wire; no localStorage auth source.

Phase 4 - Public API + Caching

Shipped.

  • Public articles, categories, tags, authors, search, newsletter, save, and reaction APIs.
  • Redis response caching, search caching, newsletter rate limiting, and buffered article view counters.
  • Public pages use src/lib/content-api.js.

Phase 5 - Admin/CMS API

Shipped.

  • Role-gated article CRUD, publish, schedule, category/tag/user/author management, uploads, activity logs, and dashboard metrics.
  • Admin panels use src/lib/admin-api.js and show real API data only.
  • No mock/example data should appear in admin, writer, reviewer, media, activity, or dashboard views.
  • Media uploads are tracked in MediaAsset; admin/editor media library is backed by /api/v1/admin/media.

Phase 6 - Native Deployment

Shipped.

  • Production runbook: DEPLOY.md.
  • nginx templates: nginx/nginx.conf.example and nginx/nginx.default.conf.
  • systemd assets: deploy/systemd/teknav-backend.service, teknav-migrate.service, teknav-publish-due.service/.timer, and teknav-backup.service/.timer.
  • Log rotation: deploy/logrotate/teknav.
  • Backups: scripts/systemd-backup.sh.
  • Schema application: backend/scripts/apply-schema.mjs via npm run prisma:apply.

Phase 7 - Production CMS Readiness

Shipped.

  • Public profiles and profile editing.
  • Avatar uploads and WebP conversion support.
  • HTML article editor with image upload.
  • Email verification and password reset via SMTP.
  • Phone OTP via Kavenegar.
  • Article scheduling and due-publish timer.
  • Activity CSV export.
  • Persian SEO metadata, canonical www.teknav.ir, sitemap, robots, and RSS feed.
  • Three writer-admin seed accounts added for آرسام صباغ, رادمان قلیچی, and سیداحمدرضا محجوب.

Phase 8 - Engagement + Real-Time Admin

Implemented; Linux validation pending.

  • Prisma schema adds comments, comment flags, reading history, notifications, and writer follows.
  • Article pages include real API-backed comments/replies, flagging, history tracking, and comment count.
  • Header notifications use authenticated SSE at /api/v1/auth/notifications/stream.
  • Writer profiles expose follower count and follow/unfollow; own profile shows reading history and followed writers.
  • Admin/editor dashboard uses SSE at /api/v1/admin/stream for active visitors, activity, and live view counter updates.
  • Admin/editor comments panel supports flagged filtering, delete, and clear-flag actions.
  • nginx templates disable buffering/compression for SSE stream paths.

Phase 9 - Content Modernization + Publication Features

Implemented. Linux production validation pending.

  • Prisma schema adds article SEO fields, daily article view logs, comment likes, newsletter campaigns, article series, editorial review workflow, and reading lists.
  • Public API adds related articles, series pages, newsletter unsubscribe, comment likes, and reading-list endpoints.
  • Admin API adds analytics, review queue, newsletter campaign send/list, and series CRUD endpoints.
  • Frontend article pages consume richer SEO metadata, expose comment likes, keep related articles API-backed, and route public series pages at /series/:slug.
  • Admin panel adds API-backed Phase 9 sections for analytics, review workflow, newsletter campaigns, and article series.
  • teknav-data.js finalizes Phase 9 seed/reference metadata: 23 published articles, refreshed dates, canonical paths, Open Graph metadata, and generated content for former placeholders.
  • scripts/generate-seo.mjs now uses dateModified, canonical paths, meta descriptions, and RSS content:encoded.
  • scripts/generate-og-images.mjs provides local OG image generation for article cards; install dependencies on Linux before use.
  • Series prev/next navigation banner added to article pages (SeriesNavBanner), pulling live series membership from the public article API.

Phase 10 - SEO Growth, Trust, and Writer Studio

Implemented. Linux production validation pending.

SEO and trust foundations

  • Public topic authority hubs at /topics/ai, /topics/security, /topics/software, /topics/hardware, /topics/startups, and /topics/data with CollectionPage, FAQPage, ItemList, and BreadcrumbList JSON-LD.
  • scripts/generate-seo.mjs covers topic hubs, public author profiles, glossary terms, newsletter archive, and /ACCOUNTS.md robots blocking.
  • Prisma schema adds editorial trust fields (factCheckedAt, reviewedById, sourceNotes, contentFreshnessStatus), TopicFollow, newsletter campaign slugs, and the first-party AnalyticsEvent table.
  • First-party analytics events for article views, newsletter subscriptions, saves, writer/topic follows, and share clicks.
  • Topic follows at /api/v1/topics/:slug/follow with counts on hub pages.
  • Public newsletter archive at /newsletter and /newsletter/:slug.
  • Role-aware panel metrics at GET /api/v1/admin/panel-metrics.
  • Article approval-to-publish quality gates: review workflow, Phase 10 metadata completion, cache refresh, and writer/topic follower notifications.
  • Public tag pages and GET /api/v1/articles?tag=....
  • Admin API adds GET /api/v1/admin/seo/audit, GET /api/v1/admin/analytics/content, GET /api/v1/admin/analytics/newsletter, GET /api/v1/admin/analytics/engagement.
  • npm run smoke:prod production health checks.

Community and retention

  • PWA with manifest.json, service worker, offline caching, and install prompt.
  • Personalized home feed (sort=personalized) using followed topics, followed writers, and read history.
  • Comment upvoting with best-comment sorting; expanded heart/fire/thinking reactions.
  • 5-day reading streaks and "Continue Reading" progress tracking.
  • Threaded article Q&A at /api/v1/articles/:slug/qa.
  • Glossary/dictionary term pages at /glossary/:slug.
  • "X vs Y" comparison templates with responsive comparison-table styling.

Auth and trust

  • Google/GitHub OAuth at /api/v1/auth/oauth/:provider.
  • SMS 2FA via Kavenegar OTP; tek_2fa ticket-based login completion.
  • Verified expert badges on author records, profiles, lists, and article bylines.
  • Published article corrections/errata via ArticleCorrection.
  • Google Discover readiness: 1200×630 local hero images, fetchPriority="high", max-image-preview:large.

Monetization foundations

  • /jobs with JobListing and company submission API.
  • /courses with course API and public page.
  • /membership premium membership page.
  • User.membershipTier, Article.premiumOnly, content locking for non-premium readers.
  • Article.sponsored and public "Promoted Content" labels.

Operations

  • Global Fastify rate limiting.
  • Bulk comment moderation.
  • First-party client error capture at /api/v1/errors.
  • backend/tests/phase10-smoke.test.mjs for auth/article/comment smoke coverage.
  • Weekly newsletter digest job: npm run newsletter:digest and teknav-weekly-digest.timer.

Writer Studio V5 (close-out polish)

  • HtmlEditor toolbar: grouped buttons (Formatting | Headings | Inline+Block | Lists | Media) with hover states; Bold/Italic labels styled; keyboard shortcuts Ctrl+B, Ctrl+I in editor and Ctrl+S to save draft globally.
  • Live word count and character count footer on the editor textarea.
  • WritingTipCard: manual prev/next navigation with position counter; auto-advance timer resets on manual nav.
  • ArtifactStudio diagram library: gradient placeholder cards replaced with live scaled DiagramRenderer compact mini-previews.
  • ArtifactStudio code mode: relabelled "code preview" with empty-state hint; was falsely claiming "live preview".
  • WeeklyChart data pipeline fixed: was reading non-existent weeklyViews; now correctly uses viewsByDay.slice(-7).map(d => d.views).
  • Analytics sparklines upgraded: full-width filled-area SVG with gradient, dot on latest point, "۳۰ روز پیش → امروز" axis labels.
  • Analytics table: sparklines prefetched for all articles on mount; inline 80×20 mini-sparkline per row; totals footer row; column header corrected to "روند اخیر".
  • Overview tab: amber needsRevision banner when reviewer has flagged articles; dynamic time-of-day greeting (صبح/ظهر/عصر/شب بخیر) with matching tagline.
  • Article editor meta-panel: fields grouped into "اطلاعات پایه", "زمان‌بندی", and collapsible "سئو پیشرفته" sections; slug field added to SEO section.
  • Article editor preview mode: renders selected diagram (DiagramRenderer) and subtitle above content.
  • Article editor: dirty-state indicator (● ذخیره نشده · Ctrl+S) shown when form has unsaved changes.
  • Article editor: amber "بازخورد ویراستار" banner when opening a نیازمند اصلاح article that has a reviewer note.
  • Articles list: hard cap of 15 replaced with show-more/less pagination button; reviewer note shown inline for revision-flagged rows.
  • Overview recent-articles: reviewer note shown inline for نیازمند اصلاح articles.
  • Comments tab: article title chip next to commenter name; "8-recent" cap note with redirect to article; button relabelled to direct to full comment thread.
  • Backend: articleInclude joins review { note, status }; publicArticle exposes reviewNote; this flows through writer dashboard, articles list, and editor.

Phase 11 — Platform Completeness

Implemented. Linux production validation pending.

Track 1 — Admin completeness

  • Sponsored / premiumOnly / featured toggle buttons in ArticleEditor meta-panel (flags group).
  • Content freshness filter dropdown (current / needs_update / scheduled_refresh / archived) in articles management list.
  • Dedicated SEO audit tab in AdminPanel — full paginated table with severity badges (خطا/هشدار/پیشنهاد) and per-article links; removed hard-capped inline audit from analytics panel.
  • Dedicated engagement analytics sub-tab inside analytics panel — 7-day bar chart, event-type breakdown table, top-5 articles.
  • Bulk comment moderation: checkbox per row, floating action bar (حذف/تأیید/علامت‌گذاری/لغو انتخاب), wired to existing POST /api/v1/admin/comments/bulk.

Track 2 — Reader UX

  • Article card reading list picker: bookmark icon (admin only for logged-in users) opens ReadingListModal from any card on the home feed.
  • Continue-reading progress overlay: progress bar + "ادامه مطالعه" chip on home feed cards when user has 5–95% progress via engagementApi.getStreaks().
  • Scheduled-publish topic notifications: backend/scripts/publish-due.mjs now also queries TopicFollow for the article's category and notifies topic followers (deduped against writer-follow notifications).
  • Google Search Console and Bing Webmaster placeholder verification files in public/ (google-token-placeholder.html, BingSiteAuth.xml).

Track 3 — Monetization

  • Premium gate card redesign: blurred/faded content with mask-image gradient, PremiumGateCard component with crown icon, 3-bullet benefit list, "عضویت ویژه" CTA, and "ورود به حساب" secondary for unauthenticated users.
  • Zarinpal membership subscription flow: POST /api/v1/membership/subscribe → Zarinpal payment request → gateway redirect; GET /api/v1/membership/callback → verify → upgrade User.membershipTier='premium' + membershipExpiresAt + Notification; GET /api/v1/membership/status; MembershipPage wired with live status and subscribe button; MembershipSuccessPage at /membership/success.
  • Job listing admin panel: GET /api/v1/admin/jobs (with status filter) and PATCH /api/v1/admin/jobs/:id (approve/reject/featuredUntil) in monetization.ts; JobsPanel component in admin sidebar; JobListing.featuredUntil field added to schema.
  • Premium enforcement confirmed: publicArticle() in public.ts already strips body and sets premiumLocked: true for non-premium users on premiumOnly articles.

Track 4 — Reliability

  • ClientError Prisma model: persists client errors from POST /api/v1/errors (was logging-only); GET /api/v1/admin/errors returns top-10 messages by count, daily counts (30 days), and 20 most recent raw errors; ClientErrorsPanel admin tab with daily sparkline, top-errors table, recent errors list.
  • StorageAdapter interface in backend/src/lib/storage.ts: LocalStorageAdapter (default, active on STORAGE_BACKEND=local or unset — all uploads go to config.UPLOAD_DIR), S3StorageAdapter stub (activate with STORAGE_BACKEND=s3; not yet wired to a real S3 client). Upload handler in admin.ts switched to use the adapter.
  • Schema additions: ClientError, MembershipPayment, JobListing.featuredUntil, NotificationType.system.

Data completeness

  • teknav-data.js expanded to 32 articles (art1–art32) with full content via article-contents-*.js files; all contentFreshnessStatus values corrected from fresh/stable to current.

Phase 12 — Web Push + Published Article Editing

Implemented. Linux production validation pending (VAPID keys + web-push install + PushSubscription schema apply).

Web push notifications

  • PushSubscription Prisma model: id, userId, endpoint (unique), auth, p256dh, userAgent, createdAt; @@index([userId]); cascade-delete on user removal.
  • backend/src/lib/push.ts: VAPID init guarded by env var presence (no-op if unconfigured); buildPushPayload() maps all 8 NotificationType values to Persian {title, body, url, icon}; sendPushToUser() queries subscriptions, sends via web-push, auto-deletes expired (410) endpoints.
  • Three new authenticated routes in notifications.ts: GET /api/v1/auth/push/vapid-key (returns public key), POST /api/v1/auth/push/subscribe (upsert by endpoint), DELETE /api/v1/auth/push/unsubscribe.
  • createNotification() in realtime.ts extended: fire-and-forget sendPushToUser() call after SSE publish; in-app notification path unchanged.
  • Service worker: push event handler shows RTL/Persian notification with badge; notificationclick handler focuses existing window or opens new one at data.url.
  • pushApi client in engagement-api.js: getVapidKey(), isSubscribed(), subscribe(), unsubscribe() with CSRF token from cookie.
  • PushNotificationPrompt dismissible banner in teknav-ui.jsx: shown to authenticated users when Notification.permission === 'default' and not previously dismissed; bottom-right dark overlay, RTL.
  • Push toggle in ProfileSettingsModal (teknav-profile.jsx): handles enabled / blocked / unsupported states; calls pushApi.subscribe() / unsubscribe().

Published article editing

  • ArticleEditor accepts role prop (default 'writer'); derives isPublished and canPublishDirectly (true for admin/editor).
  • Info banners: blue for writers (changes go to draft/review), green for admin/editor (direct publish with Ctrl+S note).
  • Button set branches: admin/editor on published article → "بروزرسانی و انتشار" / "تبدیل به پیش‌نویس" / "زمان‌بندی مجدد"; writer on published article → "ذخیره پیش‌نویس" / "ارسال برای بررسی مجدد".
  • Backend PATCH bug fixed in admin.ts: removed PUBLISHED → PENDING conversion in bulk data update; requestedStatus === PUBLISHED is now excluded from the initial DB write and handled cleanly by the existing publishArticleWithPhase10Checks() block (preserves original publishedAt, runs quality gates).
  • quality_check_failed (409) error surfaced in ArticleEditor save handler — shows specific issue list via toast.

Bug fixes

  • scripts/generate-seo.mjs: local xml variable inside url() function renamed to lines; was shadowing the outer xml() HTML-escape function, causing image titles to not be escaped.

Phase 13 — Community Depth + Writer Tools

Implemented. Linux production validation pending (requires prisma:apply for new schema additions).

Schema additions

  • PushSubscription.userId made nullable (supports guest subscriptions); topics String[] array added.
  • NotificationPreference model: per-user, per-eventType, per-channel (push/email/sms) opt-out toggle; defaults to enabled.
  • UserBadge model: earned reading badges (AI enthusiast, streak-7, etc.) with @@unique([userId, badgeType]).
  • ArticleRevision model: content snapshot before each article PATCH, capped at 20 per article.

Web Push for guests

  • POST /api/v1/push/guest-subscribe (unauthenticated, IP-rate-limited 5/min): stores PushSubscription with userId=null and topics array.
  • DELETE /api/v1/push/guest-unsubscribe: removes guest subscription by endpoint.
  • GET /api/v1/push/vapid-key: unauthenticated VAPID public key endpoint.
  • backend/src/lib/push.ts: sendGuestPushByTopic(topic, payload) fans out to userId IS NULL AND topics @> [topic].
  • backend/scripts/publish-due.mjs: after notifying registered topic followers, also calls sendGuestPush for each published article's topic.
  • Topic hub pages (teknav-pages.jsx): "🔔 دریافت اعلان مقالات" button next to follow button; works without login; persists in browser push subscription.

Fine-Grained Notification Center

  • GET /api/v1/auth/notifications/preferences: returns full 8×3 matrix (eventType × channel) with enabled state (default true for unset).
  • PUT /api/v1/auth/notifications/preferences: batch upsert via @@unique([userId, eventType, channel]).
  • sendPushToUser() in push.ts now checks NotificationPreference for channel='push' before delivering — honors user opt-out.
  • NotificationPreferencesPanel collapsible section in ProfileSettingsModal: toggle grid with inline optimistic updates.

Verified Reader Badges

  • Badge rules: ai_enthusiast, security_expert, data_scientist, hardware_geek, software_craftsman, startup_explorer (10 articles read in topic), plus streak_7 and streak_30 (streak count).
  • Evaluation runs in publish-due.mjs cron — NOT on the article-view hot path.
  • GET /api/v1/auth/badges and GET /api/v1/admin/users/:id/badges endpoints.
  • engagementApi.listBadges() client method.

Article Version History

  • ArticleRevision snapshot created before every PATCH update in admin.ts (captures title, content, summary, status, savedById).
  • Pruned to 20 most recent per article at write time.
  • GET /api/v1/admin/articles/:id/revisions (paginated list, no content), GET /api/v1/admin/articles/:id/revisions/:revisionId (with full content), POST /api/v1/admin/articles/:id/revisions/:revisionId/restore (admin/editor only; snapshots current state before restoring).
  • RevisionDrawer side-panel in ArticleEditor: lists revisions with date/author/status; click to preview content; "بازیابی این نسخه" restores for admin/editor.
  • revisionsApi client in engagement-api.js.

Collaborative Editing Presence

  • Heartbeat: POST /api/v1/admin/articles/:id/heartbeat sets Redis SET presence:article:{id}:user:{uid} with 45s TTL.
  • GET /api/v1/admin/articles/:id/presence: SCAN + MGET, enriches with user name/avatar from DB.
  • ArticleEditor fires heartbeat on mount and every 30s; polls presence every 30s.
  • Shows avatar-chip row in editor header when 2+ editors are online on the same article.
  • presenceApi client in engagement-api.js.

Production Follow-Ups

  • On Linux: run npm run preflight:prod, then cd backend && npm run prisma:generate && npm run prisma:apply && npm run seed, then frontend SEO/OG generation, frontend/backend builds, strict backend endpoint tests, and npm run smoke:prod.
  • Verify all flows after schema apply: auth, comments/likes/flags, history, notifications/SSE, reading lists, topic/writer follows, tag pages, series pages, topic hubs, newsletter archive/campaigns, review workflow, analytics endpoints, panel metrics, first-party events.
  • Rotate all seed/admin passwords after first production login.
  • Remove resetPasswordOnSeed from writer-admin credentials after rotation.
  • Confirm SMTP and Kavenegar credentials on the server before sending emails/OTPs.

Post-Phase 13 Production Hardening

Implemented.

  • Added root .env.prod.example for /etc/teknav/backend.env, covering database, Redis, sessions, CORS, uploads, SMTP, SMS, VAPID, Zarinpal, and local storage defaults.
  • Added npm run preflight:prod via scripts/production-readiness.mjs to catch missing templates, nginx SSE/credential-protection regressions, generated Prisma engine artifacts, and missing test coverage before deployment.
  • Added backend/tests/public-contract.test.mjs for public/anonymous API contract checks, and made smoke tests strict with TEST_REQUIRE_SERVER=1 when a running backend must be validated.
  • Added minimal public /api/v1/health, added /api/v1/ready dependency readiness, and added admin-only /api/v1/admin/health diagnostics with non-secret feature flags.

Phase 14 — Farsi Knowledge & Tech Ecosystem

Implemented. Linux production validation pending (CREATE EXTENSION vector, prisma:apply).

  • Wiki & Glossary Proposals: WikiProposal and GlossaryProposal Prisma models; POST /api/v1/wiki/proposals and PATCH /api/v1/admin/wiki/proposals/:id; DiffViewer React component.
  • Automated Internal Linking Engine: link-engine.ts with cheerio; injects <a href="/glossary/:slug"> anchors into published articles.
  • Semantic Search & RAG: ArticleEmbedding model; pgvector; POST /api/v1/search/semantic; GET /api/v1/rag/:slug.
  • LMS: LearningPath, LearningModule, Quiz, UserCertification models; auto-certification at ≥80% pass score.
  • Tech Directory (backend): CompanyProfile, CompanyClaim Prisma models; DirectoryPanel admin UI.
  • Production note: requires CREATE EXTENSION vector as PostgreSQL superuser before prisma:apply.

Phase 15 — Viewership & Top-of-Funnel Scaling

Implemented. Build verified: 0 CDN refs, 0 preflight failures.

15A — Web Stories:

  • CSS scroll-snap story pages for all published articles at dist/stories/{slug}/index.html.
  • OG + Twitter Card meta tags on each story page; keyboard navigation (arrow keys).
  • sitemap-stories.xml added to sitemap index; <link rel="alternate"> on every article page.
  • scripts/generate-web-stories.mjs — build script; runs after generate-article-pages.

15B1 — Quote Card Sharer:

  • src/components/QuoteSharer.jsx — Selection API tooltip, Canvas 1080×1080 branded card.
  • RTL text wrapping, dark gradient, gold separator, Teknav branding.
  • Actions: Web Share API → PNG download fallback, copy-to-clipboard (text + URL), Escape-to-close.
  • Analytics: contentApi.trackEvent({ type: 'share_clicked', metadata: { channel: 'quote_card' } }).
  • Mounted in ArticleDetail for non-premium, non-TekRAG articles.

15B2 — Embeddable Widget System:

  • embed.html — second Vite rollup entry; <meta name="robots" content="noindex,nofollow">.
  • src/embed.jsx — bootstrapper routing by URL path type.
  • src/widgets/GlossaryWidget.jsx / ArticleCardWidget.jsx / CompanyWidget.jsx — dark mode, postMessage resize on height change only.
  • public/embed-loader.js — third-party <script> snippet injecting sandboxed <iframe>.
  • nginx: /embed/ location with frame-ancestors * CSP.

15C1 — Comparison Pages:

  • 10 comparisons in TeknavData.comparisons; dist/compare/{slug}/index.html with ItemList + FAQPage + BreadcrumbList JSON-LD.
  • ComparisonPage — two-column pros/cons, use cases, verdict, localStorage vote widget, share button, factCheckedAt.
  • ComparisonsListPage at /compare with search/filter.
  • Related comparisons block auto-injected on article pages.
  • scripts/generate-comparison-pages.mjs.

15C2 — Tech Directory:

  • 10 companies in TeknavData.companies; dist/directory/{slug}/index.html with Organization + BreadcrumbList JSON-LD.
  • DirectoryListPage + CompanyProfilePage with claim button.
  • GET /api/v1/directory/companies and GET /api/v1/directory/companies/:slug in backend/src/routes/directory.ts.
  • scripts/generate-company-pages.mjs.

Additional:

  • StoriesListPage at /stories — 9:16 thumbnail grid with title + category overlay, opens story in new tab.
  • Footer "ابزارها" nav section: compare, stories, directory, glossary, tools.
  • Profile badge display — 8 badge types from engagementApi.getBadges().
  • art37 vibe-coding-mcp-2026 — 14-section Persian article on Vibe Coding + MCP (9 h2 sections, 14KB).