Let’s create a simple todo list application with full CRUD functionality.
1
Set Up the Database
Create a directory for SQLPage configuration:
mkdir -p sqlpage/migrations
Create the database schema in sqlpage/migrations/0000_init.sql:
sqlpage/migrations/0000_init.sql
CREATE TABLE todos ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, completed BOOLEAN DEFAULT FALSE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);-- Add some sample dataINSERT INTO todos (title, completed) VALUES ('Learn SQLPage basics', TRUE), ('Build a todo app', FALSE), ('Deploy to production', FALSE);
SQLPage automatically runs migration files in the sqlpage/migrations/ directory on startup, in alphabetical order.
2
Create the Main Page
Replace your index.sql with this todo list:
index.sql
-- Page headerSELECT 'dynamic' as component, sqlpage.run_sql('shell.sql') as properties;-- Display todosSELECT 'list' as component, 'My Todo List' as title, 'No todos yet!' as empty_title;SELECT title, CASE WHEN completed THEN 'green' ELSE 'gray' END as color, 'edit.sql?id=' || id as edit_link, 'delete.sql?id=' || id as delete_linkFROM todosORDER BY completed, created_at DESC;-- Add buttonSELECT 'button' as component, 'center' as justify;SELECT 'form.sql' as link, 'Add New Todo' as title, 'green' as color, 'circle-plus' as icon;
3
Create the Add/Edit Form
Create form.sql to add or edit todos:
form.sql
-- Handle form submissionINSERT INTO todos (title, completed)SELECT $title, COALESCE($completed, FALSE)WHERE $title IS NOT NULL AND $id IS NULL;UPDATE todos SET title = $title, completed = COALESCE($completed, FALSE)WHERE id = $id AND $title IS NOT NULL;-- Redirect back to home page after submissionSELECT 'redirect' as component, '/' as linkWHERE $title IS NOT NULL;-- Display the formSELECT 'form' as component, COALESCE('Edit Todo', 'Add New Todo') as title, 'Save' as validate;SELECT 'title' as name, 'text' as type, TRUE as required, title as valueFROM todos WHERE id = $idUNION ALLSELECT 'title', 'text', TRUE, NULL WHERE $id IS NULL;SELECT 'completed' as name, 'checkbox' as type, 'Completed' as label, completed as checkedFROM todos WHERE id = $idUNION ALLSELECT 'completed', 'checkbox', 'Completed', FALSE WHERE $id IS NULL;
4
Add Delete Functionality
Create delete.sql to remove todos:
delete.sql
DELETE FROM todos WHERE id = $id;SELECT 'redirect' as component, '/' as link;
5
Optional: Add a Shell
Create shell.sql for consistent page styling:
shell.sql
SELECT 'shell' as component, 'Todo App' as title, 'list-check' as icon, '/' as link, 'cyan' as color;
SELECT 'card' as component;SELECT name as title, description, CASE status WHEN 'active' THEN 'green' WHEN 'pending' THEN 'yellow' ELSE 'gray' END as color, image_url as top_imageFROM products;
SELECT 'form' as component, 'Contact Us' as title, 'send.sql' as action;SELECT 'name' as name, 'text' as type, TRUE as required;SELECT 'email' as name, 'email' as type, TRUE as required;SELECT 'message' as name, 'textarea' as type, 5 as rows;