Chuyển đến nội dung
Jok Holk
EN | VI

Đăng ngày 8 phút đọc

Hành trình của tôi với tư cách là một nhà phát triển web tự do tại Etugi

Xây dựng website thương mại điện tử thuần HTML, CSS, JS — không backend, không CMS.

  • JS
  • CSS
  • HTML
  • Website
Trong bài này

Tóm Tắt

  • Xây dựng website thương mại điện tử đầy đủ cho Etugi Bình Dương — thuần HTML, CSS, JS, không backend.
  • Blog lưu Markdown. Sản phẩm lưu JSON. Giỏ hàng lưu cookie.
  • Đơn hàng gửi qua EmailJS. Ba tài khoản riêng cho ba form khác nhau.
  • UI đẹp. SEO thảm. Tự chấm: 7.25/10.
  • Dự án freelance đầu tiên. Khó nhất tôi từng làm. Và tôi không hối tiếc.

Lúc đó tôi không có portfolio. Không có dự án nào để khoe. Không có gì cả.

Vậy mà khi Etugi Bình Dương — một công ty lọc nước tại quê tôi — liên hệ và hỏi tôi có thể làm website cho họ không, tôi gật đầu trước khi hiểu mình đang nhận việc gì.

Yêu cầu của họ nghe rất đơn giản:

"Chúng tôi cần một website để giới thiệu sản phẩm và thương hiệu."

Tôi nói với họ tôi sẽ làm từ đầu. Không WordPress. Không template. Thuần HTML, CSS, và JavaScript.

Tôi thật sự tin rằng sẽ đơn giản. Nó không đơn giản chút nào.


1. Etugi Cần Gì

Etugi Bình Dương bán hệ thống lọc nước — dân dụng, công nghiệp, lọc tổng. Khách hàng của họ là người địa phương, nên toàn bộ website cần bằng tiếng Việt.

Cấu trúc họ muốn không nhỏ:

  • Trang chủ
  • Giới thiệu (tổng quan công ty + showroom)
  • Sản phẩm — sáu nhóm: Dân Dụng, Bán Công Nghiệp, Công Nghiệp, Thiết Bị Lọc Tổng, Vật Liệu Lọc Nước, Phụ Kiện Máy Lọc Nước
  • Trang công nghệ MOFs
  • Blog / Tin tức
  • Giỏ hàng & Thanh toán
  • Liên hệ

Cái cuối cùng đó — Giỏ hàng & Thanh toán — là nơi mọi thứ trở nên thú vị.


2. Stack Tôi Chọn (và Tại Sao Tôi Không Hối Tiếc)

Tôi có một quy tắc khi bắt đầu: không backend.

Không phải vì đó là lựa chọn thông minh. Mà vì lúc đó tôi chưa biết làm backend và không muốn thừa nhận điều đó với khách hàng. Nên tôi xoay xở bằng những gì mình có.

Tôi lấy cảm hứng từ HKAngles Freshter — layout sản phẩm sạch, hiện đại, hợp với tầm nhìn của Etugi. Tôi không copy. Tôi nghiên cứu nó, phân tích những gì hiệu quả, và tạo ra thứ của riêng mình. Kiểu "steal like an artist" đúng nghĩa.

Kiến trúc cuối cùng là:

  • Danh mục sản phẩm → file JSON fetch động
  • Blog → file Markdown fetch và render trực tiếp
  • Đơn hàng → EmailJS
  • Lưu giỏ hàng → cookie trình duyệt

Mỗi quyết định trong số này đều quay lại ám tôi theo cách riêng.


3. Hệ Thống Blog

Tôi nghĩ lưu bài viết dưới dạng file .md sẽ rất tinh tế. Nhẹ. Thân thiện với developer.

Thực tế: đó là cơn ác mộng bảo trì.

Mỗi bài viết mới đồng nghĩa với việc tạo file thủ công, cấu hình path, viết metadata bằng tay. Không dashboard. Không CMS. Không cách nào để khách hàng tự động. Mọi cập nhật đều phải qua tôi.

Về SEO thì gần như vô hình:

  • Không có metadata động cho từng bài
  • Cấu trúc URL mà Google không hiểu nổi
  • Search Console liên tục báo lỗi index

Blog hoạt động. Nhưng nó hoạt động kiểu như một chiếc xe không có kính chắn gió vậy — về mặt kỹ thuật là chạy được, nhưng rất khó chịu khi dùng lâu dài.


4. Trang Sản Phẩm

Sáu nhóm sản phẩm. Hàng chục sản phẩm. Tất cả nằm trong một file JSON duy nhất.

Fetch nó, loop qua, render ra — nghe clean trên lý thuyết. Trên thực tế, file phình to rất nhanh. Chỉnh sửa bất cứ thứ gì cũng phải mở blob JSON khổng lồ, tìm đúng entry, sửa cẩn thận, và hy vọng không có gì bị vỡ.

Khách hàng không thể tự làm gì. Mỗi lần cần cập nhật sản phẩm là một cuộc gọi cho tôi. Điều đó không bền vững cho bất kỳ ai.


5. Giỏ Hàng (hay: Cách Tôi Tự Phát Minh Ra Backend Mà Không Có Backend)

Đây là phần tôi vừa tự hào nhất, vừa xấu hổ nhất.

Khách hàng muốn một flow đầy đủ: duyệt → thêm vào giỏ → điền thông tin giao hàng → cả hai bên nhận email xác nhận. Đơn giản thôi. Cực kỳ dễ nếu có backend.

Không có backend, tôi mất vài tuần mới làm ra được.

Lưu Dữ Liệu Giỏ Hàng

Vấn đề: làm sao giữ trạng thái giỏ hàng khi người dùng chuyển qua lại giữa các trang mà không có server?

Giải pháp của tôi: cookie.

Khi ai đó nhấn "Thêm vào giỏ", JavaScript ghi tên sản phẩm, giá, số lượng vào cookie. Khi họ mở trang giỏ hàng, JavaScript đọc cookie đó và render danh sách. Nó fragile. Không scalable. Xóa cookie là mất giỏ hàng. Nhưng nó hoạt động, và lúc đó tôi thật sự tự hào khi tìm ra cách làm.

Gửi Email Đơn Hàng

Không có backend nghĩa là không có cách gửi email từ server. Nên tôi dùng EmailJS — một service cho phép gửi email từ JavaScript phía frontend.

Đây là phần vẫn khiến tôi nhăn mặt mỗi khi nghĩ lại: tôi tạo ba tài khoản EmailJS riêng vì không biết rằng có thể dùng nhiều template trong một tài khoản. Một cái cho form liên hệ trang chủ. Một cái cho trang liên hệ. Một cái cho hệ thống đặt hàng.

Flow checkout cuối cùng trông như này:

[Khách hàng] → Thêm vào giỏ → [Cookie]
[Trang giỏ hàng] → JS đọc cookie + thu thập thông tin giao hàng
[EmailJS] → gửi tóm tắt đơn hàng cho Etugi
          → gửi xác nhận cho khách hàng

Tất cả được xây từ đầu, không framework, không implementation mẫu nào. Chỉ có tôi nhìn chằm chằm vào documentation lúc 2 giờ sáng cố làm cho nó chạy.


6. SEO Là Thảm Họa

Tôi sẽ không tô vẽ cho đẹp. Website này gần như không có SEO.

Không có metadata động. Không có schema markup. Không có sitemap đúng nghĩa. Google Search Console bối rối với kiến trúc từ ngày đầu tiên.

Rồi mọi thứ tệ hơn. Cloudflare analytics bắt đầu hiện hàng nghìn lượt truy cập mỗi ngày từ các quốc gia ngẫu nhiên — những quốc gia không có lý do gì để vào website lọc nước Việt Nam. Rõ ràng đang bị DDoS. Và công ty SEO mà Etugi thuê hóa ra không làm SEO thật — chỉ tạo traffic giả, khiến mọi thứ tệ hơn thay vì tốt hơn.

Website không bao giờ rank được như đáng lẽ phải vậy. Không hoàn toàn là lỗi của tôi, nhưng nền SEO tôi xây khiến mọi thứ càng khó sửa hơn về sau.


7. Tự Chấm: 7.25/10

Website ra mắt. Chạy được. Etugi dùng được.

Điểm mạnh: UI thực sự đẹp — sạch, hiện đại, nhanh. Flow đặt hàng hoạt động đầy đủ. Khách hàng đặt đơn và nhận email xác nhận. Với một frontend thuần không có backend, đó là thành tựu thật sự.

Điểm yếu: mọi thứ sau khi ra mắt. SEO. Gánh nặng bảo trì. Việc không ai trong team Etugi có thể tự cập nhật gì mà không gọi cho tôi. Dữ liệu giỏ hàng trong cookie. Đơn hàng chỉ tồn tại trong hộp thư email, không có database nào lưu lại.

7.25 vì tôi đã deliver đúng những gì hứa — một website đẹp, hoạt động được. 2.75 điểm còn thiếu là sự thừa nhận thành thật rằng "hoạt động" và "production-ready" không phải là một, và tôi học ra điều đó theo cách khó nhất.


8. Những Gì Tôi Thật Sự Học Được

Không phải những thứ chung chung. Những thứ thật:

UI đẹp mà không có SEO như cái cây đổ trong rừng vắng. Không ai tìm thấy. Không ai dùng. Những giờ bạn dành cho hover animation không có nghĩa lý gì nếu Google không index được trang.

"Không backend" không phải triết lý — đó là giới hạn. Tôi đóng khung nó như một quyết định thiết kế. Thực ra không phải. Đó là giới hạn tôi xoay xở sáng tạo, và dù tự hào về sự sáng tạo đó, tôi đáng ra phải thành thật với mình về những đánh đổi.

Khách hàng không thể bảo trì thứ họ không thể truy cập. Mỗi lần Etugi cần cập nhật sản phẩm, họ phải gọi cho tôi. Đó không phải sản phẩm — đó là sự phụ thuộc. Tool tốt phải trả quyền kiểm soát nội dung về tay khách hàng.

Khách hàng đầu tiên là khó kiếm nhất. Một khi có Etugi, kiếm khách tiếp theo dễ hơn hẳn. Trước Etugi, tôi không có gì để show. Dự án đầu tiên — dù không hoàn hảo — đã thay đổi tất cả.

Quan trọng hơn hết: dự án này là lý do tôi có thể viết HTML và CSS trong giấc mơ. Mỗi giới hạn khó chịu buộc tôi phải hiểu nền tảng sâu thay vì reach for a library. Nền tảng đó vẫn theo tôi trong mỗi project tôi làm hôm nay.


Đây là dự án thật đầu tiên của tôi. Lộn xộn, không hoàn hảo, và thực sự khó. Nhưng nó được ship. Và ship thứ gì đó không hoàn hảo còn hơn mãi mãi không ship thứ gì hoàn hảo.

Bắt đầu trước khi bạn sẵn sàng. Học trong lúc làm. Cứ ship đi.