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 · Onboarding survey responses · Launch post on X · Mainnet contract on Stellar Expert · Testnet contract on Stellar Expert
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.
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.
Most roadmaps live in docs. Most “shipped” badges live in app state. Those two worlds drift apart.
Doqtri closes the gap:
- Watch a living source (Docs, Notion, markdown).
- Compile it into a typed, executable mindmap.
- When a node is scaffolded into n8n / Make / Retool / Langflow, record build status.
- 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.
| 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 |
- Document versions — SHA-256 content hash per
doc_id, version increments on every semantic update - Node build status —
Planned → Building → Built → Verifiedwith 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)withdoc_idpayload
- 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
web/— previous Freighter + Soroban UI (kept for reference, not primary)contract/— DoqtriRegistry, deployed on Stellar mainnet and testnet (built in CI)
The app runs against mainnet. Testnet stays live as the free sandbox and is where the 50-user product test below was run.
| 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>.
| # | 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 |
| Field | Value |
|---|---|
| Network | Stellar Testnet |
| Contract ID | CCB5DFZRFFDCIBV5H5KWO6UCVN4ZXIPUSXONMBA6HVF433SPO7YEWMSB |
| CLI alias | doqtri |
| WASM hash | ef0124a4a22b60ba1f4e0e41823d31b175d90d38b1ba034970e58e0cf4e0e252 |
Explorer links
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.
| # | 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 |
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 |
| 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.
Each item below is scoped from the exported responses above. Baseline commit links point at the code the feedback was collected against.
“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
“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
“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_idread from the ledger - In-app send UI (amount form, pending, success/failure, hash link) — today only the legacy
web/frontend has it
“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
“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
- 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.
End-to-end wallet flow on Stellar Testnet, verified on-chain.
Freighter installed and switched to Stellar Testnet, account funded from Friendbot with 10,000 XLM.
| Field | Value |
|---|---|
| Network | Stellar Testnet |
| Account | GB7KVJMPJDVI6NTRNENAMFGYQAZVRI266B4BZ4UMN2RA2NBHFOB6ZC5D |
| Created | 2026-07-27 11:03:17 UTC |
| Initial balance | 10,000 XLM |
Connect and disconnect are implemented in the app via
Stellar Wallets Kit pinned to Networks.TESTNET
(Freighter plus the other default modules).
| 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.
The connected account's XLM balance, read from testnet Horizon and shown on Stellar Expert after the transaction below:
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 HorizonloadAccountcall and displaying it in the vault header is the remaining piece.
A 2 XLM payment signed with Freighter on testnet:
| Field | Value |
|---|---|
| Status | ✅ Successful |
| Transaction hash | 38a1ccf5a26e236756c961e2a8e26ecb56856c91fff7f90b8dd0d9b72bedac4e |
| Ledger | 3826447 |
| Processed | 2026-07-27 11:13:09 UTC |
| Amount | 2 XLM |
| From → To | GB7KVJ…B6ZC5D → GCPF…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 legacyweb/frontend.
| Layer | Package | Badge |
|---|---|---|
| Smart contracts | soroban-sdk 22 |
|
| Contract language | Rust | |
| CLI / deploy | Stellar CLI | |
| Frontend | Next.js 15 + React 19 |
|
| Language | TypeScript | |
| Chain client | @stellar/stellar-sdk | |
| Wallet | @creit.tech/stellar-wallets-kit + Freighter | |
| Fonts | Instrument Sans · Outfit · IBM Plex Mono |
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.
Upload / note doqtri/frontend Supabase
┌──────────┐ ┌────────────────┐ ┌─────────────┐
│ PDF/DOCX │ ingest │ vault editor │──────►│ documents │
│ markdown ├────────►│ graph+mindmap │ │ + Storage │
└──────────┘ │ /api/* + AI │ └─────────────┘
└────────────────┘
| 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)
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 devOpen http://localhost:3000 → /login → vault.
npm test
npm run build
npm run startThe 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=CCP5KFIWLUNPV2G7ATBKFMIZF54JYRC343P5JCTARC4PRTGM23IU6ET4The 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).
Prerequisites:
- Rust stable +
rustup target add wasm32v1-none - Stellar CLI
# from repo root
cargo test -p doqtri-registry
cd contract
stellar contract buildWASM (workspace layout):
target/wasm32v1-none/release/doqtri_registry.wasm
# 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 doqtriSame 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 mainnetCONTRACT=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"GitHub Actions (.github/workflows/ci.yml):
- Test —
cargo test -p doqtri-registry - Build WASM — install Stellar CLI,
stellar contract build, upload artifact
- 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
MIT — see project root.




