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

  1. Chạy queue và khỏi tạo như bt (Ví dụ import từ Redbubble).
  2. 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

  1. Add deploy key dùng job: http://jenkins.sweb.vn/job/sweb/job/Add_user_deploy/
  2. 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:

domainkeywordsimilar_keywordstopicimport_redbubbledesign_namedesign_url
chillguy.storechill guychill guy, chilling guymeme0Black chill guyhttps://example.com/blackchil.png
white chill guyhttps://example.com/whiteguy.png
thesimpson.storethe simpsonthe simpsontv series1

Chú thích

  1. 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
  2. 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
  3. 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:

  1. Đăng nhập vào hubA, tải xuống file database của store meocua.com
  2. Tạo 1 store với domain meocua.com trên hubB
  3. Upload file database vừa tải trên hubA vào store vừa tạo trên hubB
  4. Trỏ địa chỉ IP của domain sang hubB.
  5. Xóa site cũ trên hubA

Toggle chế độ maintenance của 1 store

Có 2 cách để thực hiện:

  1. Đăng nhập vào hub, và chọn Toggle maintenance của store.
  2. Tắt bật trong admin General->Site Settings củ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

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

  1. Kiểm tra domain đã được cấu hình trỏ về đúng hub server chưa
  2. 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

  1. Collection không có sản phẩm
  2. 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

  1. Kiểm tra proxy của zenrows còn quota hay không
  2. 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.

  1. Nếu là upload trong block của page builder, thử xóa block và tạo block mới để upload lại.
  2. 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:

  1. 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