laravel #livewire #alpinejs
Project dùng cho việc provision nhanh chóng các store bán merch theo chủ đề. (Sản phẩm chủ yếu lấy từ Redbubble).
Domain chính: tdalunar.com
Dev server: dev.tdalunar.com
HQ control: hq.tdalunar.com
Mô hình hệ thống
Từng server sẽ được setup 1 website chính, gọi là hub (central). Các hub sẽ tạo các website trên server. Quy tắc đặt tên s1.tdalunar.com, s2.tdalunar.com, …
Lunar hub là gì?
Lunar hub các các website chính cài trên từng server, phụ trách cho việc khởi tạo các website trên server này.
Hub admin url: hubdomain/hub
Giao diện admin của hub có thể thực hiện các hành động sau:
- Toggle chế độ maintenance của website
- Download, upload (replace) database của 1 store (hỗ trợ cho việc việc chuyển store từ server này sang server khác)
- Quản lý store
Tenant store là gì?
Tenant hay là các store bán sản phẩm, được tạo trên 1 hub.
Store admin url: `domain/lunar
Admin của store sử dụng cho việc quản lý sản phẩm,…
Payment gateway
Các store lunar ko sử dụng checkout trên web, mà chúng ta sẽ thông qua 1 payment gateway khác (Woocommerce), hay còn gọi là redirect pay. Giảm thiểu việc cài đặt các tài khoản trên hàng ngàn store, khó trong việc quản lý.
Stack sử dụng
Stack:
- Laravel
- AlpineJS
- Livewire
- SQLite
- File storage: Bunny
- Queue: Redis + horizon
Server:
- Caddy: cấu hình đơn giản, auto TLS thay vì Nginx và Certbot.
- SQLite
- PHP-FPM
Kiến trúc website sử dụng 2 package chính là
- Lunarphp cho các function và backend liên quan đến ecommerce
- TenancyForLaravel dùng cho kiến trúc multi tenancy, 1 server sẽ phục vụ nhiều website.
Các feature có thể viết như 1 app Laravel cơ bản, hoặc chia thành các package trong thư mục packages của dự án. Điều này giúp cho việc maintain code nhẹ nhàng hơn.
Toàn bộ các website sử dụng chung 1 Bunny storage, được chia thành các sub folder theo tên domain.
Installation
Đọc trong readme.md của project
Chú ý môi trường dev cần hỗ trợ Virtual Host, trên MacOS có thể sử dụng Valet, ngoài ra còn có các option khác như Laragon hoặc Herd hoặc
Tạo dev store với demo data
Trước hết cần phải setup hub trước, sau đó tạo 1 store trong hub.
Chú ý domain local có thể phải update file /etc/hosts để trỏ về ip của hub. File host sẽ tùy vào hệ điều hành.
Ví dụ domain của tenant là lunar1.test, cần add vào file host như sau:
127.0.0.1 lunar1.test
Chú ý chỉ nên sử dụng các tld test vd: .test, .local,…
Fill demo data
- Chạy queue và khỏi tạo như bt (Ví dụ import từ Redbubble).
- Download database từ 1 store đã được khởi tạo, vào upload ngược lại vào trong hub. Download images trong bunny của production storage, upload ngược lại sang dev storage và đổi tên thư mục trùng với domain của tenant ở local.
Khởi tạo 1 hub
Server requirements:
- Ubuntu 22.04
Các bước khỏi tạo hub sẽ thực hiện trên Jenkins
- Add deploy key dùng job: http://jenkins.sweb.vn/job/sweb/job/Add_user_deploy/
- Provision server cho hub dùng job: http://jenkins.sweb.vn/job/lunar2/job/provision/
Khởi tạo 1 store
Truy cập vào từng hub để khởi tạo store. Có 2 bước chính là trỏ domain và khởi tạo, có thể làm song song, không ảnh hưởng đến nhau.
Trỏ domain về hub
Có 2 cách đề trỏ domain về hub, ví dụ dưới đây hướng dẫn khi sử dụng Cloudflare.
3. Tạo CNAME record cho root domain, trỏ về vd s20.tdalunar.com (domain của hub).
4. Tạo A record trỏ về IP của từng hub (không khuyến khích).
Chú ý không được sử dụng proxied mode (đám mây vàng) của Cloudflare
Provision website trên hub
- domain: domain chính của website
- keyword: keyword chính cho việc SEO, đồng thời cũng là chủ đề của website)
- related keywords: các keyword liên quan đến keyword chính (hiện tại sử dụng cho việc lọc title sản phẩm khi crawl về)
- topic: chủ đề web, ví dụ: anime, movie, tv series,…
Bulk khởi tạo nhiều store
Khởi tạo thông qua N8N form
Chuẩn bị các thông tin qua file csv, chọn server và submit. Chú ý trỏ domain về đúng server của hub.
Định dạng file csv có thể xem trên file mẫu ở form n8n, hoặc format cơ bản như sau:
| domain | keyword | similar_keywords | topic | import_redbubble | design_name | design_url |
|---|---|---|---|---|---|---|
| chillguy.store | chill guy | chill guy, chilling guy | meme | 0 | Black chill guy | https://example.com/blackchil.png |
| white chill guy | https://example.com/whiteguy.png | |||||
| thesimpson.store | the simpson | the simpson | tv series | 1 |
Chú thích
- import_redbubble: có thể có các giá trị sau
- 0: Không import bên redbubble
- 1: Import bên redbubble và ko tạo design
- 2: Import cả redbubble và tạo sản phẩm từ file design
- design_name: tên của design, sẽ được ghép với tên của collection để tạo tên sản phẩm
- design_url: link file ảnh của design
Nếu ko cần tạo product từ design, chỉ cần import từ Redbubble, thì để trống design_name và design_url, set import_redbubble = 1.
Triển khai 1 theme mới
Theme cho project sử dụng tailwindcss và alpinejs là chủ yếu. Node package manager sử dụng pnpm
Sử dụng command
php artisan make:theme demo
Trong đó shopee là tên theme muốn tạo.
Sau đó 1 thư mục theme mới được tạo themes/demo
*Thư mục themes/demo được ignore nên ko được push lên git
Edit file packages/lunar-theme/config/themes.php, thêm tên file vào trong array themes.
Update file vite.config.js, thêm vào dòng themes/demo/css/app.css
Sau đó vào admin tại /lunar -> settings -> site settings
Chọn theme là theme vừa tạo.
Cấu trúc 1 theme
- themes
- demo # theme vừa tạo
- css
- app.css
- views # nơi chứa các file views cho việc overwrite
- home.blade.php
- components
- layouts
- styles.blalde.php # file cấu hình style của theme
- tailwind.config.js # file cấu hình tailwindcss
Cơ chế theme hoạt động theo kiểu kế thừa và overwrite, nội dung file template gốc trong resources/views
Cách đơn giản nhất là copy file và thư mục tương ứng từ theme gốc và chỉnh sửa lại style của từng phần
Chú ý nhớ commit code.
Các action thực hiện trên hệ thống
Thay đổi pass user hàng loạt cho toàn bộ stores
Việc này có thể thực hiện trên Jenkins thông qua artisan-command runner.
Command:
php artisan tenants:change-password "admin@sweb.vn" "newpassword"Chuyển website từ hub này sang hub khác.
Ví dụ bạn muốn chuyển store meocua.com từ hubA sang hubB, thực hiện các bước như sau:
- Đăng nhập vào hubA, tải xuống file database của store
meocua.com - Tạo 1 store với domain
meocua.comtrên hubB - Upload file database vừa tải trên hubA vào store vừa tạo trên hubB
- Trỏ địa chỉ IP của domain sang hubB.
- Xóa site cũ trên hubA
Toggle chế độ maintenance của 1 store
Có 2 cách để thực hiện:
- Đăng nhập vào hub, và chọn
Toggle maintenancecủa store. - Tắt bật trong admin
General->Site Settingscủa từng store.
Auto backup
Database của các store sẽ được backup 1 tuần 1 lần, lưu trên Bunny.
Các tính năng của store
Production combination
Là danh sách các variant được định nghĩa cho từng danh mục sản phẩm (category). Ví dụ, sản phẩm thuộc nhóm category T-Shirts gồm các thành phần:
- Type:
Unisex - Color:
blue,red,pink, … - Size:
S,M,L,XL,2XL, … - Print location:
Front,Back,Front and Back
Ví dụ 1 sản phẩm T-Shirt: https://thesimpson.shop/product/the-simpson-t-shirts-the-simpsons-stonecutters-classic-t-shirt-rb0709
Danh sách các combination được lưu tại Customedge
Lưu ý
Các collection được khỏi tạo với cấu hình trong meta ví dụ như:
combination_id: # Cấu hình bộ option và giá tiền cho các sản phẩm trong collection khi được import về, giá trị này trong product độc lập với bên collection
redbubble_style: # cho việc map khi import Redbubble
redbubble_ia_code: # cho việc map khi import Redbuble
Một số store được import từ bên Woocommerce sẽ không có giá trị này.
Rebubble importer
Import các sản phẩm từ Redbubble theo từ khóa search, hiện tại đang sử dụng proxy của zenrows.com
Woocommerce importer
Import sản phẩm cũ từ Woocommerce thông qua api.
URL Redirect
Redirect link cho SEO.
Support form
Được nhúng trong page /contact-us, là 1 iframe đến https://maiden.customedge.co/tickets/create?domain=lunar1.test, trong đó domain là domain của website hiện tại. Thông tin thêm xem tại Maiden
Support bubble
Là 1 popup đơn giản cho việc hỗ trợ khách hàng, có thể nhúng cho website Wordpress hoặc Lunar thông qua đoạn code. Đây là một mini project viết bằng Vue, source code tại: https://github.com/swebvn/support-bubble
<script type="text/javascript" src="//support-bubble.customedge.co/support-bubble.js" async></script>Tracking order
Track vào gửi thông tin order cho khách về email, sử dụng API gọi đến Portal
Theming
Theme cơ bản chỉ là override lại các file .blade.php cho việc xử lí giao diện. Chi tiết setup có trong readme.md của source code.
Pin product URL to Pinterest
Sử dụng tài khoản Pinterest thông qua cookie để pin product url kèm ảnh sản phẩm.
Function này đang được migrate sang Maiden nhưng hiện tại đang pending.
Auto generate collection thumbnail
Khi khởi tạo, ảnh collection sẽ tự động generate bằng template lunar-collection trên OG Image, bằng cách sử dụng 1 ảnh sản phẩm bất kì của collection đó và remove được remove background với Remove Background
Auto generate logo
Tương tự như khi tạo ảnh collection, sử dụng template lunar-logo, với nội dung là keyword chính của website, hiện tại đang random dựa trên 4 layouts.
Generate products from Mockup
Tính năng tạo sản phẩm từ mockup dạng đơn giản, chỉ là các layer ảnh chồng lên nhau. Đối với các sản phẩm có bề mặt cong sẽ không giống thật cho lắm.
Các mockup được gọi là template trên OG Image
Thông tin sample: https://docs.google.com/spreadsheets/d/1Yabuf6uW_5HYGeCsClUy0xWUdlkqgXq5G_ULsk7rmNM/edit?gid=1874976781#gid=1874976781
- 1 collection sẽ có nhiều templates, là các style khách nhau của 1 loại, ví dụ hình dạng túi, áo, …
Crawl sản phẩm từ Amazon
Các collection trong Lucommerce được phân loại bằng type_code. Việc tìm kiếm thông tin sản phẩm sử dụng qua discovery api của Zenrows, tìm kiếm với từ khóa là tên collection. Cần cấu hình rh id (refined hierarchy) cho từng collection tương ứng với trên Amazon để cho kết quả chính xác nhất. Cấu hình trong file app/Models/CollectionTypeCode.php
Troubleshot
Import nhưng không truy cập được vào website
- Kiểm tra domain đã được cấu hình trỏ về đúng hub server chưa
- Website đã được khởi tạo trên hub hay chưa
Domain lỗi SSL
Không bao giờ xảy ra.
Nếu xảy ra cần check log của caddy trên server 🤣
Lỗi khi generate ảnh thumbnail của Collection
- Collection không có sản phẩm
- Có thể server OG Image sida, cần check log
/horizonđể biết thêm thông tin.
Lỗi không import được sản phẩm từ Redbubble
- Kiểm tra proxy của zenrows còn quota hay không
- Redbubble có thay đổi cấu trúc api hay ko (hiện đang sử dụng graphQL của nó)
Upload ảnh bị lỗi.
- Nếu là upload trong block của page builder, thử xóa block và tạo block mới để upload lại.
- Chờ khoảng 1-2 phút sau và thử lại, nếu không được thì ping dev.
Chức năng auto import không hoạt động
Store trên hub đến từ nhiều nguồn, có thể được import từ bên Woocommerce, do đó có thể không được config đúng như khi khởi tạo từ ban đầu.
Lunar HQ
Server trung tâm dành cho việc setup các common stuff cho hệ thống store. Hiện tại các function chưa được quy hoạch và đang để ở những website khác nhau.
Hiện tại HQ có các api sau:
- Api cho phép tạo Google Analytics scripts để nhúng vào các website mới khỏi tạo
Plan quy hoạch
- Chuyển cấu hình combination từ bên Customedge
- Chuyển iframe submit ticket cho khách hàng từ Maiden