Hello, Database! (read‑only list)

Goal: Render a live list of Todos coming straight from SQLite—no forms, no JavaScript, just PageQL.

Estimated time: 10 minutes.

1 Prerequisites

If you have not installed PageQL yet:

pip install --upgrade pageql

2 Create a tiny project

mkdir todomvc-pageql
cd todomvc-pageql
# Creates templates/, an empty SQLite file (todos.db), **and starts the dev server on port 8000**
pageql todos.db templates --create

You now have:

📂 todomvc-pageql/
 ├─ templates/
 │   └─ (empty for now)
 └─ todos.db            # blank SQLite database

3 Add todos.pageql

Create templates/todos.pageql with the contents below. We keep it deliberately short—only 25 lines of template code.

templates/todos.pageql
{{!-- Ensure the table exists (harmless if already created) --}}
{{#create table if not exists todos (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    text TEXT NOT NULL,
    completed INTEGER DEFAULT 0 CHECK(completed IN (0,1))
)}}

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Todos (read‑only)</title>
</head>
<body>
  <h1>Todos</h1>
  <ul>
    {{!-- 🚀  Query & loop in one tag --}}
    {{#from todos ORDER BY id}}
      <li>{{text}}</li>
    {{/from}}
  </ul>

  <p><em>This page is read‑only—for now!</em></p>
</body>
</html>

What did we use?

Tag Purpose
#create table One‑off schema bootstrap—safe to run every request.
#from Runs a SELECT and streams each row into the surrounding HTML.
{{text}} Outputs the text column. The single‑word shorthand omits the leading :.

Why no controllers? PageQL routes every public partial and every top‑level template automatically. Because we wrote plain markup at the top level, visiting /todos just works.

4 View in your browser

Open http://localhost:8000/todos in your browser. You should see an empty bullet list—that means the template ran and the table exists.

Add a couple of rows directly in SQLite to prove the loop is live:

sqlite3 todos.db "insert into todos(text) values ('Taste PageQL'), ('Profit!');"

Reload the page → the two items appear instantly. 🎉

5 Recap & next step

You have already learned:

Next: Part 2: Adding data