- دکمه پررنگ «نوشتن مقاله جدید» بالای صفحه وبلاگ (فقط در حالت ویرایش) — ساخت مقاله جدید و باز شدن مستقیم کشوی نوشتن - ترتیب فیلدهای کشوی مقاله: عنوان، سپس ویرایشگر WYSIWYG — نوشتن اول، متادیتا (دسته/تاریخ/اسلاگ و...) بعد - رفع باگ: ساخت رکورد قبلاً کل درخت را reload میکرد و کشوی تازهساختهشده بیدرنگ بسته میشد؛ حالا آیتم ساختهشده بهصورت خوشبینانه به لیست اضافه میشود و کشو باز میماند
گروه ساختمانی آرامش — پروژه کامل (فرانتاند + بکاند)
مونوریپوی سایت گروه ساختمانی آرامش شامل:
frontend/— سایت React + Vite + Tailwind (تمام متنها و تصاویر از API خوانده میشود)backend/— بکاند FastAPI + SQLAlchemy 2 + PostgreSQL + JWT + MinIO
معماری
Traefik (پورت ۵۱۷۳ — تنها نقطه ورود)
├── / → Caddy (فایلهای استاتیک SPA)
├── /api → FastAPI (بکاند)
└── /media → MinIO (باکت aramesh-media — تصاویر آپلودی)
- همه محتوای متنی سایت در PostgreSQL است — هیچ متنی در کد فرانتاند هاردکد نشده؛
با یک درخواست
GET /api/siteبارگذاری و از پنل مدیریت ویرایش میشود - تصاویر آپلودی در MinIO (Object Storage سازگار با S3) ذخیره میشوند و با مسیر نسبی
/media/...برگردانده میشوند — بکاند ذخیرهسازی بدون تغییر محتوای دیتابیس قابل تعویض است - مسیریابی همهچیز روی Traefik است (با Docker labels) — nginx در پروژه وجود ندارد
ساختار
├── frontend/ # سایت React
│ ├── src/ # کد منبع (api.tsx = لایه اتصال به بکاند)
│ ├── Dockerfile # بیلد Node + سرو استاتیک با Caddy
│ └── Caddyfile # فقط سرو فایلهای استاتیک (مسیریابی روی Traefik است)
├── backend/ # بکاند FastAPI
│ ├── app/ # کد منبع (آپلود تصویر: app/api/admin.py)
│ ├── requirements.txt
│ ├── Dockerfile
│ └── .env.example
└── docker-compose.yml # اجرای کامل با یک دستور
اجرا با Docker (سادهترین راه)
docker compose up --build
- سایت: http://localhost:5173 (از طریق Traefik)
- مستندات API: http://localhost:8001/docs (با
docker-compose.override.ymlمحلی) - کنسول MinIO: http://localhost:9001 — کاربر/رمز از متغیرهای
MINIO_ROOT_*در compose - دیتابیس PostgreSQL و آبجکتاستور MinIO هر دو در کانتینر جدا با volume دائمی
- بکاند هنگام شروع، خودش جداول را میسازد و فقط جدولهای خالی را seed میکند — ارتقای نسخه دادههای فعلی را از بین نمیبرد
- در اولین اجرا، سرویس
minio-setupباکتaramesh-mediaرا میسازد و خواندن عمومی را فعال میکند
اجرای محلی (توسعه)
بکاند
cd backend
python -m venv .venv
.venv\Scripts\activate # ویندوز — در لینوکس: source .venv/bin/activate
pip install -r requirements.txt
# فایل .env از روی .env.example بسازید و DATABASE_URL را تنظیم کنید
python -m app.seed # ساخت جداول + محتوای اولیه
uvicorn app.main:app --reload
فرانتاند
cd frontend
npm install
npm run dev
در حالت توسعه، Vite درخواستهای /api و /media را به Traefik (پورت ۵۱۷۳) پروکسی میکند؛
پس استک Docker باید در حال اجرا باشد. آدرس بکاند در frontend/src/config.ts از
VITE_API_URL خوانده میشود — پیشفرض خالی یعنی درخواستهای هممبدأ.
امکانات بکاند
- API عمومی: برند، منو، هیرو، خدمات، پروژهها، مقالات، نظرات، سوالات متداول، تیم، تایملاین، آمار، دفاتر، مدلهای سرمایهگذاری و... — همه در دیتابیس
- فرم تماس
POST /api/contactو خبرنامهPOST /api/newsletter - پنل مدیریت با JWT: ورود
POST /api/auth/login(پیشفرض:admin/aramesh123) و سپس CRUD کامل همه محتواها در/api/admin/... - آپلود تصویر
POST /api/admin/upload(فقط توکن ادمین، حداکثر ۱۰MB) — فایل در MinIO ذخیره و URL نسبی/media/...برمیگردد - ویرایش جزئی
PATCH /api/admin/{resource}/{id}— فقط فیلدهای ارسالشده عوض میشوند - ترتیببندی
POST /api/admin/{resource}/reorder— با{"ids": [...]} - همه محتوا در یک درخواست:
GET /api/site
در محیط واقعی حتماً
SECRET_KEY،ADMIN_PASSWORDوMINIO_ROOT_PASSWORDرا تغییر دهید.
ویرایش زنده سایت (دوقلوی دیجیتال)
ادمینها نیازی به داشبورد جدا ندارند — خود سایت ویرایشگر است:
- به
/admin/loginبروید و وارد شوید - نوار شناور پایین صفحه ظاهر میشود؛ حالت ویرایش را روشن کنید
- روی هر متن کلیک کنید و ویرایش کنید — خروج از کادر، بلافاصله ذخیره میشود (Enter ذخیره، Esc لغو)؛ وضعیت ذخیره در نوار پایین دیده میشود
- آیتمهای مجموعهها (خدمات، پروژهها، مقالات، نظرات، تیم و...) با هاور، دکمههای ویرایش / حذف / جابهجایی ترتیب نشان میدهند؛ دکمه «افزودن» هم انتهای هر لیست هست
- تصویرها از همان کشوها به MinIO آپلود میشوند
- در حالت ویرایش، لینکها کلیک نمیشوند تا ویرایش متن ممکن باشد
- بازدیدکنندههای عادی هیچ اثری از این لایه نمیبینند (بدون توکن، همه درخواستهای
مدیریتی
401برمیگردند) - تمام تغییرها بلافاصله در PostgreSQL ثبت میشوند — با Ctrl+F5 هم میمانند
وبلاگ — نوشتن با ویرایشگر WYSIWYG
مقالات با ویرایشگر غنی TipTap نوشته میشوند (همان تجربه Medium):
- در حالت ویرایش، روی هر مقاله در صفحه وبلاگ دکمه ویرایش را بزنید — کشوی نوشتن باز میشود
- تیتر (H2/H3)، بولد/ایتالیک/زیرخط، لیست نقطهای و شمارهای، نقلقول، لینک و واگرد
- درج تصویر داخل متن: دکمه تصویر، یا چسباندن/کشیدن تصویر داخل نوشته — فایل مستقیم در MinIO ذخیره و در متن قرار میگیرد
- راستبهچپ کامل با فونت و تم سایت
- ذخیره خودکار: هر مکث کوتاه در تایپ، تغییرها را ذخیره میکند؛ بستن کشو هم ذخیره میکند
فرمت ذخیره: بدنه مقاله یک سند ساختاریافته TipTap (JSON) در PostgreSQL است — نه HTML خام. صفحه مقاله آن را با رندر استاتیک TipTap به HTML تبدیل میکند، پس فقط تگهای شناختهشده (پاراگراف، تیتر، لیست، نقلقول، تصویر، لینک) تولید میشوند. مقالات قدیمی (لیست پاراگراف) در اولین اجرا بهصورت خودکار به این فرمت تبدیل میشوند.
نکات امنیتی
- فایل
.envهرگز commit نمیشود (در.gitignoreاست) - رمز عبور ادمین با bcrypt هش میشود
- توکنهای JWT امضا دارند و مدت اعتبارشان قابل تنظیم است
- تصاویر باکت MinIO عمومی (فقط خواندن) هستند؛ آپلود فقط با توکن ادمین ممکن است