Skip to content

media.danghong.me Ops ​

media.danghong.me là nơi lưu một bản duy nhất của thông tin cá nhân, ảnh, video, tài liệu và các đường link về Hồng. Các site khác (danghong.me, các subdomain trong tương lai) đọc lại từ đây thay vì giữ bản sao riêng.

GitHub chỉ giữ code. Nội dung nằm trên Cloudflare:

  • D1 danghong-media: hồ sơ, giới thiệu, album, câu chuyện, con người, link, video, thông tin từng file.
  • R2 danghong-media: mọi file (ảnh, PDF, video). Key trong R2 chính là đường dẫn công khai: key photos/avatar.png → https://media.danghong.me/photos/avatar.png.

Sửa ở trang quản trị /admin/ là media đổi ngay, không cần commit hay deploy. Trang quản trị cũng chứa nội dung của danghong.me (nhóm tab danghong.me); phần đó lên web sau khi bấm Xuất bản website (xem Data).


1. CẤU TRÚC ​

text
media/
├── functions/[[path]].js   # Pages Function nhận mọi request: /admin, /api/*.json, trang HTML, file R2
├── src/
│   ├── site.js             # Đọc D1, ráp album/link/người…, sinh JSON API
│   ├── render.js           # Giao diện các trang (HTML/CSS)
│   ├── admin.js            # API của trang quản trị (ghi D1, upload R2, xuất bản website)
│   ├── access.js           # Kiểm tra đăng nhập Cloudflare Access + danh sách email được phép
│   └── admin-ui.js         # Khung HTML của trang quản trị
├── public/                 # Thư mục output của Pages: robots.txt, admin-app.js (script trang quản trị)
├── schema.sql              # Bảng D1
├── test/                   # node --test
└── wrangler.toml           # Pages project "danghong-media" + binding DB (D1), BUCKET (R2)

Mỗi request được xử lý theo thứ tự:

Đường dẫnXử lý
/admin/…Trang quản trị và API của nó (chỉ email được phép, qua Cloudflare Access)
/api/<tên>.jsonJSON dựng từ D1
Kết thúc bằng /, không có phần mở rộng, hoặc /assets/site.cssTrang HTML render từ D1
Còn lạiObject có key tương ứng trong R2, rồi tới public/ (robots.txt, admin-app.js)

Các trang công khai và route: sitemap.

2. THÊM / BỚT NỘI DUNG ​

Mở media.danghong.me/admin/ và đăng nhập bằng email dangtuyethong2324@gmail.com (Cloudflare Access gửi mã một lần vào email). Email khác bị từ chối.

2.0. Phân quyền ​

  • Cloudflare Access (Zero Trust) có một Self-hosted application cho media.danghong.me/admin*, policy Allow chỉ gồm email trên. Access chặn mọi người khác trước khi request tới Function.
  • Function kiểm tra lại (src/access.js): JWT Cf-Access-Jwt-Assertion phải có chữ ký đúng của team ACCESS_TEAM_DOMAIN, đúng ACCESS_AUD, còn hạn, và email nằm trong ADMIN_EMAILS. Ba biến này nằm trong media/wrangler.toml. Thiếu ACCESS_TEAM_DOMAIN thì /admin/ trả 503 (đóng mặc định).
  • Thêm người quản trị: thêm email vào policy của Access và vào ADMIN_EMAILS, rồi deploy.
  • Mọi thao tác ghi cần header X-Admin: 1 nên trang khác không gửi request thay người đã đăng nhập được.
Tôi muốn…Làm gì
Thêm ảnh vào albumTab Ảnh & file → nhập thư mục của album → chọn ảnh → Tải lên. Hoặc bấm + Thêm ảnh trên trang album.
Tạo album mớiTải ảnh lên một thư mục mới trong photos/, rồi tab Album → + Thêm với id, tiêu đề, thư mục.
Dùng một ảnh trong nhiều albumThêm key ảnh vào trường Ảnh thêm ngoài thư mục của album kia.
Đặt tiêu đề, alt, mô tả, thẻ cho ảnhTab Ảnh & file → Sửa.
Lấy link ảnhTab Ảnh & file → Copy link.
Thêm câu chuyệnTab Câu chuyện: body (đoạn cách nhau một dòng trống), sections, hoặc chỉ link tới bài gốc.
Thêm người, link, videoTab tương ứng → + Thêm. Nút ↑ ↓ đổi thứ tự.
Sửa hồ sơ, giới thiệuTab Hồ sơ và Giới thiệu (sửa JSON: hành trình, niềm tin, triết lý, học vấn, khóa học, sở thích, phim).
Sửa sản phẩm, khoá học, sách, gia đình… của danghong.meNhóm tab danghong.me → sửa → Xuất bản website (build lại trong vài phút).

id chỉ dùng chữ thường không dấu, số và dấu gạch ngang; link và video để trống id thì tự tạo. Trường nào không có ô riêng (ví dụ admirations, lessons, quotes của người) nằm trong ô Trường khác (JSON).

2.1. Giới hạn ​

  • Mỗi file upload qua trang quản trị tối đa 100 MB (giới hạn body request của Workers). File lớn hơn upload bằng wrangler r2 object put, rồi thêm dòng vào bảng files.
  • Video dài nên đưa lên YouTube và dùng link ngoài.
  • Nén ảnh trước khi tải (khuyến nghị dưới 500 KB, cạnh dài khoảng 2000px).
  • Thư mục cấp đầu api, assets, admin là tên dành riêng; file cần có phần mở rộng.
  • Xoá file ở trang quản trị là xoá vĩnh viễn khỏi R2.

3. CHẠY THỬ LOCAL ​

bash
cd media
npm install
echo "ADMIN_DEV_EMAIL=dangtuyethong2324@gmail.com" > .dev.vars   # chỉ có tác dụng trên localhost
npx wrangler d1 execute danghong-media --local --file schema.sql
npm run dev       # http://localhost:8788, D1/R2 local trong .wrangler/
npm test

D1/R2 local ban đầu trống. Muốn có dữ liệu thật để thử, export từ remote: npx wrangler d1 export danghong-media --remote --output dump.sql, rồi npx wrangler d1 execute danghong-media --local --file dump.sql.

Biến MEDIA_BASE_URL (trong wrangler.toml) là domain dùng trong URL tuyệt đối của JSON.


4. SAO LƯU ​

D1 có Time Travel (khôi phục về thời điểm bất kỳ trong 30 ngày): npx wrangler d1 time-travel restore danghong-media --timestamp <ISO>. R2 chưa có bản sao lưu tự động (xem Infrastructure I4).