steelforesight/panel
alireza 09385a0a18 Add admin panel + wire main site to fetch articles from panel API
- panel/: standalone Express + SQLite + JWT admin (server.js, db.js, seed.js,
  vanilla-JS admin UI under public/). CRUD for articles with cover image
  uploads. README documents API, run instructions, and integration steps.
- src/data/reports.ts: appended bootstrapReports() that fetches from
  VITE_PANEL_API (defaults to http://localhost:3001) and mutates the in-memory
  reports array. Static array kept as fallback when panel is offline.
- src/main.tsx: awaits bootstrapReports() before initial render so all
  existing consumers see panel data without per-file changes.
2026-05-26 17:11:04 +03:30
..
public Add admin panel + wire main site to fetch articles from panel API 2026-05-26 17:11:04 +03:30
.env.example Add admin panel + wire main site to fetch articles from panel API 2026-05-26 17:11:04 +03:30
.gitignore Add admin panel + wire main site to fetch articles from panel API 2026-05-26 17:11:04 +03:30
README.md Add admin panel + wire main site to fetch articles from panel API 2026-05-26 17:11:04 +03:30
db.js Add admin panel + wire main site to fetch articles from panel API 2026-05-26 17:11:04 +03:30
package-lock.json Add admin panel + wire main site to fetch articles from panel API 2026-05-26 17:11:04 +03:30
package.json Add admin panel + wire main site to fetch articles from panel API 2026-05-26 17:11:04 +03:30
seed.js Add admin panel + wire main site to fetch articles from panel API 2026-05-26 17:11:04 +03:30
server.js Add admin panel + wire main site to fetch articles from panel API 2026-05-26 17:11:04 +03:30

README.md

Andishkade Foolad — Admin Panel

A standalone Node/Express + SQLite admin panel for managing articles published on the Andishkade Foolad site.

Features

  • Login (single admin, bcrypt-hashed password, JWT session)
  • CRUD for articles with all fields used on the site: title, category, type, author / role / initial, publish date (Jalali string), pages, price, isFree, summary, body, cover image, tags, featured flag
  • Cover image upload (multer, stored on disk under uploads/)
  • Public read API (GET /api/articles) that the main React site can consume

Stack

  • Node 20+
  • Express 4
  • better-sqlite3 (single-file data.db)
  • multer for uploads
  • bcryptjs + jsonwebtoken for auth
  • Vanilla JS admin UI (no build step)

First-time setup

cd panel
npm install
cp .env.example .env       # then edit .env, especially JWT_SECRET and ADMIN_PASSWORD
npm run seed               # creates the admin user from .env
npm start

Then open http://localhost:3001.

Login with the ADMIN_USERNAME / ADMIN_PASSWORD values from .env.

API

All write endpoints require Authorization: Bearer <token>. The token is returned by POST /api/auth/login.

Method Path Auth Purpose
POST /api/auth/login {username, password}{token, user}
GET /api/auth/me yes current user info
GET /api/articles list articles (newest first)
GET /api/articles/:id single article
POST /api/articles yes create article
PUT /api/articles/:id yes update article
DELETE /api/articles/:id yes delete article
POST /api/uploads yes multipart file{url}
GET /api/health {ok: true}

Article shape

{
  "id": "abc123…",
  "title": "…",
  "category": "بازار جهانی",
  "type": "special",
  "author": "دکتر علی محمدی",
  "authorRole": "مدیر ارشد پژوهش",
  "authorInitial": "م",
  "publishDate": "بهمن ۱۴۰۳",
  "pages": 84,
  "price": 850000,
  "isFree": false,
  "summary": "…",
  "body": "متن کامل …",
  "coverImage": "/uploads/abc.jpg",
  "tags": ["تجارت جهانی", "صادرات"],
  "featured": true,
  "createdAt": "2026-05-26T13:20:00.000Z",
  "updatedAt": "2026-05-26T13:20:00.000Z"
}

This shape is intentionally compatible with the Report type in ../src/data/reports.ts, so the main site can swap the hardcoded array for fetch('/api/articles') without touching its UI components.

Wiring the main site to the panel

In the main Vite app, replace the hardcoded import:

// src/lib/articles.ts
const API = import.meta.env.VITE_PANEL_API || 'http://localhost:3001';

export async function fetchReports() {
  const res = await fetch(`${API}/api/articles`);
  return res.json();
}

Then in the consuming components (e.g. LatestNewsBentoSection.tsx), call fetchReports() inside a useEffect / React Query hook instead of the static reports array.

Set VITE_PANEL_API in the main app's .env to the panel's public URL when deploying.

Deployment notes

  • The panel listens on PORT (default 3001). It serves the admin UI at / and exposes /api/*.
  • Persist the data.db file and the uploads/ folder — these are your content. Both are gitignored.
  • For HF Spaces, the panel is not the same image as the main site; deploy it as a separate Space (Docker SDK) or on a small VPS.
  • Always change JWT_SECRET and ADMIN_PASSWORD in production.

Reset admin password

sqlite3 data.db "DELETE FROM users WHERE username='admin';"
# edit .env with the new password, then:
npm run seed