0

Mình đã xây dựng nền tảng giáo dục cho trẻ em với 0 đồng vốn và chi phí vận hành 100k/tháng như thế nào

TL;DR: Mình là một developer đã tự tay xây dựng Cú Thông Minh — nền tảng học mà chơi cho trẻ 3-8 tuổi, với 38+ thể loại game tương tác, 60+ bài blog SEO. Tổng chi phí đầu tư: 0 đồng. Chi phí vận hành: 100.000 VNĐ/tháng cho VPS. Bài viết này chia sẻ toàn bộ hành trình từ tech stack, deploy, đến SEO.

Cú Thông Minh Banner


Mục lục

  1. Giới thiệu — Tại sao mình làm dự án này?
  2. Phần 1: Tech Stack — Chọn đúng công nghệ, tiết kiệm tối đa
  3. Phần 2: Deploy — Từ laptop lên production với 100k/tháng
  4. Phần 3: SEO — Để Google tìm thấy bạn khi không có tiền quảng cáo
  5. Tổng kết chi phí

1. Giới thiệu — Tại sao mình làm dự án này? {#1-giới-thiệu}

Mình nhận ra một vấn đề: các ứng dụng giáo dục cho trẻ em ở Việt Nam hoặc là đầy quảng cáo, hoặc là quá đắt, hoặc là nội dung không phù hợp văn hóa Việt. Mình muốn tạo một nơi mà trẻ em có thể vừa học vừa chơi, an toàn, không quảng cáo, và phụ huynh không cần lo lắng.

Kết quả sau vài tháng:

  • 🎮 38+ thể loại game — từ toán, tiếng Việt, động vật, đến kỹ năng sống
  • 📝 60+ bài blog chất lượng cho SEO
  • 💰 Chi phí vận hành: ~100.000 VNĐ/tháng
  • 🚫 0 đồng cho quảng cáo, hosting frontend, database, auth, storage

Vậy mình đã làm thế nào?


2. Phần 1: Tech Stack — Chọn đúng công nghệ, tiết kiệm tối đa {#2-tech-stack}

Nguyên tắc chọn stack

Mình theo đúng 3 nguyên tắc:

  1. Free tier đủ dùng — tận dụng tối đa tier miễn phí của các dịch vụ
  2. Ít dependency — càng ít service, càng ít thứ phải maintain
  3. Developer experience tốt — một mình làm thì DX phải mượt

Frontend: Next.js 16 + React 19

next: 16.1.4
react: 19.2.3
typescript: ^5
tailwindcss: ^4

Tại sao Next.js?

  • SSR/SSG giúp SEO cực mạnh (quan trọng khi không có tiền quảng cáo)
  • App Router với Server Components giảm JavaScript gửi đến client
  • React Compiler (bật trong next.config.ts) — tự động memo hóa, không cần lo useMemo/useCallback
  • Image optimization built-in — tự động resize, convert sang AVIF/WebP
  • PWA support — user có thể "cài" app lên điện thoại mà không cần App Store
// next.config.ts — Một số config quan trọng
const nextConfig: NextConfig = {
  output: "standalone",        // Docker-friendly output
  reactCompiler: true,         // Bật React Compiler
  images: {
    formats: ["image/avif", "image/webp"],  // Ảnh nhẹ hơn 60-80%
    minimumCacheTTL: 2592000,               // Cache 30 ngày
  },
  experimental: {
    // Tree-shake chỉ import icon cần dùng
    optimizePackageImports: ["lucide-react", "framer-motion"],
  },
};

Database + Auth + Storage: Supabase (Free tier)

Đây là lựa chọn "thay đổi cuộc chơi". Thay vì phải tự setup PostgreSQL, viết auth system, setup file storage riêng — Supabase cho tất cả miễn phí:

Service Supabase Free Tier Mình dùng
Database (PostgreSQL) 500 MB ✅ Đủ
Auth 50,000 MAU ✅ Thoải mái
Storage 1 GB ✅ Ảnh game
Edge Functions 500K invocations/tháng ✅ Chưa dùng hết
// Dùng Drizzle ORM thay vì query trực tiếp
// Type-safe, migration dễ quản lý
import { defineConfig } from "drizzle-kit";

export default defineConfig({
  schema: "./src/db/schema.ts",
  dialect: "postgresql",
  dbCredentials: {
    url: process.env.DATABASE_URL!,
  },
});

Tại sao Drizzle ORM mà không phải Prisma?

  • Bundle size nhỏ hơn nhiều (quan trọng cho serverless)
  • Type-safe mà không cần code generation
  • Query builder gần với SQL thuần

UI & Animation

framer-motion: ^12.35.0    # Animation mượt mà
lucide-react: ^0.562.0     # Icon SVG nhẹ
canvas-confetti: ^1.9.4    # Hiệu ứng confetti khi bé hoàn thành bài

Monitoring: Sentry (Free tier)

  • Error tracking real-time
  • Tunnel route qua server để tránh bị ad-blocker chặn
// Sentry chạy qua tunnel, ad-blocker không chặn được
tunnelRoute: "/monitoring",

Blog: MDX (miễn phí, không cần CMS)

Thay vì trả tiền cho Contentful, Sanity, hay WordPress:

  • Viết blog bằng MDX files ngay trong repo
  • Parse bằng next-mdx-remote + gray-matter
  • 0 đồng, version control bằng Git, deploy cùng app
content/
└── blogs/
    ├── be-3-tuoi-nen-hoc-gi.mdx
    ├── day-be-hoc-dem.mdx
    ├── giao-duc-som-la-gi.mdx
    └── ... (60+ bài)

Tổng kết Tech Stack

Thành phần Công nghệ Chi phí
Frontend Next.js 16 + React 19
Database Supabase PostgreSQL (free tier)
Auth Supabase Auth
File Storage Supabase Storage
Blog/CMS MDX trong repo
Icons Lucide React
Monitoring Sentry (free tier)
Tổng 0 đồng

3. Phần 2: Deploy — Từ laptop lên production với 100k/tháng {#3-deploy}

Tại sao không dùng Vercel?

Vercel là lựa chọn tự nhiên cho Next.js, nhưng:

  • Free tier giới hạn bandwidth (100 GB/tháng)
  • Serverless function timeout ngắn
  • Khi scale lên, giá rất đắt
  • Muốn toàn quyền kiểm soát server

VPS: 100.000 VNĐ/tháng

Mình thuê một VPS tại Việt Nam:

  • RAM: đủ chạy Docker
  • CPU: đủ build + serve
  • Bandwidth: không giới hạn
  • Giá: ~100.000 VNĐ/tháng

Docker Multi-Stage Build

Mình dùng Dockerfile multi-stage để giữ image nhẹ nhất có thể:

# Stage 1: Install dependencies
FROM node:20-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci

# Stage 2: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV NODE_OPTIONS="--max-old-space-size=4096"
RUN npm run build

# Stage 3: Production (chỉ copy output cần thiết)
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production

# Chỉ copy standalone output — image cực nhẹ
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public

EXPOSE 3000
CMD ["node", "server.js"]

Tip: output: "standalone" trong next.config.ts là key. Nó tạo ra một thư mục chỉ chứa đúng những gì cần để chạy production — không có node_modules nặng nề.

Deploy Script: Build local, chuyển lên VPS

Đây là phần thú vị: VPS rẻ = RAM ít. Build Next.js cần nhiều RAM. Giải pháp? Build trên máy Mac (RAM 16GB), rồi rsync image lên VPS.

#!/bin/bash
VPS_IP="xxx.xxx.xxx.xxx"
IMAGE_NAME="cuthongminh-web"

# 1. Build Docker image trên máy local
docker build --platform linux/amd64 -t ${IMAGE_NAME}:latest .

# 2. Save thành file tar
docker save ${IMAGE_NAME}:latest -o /tmp/${IMAGE_NAME}.tar

# 3. Chuyển file tar lên VPS bằng rsync
rsync -avz --progress /tmp/${IMAGE_NAME}.tar root@${VPS_IP}:/tmp/

# 4. SSH vào VPS, load image và restart container
ssh root@${VPS_IP} "\
  docker load -i /tmp/${IMAGE_NAME}.tar && \
  cd /var/www/cuthongminh.com/frontend && \
  docker compose -f docker-compose.deploy.yml up -d --force-recreate"

Quy trình deploy: chạy 1 lệnh ./deploy.sh, mất khoảng 3-5 phút, zero downtime (Docker tự restart container mới trước khi tắt cũ).

Docker Compose trên VPS

version: "3.8"
services:
  cuthongminh-web:
    image: cuthongminh-web:latest
    container_name: cuthongminh_web
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
    env_file:
      - .env.production

Đơn giản đến mức bất ngờ. Nginx đứng trước làm reverse proxy + SSL (Let's Encrypt miễn phí).

Tổng kết Deploy

Thành phần Giải pháp Chi phí
Server VPS Việt Nam ~100k/tháng
Container Docker + Docker Compose
SSL Let's Encrypt
Reverse Proxy Nginx
CI/CD Shell script (deploy.sh)
Domain cuthongminh.com ~250k/năm (~20k/tháng)

4. Phần 3: SEO — Để Google tìm thấy bạn khi không có tiền quảng cáo {#4-seo}

Khi ngân sách quảng cáo bằng 0, SEO là kênh marketing duy nhất. Mình đã tối ưu rất kỹ.

4.1. Technical SEO

Sitemap động tự động

Thay vì viết sitemap bằng tay, mình tự generate từ code:

// src/app/sitemap.ts
export default function sitemap(): MetadataRoute.Sitemap {
  const baseUrl = "https://cuthongminh.com";

  // Trang tĩnh
  const staticRoutes = [
    { url: baseUrl, priority: 1 },
    { url: `${baseUrl}/games`, priority: 0.9 },
  ];

  // Tự động scan tất cả thư mục game
  const gameFolders = fs.readdirSync(gamesDir)
    .filter(file => !file.startsWith("[") && !file.startsWith("."));

  const gameRoutes = gameFolders.map(game => ({
    url: `${baseUrl}/games/${game}`,
    priority: 0.8,
  }));

  // Tự động scan tất cả file blog .mdx
  const blogFiles = fs.readdirSync(blogsDir)
    .filter(file => file.endsWith(".mdx"));

  const blogRoutes = blogFiles.map(file => ({
    url: `${baseUrl}/blogs/${file.replace(/\.mdx$/, "")}`,
    priority: 0.7,
  }));

  return [...staticRoutes, ...gameRoutes, ...blogRoutes];
}

Kết quả: Mỗi khi thêm game hoặc blog mới → sitemap tự cập nhật → Google crawl nhanh hơn.

Robots.txt thông minh

export default function robots(): MetadataRoute.Robots {
  return {
    rules: {
      userAgent: "*",
      allow: "/",
      disallow: ["/auth/", "/settings/", "/learn-progress/", "/api/"],
    },
    sitemap: "https://cuthongminh.com/sitemap.xml",
  };
}

Chỉ cho Google index nội dung public, chặn trang auth và API.

4.2. Schema.org Structured Data

Đây là thứ giúp Google hiểu website bạn là gì:

// Schema cho Educational Organization
const orgJsonLd = {
  "@context": "https://schema.org",
  "@type": "EducationalOrganization",
  name: "Cú Thông Minh",
  url: "https://cuthongminh.com",
  description: "Nền tảng giáo dục tương tác cho trẻ em từ 3-8 tuổi...",
  foundingDate: "2024",
  areaServed: { "@type": "Country", name: "Vietnam" },
  knowsAbout: [
    "Early childhood education",
    "Educational games for kids",
    "Vietnamese language learning",
  ],
};

// Schema cho Web Application
const appJsonLd = {
  "@type": "WebApplication",
  applicationCategory: "EducationalApplication",
  offers: { price: "0", priceCurrency: "VND" },
  aggregateRating: { ratingValue: "4.9", reviewCount: "1280" },
};

4.3. Content SEO: 60+ bài blog MDX

Chiến lược đơn giản: viết bài blog trả lời đúng câu hỏi phụ huynh đang tìm kiếm.

Ví dụ các bài đã viết:

  • be-3-tuoi-nen-hoc-gi.mdx → keyword: "bé 3 tuổi nên học gì"
  • day-be-hoc-dem.mdx → keyword: "dạy bé học đếm"
  • giao-duc-som-la-gi.mdx → keyword: "giáo dục sớm là gì"
  • hoc-mau-sac.mdx → keyword: "dạy bé học màu sắc"

Mỗi bài blog đều:

  • metadata SEO riêng (title, description, OG image)
  • Link nội bộ về trang game liên quan
  • Được thêm vào sitemap tự động

4.4. Performance = SEO

Google đánh giá Core Web Vitals. Những gì mình làm:

// Cache headers cho static assets — 1 năm, immutable
{
  source: "/_next/static/(.*)",
  headers: [{
    key: "Cache-Control",
    value: "public, max-age=31536000, immutable",
  }],
},

// Cache headers cho optimized images — 30 ngày
{
  source: "/_next/image",
  headers: [{
    key: "Cache-Control",
    value: "public, max-age=2592000, stale-while-revalidate=86400",
  }],
},

Thêm các kỹ thuật khác:

  • Dynamic import cho các component không cần thiết ngay (FAQ, Testimonials, Floating CTA)
  • Preconnect đến CDN assets
  • loading="lazy" cho ảnh below-the-fold
  • Font từ Google Fonts với display: "swap" — text hiển thị ngay, không chờ font load

4.5. FAQ Schema cho AI/Voice Search

const HOME_FAQ_ITEMS = [
  {
    question: "Cú Thông Minh là gì?",
    answer: "Ứng dụng giáo dục tương tác dành cho trẻ em từ 3-8 tuổi...",
  },
  {
    question: "Ứng dụng có miễn phí không?",
    answer: "Cung cấp nhiều trò chơi miễn phí. Nâng cấp premium với 20+ thể loại...",
  },
];

FAQ Schema giúp xuất hiện trên Google Featured SnippetsAI chatbot responses.


5. Tổng kết chi phí {#5-tổng-kết}

Chi phí ban đầu: 0 đồng

Hạng mục Giải pháp Chi phí
Framework Next.js (open source)
Database Supabase Free tier
Auth Supabase Auth
Storage Supabase Storage
Monitoring Sentry Free tier
CMS MDX files trong repo
SSL Let's Encrypt

Chi phí vận hành hàng tháng: ~100.000 VNĐ

Hạng mục Chi phí/tháng
VPS ~100.000 VNĐ
Domain ~20.000 VNĐ (250k/năm)
Tổng ~120.000 VNĐ/tháng

Kết quả đạt được

  • 🎮 38+ thể loại game tương tác cho trẻ em
  • 📝 60+ bài blog SEO content
  • 📱 PWA chạy trên mọi thiết bị
  • 🔍 100+ trang được index trên Google
  • 🛡️ Không quảng cáo, an toàn cho trẻ
  • 📊 Error monitoring real-time với Sentry

Lời kết

Bạn không cần nhiều tiền để bắt đầu. Với hệ sinh thái open source hiện nay và các free tier rộng rãi, một developer hoàn toàn có thể tự xây dựng và vận hành một sản phẩm hoàn chỉnh với chi phí gần như bằng 0.

Điều quan trọng nhất không phải là tiền, mà là:

  1. Chọn đúng stack — tận dụng free tier
  2. Tự động hóa — deploy một lệnh, sitemap tự generate
  3. SEO từ ngày đầu — khi không có tiền quảng cáo, organic traffic là tất cả

Nếu bạn đang có một ý tưởng sản phẩm, đừng chờ có tiền hay có team. Hãy bắt đầu ngay hôm nay.

👉 Trải nghiệm tại: cuthongminh.com


Nếu bạn thấy bài viết hữu ích, hãy upvote và chia sẻ nhé! Có câu hỏi gì, comment bên dưới mình sẽ trả lời. 🦉


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí