Bên trong một app do AI tạo thực ra có gì: chuyến tham quan cho người không phải lập trình viên

Nếu bạn đã cho ra mắt một thứ gì đó bằng công cụ tạo app bằng AI và muốn hiểu mình đang nhìn vào cái gì, đây là một chuyến tham quan có hướng dẫn thân thiện về các thành phần — không thuật ngữ rối rắm.

Bạn gõ một bản mô tả, nhấn nút chạy, và hai mươi phút sau bạn có một app hoạt động được. Tuyệt. Nhưng giờ bạn vừa bấm “xem các tệp tin” và đang trố mắt nhìn một cây thư mục trông như được viết bằng một thứ tiếng khác. package.json là gì? Tại sao lại có bốn mươi thứ trong node_modules? “Schema” nghĩa là gì và sao bạn lại có một cái?

Bài viết này là một chuyến tham quan có hướng dẫn. Không phải hướng dẫn từng bước — mà là một chuyến tham quan. Sau khi đọc xong, bạn sẽ không biết cách tự viết bất kỳ tệp nào trong số này, nhưng lần tới khi có gì đó trông kỳ lạ, bạn sẽ biết nên chỉ tay vào góc nào của app.

Tôi sẽ dùng ba ví dụ xuyên suốt cả bài, để những phần trừu tượng có một thứ gì đó cụ thể để bám vào:

  • Maya, một trưởng nhóm marketing, người đã xây một bảng xếp hạng giới thiệu cho đội của mình.
  • Jordan, một giáo viên yoga, người đã xây một trang đặt lịch lớp học.
  • Sam, người mở tiệm bánh, đã xây một trang “đặt trước bánh sừng bò cho ngày mai”.

Cả ba người họ đều dùng một công cụ tạo app bằng AI. Cả ba app trông hoàn toàn khác nhau dưới mắt khách hàng. Còn bên trong, chúng lại có hình dạng giống nhau đến bất ngờ.

Frontend: thứ mà khách hàng của bạn thực sự nhìn thấy

Frontend là tất cả những gì tải lên trong trình duyệt của ai đó. Các nút bấm, bố cục, phông chữ, hiệu ứng động, cái cách một biểu mẫu tự xóa sạch sau khi bạn gửi đi. Nếu bạn nhìn thấy được, thì đó là frontend.

Với Maya, frontend là một bảng xếp hạng có thứ hạng, tên, và số lượt giới thiệu. Với Jordan, đó là một lịch các lớp học kèm nút “đặt chỗ”. Với Sam, đó là một danh sách bánh ngọt với những nút cộng-trừ nhỏ bên cạnh mỗi món.

Bên trong dự án, frontend thường nằm trong một thư mục có tên kiểu như app/, pages/, hoặc src/. Bạn sẽ thấy những tệp kết thúc bằng .tsx hoặc .jsx. Mỗi tệp đại khái là “một màn hình” hoặc “một phần của màn hình”. Hàng trên bảng xếp hạng là một tệp. Phần đầu trang là một tệp khác. Trang gắn tất cả lại với nhau là tệp thứ ba.

Khi bạn nhờ công cụ tạo app bằng AI “làm cho các nút tròn hơn” hay “dời bảng xếp hạng sang phải”, đây chính là phần thay đổi.

Backend: phần biết suy nghĩ

Backend là phần không ai nhìn thấy, nhưng ai cũng phụ thuộc vào. Đó là đoạn code chạy ở một nơi khác — trên một máy chủ, chứ không phải trong trình duyệt của khách hàng — khi cần làm một việc gì đó mà trình duyệt của khách hàng không nên được tin tưởng để tự làm một mình.

Tại sao trình duyệt không thể làm hết mọi thứ? Vì trình duyệt là máy của khách hàng, và bạn không thể tin nó. Nếu bảng xếp hạng của Maya cập nhật số lượt giới thiệu thuần túy trong trình duyệt, bất kỳ ai cũng có thể nhấp chuột phải và tự cộng cho mình 9.000 lượt giới thiệu. Vậy nên backend là nơi các quy tắc trú ngụ: “người này được làm cái này, nhưng không được làm cái kia”, “thực sự lưu cái này vào cơ sở dữ liệu”, “gửi email này đi”.

Backend thường nằm trong một thư mục tên là api/, server/, hoặc app/api/. Các tệp ở đó thường ngắn. Mỗi tệp xử lý một yêu cầu cụ thể: “tạo một lượt đặt lịch”, “liệt kê bánh sừng bò của hôm nay”, “thêm một lượt giới thiệu”.

Khi một thứ gì đó hoạt động trong app của bạn nhưng kết quả lại không được giữ lại — bạn nhấn gửi, bạn thấy một thông báo xác nhận, nhưng ngày mai dữ liệu biến mất — thì lỗi gần như luôn nằm ở backend.

Cơ sở dữ liệu: bộ nhớ của app bạn

Hãy hình dung bộ nhớ của app bạn như một dãy tủ hồ sơ. Mỗi tủ có một nhãn dán ở mặt trước. Một tủ ghi “users”. Một tủ ghi “bookings”. Một tủ ghi “croissant_orders”. Bên trong mỗi tủ, mỗi ngăn kéo là một hàng. Mỗi ngăn kéo có cùng một bộ ô: một cái tên, một email, một created_at, một status.

Cái cấu trúc đó — “có những tủ nào tồn tại, mỗi hàng có những ô nào” — được gọi là schema. Đó là tệp quan trọng nhất trong dự án, dù nó cũng có lẽ là tệp trông nhàm chán nhất. Hãy tìm một tệp tên schema.ts, schema.prisma, hoặc một thứ gì đó bên trong một thư mục tên db/ hay migrations/. Mở nó ra. Bạn sẽ thấy một danh sách phản chiếu đúng những gì mà app của bạn thực sự ghi nhớ về thế giới.

Schema của Jordan có một bảng classes, một bảng bookings, và một bảng users. Của Sam có products, orders, và order_items. Của Maya có members và referrals. Hình dạng của schema là hình dạng của sản phẩm, đó là lý do vì sao thay đổi nó về sau khó hơn thay đổi diện mạo của các nút.

Một mẹo hữu ích: nếu bạn có thể mô tả những gì app của mình ghi nhớ, bằng lời thường, thì bạn thường có thể mô tả được schema. “Tôi nhớ tên và email của từng khách hàng. Với mỗi khách hàng, tôi nhớ những đơn hàng họ đã đặt. Với mỗi đơn hàng, tôi nhớ những món bánh nào và mỗi loại bao nhiêu cái.” Câu đó, gần như đúng từng chữ, chính là schema.

Auth: người gác cửa

“Auth” là hai từ ghép lại: authentication (xác thực — bạn là ai?) và authorization (phân quyền — bạn được phép làm gì?). Cả hai thường được xử lý bởi một nhóm nhỏ các tệp trong một thư mục tên auth/, hoặc bởi một dịch vụ mà cái tên có thể bạn nhận ra: Clerk, Auth0, Supabase Auth, NextAuth.

Hai câu hỏi này khác nhau. Xác thực trả lời: “đây có thật sự là Maya không?” — thường bằng một mật khẩu, một lượt đăng nhập Google, hoặc một liên kết kỳ diệu gửi qua email cho cô ấy. Phân quyền trả lời: “Maya có được phép xóa lượt giới thiệu của người khác không?” — và câu trả lời thành thật cho hầu hết app do AI tạo trong tuần đầu tiên của chúng là “chúng tôi quên kiểm tra”.

Đây là phần thường âm thầm bị hỏng nhất. Màn hình đăng nhập chạy được, nên có vẻ an toàn. Nhưng backend không phải lúc nào cũng kiểm tra rằng người đang đăng nhập đúng là người mà dữ liệu họ đang cố đọc thuộc về. Nếu app của bạn có bất kỳ khái niệm nào về “dữ liệu của tôi và dữ liệu của bạn”, hãy nói rõ với công cụ tạo app bằng AI: “Hãy đảm bảo người dùng chỉ thấy và chỉnh sửa được dữ liệu của chính họ.” Bạn sẽ ngạc nhiên là một câu đó hé lộ một bước kiểm tra còn thiếu thường xuyên đến mức nào.

Tích hợp: những thứ bạn không tự xây nhưng vẫn đang dùng

Đây là chỗ mà hầu hết người không phải lập trình viên đánh giá thấp những gì thực sự đang diễn ra. Thứ gửi đi email “bánh sừng bò của bạn đã xong” của Sam không phải là code — đó là một tài khoản ở SendGrid hay Resend. Thứ xử lý khoản thanh toán lớp học của Jordan không phải là code — đó là Stripe. Thứ lưu trữ những bức ảnh trên bảng xếp hạng của Maya không phải là code — đó là một dịch vụ lưu trữ như S3 hay Cloudinary.

Mỗi tích hợp xuất hiện ở hai nơi. Có một mẩu code nhỏ trong backend nói “này Stripe, hãy tính tiền cái thẻ này”. Và có một khóa — một chuỗi bí mật dài — được lưu ở một nơi an toàn (thường là một tệp tên .env mà không ai nên đưa lên kho mã nguồn) chứng minh với Stripe rằng yêu cầu đến từ tiệm bánh của Sam chứ không phải một người lạ.

Nếu có khi nào bạn thắc mắc vì sao app của mình đột nhiên ngừng gửi email hay ngừng nhận thanh toán, nguyên nhân gần như luôn là một trong những điều này: một khóa hết hạn, một giới hạn sử dụng đã chạm tới, hoặc một thay đổi trong chính sách của bên tích hợp. Code không hỏng. Cái bắt tay mới hỏng.

Deploy: cách nó lên được internet

Mảnh cuối cùng là phần biến cái thư mục trên ổ đĩa của bạn thành một thứ mà khách hàng có thể ghé thăm ở một URL. Điều này thường có nghĩa là ba thứ nhỏ phối hợp với nhau:

  • Host (máy chủ lưu trú): một dịch vụ như Vercel, Netlify, Fly, hay Render chạy backend và phục vụ frontend của bạn.
  • Tên miền (domain): một cái tên kiểu như mayas-leaderboard.com trỏ về host của bạn.
  • Build (bản dựng): công thức lấy các tệp mã nguồn lộn xộn của bạn và biến chúng thành phiên bản gọn hơn, nhanh hơn để thật sự chạy.

Khi một thứ gì đó hoạt động trên máy của bạn nhưng lại hỏng khi lên production, rắc rối thường nằm ở đây. Một khóa được thiết lập trên laptop của bạn nhưng không có trên host. Một thư viện được cài trong môi trường phát triển nhưng không có trong production. Một cơ sở dữ liệu tồn tại trong trình duyệt của bạn nhưng không có trên trang web thực tế.

Thói quen năm phút tự bù lại chi phí cho chính nó

Bạn không cần đọc mọi tệp trong dự án của mình. Bạn không cần biết hầu hết chúng làm gì. Nhưng mỗi tuần một lần, bạn nên thực hiện một lượt đi dạo năm phút, mở từng thư mục ở trên ra và hỏi công cụ tạo app bằng AI, bằng lời thường, cái gì đã thay đổi.

Maya làm điều này mỗi chiều thứ Sáu. Cô gõ: “Tuần này có gì thay đổi trong schema, và vì sao?” Và: “Trong app này có tích hợp mới nào mà tôi không yêu cầu không?” Các câu trả lời gần như luôn yên lòng. Vài lần hiếm hoi không yên lòng, cô bắt được sự cố khi chúng còn nhỏ.

Đó là toàn bộ ý nghĩa của việc hiểu các thành phần. Không phải để trở thành lập trình viên. Chỉ là để có thể đặt những câu hỏi tốt hơn.

Đi đâu tiếp theo

Nếu chuyến tham quan này có ích, có hai bài tiếp nối đáng để bạn bỏ thời gian. Lỗi ‘trông vẫn ổn’ nói về việc cần làm khi một trong những thành phần này âm thầm bị hỏng, và sẵn sàng demo và sẵn sàng cho production nói về cách nhận biết khi nào app của bạn đã chuyển từ giai đoạn đầu sang giai đoạn sau. Cùng một tấm bản đồ, những công dụng khác nhau cho nó.