8.1 Not from Scratch
Two entries into one store - that is useful. Two entries into two stores with the same name
- those are two separate tools that have no idea the other exists. The difference is not noticed immediately: everything looks normal right up until one entry searches for something put in through the other.
What You Need
The command line writes tasks to tasks.json. The server could read from the same file -
then both entries would lead to one store. Right now the server always starts with an empty
store. A few lines in crates/api/src/main.rs change that: load the config, load the
tasks from disk, hand them to TaskStore.
The Build
The full crates/api/src/main.rs:
// crates/api/src/main.rs - CHANGED
mod routes;
use axum::{Router, routing::get};
use routes::SharedStore;
use std::path::Path;
use std::sync::{Arc, Mutex};
use tq_core::config::Config;
use tq_core::persistence;
use tq_core::store::TaskStore;
async fn health() -> String {
"tq ok".to_string()
}
#[tokio::main]
async fn main() {
let config = Config::load(Path::new("config.toml"), None).unwrap_or_default();
let data_path = config.data_dir.join("tasks.json");
let tasks = persistence::load(&data_path).unwrap_or_default(); // empty vec if file missing
let store: SharedStore = Arc::new(Mutex::new(TaskStore::new(tasks)));
let app = Router::new()
.route("/", get(health))
.merge(routes::router(store));
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
The Result
Add tasks through the command line, then start the server. If a tasks.json remains from
earlier chapters, clear it first:
$ rm -f tasks.json
$ cargo run -p tq-cli -- add "buy milk"
$ cargo run -p tq-cli -- add "send report"
$ make serve
In another terminal:
$ curl -s localhost:3000/tasks
[{"id":1,"title":"buy milk","status":"Todo","created_at":"2026-06-20T10:00:00Z"},
{"id":2,"title":"send report","status":"Todo","created_at":"2026-06-20T10:05:00Z"}]
Both entries look into the same ledger. Tasks added through the CLI are visible through the API.
Tasks added through the API are not yet saved - all changes made through the server live only in process memory. The next step will fix that.
The complete
tqcode for this chapter is in8-ready/01-not-from-scratch/.