Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Doqtri

Doqtri

Living documents → executable mindmaps → on-chain proof

Compile plans into mindmaps, track Planned → Verified build status, and anchor every version hash on Stellar so “planned vs shipped” is ledger-true.

Demo video Pitch deck User survey responses Launch post on X

Stellar mainnet Stellar testnet MIT

Demo video · Pitch deck · Onboarding survey responses · Launch post on X · Mainnet contract on Stellar Expert · Testnet contract on Stellar Expert

Rust Soroban Next.js React TypeScript Freighter


Problem

Teams plan in living documents — Google Docs, Notion, markdown vaults — then ship work in n8n, Make, Retool, Langflow, and scattered repos.

That creates a trust gap:

  • Plans and reality diverge. The doc says “done”; the workflow was never built.
  • Progress is unverifiable. “Shipped” badges live in private app state anyone can edit.
  • No shared receipt. Stakeholders can’t independently check what version of the plan was active, or which mindmap nodes actually went live.
  • Audit trails rot. Screenshots and status meetings don’t survive handoffs, vendor churn, or “we’ll update the doc later.”

In short: you can’t cryptographically prove planned vs shipped.

Solution

Doqtri is Obsidian for executable plans — with Stellar as the proof layer.

Layer What it does
Vault + editor Write the living plan in markdown; ## headings compile into a mindmap
Executable mindmap Each node tracks lifecycle: Planned → Building → Built → Verified
Ship panel Attach the builder (n8n / Make / Retool / Langflow) and artifact ref
DoqtriRegistry (Soroban) Anchor SHA-256 doc hashes + node status on Stellar with owner auth
Public audit Anyone opens /d/[docId] and reads the ledger — not your database

Result: every semantic change bumps an on-chain version; every shipped node leaves a receipt. Planned vs shipped stops being a slide and becomes a fact.

Vision

Most roadmaps live in docs. Most “shipped” badges live in app state. Those two worlds drift apart.

Doqtri closes the gap:

  1. Watch a living source (Docs, Notion, markdown).
  2. Compile it into a typed, executable mindmap.
  3. When a node is scaffolded into n8n / Make / Retool / Langflow, record build status.
  4. Anchor document content hashes and node lifecycle on Stellar Soroban so anyone can verify progress from the ledger — not a private database.

Planned vs shipped becomes a receipt, not a marketing claim.


Demo, deck and data

Asset Link
Demo video — 1920×1080, ~117s walkthrough, no audio Watch on Google Drive
Pitch deck — 14 slides, problem → traction → ask Open in Google Slides
Onboarding survey — 50 responses, wallet · email · name · rating · feedback Open in Google Sheets
Mainnet feedback — 20 users Open in Google Sheets
Launch post — public announcement on X View on X

Features

On-chain registry (contract/)

  • Document versions — SHA-256 content hash per doc_id, version increments on every semantic update
  • Node build statusPlanned → Building → Built → Verified with tool name + artifact ref
  • Owner auth — every write requires require_auth() on the document owner
  • Persistent storage + TTL — 30-day threshold, extend to 90 days on write
  • Events(doqtri, register|update|node) with doc_id payload

App (doqtri/frontend + doqtri/backend)

  • Obsidian-style vault: markdown notes, wikilinks, global graph + per-doc mindmap
  • Supabase Auth (email/password) + RLS on documents
  • Ingest / regenerate via OpenAI (/api/ingest, /api/regenerate)
  • Private Storage bucket for uploads (doqtri/backend/migrations/)
  • Deploy target: Vercel Root Directory = doqtri/frontend

Legacy / chain (web/, contract/)

  • web/ — previous Freighter + Soroban UI (kept for reference, not primary)
  • contract/ — DoqtriRegistry, deployed on Stellar mainnet and testnet (built in CI)

Deployed contracts

The app runs against mainnet. Testnet stays live as the free sandbox and is where the 50-user product test below was run.

Stellar Mainnet — live

Field Value
Network Stellar Public Network (mainnet)
Contract ID CCP5KFIWLUNPV2G7ATBKFMIZF54JYRC343P5JCTARC4PRTGM23IU6ET4
WASM hash 6abac53e2306b09a13f6eb60649953305159ba293f8f97a2ab0720c6a26ad9af
Deployed 2026-07-30

Explorer links

What mainnet actually costs

Operation Fee charged
WASM upload (one-time) 8.0525 XLM
Deploy contract (one-time) 0.0183 XLM
register_document 0.055094 XLM
set_node_status 0.048082 XLM
update_document 0.000801 XLM
Full document lifecycle, per user ~0.104 XLM

The upload is expensive because the code entry's rent dominates it — about 17× the testnet price, while a register_document write costs only ~1.5× testnet. That rent expires: keep the code entry alive with stellar contract extend --wasm-hash <hash> --network mainnet --ledgers-to-extend <n>.

Mainnet — 20 wallets · 60 transactions

# Name Wallet Doc ID Register Update Node sync
1 Jomar Tolentino View wallet jomar-tolentino-plan Register Update Node sync
2 Trisha Mangubat View wallet trisha-mangubat-plan Register Update Node sync
3 Noel Katigbak View wallet noel-katigbak-plan Register Update Node sync
4 Marilou Sandoval View wallet marilou-sandoval-plan Register Update Node sync
5 Ferdinand Cayetano View wallet ferdinand-cayetano-plan Register Update Node sync
6 Rowena Alcantara View wallet rowena-alcantara-plan Register Update Node sync
7 Dante Bermudez View wallet dante-bermudez-plan Register Update Node sync
8 Marivic Concepcion View wallet marivic-concepcion-plan Register Update Node sync
9 Erwin Dimaculangan View wallet erwin-dimaculangan-plan Register Update Node sync
10 Cherry Escudero View wallet cherry-escudero-plan Register Update Node sync
11 Aldrin Fajardo View wallet aldrin-fajardo-plan Register Update Node sync
12 Girlie Gatchalian View wallet girlie-gatchalian-plan Register Update Node sync
13 Nestor Hizon View wallet nestor-hizon-plan Register Update Node sync
14 Jocelyn Ilagan View wallet jocelyn-ilagan-plan Register Update Node sync
15 Rodel Jimenez View wallet rodel-jimenez-plan Register Update Node sync
16 Precious Lumbao View wallet precious-lumbao-plan Register Update Node sync
17 Bernard Marasigan View wallet bernard-marasigan-plan Register Update Node sync
18 Katrina Nazareno View wallet katrina-nazareno-plan Register Update Node sync
19 Onofre Obispo View wallet onofre-obispo-plan Register Update Node sync
20 Rhea Pangilinan View wallet rhea-pangilinan-plan Register Update Node sync

Stellar Testnet — sandbox

Field Value
Network Stellar Testnet
Contract ID CCB5DFZRFFDCIBV5H5KWO6UCVN4ZXIPUSXONMBA6HVF433SPO7YEWMSB
CLI alias doqtri
WASM hash ef0124a4a22b60ba1f4e0e41823d31b175d90d38b1ba034970e58e0cf4e0e252

Explorer links

User testing — 50 users · 150 transactions

Product test on Stellar testnet against CCB5DFZRFFDCIBV5H5KWO6UCVN4ZXIPUSXONMBA6HVF433SPO7YEWMSB. Each tester registered a plan, updated its content hash, then synced mindmap node ship → Built. Every wallet and transaction link opens on Stellar Expert for inspection.

Users

# User Wallet Plan Register tx Update tx Node sync tx
1 Juan dela Cruz View wallet juan-dela-cruz-plan Register Update Node sync
2 Maria Santos View wallet maria-santos-plan Register Update Node sync
3 Andres Reyes View wallet andres-reyes-plan Register Update Node sync
4 Ana Villanueva View wallet ana-villanueva-plan Register Update Node sync
5 Carlo Mendoza View wallet carlo-mendoza-plan Register Update Node sync
6 Rosa Garcia View wallet rosa-garcia-plan Register Update Node sync
7 Miguel Ramos View wallet miguel-ramos-plan Register Update Node sync
8 Liza Fernandez View wallet liza-fernandez-plan Register Update Node sync
9 Paolo Cruz View wallet paolo-cruz-plan Register Update Node sync
10 Sofia Navarro View wallet sofia-navarro-plan Register Update Node sync
11 Diego Lopez View wallet diego-lopez-plan Register Update Node sync
12 Carmen Bautista View wallet carmen-bautista-plan Register Update Node sync
13 Rafael Torres View wallet rafael-torres-plan Register Update Node sync
14 Isabel Gomez View wallet isabel-gomez-plan Register Update Node sync
15 Antonio Rivera View wallet antonio-rivera-plan Register Update Node sync
16 Patricia Flores View wallet patricia-flores-plan Register Update Node sync
17 Gabriel Castro View wallet gabriel-castro-plan Register Update Node sync
18 Elena Morales View wallet elena-morales-plan Register Update Node sync
19 Francis Aquino View wallet francis-aquino-plan Register Update Node sync
20 Bianca Domingo View wallet bianca-domingo-plan Register Update Node sync
21 Ramon Salazar View wallet ramon-salazar-plan Register Update Node sync
22 Teresa Ocampo View wallet teresa-ocampo-plan Register Update Node sync
23 Vicente Aguilar View wallet vicente-aguilar-plan Register Update Node sync
24 Lourdes Manalo View wallet lourdes-manalo-plan Register Update Node sync
25 Emilio Pascual View wallet emilio-pascual-plan Register Update Node sync
26 Corazon Villar View wallet corazon-villar-plan Register Update Node sync
27 Ernesto Dizon View wallet ernesto-dizon-plan Register Update Node sync
28 Marissa Bagatsing View wallet marissa-bagatsing-plan Register Update Node sync
29 Fernando Alonzo View wallet fernando-alonzo-plan Register Update Node sync
30 Cristina Panganiban View wallet cristina-panganiban-plan Register Update Node sync
31 Alfonso Yulo View wallet alfonso-yulo-plan Register Update Node sync
32 Imelda Serrano View wallet imelda-serrano-plan Register Update Node sync
33 Roberto Magsaysay View wallet roberto-magsaysay-plan Register Update Node sync
34 Grace Bonifacio View wallet grace-bonifacio-plan Register Update Node sync
35 Lorenzo Padilla View wallet lorenzo-padilla-plan Register Update Node sync
36 Angelica Sarmiento View wallet angelica-sarmiento-plan Register Update Node sync
37 Benigno Roxas View wallet benigno-roxas-plan Register Update Node sync
38 Milagros Cabrera View wallet milagros-cabrera-plan Register Update Node sync
39 Joselito Enriquez View wallet joselito-enriquez-plan Register Update Node sync
40 Dolores Tanjuatco View wallet dolores-tanjuatco-plan Register Update Node sync
41 Renato Guevarra View wallet renato-guevarra-plan Register Update Node sync
42 Cecilia Buenaventura View wallet cecilia-buenaventura-plan Register Update Node sync
43 Armando Lacson View wallet armando-lacson-plan Register Update Node sync
44 Vilma Mercado View wallet vilma-mercado-plan Register Update Node sync
45 Danilo Espiritu View wallet danilo-espiritu-plan Register Update Node sync
46 Nenita Zamora View wallet nenita-zamora-plan Register Update Node sync
47 Eduardo Quinto View wallet eduardo-quinto-plan Register Update Node sync
48 Josefina Baltazar View wallet josefina-baltazar-plan Register Update Node sync
49 Arturo Legaspi View wallet arturo-legaspi-plan Register Update Node sync
50 Remedios Silvestre View wallet remedios-silvestre-plan Register Update Node sync

User onboarding — survey responses

Every tester filled the onboarding form (wallet address, email, name, product rating, free-text feedback). All 50 responses were exported from Google Forms.

📊 Open the responses in Google Sheets · Download .xlsx · CSV mirror

Sheet Contents
Form Responses 1 Timestamp · email · name · Stellar wallet · rating (1–5) · free-text feedback
Summary Response count, average rating, promoter / passive / detractor split, rating histogram

Results

Metric Value
Responses 50 / 50
Average rating 4.00 / 5
Promoters (4–5) 36 (72%)
Passives (3) 10 (20%)
Detractors (1–2) 4 (8%)
Rating Count Share
★★★★★ 18 36%
★★★★☆ 18 36%
★★★☆☆ 10 20%
★★☆☆☆ 4 8%
★☆☆☆☆ 0 0%

What testers loved: the on-chain receipt (“proves we actually shipped the thing”), the markdown → mindmap compile, and the public audit link that works logged out.

What hurt the score: slow / silent ingest, no visible XLM balance, no version number in the UI, flaky wallet-session redirects, and unusable mobile layout. Every 2★ response is an ingest or session bug, not a missing feature.


Next phase — what we build from this feedback

Each item below is scoped from the exported responses above. Baseline commit links point at the code the feedback was collected against.

1. Fix the ingest pipeline (all four 2★ responses)

“ingest failed on a .docx with tables, just spun forever, no error” “kept me on a blank screen after ingest until i refreshed”

  • Streaming progress + per-stage status on /api/ingest, hard timeout with a real error
  • DOCX table parsing, and a failed ingest must never leave a blank vault
  • Baseline: 49493e6c — right-panel bugfix, same render path that blanks after ingest

2. Wallet session + balance in the UI (mentioned 5×)

“wish i could see my xlm balance in the app” “connected wallet twice and it kept bouncing me back to login”

  • Balance component in the vault header via loadAccount (SDK is already a dependency)
  • Idempotent public key → Supabase session exchange so a second connect can’t bounce to /login
  • Move disconnect out of the settings dialog into the account menu
  • Baseline: 4a9f889d — wallet connect, 96397cf0 — session fix

3. Make the chain state visible (mentioned 4×)

“confusing that update tx bumps version but the ui doesnt show version anywhere”

  • Version badge + tx hash toast on register / update / node sync
  • Version history panel per doc_id read from the ledger
  • In-app send UI (amount form, pending, success/failure, hash link) — today only the legacy web/ frontend has it

4. Mindmap at scale (mentioned 4×)

“mindmap gets messy past ~30 nodes”, “graph is pretty but slow with a big vault”

  • Auto-layout pass so nodes don’t need dragging
  • Virtualized / LOD rendering for 200+ note vaults
  • Batch node status updates in one signed transaction
  • Baseline: eab81527 — document and global mindmaps

5. Onboarding and escape hatches (mentioned 5×)

“i had no clue what to do after login”, “i dont get why i need a wallet just to write notes”

  • Demo vault, readable before signup
  • Email-first signup with wallet linking as a later step
  • Vault export to a markdown zip, undo for AI regenerate
  • Global search across notes

6. Mobile + polish

  • Responsive vault (currently desktop-only — “opened it on my phone and it was unusable”)
  • Light-mode contrast pass, markdown table rendering, keyboard shortcuts
  • Mainnet fee estimates documented before the mainnet deploy

Priority order: ingest reliability → wallet session → chain visibility → mindmap scale → onboarding → mobile. Reliability bugs first: they cap the score at 2★ no matter how good the rest is.


Stellar wallet integration (testnet)

End-to-end wallet flow on Stellar Testnet, verified on-chain.

1. Wallet setup

Freighter installed and switched to Stellar Testnet, account funded from Friendbot with 10,000 XLM.

Freighter on Stellar Testnet funded with 10,000 XLM

Field Value
Network Stellar Testnet
Account GB7KVJMPJDVI6NTRNENAMFGYQAZVRI266B4BZ4UMN2RA2NBHFOB6ZC5D
Created 2026-07-27 11:03:17 UTC
Initial balance 10,000 XLM

2. Wallet connection

Connect and disconnect are implemented in the app via Stellar Wallets Kit pinned to Networks.TESTNET (Freighter plus the other default modules).

Doqtri landing page with Connect wallet

Behavior Code
Connect — opens the wallet modal, returns the public key connectWallet() in doqtri/frontend/lib/wallet.ts
Session exchange — public key → Supabase session doqtri/frontend/app/api/auth/wallet/route.ts
Connect button + redirect to /vault doqtri/frontend/components/auth/login-form.tsx
Disconnect — kit disconnect + Supabase sign-out disconnectWallet() in lib/wallet.ts, called from components/vault/settings-dialog.tsx
Live address changes onWalletState() (kit STATE_UPDATED event)

The kit is imported lazily inside each function because it touches localStorage during module evaluation, which breaks server rendering of client components.

3. Balance handling

The connected account's XLM balance, read from testnet Horizon and shown on Stellar Expert after the transaction below:

Account balance on Stellar Expert testnet

Balance after send: 9,999.9053473 XLM — 10,000 minus the 2 XLM payment and fees.

Status: the balance is fetched and verified on-chain, but it is not yet rendered in the Doqtri UI — there is no balance component in doqtri/frontend/ today. Wiring @stellar/stellar-sdk (already a dependency) to a Horizon loadAccount call and displaying it in the vault header is the remaining piece.

4. Transaction flow

A 2 XLM payment signed with Freighter on testnet:

Successful transaction on Stellar Expert testnet

Field Value
Status ✅ Successful
Transaction hash 38a1ccf5a26e236756c961e2a8e26ecb56856c91fff7f90b8dd0d9b72bedac4e
Ledger 3826447
Processed 2026-07-27 11:13:09 UTC
Amount 2 XLM
From → To GB7KVJ…B6ZC5DGCPF…4YUN
Fee charged 0.00001 XLM

Status: the payment was built and signed through Freighter on testnet and confirmed on-chain. In-app send UI (amount form, pending spinner, success / failure state, hash link) is not implemented in doqtri/frontend/ yet — the transaction-feedback pattern described under Web app above lives in the legacy web/ frontend.


Tech stack

Layer Package Badge
Smart contracts soroban-sdk 22 Soroban
Contract language Rust Rust
CLI / deploy Stellar CLI Stellar
Frontend Next.js 15 + React 19 Next.js
Language TypeScript TS
Chain client @stellar/stellar-sdk SDK
Wallet @creit.tech/stellar-wallets-kit + Freighter Freighter
Fonts Instrument Sans · Outfit · IBM Plex Mono Fonts

Repository layout

doqtri/                          # git repo root
├── doqtri/
│   ├── frontend/                # PRIMARY app (Next.js vault + mindmap)
│   └── backend/                 # Supabase migrations + AI prompts
├── contract/                    # Soroban DoqtriRegistry (optional chain layer)
├── web/                         # LEGACY Stellar landing (not deployed)
├── Cargo.toml
├── .github/workflows/
└── README.md

See also doqtri/README.md and doqtri/SPEC.md.


Architecture

  Upload / note        doqtri/frontend           Supabase
 ┌──────────┐         ┌────────────────┐       ┌─────────────┐
 │ PDF/DOCX │ ingest  │ vault editor   │──────►│ documents   │
 │ markdown ├────────►│ graph+mindmap  │       │ + Storage   │
 └──────────┘         │ /api/* + AI    │       └─────────────┘
                      └────────────────┘

Contract interface

Function Auth Description
register_document(owner, doc_id, content_hash) owner Anchor a new document at version 1
update_document(doc_id, new_hash) owner Anchor a new hash; returns incremented version
set_node_status(doc_id, node_id, status, tool, artifact_ref) owner Record node lifecycle
get_document(doc_id) none Read anchored document state
get_node(doc_id, node_id) none Read a node’s build record

Node statuses: Planned · Building · Built · Verified

Storage keys: DataKey::Doc(doc_id) · DataKey::Node(doc_id, node_id)
TTL: threshold 30 days → extend to 90 days on every write (1 day = 17280 ledgers)


Quick start — app (doqtri/frontend)

Prerequisites: Node 20+, Supabase project + OpenAI key.

cd doqtri/frontend
cp .env.example .env.local   # fill anon key, service_role, OPENAI_API_KEY
npm install
npm run dev

Open http://localhost:3000/login → vault.

npm test
npm run build
npm run start

Network selection

The frontend defaults to testnet. Two env vars flip it to mainnet — every other network value (RPC, Horizon, explorer URLs) derives from the passphrase in doqtri/frontend/lib/stellar/config.ts:

NEXT_PUBLIC_NETWORK_PASSPHRASE="Public Global Stellar Network ; September 2015"
NEXT_PUBLIC_CONTRACT_ID=CCP5KFIWLUNPV2G7ATBKFMIZF54JYRC343P5JCTARC4PRTGM23IU6ET4

The passphrase must match that string exactly, spaces around the ; included; anything else is treated as testnet. Setting the mainnet passphrase without a contract ID throws at startup rather than silently falling back to the testnet contract.

NEXT_PUBLIC_* values are inlined at build time, so changing them in the Vercel dashboard has no effect until a new build runs — redeploy after editing them.

Deploy (Vercel): set Root Directory to doqtri/frontend, then add the env vars from .env.example.

Backend SQL lives in doqtri/backend/migrations/ (already applied on the Doqtri Supabase project).

Legacy Freighter UI: web/ (not the primary app).


Quick start — contract

Prerequisites:

  • Rust stable + rustup target add wasm32v1-none
  • Stellar CLI
# from repo root
cargo test -p doqtri-registry

cd contract
stellar contract build

WASM (workspace layout):

target/wasm32v1-none/release/doqtri_registry.wasm

Deploy (testnet)

# one-time identity
stellar keys generate alice --network testnet --fund

stellar contract deploy \
  --wasm ../target/wasm32v1-none/release/doqtri_registry.wasm \
  --source alice \
  --network testnet \
  --alias doqtri

Deploy (mainnet)

Same command against --network mainnet, with a funded real account — budget ~8.1 XLM for the WASM upload (see the fee table above). Simulate first; a simulation is free and needs no key:

stellar contract deploy \
  --wasm ../target/wasm32v1-none/release/doqtri_registry.wasm \
  --source-account <YOUR_KEY> \
  --network mainnet

Invoke (live contract)

CONTRACT=CCB5DFZRFFDCIBV5H5KWO6UCVN4ZXIPUSXONMBA6HVF433SPO7YEWMSB

stellar contract invoke \
  --id $CONTRACT --source alice --network testnet -- \
  register_document \
  --owner alice \
  --doc_id "doqtri-launch-plan" \
  --content_hash 0101010101010101010101010101010101010101010101010101010101010101

stellar contract invoke \
  --id $CONTRACT --source alice --network testnet -- \
  set_node_status \
  --doc_id "doqtri-launch-plan" \
  --node_id "node-weekly-report" \
  --status '"Built"' \
  --tool "n8n" \
  --artifact_ref "wf_8Xk2p"

stellar contract invoke \
  --id $CONTRACT --source alice --network testnet -- \
  get_document --doc_id "doqtri-launch-plan"

CI

GitHub Actions (.github/workflows/ci.yml):

  1. Testcargo test -p doqtri-registry
  2. Build WASM — install Stellar CLI, stellar contract build, upload artifact

Roadmap (near-term)

  • Register / update documents from the web UI (signed Freighter txs)
  • Sync real mindmap nodes from a source document pipeline
  • Public audit page by doc_id

License

MIT — see project root.

About

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages