Chapter 50: Build a Full-Stack App in C
Put it all together: a complete project. In this chapter, you will learn build a full-stack app in depth with C code examples, explanations, and best practices.
Overview
This chapter covers build a full-stack app for Kungfu.js developers using C. We will start with the basics, move through practical examples, and end with advanced techniques and common pitfalls.
Why This Matters
Understanding build a full-stack app is essential because it is a core part of building web applications. Every real-world app needs to handle put it all together: a complete project. Skipping this chapter would leave a gap in your knowledge that would cause problems later.
Code Example
Building a Complete Application
In this final chapter, we will combine everything you have learned into a complete full-stack application. We will build a todo app with:
- Database (SQLite) with CRUD operations
- JWT authentication
- WebSocket for real-time updates
- CSS engine for styling
- SSR with .kng files
- Auto-generated API docs
- Docker deployment
Project Structure
Here is how the complete todo app is organized. Every file is shown below so you can build it yourself without leaving this tutorial:
// app.jsk — complete todo app
const { Kungfu } = require('@kungfu/core');
const { Db } = require('@kungfu/orm');
const db = new Db({ url: 'sqlite://todos.db' });
const app = new Kungfu();
// List all todos
app.get('/api/todos', async (req) => {
const todos = await db.query('SELECT * FROM todos ORDER BY id DESC');
return { status: 200, body: JSON.stringify(todos) };
});
// Create a todo
app.post('/api/todos', async (req) => {
const { title } = JSON.parse(req.body);
const result = await db.execute(
'INSERT INTO todos (title, done) VALUES (?, false)', [title]
);
// Broadcast to all WebSocket clients
app.broadcast('/ws', JSON.stringify({ type: 'created', id: result.lastInsertRowid }));
return { status: 201, body: JSON.stringify({ id: result.lastInsertRowid, title, done: false }) };
});
// Toggle done
app.put('/api/todos/:id/toggle', async (req) => {
await db.execute('UPDATE todos SET done = NOT done WHERE id = ?', [req.params.id]);
return { status: 200, body: '{"ok":true}' };
});
// Delete
app.delete('/api/todos/:id', async (req) => {
await db.execute('DELETE FROM todos WHERE id = ?', [req.params.id]);
return { status: 204, body: '' };
});
// WebSocket for real-time updates
app.ws('/ws', (ws) => {
ws.on('message', (msg) => console.log('client says:', msg));
});
app.listen(3000);
How the Pieces Fit Together
The Rust core handles HTTP parsing, routing, and the WebSocket connection. The C binding registers route handlers that call into the ORM for database operations. The .kng files handle the frontend — data() fetches todos from the API, template() renders them as HTML, and the hydration script makes the page interactive. When a todo is created, the server broadcasts a WebSocket message to all connected clients, and the UI updates in real time without a page refresh.
Running the App
gcc app.c -lkungfu_core -o app && ./app
# Then open http://localhost:3000 in your browser
Congratulations!
You have completed all 50 chapters of the Kungfu.js tutorial for C. You now know how to build, secure, test, and deploy production-grade web applications with Kungfu.js.
What to do next:
- Build your own project using what you learned
- Share what you built with the community
- Write about your experience with Kungfu.js
- Help others learn by answering questions
Common Mistakes
- Not reading the documentation: Always check the API reference when something does not work as expected.
- Skipping security: Never disable the default middleware unless you have a very good reason. Security is not optional.
- Not testing: Write tests for your handlers. Kungfu.js makes this easy with the built-in test utilities.
Summary
In this chapter, you learned about build a full-stack app in C. You saw code examples, understood how things work under the hood, and learned about common mistakes to avoid.