Explore a Real Dataset — Star Wars Tutorial

Open inAnthropic

Clone a pre-populated Star Wars database to your local TerminusDB instance and explore it with queries, branches, and diffs — in 15 minutes.

Prerequisites

  • TerminusDB running on localhost:6363. Verify: curl -s -u admin:root http://localhost:6363/api/info should return JSON containing "authority": "admin". If you get "connection refused", start TerminusDB first.
  • Completed the First 10 Minutes quickstart — you should be comfortable with branches and diffs. This tutorial builds on those concepts with a richer dataset.

What you will build

You will clone a complete Star Wars database (characters, films, planets, starships, species) from a public server, run queries that traverse document relationships, create a speculative branch ("what if Anakin turned to the Dark Side?"), and see a field-level structural diff of your changes.

Step 1 — Clone the Star Wars database

Pull the entire Star Wars dataset from the public templates server to your local instance in one command:

{"remote_url": "https://data.terminusdb.org/public/star-wars", "label": "Star Wars", "comment": "Cloned from public templates server"}

Loading…

You just pulled a complete Star Wars database — characters, films, planets, starships — from a public TerminusDB server to your local instance. No account needed, no sign-up, no credentials. The data is now yours to query, branch, and modify.

Step 2 — Explore what you have

List the document types defined in the schema:

Loading…

You will see types including People, Film, Planet, Starship, Vehicle, and Species.

List the characters (called People in the SWAPI schema):

Loading…

You now have over 80 characters plus films, planets, ships, and species. All of Star Wars, versioned and queryable. Let's ask it some questions.

Step 3 — Query the data

Which characters appear in "A New Hope" (Episode IV)?

In a relational database, you would write a JOIN across a junction table: SELECT c.name FROM characters c JOIN film_characters fc ON ... JOIN films f ON ... WHERE f.title = 'A New Hope'. In TerminusDB, documents link directly to other documents — a Film has a character property that points to People documents. You traverse the link, not a junction table:

Loading…

Expected output includes character names: Luke Skywalker, Leia Organa, Han Solo, Obi-Wan Kenobi, Chewbacca, R2-D2, C-3PO, and more (18 characters total).

Notice what happened: the query says "find a Film with this label, follow its character link to People documents, then get their label." Three hops through the graph — Film → character → People → label. No junction tables, no foreign key declarations, no JOINs. The relationships are part of the data structure itself, and traversing them is how you query.

TypeScript equivalent:

Example: TypeScript
import TerminusClient from "@terminusdb/terminusdb-client";

const client = new TerminusClient.WOQLClient("http://localhost:6363", {
  user: "admin",
  organization: "admin",
  key: "root",
});
client.db("star-wars");

const WOQL = TerminusClient.WOQL;
const query = WOQL.and(
  WOQL.triple("v:Film", "label", WOQL.string("A New Hope")),
  WOQL.triple("v:Film", "character", "v:Character"),
  WOQL.triple("v:Character", "label", "v:CharacterName")
);

const result = await client.query(query);
console.log(result.bindings.map((b) => b["CharacterName"]["@value"]));

Step 4 — Branch and modify

What if Darth Vader had never turned to the dark side? Let's update his record on a branch and see what TerminusDB tracks.

Create a branch called what-if:

Loading…

Expected output:

{
  "@type": "api:BranchResponse",
  "api:status": "api:success"
}

Now modify Anakin Skywalker's record on the branch — rewriting him as if he fell to the Dark Side. First, fetch his full document:

curl -s -u admin:root \
  "http://localhost:6363/api/document/admin/star-wars/local/branch/what-if?id=terminusdb:///star-wars/People/11" > anakin.json

Edit anakin.json — change four fields to tell the Dark Side story:

  • "label": "Anakin Skywalker""Darth Vader"
  • "eye_color": "blue""yellow"
  • "mass": "84""120"
  • "skin_colors": "fair""pale"

Then PUT the modified document back:

curl -s -u admin:root -X PUT \
  "http://localhost:6363/api/document/admin/star-wars/local/branch/what-if?author=admin&message=What+if+Anakin+turned+to+the+Dark+Side" \
  -H "Content-Type: application/json" \
  -d @anakin.json

Expected response:

Example: JSON
["terminusdb:///star-wars/People/11"]

You just rewrote history — on a branch. Main still has Anakin Skywalker (blue eyes, fair skin, mass 84). Your what-if branch has Darth Vader (yellow eyes, pale skin, mass 120). Notice the @id stays the same (People/11) — TerminusDB tracks object identity through changes, not content. Let's see exactly what changed.

Step 5 — See what changed (the diff)

This is the moment. In any other database, answering "what changed between these two versions?" means writing audit triggers, maintaining changelog tables, or exporting both states and diffing them externally. In TerminusDB, you ask the database directly:

Loading…

Expected output:

[
  {
    "@id": "People/11",
    "eye_color": {
      "@op": "SwapValue",
      "@before": "blue",
      "@after": "yellow"
    },
    "label": {
      "@op": "SwapValue",
      "@before": "Anakin Skywalker",
      "@after": "Darth Vader"
    },
    "mass": {
      "@op": "SwapValue",
      "@before": "84",
      "@after": "120"
    },
    "skin_colors": {
      "@op": "SwapValue",
      "@before": "fair",
      "@after": "pale"
    }
  }
]

This diff is structural, not textual. TerminusDB is not comparing strings line by line — it knows the document schema, understands which field changed, what the old value was, and what the new value is. Each change is a typed operation (SwapValue) that can be applied, reversed, or composed with other patches programmatically.

You sent a full document replacement, but TerminusDB detected only the four fields that actually changed: eye_color, label, mass, and skin_colors. Compare this to the alternative: export both database states as JSON, run a generic diff tool, then parse the text output to figure out what actually changed. Or maintain an audit table with triggers that fire on every update. Or write custom comparison logic in your application.

TerminusDB replaces all of that with one API call. The database is the version history — diffs are a native operation, not an afterthought bolted on top.


What you just did

In 15 minutes, you:

  1. Cloned a complete Star Wars database from a public server — one command, no account
  2. Queried relationships across documents (films to characters) using WOQL
  3. Branched the database and made a speculative change ("what if Anakin turned to the Dark Side?")
  4. Diffed the branch against main and saw field-level changes

These four operations — clone, query, branch, diff — are the core of TerminusDB. Every operation you just ran works at any scale: 200 documents or 2 million.

Prefer a business dataset?

Try Explore an Ecommerce Dataset → — the same workflow with customers, orders, and products.

Next steps

Was this helpful?