What We Built
BioMat Finder is a semantic biomaterials discovery engine powered by a living knowledge graph. Scientists and engineers describe what they need in plain English — "a flexible, biocompatible scaffold that degrades in saline" — and the system reasons across a graph of biological species, materials, and confidence-weighted claims to surface the best candidates. Every recommendation comes with a traceable confidence score, not just a list.
Inspiration
Materials science has a discovery problem. The literature is vast, scattered, and riddled with results that don't replicate. A researcher hunting for a spider silk analog for cartilage repair might miss the most relevant study because it was published in a niche entomology journal and tagged with completely different keywords.
We were inspired by how physicists at CERN treat uncertainty — not as noise to filter out, but as a first-class quantity to track. What if a biomaterials database worked the same way? What if every claim had a confidence score that moved when new evidence arrived, and the system refused to let hype or bad actors silently corrupt it?
That question became BioMat Finder.
How We Built It
The stack is a pnpm monorepo with a React + Vite frontend and an Express API server, connected to a PostgreSQL knowledge graph hosted on MongoDB with a marketplace like setup for sharing and tracking research.
The knowledge graph sits at the core: species to materials to claims, where every edge carries a confidence score between 0 and 1, an evidence count, and a status (unverified, verified, disputed, retracted). Claims only reach verified at ≥ 0.80 confidence with at least 3 independent evidence items.
The belief revision engine is where the real work happens. Every new evidence submission passes through five sequential layers before it can move a confidence score:
Injection guard — regex patterns catch and log any attempt to overwrite graph data through text inputs Out-of-scope detection — domain vocabulary check flags evidence about non-existent claims or off-topic subjects Anecdotal gate — anecdotal reports with fewer than 3 replications are stored as pending with zero delta; they sit in the queue without influencing beliefs Hype/fraud heuristics — anonymous + extraordinary + zero replications to flagged and held for review Inertia factor — effectiveDelta = rawDelta / (1 + √evidenceCount × 0.5) — well-established claims resist single new results; retractions bypass inertia entirely The AI layer uses Gemini 2.5 Flash through Replit's integrations proxy. The chat copilot streams responses in real time, parses structured blocks from model output to auto-populate the graph, and runs injection detection before any prompt reaches the model.
The frontend has eight views: Chat Copilot, Mission Control dashboard, Semantic Graph, Species Explorer, Materials Library, Knowledge Claims table, Evidence Feed.
What We Learned
Bayesian thinking changes how you design APIs. Once we committed to confidence scores as a first-class field, every route — GET, POST, PATCH — had to reason about uncertainty. That discipline forced cleaner data modeling than we would have had otherwise.
Prompt injection is weirder than it sounds. We expected users to try overwriting data through the chat interface. What we didn't expect was how much legitimate scientific text — "this study contradicts the prior claim that…" — looks like an injection attempt. Tuning the guard without false-positiving real evidence required building a real domain vocabulary list, not just pattern matching.
Inertia is the right metaphor. Early versions of the belief engine treated all evidence equally. Results swung wildly. Adding the 1 + √n × 0.5 dampening factor — borrowed from how physicists weight measurements — made the graph feel epistemically honest: new results nudge beliefs, they don't override them.
Challenges
The OpenAPI to codegen pipeline broke twice on bare type: object schemas, which emitted zod.looseObject (a Zod v4-only construct) on our v3 codebase. We solved it by ensuring every schema has typed properties, then baking that rule into our memory for future work.
Streaming chat and codegen don't mix. Orval can generate typed REST hooks cleanly, but SSE endpoints fall outside what it can model. We ended up using raw fetch + ReadableStream on the frontend for the chat stream — the right call, but it meant two different API patterns in the same codebase.t.

Log in or sign up for Devpost to join the conversation.