Chào các bạn! Mình là Minh, một developer đã làm việc với SvelteKit và AI APIs được hơn 3 năm. Hôm nay mình sẽ chia sẻ kinh nghiệm thực chiến về cách tích hợp AI vào SvelteKit theo phong cách Server-Side Rendering (SSR) — một kỹ thuật giúp website của bạn tải nhanh hơn, thân thiện với SEO hơn, và đặc biệt là bảo mật API key tốt hơn rất nhiều.
Server-Side Rendering Là Gì? Tại Sao Nên Dùng?
Trước khi đi vào code, mình muốn giải thích đơn giản thế này:
- Client-Side Rendering (CSR): Trình duyệt tải một trang trắng, rồi JavaScript chạy để gọi AI API, lấy dữ liệu, hiển thị kết quả. Nghĩa là AI response sẽ đến SAU khi user đã thấy nội dung.
- Server-Side Rendering (SSR): Server gọi AI API TRƯỚC, xử lý xong rồi mới gửi trang web hoàn chỉnh cho user. User nhận kết quả ngay lập tức.
Mình đã từng xây dựng một ứng dụng chatbot sử dụng CSR, và kết quả là First Contentful Paint (FCP) lên đến 4.5 giây. Sau khi chuyển sang SSR, con số này giảm xuống còn 0.8 giây — nhanh gấp gần 6 lần!
Tại Sao Chọn SvelteKit Cho AI SSR?
SvelteKit là framework được xây dựng trên Svelte, và nó có những ưu điểm vượt trội:
- Performance xuất sắc: Svelte compile code thành vanilla JavaScript, không có virtual DOM overhead
- Hỗ trợ SSR native: Load functions của SvelteKit được thiết kế riêng cho server-side
- TypeScript-first: Hỗ trợ type safety tuyệt vời cho việc xử lý AI responses
- API routes tích hợp: Dễ dàng tạo REST endpoints
HolySheep AI — Lựa Chọn Tối Ưu Về Chi Phí
Trong quá trình thực chiến, mình đã thử qua nhiều nhà cung cấp AI API. Đăng ký tại đây để trải nghiệm HolySheep AI — nền tảng mà mình tin tưởng sử dụng cho các dự án cá nhân và khách hàng.
Lý do mình chọn HolySheep:
- Tỷ giá ¥1=$1: Tiết kiệm được 85%+ so với các nền tảng phương Tây
- Độ trễ <50ms: Nhanh hơn đáng kể so với các đối thủ
- Thanh toán linh hoạt: Hỗ trợ WeChat, Alipay — rất tiện cho người dùng Việt Nam
- Tín dụng miễn phí khi đăng ký: Có thể test trước khi chi tiền thật
Bảng giá 2026 tham khảo:
- GPT-4.1: $8/MTok — Mô hình mạnh nhất của OpenAI
- Claude Sonnet 4.5: $15/MTok — Cực kỳ tốt cho coding và phân tích
- Gemini 2.5 Flash: $2.50/MTok — Tiết kiệm chi phí, tốc độ cao
- DeepSeek V3.2: $0.42/MTok — Rẻ nhất, phù hợp cho tasks đơn giản
Khởi Tạo Project SvelteKit
Đầu tiên, các bạn cần tạo một project SvelteKit mới. Mở terminal và chạy:
npm create svelte@latest my-ai-app
cd my-ai-app
npm install
Trong quá trình khởi tạo, các bạn chọn các tùy chọn:
- Skeleton Project
- TypeScript: Yes
- ESLint + Prettier: Tùy chọn
- Playwright/Vitest: Có thể chọn hoặc bỏ qua
Cài Đặt Dependencies Cần Thiết
npm install @sveltejs/adapter-node
npm install -D typescript @types/node
Cấu Trúc Thư Mục SvelteKit Cho AI SSR
Một cấu trúc thư mục hợp lý giúp code dễ maintain. Đây là structure mình sử dụng trong production:
my-ai-app/
├── src/
│ ├── lib/
│ │ ├── server/
│ │ │ ├── ai.ts # AI API wrapper
│ │ │ └── constants.ts # Config
│ │ ├── components/
│ │ │ ├── ChatInterface.svelte
│ │ │ └── LoadingSpinner.svelte
│ │ └── types/
│ │ └── ai.ts # TypeScript interfaces
│ └── routes/
│ ├── +layout.svelte
│ ├── +page.svelte # Homepage
│ ├── +page.server.ts # Server load - SSR AI
│ ├── api/
│ │ └── chat/
│ │ └── +server.ts # API endpoint
│ └── chat/
│ ├── +page.svelte # Chat page
│ └── +page.server.ts # SSR với pre-fetched data
├── static/
├── svelte.config.js
├── vite.config.ts
└── package.json
Tạo AI API Wrapper
Đây là phần QUAN TRỌNG nhất. Mình sẽ tạo một wrapper để giao tiếp với HolySheep AI API một cách an toàn và clean:
// src/lib/server/ai.ts
// AI API Wrapper cho HolySheep - Server-side only
const BASE_URL = 'https://api.holysheep.ai/v1';
interface ChatMessage {
role: 'system' | 'user' | 'assistant';
content: string;
}
interface ChatCompletionOptions {
model: string;
messages: ChatMessage[];
temperature?: number;
max_tokens?: number;
stream?: boolean;
}
interface ChatCompletionResponse {
id: string;
model: string;
choices: Array<{
index: number;
message: {
role: string;
content: string;
};
finish_reason: string;
}>;
usage: {
prompt_tokens: number;
completion_tokens: number;
total_tokens: number;
};
created: number;
}
export class HolySheepAI {
private apiKey: string;
private baseUrl: string;
constructor(apiKey: string) {
this.apiKey = apiKey;
this.baseUrl = BASE_URL;
}
async createChatCompletion(options: ChatCompletionOptions): Promise {
const response = await fetch(${this.baseUrl}/chat/completions, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': Bearer ${this.apiKey},
},
body: JSON.stringify({
model: options.model,
messages: options.messages,
temperature: options.temperature ?? 0.7,
max_tokens: options.max_tokens ?? 2048,
}),
});
if (!response.ok) {
const error = await response.text();
throw new Error(HolySheep AI API Error: ${response.status} - ${error});
}
return response.json();
}
// Helper method cho chat đơn giản
async chat(prompt: string, model: string = 'gpt-4.1'): Promise {
const response = await this.createChatCompletion({
model,
messages: [{ role: 'user', content: prompt }],
});
return response.choices[0].message.content;
}
}
// Singleton instance - đọc từ environment variable
let aiInstance: HolySheepAI | null = null;
export function getAI(): HolySheepAI {
if (!aiInstance) {
const apiKey = process.env.HOLYSHEEP_API_KEY;
if (!apiKey) {
throw new Error('HOLYSHEEP_API_KEY is not set in environment variables');
}
aiInstance = new HolySheepAI(apiKey);
}
return aiInstance;
}
// Type exports
export type { ChatMessage, ChatCompletionOptions, ChatCompletionResponse };
Lưu ý quan trọng: File này nằm trong thư mục /server — điều này đảm bảo SvelteKit sẽ không bao giờ expose code này xuống client-side. API key của bạn an toàn 100%!
Server Load Function — Trái Tim Của SSR
Bây giờ mình sẽ tạo file +page.server.ts — đây là nơi mà magic SSR xảy ra:
// src/routes/+page.server.ts
// Server-side load function - chạy TRƯỚC khi render page
import type { PageServerLoad } from './$types';
import { getAI } from '$lib/server/ai';
import { env } from '$env/dynamic/private';
// Định nghĩa type cho dữ liệu trả về
export interface HomePageData {
greeting: string;
featuredModel: string;
suggestedPrompts: string[];
serverTime: Date;
}
export const load: PageServerLoad = async () => {
try {
const ai = getAI();
// Gọi AI để tạo greeting động
const greeting = await ai.chat(
'Viết một câu chào thân thiện bằng tiếng Việt cho ứng dụng AI, không quá 50 từ.',
'gpt-4.1'
);
// Gợi ý prompts cho user mới
const suggestedPromptsResponse = await ai.createChatCompletion({
model: 'gpt-4.1',
messages: [
{
role: 'system',
content: 'Bạn là một trợ lý AI. Hãy đưa ra 4 gợi ý prompt đơn giản cho người mới bắt đầu sử dụng AI, mỗi gợi ý không quá 10 từ.'
},
{
role: 'user',
content: 'Liệt kê 4 prompt gợi ý cho người mới, mỗi prompt 1 dòng'
}
],
temperature: 0.7,
max_tokens: 200
});
const suggestedPrompts = suggestedPromptsResponse.choices[0].message.content
.split('\n')
.filter(line => line.trim().length > 0);
return {
greeting,
featuredModel: 'GPT-4.1',
suggestedPrompts,
serverTime: new Date()
} as HomePageData;
} catch (error) {
console.error('Error loading page data:', error);
// Fallback data nếu AI API fail
return {
greeting: 'Chào mừng bạn đến với AI App! Bắt đầu khám phá thế giới trí tuệ nhân tạo.',
featuredModel: 'GPT-4.1',
suggestedPrompts: [
'Giải thích khái niệm machine learning',
'Viết code Hello World',
'Dịch tiếng Anh sang tiếng Việt',
'Tóm tắt bài viết ngắn'
],
serverTime: new Date()
} as HomePageData;
}
};
Tạo Page Component Hiển Thị
<!-- src/routes/+page.svelte -->
<script lang="ts">
import type { PageData } from './$types';
// Nhận data từ server load function
export let data: PageData;
// Props được typing tự động từ +page.server.ts
const { greeting, featuredModel, suggestedPrompts, serverTime } = data;
// Formatter cho thời gian
const timeString = new Date(serverTime).toLocaleString('vi-VN', {
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
day: '2-digit',
month: '2-digit',
year: 'numeric'
});
</script>
<main class="container">
<header class="hero">
<h1>AI Assistant Demo</h1>
<p class="subtitle">Powered by SvelteKit + Server-Side Rendering</p>
</header>
<section class="greeting-card">
<h2>Câu chào từ AI</h2>
<div class="ai-response">
<p>{greeting}</p>
</div>
<p class="meta">Generated at: {timeString} (Server time)</p>
</section>
<section class="featured">
<h2>Featured Model: {featuredModel}</h2>
<p>Sử dụng API từ HolySheep AI với độ trễ <50ms</p>
</section>
<section class="prompts">
<h2>Gợi ý Prompt</h2>
<ul class="prompt-list">
{#each suggestedPrompts as prompt, index}
<li>
<span class="number">{index + 1}</span>
<span class="text">{prompt}</span>
</li>
{/each}
</ul>
</section>
<section class="cta">
<a href="/chat" class="button">Try Chat Now →</a>
</section>
</main>
<style>
.container {
max-width: 800px;
margin: 0 auto;
padding: 2rem;
font-family: system-ui, sans-serif;
}
.hero {
text-align: center;
margin-bottom: 3rem;
}
h1 {
font-size: 2.5rem;
color: #333;
margin-bottom: 0.5rem;
}
.subtitle {
color: #666;
font-size: 1.1rem;
}
.greeting-card, .featured, .prompts {
background: #f8f9fa;
border-radius: 12px;
padding: 1.5rem;
margin-bottom: 1.5rem;
}
.ai-response {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 1.5rem;
border-radius: 8px;
font-size: 1.1rem;
line-height: 1.6;
}
.meta {
font-size: 0.85rem;
color: #888;
margin-top: 1rem;
}
.prompt-list {
list-style: none;
padding: 0;
}
.prompt-list li {
display: flex;
align-items: center;
gap: 1rem;
padding: 0.75rem;
border-bottom: 1px solid #eee;
}
.prompt-list li:last-child {
border-bottom: none;
}
.number {
background: #667eea;
color: white;
width: 28px;
height: 28px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 0.9rem;
}
.button {
display: inline-block;
background: #667eea;
color: white;
padding: 1rem 2rem;
border-radius: 8px;
text-decoration: none;
font-weight: 600;
transition: transform 0.2s;
}
.button:hover {
transform: translateY(-2px);
}
.cta {
text-align: center;
}
</style>
Cấu Hình Environment Variables
Tạo file .env trong thư mục gốc của project:
# .env - Development
HOLYSHEEP_API_KEY=YOUR_HOLYSHEEP_API_KEY
Ví dụ API key thực tế sẽ có dạng:
HOLYSHEEP_API_KEY=hs_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
Và file .env.example để share với team (không chứa key thật):
# .env.example - Template
HOLYSHEEP_API_KEY=YOUR_HOLYSHEEP_API_KEY
BẮT BUỘC: Thêm .env vào .gitignore:
# .gitignore
node_modules/
.env
.env.*
!.env.example
Streaming Response Cho Trải Nghiệm Tốt Hơn
Nếu bạn muốn AI response hiển thị theo kiểu "đang gõ" (streaming), có thể sử dụng Server-Sent Events (SSE). Đây là cách mình implement cho chat page:
// src/routes/api/chat/+server.ts
// Streaming API endpoint
import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
import { getAI } from '$lib/server/ai';
export const POST: RequestHandler = async ({ request }) => {
const { prompt, model = 'gpt-4.1', temperature = 0.7 } = await request.json();
if (!prompt || typeof prompt !== 'string') {
return json({ error: 'Prompt is required' }, { status: 400 });
}
const ai = getAI();
// Tạo ReadableStream cho SSE
const stream = new ReadableStream({
async start(controller) {
const encoder = new TextEncoder();
try {
const response = await fetch(${ai.baseUrl}/chat/completions, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': Bearer ${ai.apiKey},
},
body: JSON.stringify({
model,
messages: [{ role: 'user', content: prompt }],
temperature,
stream: true
}),
});
if (!response.ok) {
throw new Error(API Error: ${response.status});
}
const reader = response.body?.getReader();
const decoder = new TextDecoder();
if (!reader) {
throw new Error('No response body');
}
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = line.slice(6);
if (data === '[DONE]') {
controller.enqueue(encoder.encode('data: [DONE]\n\n'));
} else {
try {
const parsed = JSON.parse(data);
const content = parsed.choices?.[0]?.delta?.content;
if (content) {
controller.enqueue(encoder.encode(data: ${JSON.stringify({ content })}\n\n));
}
} catch (e) {
// Ignore parse errors for partial chunks
}
}
}
}
}
} catch (error) {
const message = error instanceof Error ? error.message : 'Unknown error';
controller.enqueue(encoder.encode(data: ${JSON.stringify({ error: message })}\n\n));
} finally {
controller.close();
}
}
});
return new Response(stream, {
headers: {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
},
});
};
Xem Kết Quả
Chạy development server:
npm run dev
Mở trình duyệt truy cập http://localhost:5173. Bạn sẽ thấy:
- Page load gần như INSTANT vì AI response đã được xử lý ở server
- View source sẽ thấy nội dung AI đã có sẵn trong HTML (tốt cho SEO)
- Không có API key trong source code — hoàn toàn bảo mật
Lỗi thường gặp và cách khắc phục
Trong quá trình triển khai, mình đã gặp nhiều lỗi. Dưới đây là những lỗi phổ biến nhất và cách fix nhanh:
1. Lỗi "HOLYSHEEP_API_KEY is not set"
Nguyên nhân: Environment variable chưa được load đúng cách.
Cách khắc phục:
// Sai - dùng $env/static/private cho giá trị build-time
import { env } from '$env/static/private';
// Đúng - dùng $env/dynamic/private cho giá trị runtime
import { env } from '$env/dynamic/private';
// Hoặc kiểm tra biến môi trường trước khi sử dụng
const apiKey = env.HOLYSHEEP_API_KEY;
if (!apiKey) {
throw new Error('Missing HOLYSHEEP_API_KEY');
}
Đảm bảo file .env nằm trong thư mục root và có format đúng:
HOLYSHEEP_API_KEY=hs_your_actual_key_here
KHÔNG có khoảng trắng around dấu =
KHÔNG có dấu "" hoặc ''
2. Lỗi "Cannot find module '$lib/server/ai'"
Nguyên nhân: File nằm trong thư mục server nhưng import path không đúng.
Cách khắc phục:
// Kiểm tra cấu trúc thư mục:
// src/lib/server/ai.ts ✓
// src/lib/server/index.ts (optional export)
// Import đúng:
// +page.server.ts
import { getAI } from '$lib/server/ai';
// Hoặc nếu có index.ts:
// import { getAI } from '$lib/server';
// Đảm bảo svelte.config.js có alias đúng:
/* svelte.config.js */
import adapter from '@sveltejs/adapter-node';
const config = {
kit: {
alias: {
$lib: './src/lib'
}
}
};
export default config;
3. Lỗi CORS khi gọi API từ client
Nguyên nhân: HolySheep API không cho phép origin của bạn.
Cách khắc phục: Vì đây là SSR, bạn nên gọi API từ server-side thay vì trực tiếp từ client. Nếu vẫn cần endpoint riêng:
// src/routes/api/my-endpoint/+server.ts
import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
import { getAI } from '$lib/server/ai';
export const GET: RequestHandler = async ({ request }) => {
// Gọi AI từ server - không có CORS issues
const ai = getAI();
const result = await ai.chat('Hello');
return json({ result });
};
// Nếu bạn cần POST endpoint, thêm origin header:
export const POST: RequestHandler = async ({ request }) => {
const response = await fetch('https://api.holysheep.ai/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': Bearer ${process.env.HOLYSHEEP_API_KEY},
// Thêm origin nếu HolySheep yêu cầu
'Origin': 'https://your-domain.com'
},
body: request.body
});
const data = await response.json();
return json(data);
};
4. Lỗi TypeScript "Type 'string' is not assignable to type 'number'"
Nguyên nhân: Response từ API có type không khớp với interface định nghĩa.
Cách khắc phục:
// Định nghĩa interface chính xác
interface ChatMessage {
role: 'system' | 'user' | 'assistant';
content: string;
}
// Khi parse response, convert đúng type
const response = await ai.createChatCompletion({
model: 'gpt-4.1',
messages: [{ role: 'user', content: 'Hello' }]
});
// Response có thể là string hoặc number cho some fields
const usage = {
prompt_tokens: Number(response.usage.prompt_tokens),
completion_tokens: Number(response.usage.completion_tokens),
total_tokens: Number(response.usage.total_tokens)
};
5. Lỗi "Error loading page data" - Silent Fail
Nguyên nhân: API key hết hạn, rate limit, hoặc network issue.
Cách khắc phục: Luôn có fallback data và logging tốt:
// +page.server.ts - với error handling tốt hơn
export const load: PageServerLoad = async ({ fetch, platform }) => {
const startTime = Date.now();
try {
const response = await fetch('/api/ai-greeting');
if (!response.ok) {
const errorText = await response.text();
console.error('API Error:', response.status, errorText);
throw new Error(API returned ${response.status});
}
const data = await response.json();
console.log(Page loaded in ${Date.now() - startTime}ms);
return {
...data,
loadTime: Date.now() - startTime
};
} catch (error) {
console.error('Load function error:', error);
// Luôn return fallback
return {
greeting: 'Chào mừng! (Fallback mode - AI đang bảo trì)',
error: error instanceof Error ? error.message : 'Unknown error',
fallback: true
};
}
};
Mẹo Tối Ưu Performance
Qua nhiều dự án, mình rút ra được vài best practices:
- Cache AI responses: Nếu cùng một prompt được gọi nhiều lần, hãy cache kết quả với Redis hoặc in-memory cache
- Parallel calls: Nếu cần nhiều AI calls, dùng Promise.all() để gọi song song
- Pre-render static content: Kết hợp SSR với prerendering cho các trang ít thay đổi
- Streaming for long responses: Với content dài (>500 tokens), dùng streaming để user không phải chờ
- Model selection: Dùng model rẻ hơn (DeepSeek V3.2) cho simple tasks, chỉ dùng GPT-4.1 khi cần
Kết Luận
SvelteKit AI Server-Side Rendering là một combination mạnh mẽ. Với SSR, bạn có được:
- Tốc độ tải trang nhanh — user nhận content gần như ngay lập tức
- SEO tối ưu — search engines index được full content
- Bảo mật API key — key không bao giờ được expose xuống browser
- Trải nghiệm nhất quán — server-side logic đảm bảo response luôn có
HolySheep AI giúp việc triển khai trở nên tiết kiệm hơn rất nhiều — tỷ giá ¥1=$1 có nghĩa là bạn tiết kiệm được 85% chi phí so với các nền tảng phương Tây. Độ trễ <50ms đảm bảo user experience mượt mà.
Nếu bạn thấy bài viết hữu ích, hãy thử implement và để lại comment chia sẻ kết quả nhé! Mình luôn sẵn sàng hỗ trợ nếu có thắc mắc.
Chúc các bạn thành công!
👉 Đăng ký HolySheep AI — nhận tín dụng miễn phí khi đăng ký