Chapter 50: Build a Full-Stack App in Elixir

Put it all together: a complete project. In this chapter, you will learn build a full-stack app in depth with Elixir code examples, explanations, and best practices.

Overview

This chapter covers build a full-stack app for Kungfu.js developers using Elixir. 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 Elixir 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

mix run --no-halt
# Then open http://localhost:3000 in your browser

Congratulations!

You have completed all 50 chapters of the Kungfu.js tutorial for Elixir. 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 Elixir. You saw code examples, understood how things work under the hood, and learned about common mistakes to avoid.