Examples

[ AxiomCore · Documentation ]

Task app

Trace a task from the Acore UI through a typed backend into SQLite, with every file, endpoint and failure the example declares.

The task app creates, lists, renames and deletes tasks with real SQLite persistence. Its UI, backend and schema are all written in Acore. This page explains how the parts fit together; Run your first app walks through running it step by step.

Two tasks created through the running Acore frontend

Run it

You need Axiom CLI 0.149.1 on macOS arm64, the web UI host 0.6.12 (axiom ui host install --target web --version 0.6.12 --non-interactive), a browser, two terminals, and free ports 8080 and 5173.

Terminal 1
git clone --depth 1 https://github.com/AxiomCore/AxiomCore.git
cd AxiomCore/examples/documentation/task-app
unset DATABASE_URL
axiom check backend/sqlite.acore
axiom run backend/sqlite.acore --port 8080
Terminal 2: same task-app directory
axiom run frontend/main.acore --target web --port 5173

Open http://127.0.0.1:5173, paste the development API key that Terminal 1 printed, and select Connect. The quickstart shows the expected output and troubleshooting.

How a request reaches the data

Task mutations and list refresh
Task mutations and list refresh
Diagram source
sequenceDiagram
  Browser->>API: Create a task with a development API key
  API->>SQLite: Validate and insert the record
  SQLite-->>API: Stored task
  API-->>Browser: Typed result
  Browser->>API: Refresh the invalidated list

Each endpoint binds to an action. The action checks the guard, validates input and calls a resource operation. A typed storage mapping implements that operation against the SQLite table. A successful create, rename or delete invalidates the tasks:list cache identity, so the frontend fetches the list again.

Find each part

FileResponsibility
database/sqlite/schema.acoreThe tasks table, its tenant and ID key, and the schema identity and version
backend/Task.acoreThe public Task model
backend/application.acoreEndpoints, guard, validation, failures, actions, CORS
backend/sqlite.acoreTyped select, insert, update and delete mappings; the entry file you run
frontend/main.acoreForm, query, mutations, error UI and list
Each AxiomDeps.tomlThe project type, targets and dependencies for that folder

The storage mapping turns a database constraint into a declared failure:

backend/sqlite.acore (excerpt)
storage tasks(schema: "../database/sqlite/schema.acore", resource: Resources.tasks) {
  select list(table: "main.tasks", fields: {id: "id", title: "title"}, limit: 100)
  insert create(table: "main.tasks", values: {id: Input.title, title: Input.title},
    fields: {id: "id", title: "title"}, constraint: "tasks_pkey",
    failure: Failures.duplicate, message: "That task already exists")
  // update and delete mappings follow in the complete file
}

The backend uses the trimmed title as the new task's ID. This keeps the example small; a real application should choose an ID and uniqueness policy that fits its domain.

In the frontend, a form model trims the title, checks it on submit with the contract's validation, and shows the server's duplicate failure on the title field.

API surface

Every endpoint requires the printed development key in the apikey header.

Method and pathRequestResult
GET /tasksNo bodyUp to 100 tasks
POST /tasks{"title":"Read the guide"}The created task; a duplicate ID returns the declared 409 failure
PATCH /tasks/{id}A JSON string, such as "Updated title"The updated task
DELETE /tasks/{id}The ID in the URLThe deleted task
ConditionHTTP status
Duplicate task ID409
Missing apikey header400
Invalid key401

The UI blocks blank titles, and the contract limits titles to 1 to 120 characters. Renaming a task does not change its ID. URL-encode IDs when you call the API directly.

Verify

  1. Create a task, then create the same title again and check the 409 failure.
  2. Call the API without the key header (400) and with a wrong key (401).
  3. Rename a task and delete another one.
  4. Reload the page, reconnect, then restart the backend and reconnect again. The kept task must still be there and the deleted one must stay deleted.

Limits

The development key represents one local principal and one tenant. The app has no user registration, production session issuance or multi-user role UI, and list responses stop at 100 tasks. Review identity and policies before you extend it to protected accounts.

If you edit an imported backend file, stop both processes, run axiom build backend/sqlite.acore, and start both again. Change the database project version before you apply a schema change.

Clean up

Stop both processes with Ctrl-C. The SQLite data stays inside the clone. Keep it to continue, or delete the clone when you no longer need the data.

Next steps