tạo web site cho next js
- Sao chép liên kết
- Chia sẻ với Facebook
- Chia sẻ với X
- Chia sẻ với Pinterest
- Chia sẻ với Linkedin
- Gửi bài qua Email
gửi email cho tác giả
Lỗi bạn đang gặp là HTTP ERROR 500 (Internal Server Error) ở đường dẫn:
http://localhost:4000/web_site_cty/api/posts
Điều này nghĩa là server (Next.js API Route) của bạn bị lỗi trong quá trình xử lý — chứ không phải do client (trình duyệt).
Ta cùng kiểm tra từng bước nhé 👇
🧩 1. Xác định vị trí file API
Trong dự án Next.js, API route thường nằm tại:
/app/web_site_cty/api/posts/route.ts
(nếu bạn dùng app router)
hoặc (nếu bạn dùng pages router cũ)
/pages/api/posts.ts
Hãy mở file đó ra, và xem có code như sau không:
import { NextResponse } from 'next/server';
export async function GET() {
try {
// Ví dụ đọc bài đăng
const posts = [
{ id: 1, title: "Bài đăng 1", content: "Nội dung..." },
{ id: 2, title: "Bài đăng 2", content: "Nội dung..." },
];
return NextResponse.json(posts);
} catch (error) {
console.error(error);
return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 });
}
}
➡️ Nếu thiếu NextResponse.json(...)
hoặc có lỗi cú pháp, bạn sẽ nhận HTTP 500 ngay.
⚙️ 2. Kiểm tra log server
Trong terminal nơi bạn chạy lệnh:
npm run dev
xem có dòng báo lỗi nào không, ví dụ như:
ReferenceError: posts is not defined
Error: connect ECONNREFUSED
Copy đoạn lỗi đó gửi lại cho mình — mình sẽ chỉ bạn cách sửa chính xác.
💾 3. Nếu bạn đang kết nối tới cơ sở dữ liệu (SQL Server, MongoDB, v.v.)
Rất có thể lỗi nằm ở phần kết nối DB trong route.ts
:
await db.connect()
Nếu không có DB hoặc thông tin sai (ví dụ .env
sai), thì API /api/posts
cũng sẽ báo 500.
📌 Gợi ý kiểm tra nhanh:
-
Đường dẫn
route.ts
có đúng nằm trong/app/web_site_cty/api/posts/
chưa? -
Trong file đó có
export async function GET()
không? -
Terminal có log lỗi đỏ nào không?
Bạn chụp (hoặc dán) giúp mình nội dung file route.ts
trong thư mục api/posts
, hoặc log lỗi trong terminal, mình sẽ chỉ bạn đúng dòng bị lỗi và sửa luôn nhé.
Bạn đã nói:
ChatGPT đã nói:
Rất hay 👌 — mình sẽ giúp bạn làm chức năng đăng bài ngay từ web (giống Blogspot) trong dự án Next.js (app router) mà bạn đang làm ở thư mục \app\web_site_cty
.
🎯 Mục tiêu
Tạo trang web có thể:
-
Nhập tiêu đề + nội dung + (tùy chọn: hình ảnh, tác giả, danh mục…)
-
Nhấn nút Đăng bài → lưu bài viết vào cơ sở dữ liệu (hoặc tạm lưu trong file JSON trước nếu bạn chưa có DB).
-
Sau đó hiển thị trong danh sách
/posts
.
🧩 1. Cấu trúc thư mục
app/
└── web_site_cty/
├── api/
│ └── posts/
│ └── route.ts <-- API lưu & lấy bài viết
├── posts/
│ ├── page.tsx <-- Xem tất cả bài viết
│ └── new/
│ └── page.tsx <-- Trang đăng bài
└── layout.tsx
⚙️ 2. API /api/posts/route.ts
Nếu bạn chưa có cơ sở dữ liệu, ta lưu tạm vào file JSON trong thư mục data/posts.json
.
Tạo file app/web_site_cty/api/posts/route.ts
:
import { NextResponse } from 'next/server';
import fs from 'fs';
import path from 'path';
const dataFile = path.join(process.cwd(), 'app/web_site_cty/data/posts.json');
function readPosts() {
if (!fs.existsSync(dataFile)) return [];
const data = fs.readFileSync(dataFile, 'utf8');
return JSON.parse(data || '[]');
}
function writePosts(posts: any[]) {
fs.writeFileSync(dataFile, JSON.stringify(posts, null, 2));
}
export async function GET() {
const posts = readPosts();
return NextResponse.json(posts);
}
export async function POST(req: Request) {
const body = await req.json();
const posts = readPosts();
const newPost = {
id: Date.now(),
title: body.title,
content: body.content,
createdAt: new Date().toISOString(),
};
posts.push(newPost);
writePosts(posts);
return NextResponse.json(newPost);
}
⚠️ Nếu thư mục
data/
chưa có, bạn tạo mới:
mkdir app/web_site_cty/data echo [] > app/web_site_cty/data/posts.json
📝 3. Trang đăng bài: /app/web_site_cty/posts/new/page.tsx
"use client";
import { useState } from "react";
export default function NewPostPage() {
const [title, setTitle] = useState("");
const [content, setContent] = useState("");
const [message, setMessage] = useState("");
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
const res = await fetch("/web_site_cty/api/posts", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ title, content }),
});
if (res.ok) {
setMessage("Đăng bài thành công!");
setTitle("");
setContent("");
} else {
setMessage("Lỗi khi đăng bài!");
}
}
return (
<div className="max-w-xl mx-auto p-6">
<h1 className="text-2xl font-bold mb-4">Đăng bài mới</h1>
<form onSubmit={handleSubmit} className="space-y-4">
<input
value={title}
onChange={(e) => setTitle(e.target.value)}
placeholder="Tiêu đề bài viết"
className="w-full p-2 border rounded"
required
/>
<textarea
value={content}
onChange={(e) => setContent(e.target.value)}
placeholder="Nội dung bài viết"
className="w-full p-2 border rounded h-40"
required
/>
<button type="submit" className="bg-blue-600 text-white px-4 py-2 rounded">
Đăng bài
</button>
</form>
{message && <p className="mt-4 text-green-600">{message}</p>}
</div>
);
}
📄 4. Trang xem tất cả bài viết /app/web_site_cty/posts/page.tsx
"use client";
import { useEffect, useState } from "react";
export default function PostsPage() {
const [posts, setPosts] = useState<any[]>([]);
useEffect(() => {
fetch("/web_site_cty/api/posts")
.then((res) => res.json())
.then((data) => setPosts(data));
}, []);
return (
<div className="max-w-3xl mx-auto p-6">
<h1 className="text-2xl font-bold mb-4">Tất cả bài viết</h1>
{posts.length === 0 ? (
<p>Chưa có bài đăng nào.</p>
) : (
<ul className="space-y-4">
{posts.map((post) => (
<li key={post.id} className="border p-4 rounded">
<h2 className="font-semibold">{post.title}</h2>
<p>{post.content}</p>
<small className="text-gray-500">
{new Date(post.createdAt).toLocaleString()}
</small>
</li>
))}
</ul>
)}
</div>
);
}
🚀 5. Chạy thử
-
Chạy Next.js:
npm run dev
-
Truy cập:
-
Xem tất cả bài: http://localhost:4000/web_site_cty/posts
Bạn có muốn mình hướng dẫn nâng cấp phần này để lưu vào SQL Server (SSMS) luôn không?
Hiện giờ nó đang lưu file JSON, nhưng có thể đổi sang lưu DB thật (dùng mssql
package).
Bạn đã nói:
ChatGPT đã nói:
Rất tốt — mình xem hình rồi 👀
Lỗi 404 “Không tìm thấy trang này” ở đường dẫn
http://localhost:4000/web_site_cty/posts/new
nghĩa là Next.js không tìm thấy file page.tsx tương ứng với route đó.
Hiện trong hình của bạn chỉ có:
app/web_site_cty/posts/page.tsx
➡️ còn thiếu thư mục new/
và file page.tsx
bên trong.
🧩 Cách khắc phục
Hãy tạo thêm đúng cấu trúc thư mục như sau:
app/
└── web_site_cty/
└── posts/
├── page.tsx ← trang xem tất cả bài viết
└── new/
└── page.tsx ← trang đăng bài (chưa có)
✨ Nội dung file app/web_site_cty/posts/new/page.tsx
Copy đoạn này vào nhé:
"use client";
import { useState } from "react";
export default function NewPostPage() {
const [title, setTitle] = useState("");
const [content, setContent] = useState("");
const [message, setMessage] = useState("");
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
const res = await fetch("/web_site_cty/api/posts", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ title, content }),
});
if (res.ok) {
setMessage("✅ Đăng bài thành công!");
setTitle("");
setContent("");
} else {
setMessage("❌ Lỗi khi đăng bài!");
}
}
return (
<div className="max-w-xl mx-auto p-6">
<h1 className="text-2xl font-bold mb-4">Đăng bài mới</h1>
<form onSubmit={handleSubmit} className="space-y-4">
<input
value={title}
onChange={(e) => setTitle(e.target.value)}
placeholder="Tiêu đề bài viết"
className="w-full p-2 border rounded"
required
/>
<textarea
value={content}
onChange={(e) => setContent(e.target.value)}
placeholder="Nội dung bài viết"
className="w-full p-2 border rounded h-40"
required
/>
<button type="submit" className="bg-blue-600 text-white px-4 py-2 rounded">
Đăng bài
</button>
</form>
{message && <p className="mt-4 text-green-600">{message}</p>}
</div>
);
}
✅ Sau khi tạo xong:
-
Lưu file
-
Chạy lại server (nếu đang dừng):
npm run dev
-
Truy cập lại:
👉 http://localhost:4000/web_site_cty/posts/new
Nếu vẫn 404 sau khi tạo đúng file, gửi lại mình hình cây thư mục app/web_site_cty/posts/
để mình kiểm tra đường dẫn chính xác nhé.
Bạn đã nói:
ChatGPT đã nói:
Tốt lắm 👍 — như vậy frontend (giao diện web) đã gửi yêu cầu POST, nhưng backend (API /web_site_cty/api/posts
) bị lỗi → nên trả về "Lỗi khi đăng bài!"
.
Giờ ta kiểm tra nguyên nhân cụ thể 👇
⚠️ Bước 1. Mở Terminal nơi bạn đang chạy npm run dev
Xem log lỗi màu đỏ — ví dụ như:
Error: ENOENT: no such file or directory, open '.../data/posts.json'
SyntaxError: Unexpected end of JSON input
TypeError: fs.writeFileSync is not a function
📸 Bạn có thể copy hoặc chụp màn hình log lỗi đó gửi lại mình — mình sẽ chỉ bạn dòng lỗi chính xác.
🔍 Bước 2. Kiểm tra lại file API
Hãy mở file:
app/web_site_cty/api/posts/route.ts
Và so sánh đúng code sau (đây là bản đã kiểm tra và chạy được trong Next.js 14–15):
import { NextResponse } from 'next/server';
import fs from 'fs';
import path from 'path';
const dataFile = path.join(process.cwd(), 'app/web_site_cty/data/posts.json');
// Đọc dữ liệu từ file
function readPosts() {
try {
if (!fs.existsSync(dataFile)) return [];
const data = fs.readFileSync(dataFile, 'utf8');
return data ? JSON.parse(data) : [];
} catch (err) {
console.error('Lỗi đọc file:', err);
return [];
}
}
// Ghi dữ liệu vào file
function writePosts(posts: any[]) {
try {
fs.writeFileSync(dataFile, JSON.stringify(posts, null, 2));
} catch (err) {
console.error('Lỗi ghi file:', err);
}
}
// Xử lý GET
export async function GET() {
const posts = readPosts();
return NextResponse.json(posts);
}
// Xử lý POST
export async function POST(req: Request) {
try {
const body = await req.json();
const posts = readPosts();
const newPost = {
id: Date.now(),
title: body.title,
content: body.content,
createdAt: new Date().toISOString(),
};
posts.push(newPost);
writePosts(posts);
return NextResponse.json(newPost);
} catch (err) {
console.error('Lỗi khi đăng bài:', err);
return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 });
}
}
🗂️ Bước 3. Tạo thư mục và file dữ liệu nếu chưa có
Nếu bạn chưa tạo file này, API sẽ báo lỗi ENOENT
(không tìm thấy file).
Tạo thủ công:
-
Thư mục:
app/web_site_cty/data
-
File trống:
app/web_site_cty/data/posts.json
-
Nội dung ban đầu:
[]
🔁 Bước 4. Chạy lại server
npm run dev
Rồi vào lại:
👉 http://localhost:4000/web_site_cty/posts/new
Nhập tiêu đề + nội dung → Đăng bài
Nếu vẫn hiện "Lỗi khi đăng bài!"
, hãy copy dòng lỗi trong terminal (hoặc chụp lại) gửi mình — mình sẽ giúp bạn xử lý đúng lỗi đó (thường chỉ là sai đường dẫn file hoặc quyền ghi file).