Files
teknav-bak/app/CLAUDE.md
T
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

13 KiB
Raw Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Directives

  • Zero CDN dependencies. No external JS, CSS, fonts, images, or cdn.* URLs. npm run build fails on any CDN reference via scripts/check-no-cdn.mjs.
  • Persian/RTL first. All UI copy is Persian. Layouts assume direction: rtl; use logical CSS properties, not left/right.
  • Frontend uses APIs only. Never call the database from frontend code. All persistence goes through /api/v1/* at the backend. Frontend API clients may pass unversioned /api/* paths because src/lib/api.js rewrites them to /api/v1/*. teknav-data.js and teknav-store.js are seed/reference data — never use them as admin-panel fallbacks.
  • No mock admin data. Admin/writer/reviewer/dashboard/media views must use real backend APIs and show empty/error states when data is missing.
  • Production is native Linux/systemd + nginx. No Docker unless explicitly asked. See DEPLOY.md.
  • Protect credentials. ACCOUNTS.md is gitignored and nginx-blocked. Never move it into public/ or dist/. Seed credentials are in backend/prisma/credentials.json.
  • Port and registry are fixed. Vite dev/preview → port 3009; npm registry → https://npm.devneeds.ir/.
  • Reuse shared styling. Use src/styles/global.css keyframes/utilities — do not redefine animation primitives.
  • Phase 15 is current. Keep ARCH.md, AGENTS.md, DEPLOY.md, and SECURITY.md aligned when schema, SEO, trust, retention, or monetization flows change. Phase 14 Linux validation (pgvector + LMS) is still pending before full production go-live.
  • Production hardening. Run npm run preflight:prod before deploy; run TEST_REQUIRE_SERVER=1 npm test in backend/ against a live backend to enforce endpoint contracts.

Commands

Frontend (repo root):

npm run dev              # Vite dev server → port 3009, proxies /api → localhost:3010
npm run build            # Full pipeline (see Build Pipeline Order)
npm run preview          # Preview dist/ on port 4173
npm run preflight:prod   # Static pre-deploy audit
npm run seo:sitemap      # Regenerate sitemap.xml, robots.txt, feed.xml
npm run og:images        # Generate OG images into public/images/og/ (Linux only)
npm run check:seo        # Audit Persian articles for indexability gaps
npm run smoke:prod       # Smoke-test all public endpoints

Backend (cd backend first):

npm run dev              # tsx watch → port 3010
npm run build            # TypeScript compile
npm run prisma:generate  # Regenerate Prisma client after schema changes
npm run prisma:apply     # Apply schema (migrations if present, else db push)
npm run seed             # Seed PostgreSQL + Persian FTS
npm run publish:due      # Publish scheduled articles + fan out notifications
npm test                 # Skips endpoint tests when no backend running
TEST_REQUIRE_SERVER=1 npm test  # Strict contract tests against a live backend

Startup order: PostgreSQL + Redis → cd backend && npm run dev → npm run dev

Schema change workflow: edit schema → npm run prisma:generate --prefix backend → npm run prisma:apply --prefix backend → backend build.

Article data change workflow: edit teknav-data.js → npm run check:seo → npm run seo:sitemap → npm run build.

Build Pipeline Order

seo:sitemap → og:images → vite build → check-no-cdn → check-responsive
  → generate-article-pages → generate-web-stories → generate-comparison-pages
  → generate-company-pages → generate-en-page → generate-author-pages
  → generate-semantic-pages → compress-dist

All generate-* scripts produce static HTML that nginx serves directly — never manually edit files under dist/. generate-article-pages must run after vite build (needs dist/index.html as template) and before compress-dist (so .gz/.br pairs are created). Phase 15 scripts output: dist/stories/{slug}/ (web stories), dist/compare/{slug}/ (comparisons), dist/directory/{slug}/ (company directory).

SEO Invariants

  • No hreflang="en". ?lang=en is a UI preference only; canonical always points to the clean URL.
  • No placeholder verification codes. Never commit INSERT_GOOGLE_VERIFICATION_CODE or similar strings.
  • Static article pages under dist/article/{slug}/index.html are build-time generated — do not edit manually.
  • Sitemap lastmod must not be future-dated. capDate() in generate-seo.mjs enforces this.
  • Organization schema: ['Organization', 'NewsMediaOrganization'] — required for Google News.
  • Article schema: ['NewsArticle', 'TechArticle'] — required for Google Article rich results.
  • Run npm run check:seo after any article metadata or content change.
  • Proven content formula (article ai-data-centric-2026 ranked #1 on Google, above Wikipedia): <p class="lead"> opening, numbered <h2> sections, <strong> entity highlighting, bilingual terminology (Persian + English inline), technical formulas/data inline, factCheckedAt timestamp, 8+ sections / ~3000 words.

Architecture

Frontend — Vite 5 + React 18 ES modules, automatic JSX runtime (no import React needed). Route dispatch in teknav-app.jsx; pages in teknav-home.jsx, teknav-articles.jsx, teknav-pages.jsx, teknav-admin.jsx, teknav-auth.jsx, teknav-profile.jsx. Providers, header, footer, shared UI in teknav-ui.jsx. Styles/fonts/keyframes in src/styles/global.css.

Backend — Fastify 4 + Prisma 5 + PostgreSQL 16 (+ pgvector for semantic search) + Redis 7. Route modules in backend/src/routes/. Global error handler registered early in backend/src/server.ts — maps FST_ERR_VALIDATION to 'invalid_input' uniformly. Config validated by Zod in backend/src/config.ts.

Data layer — teknav-data.js holds all articles (art1–art35), authors, categories, topic hub metadata, glossary reference data. Article content beyond art10 lives in article-contents-{N}.js files. src/lib/content-api.js merges API results over this local fallback (API wins). teknav-store.js handles client-side localStorage caching.

Auth — Argon2id passwords (m=19MiB, t=2, p=1), Redis sessions (tek_sid, 14-day sliding TTL), CSRF double-submit cookie (tek_csrf). Login by email or @username. Google/GitHub OAuth (authorization-code, state in Redis). SMS 2FA via Kavenegar OTP (tek_2fa ticket).

Role-based access:

Role Access
reader View, save, react, manage own profile
reviewer + Article review queue
writer + Create/edit own articles
editor + Edit any article, manage categories/tags
admin + Delete articles, manage users

Real-time — SSE at /api/v1/auth/notifications/stream (reader) and /api/v1/admin/stream (admin live signals). Redis pub/sub is the bus (backend/src/lib/realtime.ts).

Web push — RFC 8030/VAPID via web-push. PushSubscription table stores endpoint per user; userId nullable for guest topic subscriptions. sendPushToUser() checks NotificationPreference before delivering. VAPID keys in /etc/teknav/backend.env — missing keys make push a silent no-op, all other features unaffected.

Storage — LocalStorageAdapter active by default (writes to UPLOAD_DIR). S3 migration: set STORAGE_BACKEND=s3 and wire the stub in backend/src/lib/storage.ts.

Phase 14 — Farsi Knowledge & Ecosystem (current, Linux validation pending)

Requires CREATE EXTENSION vector; (PostgreSQL superuser) and prisma:apply before going live:

Subsystem Models Key endpoints
Semantic Search / RAG ArticleEmbedding POST /api/v1/search/semantic, GET /api/v1/rag/:slug
LMS LearningPath, LearningModule, Quiz, UserCertification POST /api/v1/lms/quiz/:quizId/submit, GET /api/v1/lms/me — auto-cert at ≥80
Tech Directory CompanyProfile, CompanyClaim Authenticated claim endpoint
Wiki/Glossary Proposals WikiProposal, GlossaryProposal POST /api/v1/wiki/proposals, PATCH /api/v1/admin/wiki/proposals/:id

link-engine.ts uses cheerio to auto-inject <a href="/glossary/:slug"> anchors into newly published articles.

Key Files

Path Purpose
teknav-app.jsx Root route dispatch
teknav-ui.jsx Providers, header, footer, PushNotificationPrompt
teknav-home.jsx Home page — hero, featured, latest, personalized feed, streaks
teknav-articles.jsx Article detail — comments, TOC, reactions, Q&A, series nav
teknav-pages.jsx Topic hubs, glossary, tag pages, author pages, series, newsletter archive, jobs, courses, directory
teknav-admin.jsx CMS, ArticleEditor (role-aware, RevisionDrawer, presence chips), LMS panel, directory panel
teknav-auth.jsx Login, signup, OAuth, 2FA, forgot-password
teknav-profile.jsx /profile/@username, push toggle, notification preferences, history
src/lib/api.js Fetch wrapper with credentials + CSRF
src/lib/content-api.js Public content client — merges API over local fallback
src/lib/admin-api.js Admin/CMS API client
src/lib/engagement-api.js Comments, history, notifications, follows, streaks, badges, revisions, presence
src/lib/seo.jsx Page-level meta tags and JSON-LD for all page types
backend/src/server.ts Fastify bootstrap — error handler registered before all plugins
backend/src/routes/admin.ts Role-gated article CRUD, publish quality gates, analytics, review, newsletter, series
backend/src/routes/auth.ts Local auth, OAuth, 2FA, session, /api/v1/auth/me
backend/src/routes/comments.ts Comments, replies, likes, upvotes, flags, bulk mod. Returns {items:[],total:0} (not 404) for unknown slugs.
backend/src/routes/notifications.ts Notification list, SSE stream, VAPID key, push subscribe/unsubscribe
backend/src/routes/revisions.ts Article revision list/get/restore (admin/editor only)
backend/src/routes/monetization.ts Jobs, courses, Zarinpal subscribe/callback/status
backend/src/routes/errors.ts POST /api/v1/errors → ClientError table; GET /api/v1/admin/errors
backend/src/lib/push.ts VAPID, sendPushToUser() (checks prefs), sendGuestPushByTopic(), 410 cleanup
backend/src/lib/storage.ts StorageAdapter — LocalStorageAdapter default, S3StorageAdapter stub
backend/src/lib/realtime.ts Redis pub/sub, SSE helpers, visitor counter
backend/prisma/schema.prisma Single source of truth for all models
backend/prisma/seed.ts Seed data, staff users, Persian FTS setup
scripts/production-readiness.mjs npm run preflight:prod static pre-deploy checklist
.env.prod.example Production env template → copy to /etc/teknav/backend.env
ACCOUNTS.md Operator credential sheet — gitignored, nginx-blocked
deploy/systemd/ Production systemd units and timers
nginx/nginx.conf.example Production nginx template

Production Notes

  • nginx must serve pre-rendered semantic folders (/category/, /tag/, /glossary/, /topics/, /series/, /author/, /profile/) with gzip_static on; brotli_static on; — avoids redirect loops and sub_filter cost.
  • Never copy Windows-generated Prisma engine binaries (query_engine*.node) or local node_modules to the Linux server.
  • Zarinpal requires ZARINPAL_MERCHANT_ID in env; until set, subscribe returns payment_unavailable. Use ZARINPAL_SANDBOX=1 for testing.
  • Phase 12 requires cd backend && npm install web-push and VAPID key generation once on Linux.
  • Phase 14 requires CREATE EXTENSION vector; as PostgreSQL superuser before prisma:apply.
  • After first production login, rotate writer-admin passwords via admin UI, then remove resetPasswordOnSeed from backend/prisma/credentials.json.

Large Codebase Analysis (Gemini CLI)

When multiple large files exceed context, use gemini -p with @ path syntax:

gemini -p "@src/ @backend/src/ List all API endpoints and their auth requirements"
gemini -p "@teknav-admin.jsx @backend/src/routes/admin.ts Trace the article publish flow end-to-end"
gemini --all_files -p "List all Prisma models and their relations"

Paths are relative to where you run gemini. Use for cross-file architecture questions or verifying feature coverage across many files.

Memory

See MEMORY.md for full stack context and key paths. See ARCH.md for the active roadmap and Phase 14 Linux validation checklist. See DEPLOY.md for the full production runbook. See SECURITY.md for the pre-deploy security checklist and nginx/Fastify hardening details. See PHASES.md for completed phase history. See PHASE16.md for the planned English /en/ subdirectory (blocked on LTR layout pass — not started).

Quick reference:

  • Stack: Vite 5 + React 18 / Fastify 4 + Prisma 5 / PostgreSQL 16 + pgvector + Redis 7
  • Current phase: 15 (implemented; Phase 14 Linux validation pending)
  • Writers: آرسام صباغ (arsam-sabbagh), سیداحمدرضا محجوب (ahmadreza-mahjoub), رادمان قلیچی (radman-ghelichi)
  • Constraints: Zero CDN · Persian-first RTL · native Linux/systemd · no mock admin data