Roadmap
The web app indx is becoming, screen by screen, with what already exists behind each screen and what has to be built first.
indx today is an API with four operations, /v1/plan, /v1/encode, /v1/embed and /v1/capabilities, a CLI, an in-process facade and a playground in the web app. The target is a web app: the product blueprint (日本語), an interactive mock dated 2026-09-10 whose data, scores and API paths are samples and proposals, as its own footer says. It has two layers. Layer 01 is the embedding foundation: embedding spaces, a data store, and the features and tags that give records meaning. Layer 02 builds on it: a playground, a few-shot library and endpoints. A workspace layer chooses where all of it runs.
This page walks the blueprint one screen at a time. Each section says what the screen shows, what already exists behind it on main, what is missing, and what has to come first. Every screen carries one of three states. Planned means nothing usable stands behind it yet. WIP means the service already answers what the screen would show, through the API or the playground, and the screen itself does not exist. Done is reserved for a screen a person can use in the web app, and none has earned it, because the web app does not exist yet. The engineering reasons for the order are on the build order page. An earlier version of this page measured eight steps against KR1 targets; it is kept as milestones.
The screens
Section titled “The screens”Overview — a workspace with its spaces, endpoints and improvement cycle Planned
What the screen shows. A tenant workspace with an environment pill, three embedding spaces with record counts, the endpoints built on them, and the cycle that grows knowledge: ingest, add meaning and teach, verify and use.
What exists today. /health, and a capability snapshot that already answers most of what the cards would show: the embedding spaces installed, the readers and classifiers available, and what each one costs. There is no workspace, no tenant and no sign-in.
What is missing. The workspace itself, and authentication in front of it.
Needs first. Every other screen. The overview is what the rest adds up to.
Embedding spaces — a named space with a model, a version and a record count WIP
What the screen shows. Spaces such as operations, layout and product, each with the model behind it, its dimensions, how many records it holds, how many features are declared on it, and a version that switches only after an evaluation. A button creates a new one and chooses the model it may use.
What exists today. An embedding space is a capability: default-text (hashed, no model), minilm-multilingual and clip-vit-b32 (one extra, text and image), and hosted-text (a hosted model through LiteLLM). Each is advertised on the snapshot, a request names the ones it wants, and /v1/embed encodes a query in the same space so the vectors can be searched later. The snapshot ID is the only version there is: a plan is bound to it, and a changed install invalidates the plan rather than silently changing the answer.
What is missing. A space a customer creates: a stored binding of a model, a version and a feature schema, holding a record count because something is stored under it. Versioning today is a property of the install; the blueprint makes it a property of the space.
Needs first. The data store. A space with nothing stored in it is the capability it already is.
Data store — every record, its vectors, its properties and its provenance in one table Planned
What the screen shows. A table of ingested documents with a type, a supplier, a modality and a status, a filter over it, and a detail view that traces a record from its source file through its pages and chunks to the space version that embedded it, with the related records beside it. A button ingests more.
What exists today. Nothing persists. Every call returns its blocks and vectors to the caller and forgets them, which is the non-goal “indx does not own your index” stated on the goals page. The provenance the detail view shows already exists per response, though: block IDs such as page:1/chunk:1, the source digest every plan is bound to, and the trace that names the distribution behind each part of the answer.
What is missing. The store, and the two things that fill it: the corpus run that processes a folder or a bucket with progress and per-document failures, and export, which writes what a run produced into an index with the space and query encoder named. The non-goal survives as a location rule: the store is the export target, and it lives in the customer’s environment (ADR-0049).
Needs first. The persistence decision, taken once with export and recipes both visible, which is the trigger the build order already names.
features — corpus runs and incremental results; gs: and az: sources
Features & tags — a schema of business axes on each space WIP
What the screen shows. A feature schema per space: document_type as a category, supplier as an entity, confidentiality as a category set by a person, layout_signature as a vector from a vision encoder. Each names its source, a person, a classifier, extraction or an encoder, and each is an axis to filter, classify and extract on. Features are linked to records as structured data, never appended to the model’s vector.
What exists today. Every source on that screen answers per request. Classifiers return facets such as document_type with scores; entity extractors find organisations, people, dates and amounts and point to them in the text; enrichers return tags; the caller’s own labels ride EncodeRequest.metadata onto the document block, which is the “set by a person” source; and signatures such as invoice and process-chart recognise a page’s structure, which is what layout_signature stands for. All of it is returned, none of it is declared anywhere.
What is missing. A stored schema that says which facet, entity, tag or metadata key fills each feature of a space, and filtering by it.
Needs first. Spaces and the store, because a schema is declared on a space and a filter runs over stored records.
features — classifiers, entity extraction, enrichment, document metadata
Playground — pick a feature, run it on a document, keep what was right WIP
What the screen shows. A feature to run (semantic search, information extraction, auto tagging, layout detection, few-shot detection, relationships, OCR routing, parser routing), a space to run it in, an input and a sample document. The result shows its evidence and the space used, and two buttons carry it forward: add it as an approved example, or make it an endpoint.
What exists today. One playground, the web app’s, against the real service: encode a sample or an upload, read each page with its chunks drawn where they sit and the parser that was planned for it beside the reason, search across them, read the entity spans, the classification facets and the enrichment tags, and see a slide’s process chart. There is no feature to pick: the run is one encode, and the lanes are switches on it (ADR-0057).
What is missing. The layout the sales page shows: the run’s inputs across the top, then the page on the left and its structured output on the right, where hovering a block on the page shows what indx hands over for it and the route is stated above the page. Today the form and the result share two columns and the page, its chunk list and its route are stacked. Relationships and few-shot detection, which need the store and the library and stay planned; and the two buttons, which need somewhere to put an example and an endpoint.
Needs first. Nothing for the layout and the hover: they work over the line chunks encode returns today, and gain finer targets as the blocks land. The library for the first button, endpoints for the second.
features — the stage layout, hover to output, the route header
Few-shot library — approved examples, an evaluation set, and a version that is promoted only when it scores better Planned
What the screen shows. A count of approved examples grouped by document type, an evaluation set kept apart from them, the active version, and a comparison of the current version against a candidate over the evaluation set, with a button that promotes the candidate once it wins.
What exists today. The evaluation set exists in the repository rather than in the product: the benchmark’s labelled cases carry the text, fields, entities and languages a correct read must produce, and a run scores every reader and extractor against them. A recognised format is a signature written in code, not a set of examples, and the benchmark reports few-shot setup of a similar format as not implemented rather than as a number.
What is missing. An example store; recipes, a handful of examples plus a schema per recognised format, looked up by signature; and evaluate-and-promote inside the product rather than in a repository run.
Needs first. The labelled set widened to the media types it does not score yet, which is the sourcing half of the build order’s first phase, and the store.
features — recipes and similar-format reuse
Endpoints — the foundation and each application served as its own API WIP
What the screen shows. One embedding endpoint, /v1/embed, on Layer 01, and application endpoints on Layer 02: search, extraction and detection, plus the ones a user creates from the playground, each pinned to a space version. A code panel shows the proposed SDK and the HTTP shape.
What exists today. Five paths: /v1/plan, /v1/encode, /v1/embed, /v1/capabilities and /health, one generated TypeScript client with zod schemas, the in-process Indx facade, and the CLI. Extraction and detection are options on encode, not endpoints of their own, and the from indx import Client in the mock is a proposal.
What is missing. Search, which runs over a store; extraction and detection as named endpoints; endpoints a user creates and pins to a version; and a published client with authentication, rate limiting and retries in front of it.
Needs first. The store for search, spaces for pinning, and the operational work the features page lists as maturity.
Deployment — the same foundation on a managed cloud, in your cloud, or on your own machines WIP
What the screen shows. Three targets: INDX Cloud, a private cloud and self-hosted. An execution policy per target: the data boundary, CPU by default, external models on an allowlist only, and an unapproved fallback refused into manual review. A model allowlist that treats embeddings, OCR and LLMs separately and re-embeds a new space version before a switch.
What exists today. The most built screen of the nine. A production image, a deployed AWS target behind a perimeter, and a hardened mode that closes every URI scheme. data_residency and device are request constraints the planner honours, which extras are installed decides which models exist at all, and the ladder ends at manual review so that no page is silently dropped.
What is missing. A screen for it, which /v1/capabilities can already fill; tenants for the managed target; and an allowlist per space rather than per install.
Needs first. Nothing for the screen. Spaces for the per-space allowlist, the workspace for tenants.
What the sales page promises
Section titled “What the sales page promises”The web app’s front page shows three pages, a notice with a table, a scanned attachment and a process-chart slide, and what indx hands over for each block on them. That output is the target, labelled as such on the page (ADR-0060): the pages and the routes are real, the blocks were merged by hand from the line chunks encode returns. Each promise below is a feature entry, so the gap is tracked where the rest of the work is.
| The page shows | Today | Entry |
|---|---|---|
| A paragraph as one block, its lines joined | One chunk per visual line | Chunk — sentence and paragraph boundaries |
| Headings with a level, and a section path on every block | Headings are lines; no section | Chunk — heading blocks and a section path |
| A table with columns, a box per cell and normalized values | The cells survive as lines in reading order | Chunk — table structure blocks |
| A process chart as a block, a box per symbol and connector, legend rows resolved | The graph is page metadata, with no boxes | Chunk — a diagram as a block |
| Running headers kept and excluded from search | A header is a chunk and is embedded | Chunk — page furniture |
| A paragraph continued on the next page | Two unrelated chunks | Chunk — a block that continues across a page break |
| OCR misreads corrected and dropped lines recovered, per block | The recognizer’s text as read | Read pages — OCR corrections |
| Defined terms and what they mean | Not read | Enrich — defined terms |
| Cross-references resolved to a table, a clause or a law | Not read | Enrich — cross-references |
| A photo with a caption and what it depicts | An image chunk, embeddable, undescribed | Enrich — image blocks |
| Deployed into AWS, Azure or Google Cloud | AWS deployed; the Azure and GCP workflows never dispatched | Deployment |
What already stands behind the page: the route per page and its reasons, OCR for the scan, the process-chart signature and parser, entities, embeddings, and the chart’s Draw.io and Mermaid files. When encode returns paragraph, table and diagram blocks, the page draws a real run of the same three pages and ADR-0060’s exception ends.
What comes first
Section titled “What comes first”- Now, with no dependency. The playground’s feature-first framing and the sales page’s layout (the run on top, the page and its output side by side, hover a block to read it), and a read-only deployment screen filled from
/v1/capabilities. Both are front-end work over requests that exist. Beside them, the requester gets to name the reader, the model and the extractor lane per language through additive request fields (ADR-0050): no new endpoint, no new executor. - Blocks that keep their meaning, the sales page’s promises above, as one contract change: paragraphs, headings and sections, tables, diagrams, furniture and continuation first, then defined terms, cross-references and OCR corrections over them. It waits on nothing below, and it is what makes the stored records worth storing.
- The persistence decision. Taken once, with export and recipes both on the table, as the build order already requires. Everything on Layer 01 waits on it.
- The data store. The corpus run and export, which fill it.
- Spaces and versions over the store, and the feature schema on them.
- The few-shot library, on a labelled set widened to every media type indx reads. The sourcing keeps running from day one.
- Endpoints pinned to a space version, with authentication in front of them.
- The workspace: tenants, and the managed target.
Related reading
Section titled “Related reading”- Milestones — the earlier KR1-framed step list, kept for the record
- Build order — the dependency graph behind this order
- Features — every entry above, with examples and source links
- Benchmarks — the numbers the library’s evaluation set already produces
- Playground — Layer 02 as it runs today