
Services
What we build, and how we price it.
Websites
We design and build the site, not a template with your logo on it. That means a considered visual direction, copy that says something specific, and a front end that scores well on the things that actually affect whether people convert — load time, layout stability, working on a phone, working for someone using a keyboard or a screen reader. You get the code, and it is code your own developers can read.
- Design direction and page designs
- Production front end with a typed content layer
- Accessibility review against WCAG 2.2 AA
- Performance budget, measured rather than promised
- Deployment pipeline and documentation
- Handover, with the repository and hosting in your name
This site’s own build
An excerpt of the production build for this site: settings resolved from 1Password at build time rather than committed, and every route prerendered as static HTML.
op run --env-file=app.env -- pnpm -F web build
▲ Next.js 16.3.6 (Turbopack)
Route (app)
┌ ○ /
├ ○ /services
└ ○ /work
○ (Static) prerendered as static content
Applications
Most of what we build is a product with logins, data, permissions and a business process behind it. We are comfortable owning the whole stack — interface, API, database, deployment, monitoring — and equally comfortable slotting into an existing codebase and an existing team. We start with the smallest thing that answers the real question, then build out from what you learn rather than from what was assumed at the start.
- Technical design and data model
- Working application, deployed
- Authentication, authorisation and audit where the domain needs them
- Automated tests covering the paths that matter
- Infrastructure as code
- Runbook and handover
AI integration
We have shipped MCP servers in production for a Medicare company and LLM-driven analytics across large databases for a major sports franchise. The work that goes wrong here almost always goes wrong the same way: a demo that impresses, then no way to tell whether it is right. So we build the evaluation alongside the feature, keep a human in the loop where being wrong is expensive, and are direct about the cases where a language model is the wrong tool and a query would do.
- Feasibility assessment, including where AI is the wrong answer
- MCP server or LLM feature, integrated with your systems
- Evaluation harness and a quality baseline you can re-run
- Cost and latency modelling before commitment, not after
- Documentation your team can maintain
Named integration surfaces
LLM features and MCP servers connected to named integration surfaces in your systems, not a standalone demo.
- CRM
- Ticketing
- Data warehouse
- Records DB
Workflow automation
Multi-step agent workflows with approval gates and cost ceilings, so an agent never acts past where a human should sign off.
Plan
Draft
Budget
Cost gate
Review
Human approval gate
Execute
Retrieval pipelines
Ingestion, chunking, embedding, hybrid retrieval and reranking as named, measured pipeline steps.
- Ingestion
- Chunking
- Embedding
- Vector store
- Hybrid retrieval
- Reranking
- Evaluation
MCP servers
MCP servers built on Streamable HTTP, shipped into production rather than prototyped.
server.ts
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'
const server = new McpServer({ name: 'records', version: '1.0.0' })
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined })
await server.connect(transport)Evaluation
A CI-gated eval harness that measures output quality against a baseline and alerts when it drops, rather than a claim that outputs are correct.
evals/answers.eval.ts
import { expect, it } from 'vitest'
import { answer } from '../src/answer'
import { BASELINE, score } from './score'
import { refundPolicy } from './cases/refund-policy'
it('answers from the retrieved context, not from memory', async () => {
const result = await answer(refundPolicy.question, refundPolicy.documents)
expect(result.citations).not.toHaveLength(0)
expect(score(result.text, refundPolicy.expected)).toBeGreaterThanOrEqual(BASELINE)
})Developer consulting
Sometimes the useful thing is not another pair of hands but someone who has seen the failure mode before. We review architecture before it is expensive to change, audit code for the problems that only show up under load or in front of an auditor, and work alongside your team on the part of the system nobody wants to touch. We tell you what we actually think, including when the answer is that your existing plan is fine.
- Architecture or code review with prioritised, specific findings
- Written recommendations, ordered by what they cost and what they save
- Pairing sessions with your developers
- Follow-up review once changes land
Hands-on teaching
Training that uses someone else’s example project tends not to survive contact with your repository. We teach on your code, on the problems your team actually has — testing discipline, accessibility, performance work, getting useful results out of AI tooling. Sessions are hands-on and small, and you keep the written material afterwards. Marc leads this work.
- Curriculum built from your team's current gaps
- Hands-on sessions on your codebase
- Written reference material that outlasts the session
- Follow-up review to see what stuck
Tools we build with
- AWS
- Postgres
- Next.js
- Anthropic
- OpenAI
- Terraform

Have something to build?
Thirty minutes, no preparation needed. Tell us what you are trying to do and we will tell you plainly whether we can help.
Book a 30-minute call