Getting started
SemanticSeams is a set of RDF vocabularies, worked example models, SHACL shapes, canned SPARQL queries and a read-only viewer that ties them together. This page takes you from a fresh clone to the test suite passing and the viewer open in a browser on the chat-app example.
What you need
- uv. It installs Python 3.12 from
.python-versionif you do not have it. CI runs on 3.12. - A browser with internet access. The viewer loads htmx, vis-network, elkjs, bpmn-js, dmn-js and diagram-js (via esm.sh) from a CDN.
- Nothing else: there is no database to start. The viewer reads the example model into memory through the
seamslibrary.
Install
git clone https://github.com/MetaCoding-io/SemanticSeams.git
cd SemanticSeams
uv sync --all-packages
source .venv/bin/activateThe repository is a uv workspace. uv sync --all-packages creates .venv with the exact versions pinned in uv.lock; without --all-packages it installs nothing from the members. Each member declares its own dependencies in its pyproject.toml:
| Member | Distribution | Dependencies |
|---|---|---|
packages/seams | semanticseams | rdflib, lxml |
seams_runtime | semanticseams-runtime | semanticseams, rdflib, pySHACL, SpiffWorkflow, lxml, httpx, FastAPI, python-multipart, Jinja2, uvicorn, psycopg |
seams_gen | semanticseams-gen | semanticseams, rdflib, Jinja2, PyYAML |
seams_gateway | semanticseams-gateway | FastAPI, uvicorn, httpx |
viewer | semanticseams-viewer | semanticseams, semanticseams-edit, semanticseams-cli, FastAPI, uvicorn, Jinja2, rdflib, pySHACL |
packages/seams-cli | semanticseams-cli | semanticseams, rdflib, Jinja2, PyYAML |
The root pyproject.toml adds a dev group with pytest, PyYAML, httpx, ruff and pyright. If you prefer not to activate the environment, prefix any command with uv run, for example uv run pytest.
Run the tests
pytestThe suite is the project's acceptance test. It parses every Turtle and TriG file, validates both worked examples against the seam shapes, proves the shapes reject deliberately broken seams, checks that every non-reserved seam predicate is used somewhere, asserts the exact rows of every canned query, and exercises the viewer's endpoints. CI runs the same command on every push and pull request.
The runtime's store tests run against embedded SQLite and against PostgreSQL. The PostgreSQL run needs a database URL in SEAMS_TEST_POSTGRES_URL and skips without one:
docker run -d -e POSTGRES_PASSWORD=pw -p 5433:5432 postgres:16
SEAMS_TEST_POSTGRES_URL=postgresql://postgres:pw@localhost:5433/postgres pytestCI starts a postgres:16 service and sets SEAMS_REQUIRE_POSTGRES=1, which turns that skip into a failure. Each PostgreSQL test works in its own seams_test_* schema and drops it afterwards, so nothing is left in public.
Run the chat app
The chat app's local stack runs from the generated compose.development.yaml at the repository root. It builds the runtime and gateway images from this checkout, starts PostgreSQL, and serves the app on port 8080 from the three chat_api replicas the model declares. You don't need a hand-written compose file. First check that the development environment's configuration keys and secrets exist:
seams secrets --project examples/chat-app --env development
docker compose -f compose.development.yaml up -d --buildOpen http://localhost:8080. Then confirm the running runtime serves the current model:
seams status --project examples/chat-appIt prints chat_api current and the model hash. behind means the image was built from an older model, so run up -d --build again. unreachable means the stack is not up. Stop it with docker compose -f compose.development.yaml down.
Reset old dev data
A model that declares no store runs on embedded SQLite at the file SEAMS_DB names. Since M011 a model that declares a PostgreSQL store keeps its data there instead (see ADR-0011), and nothing migrates the old SQLite data. To start clean, stop the runtime, delete the SEAMS_DB file and start it again. For a docker compose stack, including one from before M011 that kept a SQLite file on a /data volume, remove the stack with its volumes (the chat app's local stack runs from the generated compose.development.yaml):
docker compose -f compose.development.yaml down -vLint and type-check
CI runs these as their own jobs:
uv run ruff check
uv run ruff format --check
uv run pyrightRuff covers the whole tree except committed generated code. Pyright checks packages/seams in strict mode.
Open the viewer
python3 -m uvicorn viewer.app:app --port 8000The viewer loads the chat app unless SEAMS_MODEL names another TriG file or a directory of TriG files (see Authoring a model).
Open http://localhost:8000. The root redirects to the chat app's architecture view, the top of the descent. From there:
- Click Chat Web Interface to land on the interaction model it presents.
- Click Send Message to land on the BPMN process the event triggers.
- Click the Route to Provider task. Its decision is detailed by two models, so the viewer asks which one to open. Choose the DMN model, then open its decision table.
The viewer loads its Python code once, at start-up. After pulling new commits or editing viewer/*.py, restart it, or start it with --reload so it restarts itself; a viewer left running from an earlier checkout keeps serving the old views.
Using the viewer walks through the same descent with screenshots and explains everything else on the page.
What next
- Quick start: the chat app: regenerate the chat app from its model and run it with Docker Compose.
- The seams CLI:
seams generateregenerates a project's outputs, each with an<output>.trace.jsonnaming the template line and model elements behind every line, and records them inseams.lock(seams generate --lenientpreviews a model that still breaks a generator's preconditions, writing what it can and flagging the lock) andseams checkconfirms they are current and unflagged, in CI and as a pre-commit hook;seams statuschecks that a running stack's containers are on the current model;seams secretschecks that each environment's configuration keys and secrets exist beforedocker compose -f compose.development.yaml up, and--write-examplewrites the.env.exampleto copy to.env;seams sequencederives an event's sequence diagrams from the model, andseams sequence :send_message --trace <instance>draws a recorded run as executed;seams storm approval_processprints a process's derived event-storm timeline. - Build an expense approval app: write a model yourself, one layer per chapter, from an empty file to the whole system under
docker compose up. - Using the viewer: what each part of the page does, and the URLs behind it, including the Sequences section that renders an event's derived sequence diagrams.
- Diagrams are views: the idea the project rests on.
- Authoring a model: the conventions a model must follow to be navigable and to pass the shapes.
- Write your own generator: read a model through the
seamslibrary and generate your own output from it.