Using Neon Law Navigator
Open any slide to read it. View them all to unlock your certificate.
Chapter 1
Intro
Learning objectives
- Remember — identify Project, Template, Notation, Workflow, and the unique onboarding / offboarding pair.
- Understand — connect each noun to the database row that makes the workflow durable and inspectable.
- Apply — open the litigation matter, bind the shared retainer template, and view the client portal application.
- Analyze — inspect the notation state and the matter's participation-scoped views.
- Evaluate — review the client-facing portal and identify one useful improvement.
- Create — make a small, testable change in the sample project and refresh the local portal.
The running matter
The local development fixture seeds three open Projects. This is the one the workshop works:
- Name — Cruller v. Prine
- Code —
sample-litigation - Matter — trespass to land, and rescission of the doughnut instrument
- Repository — neon-law-staging/sample-litigation
- Portal —
/app/projects/sample-litigation/portal/
The other two seeded matters are sample-transactional (a company on a monthly retainer) and sample-estate (an estate
plan). Each carries its own repository and its own portal bundle, mounted the same way.
The Project code is the public URL key. Codes use lowercase letters and numbers separated by single hyphens, so a
project page is always readable as /app/projects/<code>.
Chapter 2
Develop locally
Start the local room
The same local web process resolves its public face from the host. In staging, use staging.neonlaw.com for Neon Law,
staging.deleteyourdata.com for DeleteYourData.com, and staging.lawyershook.com for Lawyer Shook. The route and
application stay shared; the host selects the brand's copy, mark, font, and colour layer.
The Navigator CLI owns the complete local lifecycle. From a New Worktree, run:
cargo run -p cli -- dev worktree-env up --path "$PWD"
set -a; source .devx/env; set +a
cargo run -p neon
The boot command provisions the KIND dependency tier, applies the schema, seeds the sample matters, clones and builds
each sample project, stages every dist/ output, and writes the generated environment. The host web process reads that
environment on startup, so the real sample applications are ready at their portal links after each boot.
The explicit refresh command uses the same build and staging path when a sample project changes. Naming one matter refreshes only that bundle, which is the fast loop while iterating on a single app:
cargo run -p cli -- dev sample-project --project sample-litigation
Restart web after refreshing so it reads the new staged bundle. The generated .devx/env contains
NAVIGATOR_SAMPLE_PROJECTS_DIR, the directory every matter's bundle is staged under; source it before starting the host
process.
Sign in
The local Rauthy fixture supplies five role-named accounts, all using the password password:
| Account | Role | Matter access |
|---|---|---|
owner@neonlaw.com | owner | firm-side matter view |
admin@neonlaw.com | admin | administration surface; participation can be granted there |
lawyer@neonlaw.com | lawyer | firm-side matter view |
clerk@neonlaw.com | clerk | supervised matter view |
client@neonlaw.com | client | client matter view and portal |
Open $NAV_BASE_URL/auth/login. Firm accounts land on /app/team; the client account lands on /app/projects. The
project list and detail page use sample-litigation in the URL. The client portal is available at:
$NAV_BASE_URL/app/projects/sample-litigation/portal/
The portal is participation-scoped. The client, lawyer, clerk, and owner rows are part of the fixture, and the admin
account is the local administrator used to exercise the participation controls at /app/admin.
Chapter 3
Work the litigation matter
The four nouns in one workflow
- Project — Cruller v. Prine, the matter that owns the work.
- Template — a versioned Markdown blueprint such as
onboarding__letter. - Notation — one client and one Template bound inside the Project.
- Workflow — the states and transitions that move a Notation from intake through review and signature.
The shared retainer template is available in the canonical catalog. A lawyer can bind it through the AIDA catalog:
aida_create_notation(template_code="onboarding__letter", project_id=<sample-litigation project id>)
The notation begins in its seeded workflow state. The lawyer reviews the generated work, advances the workflow through the configured transitions, and the resulting documents remain tied to that Project and its audit trail.
One onboarding, one offboarding
Every Project has one onboarding notation and one offboarding notation. Those two kinds are unique on the matter: a second retainer is not a second engagement, and a demand letter is not a closing letter.
Onboarding is the letter that opens the matter. Offboarding is the firm-signed closing letter that ends the
representation. Those two shared catalog codes are onboarding__letter and offboarding__letter. Opening the Project
does not create either notation; a lawyer binds them like any other template. The self-serve doors refuse any other kind
as the matter's first notation.
The CLI seeds both letters. This workshop still binds the retainer through AIDA as one onboarding walk. Close the matter with the offboarding letter. Do not bind two onboardings on one Project:
navigator site notation create onboarding__letter \
--project sample-litigation \
--client-email client@neonlaw.com
navigator site notation create offboarding__letter \
--project sample-litigation \
--client-email client@neonlaw.com
Walk the retainer intake one question at a time
AIDA binds the retainer in one call, but a lawyer can also walk it by hand at /app/lawyer/notations/{notation_id}/step
— one question per screen, the same focus-set chrome the client's own self-serve intake shares: a step list naming the
whole chain, a progress bar, and the question's own control below it. A closed choice — the engagement's governing law,
or a yes/no — renders as cards to choose between, not a bare checkbox or a compact radio list. Completed steps show as
plain markers; there is no revisit route today.
The client-facing half of the same chain is /app/projects/{code}/intake/{notation_id} — the client confirms or
corrects whatever the lawyer already entered, through the identical chrome.
The other notations on a matter
After the engagement is on file, the matter accumulates the work itself. Those later notations are not unique. A litigation matter may carry many letters and filings. An estate matter may carry a will, a trust, and directives. A review matter may carry a memo.
The vocabulary is one closed enum, Kind, in rules/src/kind.rs. A template declares kind: in its frontmatter.
Generated PDFs and lawyer uploads reuse the same strings on the asset lane. The notation kinds you add after onboarding:
letter— a letter the firm sends on the client's behalf (demand, notice, settlement)filing— a document filed with a government bodywill,trust,directive— estate instrumentsagreement— a private agreement with a third partypleading— court paper filed with a court (complaint, motion, brief)memo— an analytical work product, not an executed instrument
Filed uploads that are not templates use transcript, inbound_contract, certificate_of_naturalization, or
unclassified. Content pages (post, workshop, event) and matter dashboards are not notations on the Project.
Inspect the client portal
Sign in as client@neonlaw.com, open /app/projects, and select Cruller v. Prine. All three seeded matters are in
that list, because the fixture client participates in each one. The detail page keeps the human-readable code in the
address bar:
/app/projects/sample-litigation
Select the portal link to open the sample application's bundled client experience. The application is built from the public sample repository and mounted under the Project's code, which gives the sample a complete path from repository to matter-specific browser surface.
Make a sample-project change
The sample repository declares its Navigator Project in navigator.yaml:
project: sample-litigation
Edit the sample project, run the refresh command, restart web, and reload the portal URL. Boot validates the manifest,
builds the frontend, stages the output, and publishes the generated assets before the entry document. This keeps the
portal tied to the declared Project while the browser reloads the new version.
That manifest is the whole reason three bundles cannot collide. Each is staged in a directory named for its matter, but boot re-reads the manifest rather than trusting the directory, and refuses a bundle naming a different Project — because publishing one would put one client's application on another client's portal.
Chapter 4
Open a real Project
Fill the matter-open form
A lawyer-tier account reaches the form at /app/projects/new. It asks for a name, a code, an Entity, a description,
scope of services, the client DRI, and a required conflict-check attestation. Navigator stores the code exactly as typed
— the code is immutable, and a code already in use by another matter is refused rather than silently resolved, because
it is a coordinate the caller already committed to elsewhere (a repository's navigator.yaml, a Drive folder name).
Provision the repository and Drive folder — a separate step today
The browser form does not provision the Project's repository or Drive folder by itself. Every other way of opening a
Project — the JSON API, the CLI, the MCP tool — provisions both surfaces as part of opening; the browser form only
writes the matter row. Immediately after submitting, /app/projects/<code> names no repository yet.
Close that gap from the matter page's admin retry, or from the CLI:
navigator site projects surfaces reconcile --project <code>
This creates — or adopts, if one already exists — an empty private GitHub repository and Drive folder, and records the repository URL on the row. It writes no files.
Populate the repository
Clone the now-existing empty repository, then generate its shell:
navigator site projects repository scaffold <code> --dir . --action-version <YY.M.D>
scaffold is idempotent. It writes README.md, AGENTS.md, CLAUDE.md, an example templates/project_template.md,
tests/README.md, and two workflows — .github/workflows/gate.yml (the CI gate) and .github/workflows/publish.yml
(the portal-publish caller). It does not write portal/; that only exists once a client-facing application is built.
Pass --action-version explicitly rather than relying on a default, which only resolves from a real release build.
Commit and push. That push is what makes the CI gate live on the new repository.
Stage a document and sync it
scaffold does not write the repository's documents/ directory. It is the root-level document surface in every
Project repository, alongside apps/ and templates/, and it holds committed YAML pointers while acting as temporary
staging, not a second document store. Git keeps the pointer; Navigator keeps the bytes. Drop a local file below it, list
what a sync would do, then run it:
navigator site sync --dry-run
navigator site sync
navigator site projects repository validate .
Against a staged documents/exhibits/exhibit-a.png, the dry run prints one line per staged file and a count, and
changes nothing:
would upload documents/exhibits/exhibit-a.png
1 upload planned
The real run derives the document slug from its path below documents/, uploads the bytes through Navigator's
authenticated API, writes exhibit-a.png.yml only after the upload succeeds, and then removes the staged file. It
prints 1 uploaded. The pointer records kind, desired visibility, current revision metadata, and the previous asset
id when the chain has one. It never contains an object-storage coordinate or legal-document bytes; object storage and
the assets revision chain remain authoritative. Folder conventions infer filing for pleadings/, exhibit for
exhibits/, and agreement for agreements/; other paths use unclassified. Visibility defaults to internal.
The real run needs a stored login — navigator site login --host <host-or-url> — and a matter with that code visible to
the account. --dry-run needs neither. The first real run also creates documents/.gitignore without overwriting an
existing file; until that first sync, nothing in the checkout stops git add from staging raw bytes. validate then
rejects every file below documents/ that is not a *.yml pointer or that .gitignore:
./documents/exhibits/exhibit-a.png: error: legal documents and raw document bytes must not be committed; keep only `*.yml` pointers under `documents/`
The portal is a separate, later decision
Not every Project needs a client-facing application. When one does, its portal/ is hand-built in the vibe-react lane
against a pinned @neon-law/ux release — scaffold deliberately leaves it out, so validate can tell "no portal yet"
from "portal exists" without ambiguity.
Verify
navigator site projects doctor --project <code>
navigator site projects drift --dir ~/neon-law
doctor reports whether this machine and this Project's coordinates agree — the repository URL, the Drive folder, and
the portal mount. drift reconciles a machine's checkouts against every live Project row.
Chapter 5
Wrap Up
You finished — claim your certificate
Enter your name and email and Neon Law will send a PDF certificate of completion.
We use your email only to send this certificate.