2025-06-10 網站拆成清楚的階段

2025-06-10 網站拆成清楚的階段

「從頭、一步步、可馬上動手」的版本整理好,幫你把網站拆成清楚的階段、每一步要做的工作、範例程式與必要的注意事項。你不用馬上回答任何問題(我幫你選好預設路線),照著一步步做就能把 MVP 跑起來,之後再慢慢優化 AI 路由、UI、付款、審核等功能。

概覽(一句話)

建立一個前端 Vue 3(Vite)+ 後端 Node/Express 的網站,資料存 MySQL,後端當 AI gateway(支援 ChatGPT 與 DeepSeek / 其他 provider),MCP Server 可做為本地/特殊模型運行或作為另一個 provider。先做 MVP:使用者可註冊、提問(AI 回覆)、儲存查詢紀錄與查看歷史。

推薦技術堆疊(快速決策)

  • 前端:Vue 3 + Vite,Composition API(你喜歡 Composition)
  • 後端:Node.js + Express(快速、少摩擦)
  • 多模型 Gateway:同一個後端實作 provider adapter(OpenAI / DeepSeek)
  • DB:MySQL(可本地或雲端),起步用 mysql2,之後可改 ORM/Prisma
  • 認證:JWT + bcrypt(或使用 OAuth)
  • 部署:Frontend → Vercel / Netlify;Backend → Render / DigitalOcean / VPS;MCP Server → 先放在 Mac(開發)或雲端(生產)
  • 其他:cors, helmet, express-rate-limit, winston(logging)

系統架構(文字圖)

Frontend (Vue) ←→ Backend API (Express, /api/*) ←→ AI Providers (OpenAI / DeepSeek / MCP Server)

MySQL(讀寫儲存、歷史、會員)

MVP 功能(優先順序)

  1. 用戶系統:註冊、登入、JWT 驗證
  2. 提問功能:輸入問題 → 後端決定 provider → 回傳 AI 回覆
  3. 查詢紀錄:每次提問儲存在 readings 表,使用者可看歷史
  4. 管理後台(簡單):可查看 logs、設定 provider 權重(後期)
  5. 基本 Moderation:在發送給 AI 前做簡單關鍵詞檢查(敏感詞)

開發分階段(每階段分小步驟)

Phase 0 — 準備環境(目標:建立前端 + 後端骨架)

  1. 建 repo(frontend / backend):git init
  2. 建前端(Vite + Vue):
1
2
3
4
npm create vite@latest mindsite -- --template vue
cd mindsite
npm install
npm run dev
  1. 建後端(Express):
1
2
3
4
mkdir backend && cd backend
npm init -y
npm i express dotenv mysql2 cors helmet express-rate-limit bcrypt jsonwebtoken
# Node 18+ 建議使用 ESM (server.mjs) 或 commonjs
  1. 建 MySQL 本地資料庫(或使用雲端 MySQL):建立 mindsite DB。

驗收:能在瀏覽器看到 Vue 開發頁面、能呼叫 GET /api/healthOK


Phase 1 — 資料庫 + 認證(目標:使用者可註冊、登入)

  1. 建資料表(SQL 範例):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
name VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE readings (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
provider VARCHAR(50),
prompt TEXT,
response LONGTEXT,
cost DECIMAL(10,4) DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);
  1. 在後端實作 /api/auth/register/api/auth/login(bcrypt 存密碼、回 JWT)。

驗收:註冊成功後登入得到 JWT,可帶 Authorization 呼叫受保護 API。


Phase 2 — AI Gateway(目標:能夠向 OpenAI / DeepSeek 發問)

  1. 在後端建立 provider adapter(統一介面)。下面是一個簡化的示範(server.mjs):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// server.mjs (最簡版)
import express from 'express';
import dotenv from 'dotenv';
dotenv.config();
import mysql from 'mysql2/promise';

const app = express();
app.use(express.json());

const pool = mysql.createPool({
host: process.env.DB_HOST, user: process.env.DB_USER, password: process.env.DB_PASS, database: process.env.DB_NAME
});

// providers
const providers = {
openai: async ({ messages, opts }) => {
const res = await fetch('https://api.openai.com/v1/chat/completions', {
method:'POST',
headers:{
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
'Content-Type':'application/json'
},
body: JSON.stringify({ model: opts?.model || 'gpt-4o-mini', messages })
});
const data = await res.json();
return { text: data?.choices?.[0]?.message?.content ?? '', raw: data };
},
deepseek: async ({ messages, opts }) => {
const res = await fetch('https://api.deepseek.com/v1/chat/completions', {
method:'POST',
headers:{
'Authorization': `Bearer ${process.env.DEEPSEEK_API_KEY}`,
'Content-Type':'application/json'
},
body: JSON.stringify({ model: opts?.model || 'deepseek-v1', messages })
});
const data = await res.json();
return { text: data?.choices?.[0]?.message?.content ?? '', raw: data };
}
};

app.post('/api/chat', async (req, res) => {
const { provider = 'openai', messages, userId } = req.body;
try {
const { text, raw } = await providers[provider]({ messages });
// 存 readings
await pool.query('INSERT INTO readings (user_id, provider, prompt, response) VALUES (?, ?, ?, ?)', [userId || null, provider, JSON.stringify(messages), text]);
res.json({ provider, text, raw });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'provider error' });
}
});

app.listen(3000, ()=>console.log('listening 3000'));
  1. 前端簡單頁面 Ask.vue:給使用者輸入、呼叫 /api/chat 顯示回覆(我會在下面給完整範例)。

驗收:可在 UI 輸入一句話,後端回 ChatGPT 回覆並儲存到 DB。


Phase 3 — 功能補強與上線(目標:加權限、審查、部署)

  1. 加入 content moderation(在送 provider 前先檢查敏感詞或呼叫 moderation API)。
  2. 加入 rate-limiting、logging(winston)、錯誤告警(Sentry)
  3. 加入 user 訂閱 / 付費(若要商用)
  4. 部署流程(CI/CD):Github Actions → 自動推到 Vercel (frontend)、Render (backend)
  5. 若要在生產支援 stream(即時回覆),再處理 streaming adapter。

前端簡單範例(Ask.vue, Composition API)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<template>
<div>
<h2>問卜 / 提問</h2>
<textarea v-model="prompt" rows="4" placeholder="在這輸入你的問題..."></textarea>
<div>
<select v-model="provider">
<option value="openai">ChatGPT</option>
<option value="deepseek">DeepSeek</option>
</select>
<button @click="send">送出</button>
</div>

<div v-if="loading">等待回覆…</div>
<div v-if="answer"><h3>回覆</h3><div>{{ answer }}</div></div>
</div>
</template>

<script setup>
import { ref } from 'vue';
const prompt = ref('');
const provider = ref('openai');
const answer = ref('');
const loading = ref(false);

async function send(){
loading.value = true;
try{
const res = await fetch('/api/chat', {
method:'POST',
headers:{ 'Content-Type':'application/json' },
body: JSON.stringify({ provider: provider.value, messages: [{ role:'user', content: prompt.value }] })
});
const data = await res.json();
answer.value = data.text ?? JSON.stringify(data.raw, null, 2);
}catch(e){
answer.value = '發生錯誤';
}finally{
loading.value = false;
}
}
</script>

開發時:為了讓 Vite 在本地就能呼叫到後端,vite.config.jsserver.proxy 指向 http://localhost:3000


安全、合規重點(務必注意)

  • API Key 千萬別放前端:只能放在後端環境變數。
  • 密碼用 bcrypt,token 用 JWT(短時效)或 session。
  • 儲存/刪除個資:如果你要保存使用者敏感資訊(出生時間、姓名),要在隱私政策寫明並提供刪除功能。
  • moderation:對生成性的回覆先過濾(暴力、醫療、法律建議等敏感內容)。
  • 成本管理:記錄每次呼叫成本,針對高成本查詢(長 context / gpt-4)做限制或轉 cheap model。

專案目錄建議(簡潔)

1
2
3
4
5
6
7
8
9
10
11
12
13
mindsite/
frontend/ # Vite + Vue 3
src/
components/
pages/
App.vue
backend/
server.mjs
routes/
providers/
openai.js
deepseek.js
db/

立即可做的 5 個小步驟(你現在就能開始)

  1. 創兩個 repo:mindsite-frontendmindsite-backend
  2. 建前端 Vite 專案(上面那段命令)。
  3. 建後端 express skeleton,新增 /api/health 測試回傳 "ok".
  4. 建本地 MySQL 並建立 usersreadings 表。
  5. 把前端 dev server proxy 指向後端,實作前端 Ask.vue 與後端 /api/chat(回傳 mock 回應先)。

三個小練習(給你做)

  1. 在本機把 Vite 專案跑起來,並把 Ask.vue 顯示在首頁(驗收:能在頁面輸入並看到 fetch 發送的 log)。
  2. 在後端實作 /api/health/api/chat(初期 /api/chat 回傳固定文字),用 Postman 測試。
  3. 在 MySQL 建表並寫一個 script(Node)插入一筆 readings,然後用 SQL 查閱(驗收:能看到那筆資料)。

如果你要我幫你做什麼:

  • 我可以把 完整的後端 server.mjs(含 provider adapter、DB 連線、auth skeleton)貼給你,你直接貼上執行就能跑。
  • 或我可以把 前端完整範例(vite config + Ask.vue + proxy)產出。
  • 或我把資料庫 migration SQLdocker-compose(MySQL)給你,方便一鍵起 DB。

你想先要哪一樣?我會直接把可貼上、可執行的檔案貼給你。 (不用回答太多,我會預設先給後端 server.mjs 與 DB SQL,除非你要我改成 C# 或 Python)