We build custom applications, connect systems, and automate the work between them. From requirements meetings to reliable integrations, with clear logs and data your team can actually use.
One HTML fileNative browser APIsAutomated deployment
01 / THE PROCESS
The work, with the working shown.
Good systems start with listening. Follow a sample project from requirements meetings and shared notes into application logic, clear interfaces, integrations, and delivery.
Engineering notes / a website, explainedRead. Inspect. Explore.
First, a conversation.
Discovery / analysis
We meet the people doing the work, ask questions, and take notes. We map the current process, agree what matters, and turn assumptions into decisions before choosing a solution.
AT THE BLACKBOARD / SAMPLE WORKSHOPOperations + finance + delivery
“We need to know where an order is, without checking three systems.”
Sketch the flow. Find the gaps.
Source systemsERP · files · partner API
One order viewsame words, shared status
Your teamsearch · understand · act
What if a sync fails? → A visible review queue.
What we heard
Updates arrive by email. Staff compare spreadsheets with the ERP. Customers call for the same status information.
What we need to learn
Which system owns the order? Who can see each field? What should happen when a sync fails?
Agreed first scope
One order view, a visible last-sync time, and a searchable history of changes. Start with one source system.
Acceptance criteria
A user sees only permitted orders. Every imported update has a traceable outcome. Failed updates are visible for review.
Output → A shared brief. Priorities, owners, acceptance criteria, and questions to resolve. Example workshop notes, not a client transcript.
Turn a requirement into working code.
Custom Python / example
We build focused tools around the requirements. For this website, “read clearly” includes a sensible heading structure. This small Python parser checks the markup; the button below checks the current page in your browser.
check_headings.py
from html.parser importHTMLParserfrom pathlib importPathclassHeadingAudit(HTMLParser):def __init__(self): super().__init__() self.headings = []def handle_starttag(self, tag, attrs):if tag in ("h1", "h2", "h3"): self.headings.append(tag)page = HeadingAudit()page.feed(Path("index.html").read_text())assert page.headings.count("h1") == 1assert page.headings[0] == "h1"
Try it locally — save beside index.html, then run python check_headings.py.
Python’s HTMLParser ↗ reads the markup without another dependency. These checks confirm one main heading, placed before subheadings; they are a starting point for a wider accessibility review.
Four real checks, in your browser.
Make the rules explicit.
Django / backend
A project brief can become a business workflow. Before storing a request or scheduling work, check its input. A launch date before the start date is a useful error to catch at the boundary.
forms.py / application example
from django import formsclassProjectBrief(forms.Form): email = forms.EmailField() start = forms.DateField() launch = forms.DateField()def clean(self): data = super().clean() start = data.get("start") launch = data.get("launch")if start and launch and launch < start: self.add_error("launch", "Launch cannot precede the start." )return data
One rule, one place — validate with form.is_valid() before passing cleaned data to a service.
Django forms ↗ handle field validation and attach errors to the right input. Views handle the request; shared services handle the workflow. This example belongs in a Django application, not this static page.
Example output / validation
Start: 14 September · Launch: 12 Septemberlaunch → Launch cannot precede the start.Result: the request is not accepted until corrected.
A field-specific error the interface can display. The rule is checked before the workflow continues.
Less friction. More clarity.
HTML / frontend
Put that validated brief in front of a person. Start with a regular form, then enhance the interaction: replace just the form with its result, keeping validation on the server.
A small enhancement — the endpoint returns a form fragment for HTMX, or a full page for a normal POST.
HTMX ↗ adds targeted requests and HTML updates. This application excerpt needs a Django endpoint and HTMX loaded in its parent page. Our homepage keeps its interactions in native JavaScript.
Interactive output / form preview
Try a launch date before the start date. This local preview shows the response a person would see; nothing is submitted.
Connect the data. Keep the story.
Integrations / logging
The order view from our workshop needs a consistent language. Translate each source’s fields into a shared model, reject unknown states, and record enough context to follow the result.
orders.py / mapping example
import logginglogger = logging.getLogger("integrations.orders")def normalize_order(payload): states = {"shipped": "Dispatched", "held": "Needs review"} status = states.get(payload["state"])if status isNone:raise ValueError("Unsupported order state") order = {"external_id": str(payload["id"]),"status": status, } logger.info("Order normalized", extra=order)return order
Normalize → record → present — a public example with two source states and no customer data.
A mapping function is one part of an integration. The surrounding service records success and failure, applies retry rules, and exposes a searchable history. Logs retain useful context while sensitive payload fields are redacted. See how the systems connect ↓
Example output / operations view
Order
Sync
Details
Trace
DEMO-101
Succeeded
Dispatched
sync-001
DEMO-102
Needs attention
Unsupported source state
sync-002
DEMO-103
Succeeded
Order needs review
sync-003
3 example records.
Illustrative records. A successful sync can still carry a business status that needs review. The trace connects the visible record to its integration history.
Example record updated
Delivery is part of the product.
Ansible / devops
A good release is repeatable. Describe the desired files and permissions, then let the tooling bring the server into that state. This standalone publishing recipe uses an example web root.
publish.yaml / public recipe
- name: Publish a static pagehosts: webbecome: truetasks: - name: Create the web rootansible.builtin.file:path: /var/www/examplestate: directorymode: "0755" - name: Put HTML in placeansible.builtin.copy:src: index.htmldest: /var/www/example/index.htmlowner: rootgroup: rootmode: "0644"
Same input, same state — run with a configured web inventory group and SSH access with privilege escalation.
Ansible’s copy module ↗ manages the file and its permissions. Nginx serves it. The full deployment also configures HTTPS, checks Nginx before reloading, and schedules certificate renewal.
Example output / completed release
Page copied with the expected permissions
HTTPS configured
Nginx configuration validated
Site reloaded and certificate renewal scheduled
An illustration of the full deployment’s outcome, not a live server report. Each operation has a visible result in the deployment log.
We build AI into your platform.
Custom chat + agents + MCP
We build our own AI chat into the platform, connected to MCP servers that expose useful business tools. An agent can retrieve an order, explain an integration failure, or prepare an action using the current user’s permissions.
01
We build your chat interface.
A custom experience inside your product, with streaming replies, conversation history, and visible activity.
02
We connect agents to MCP tools.
Servers and tools that connect the agent to your application services, business data, and integrations.
03
We build permissions and activity logs.
User-aware access, confirmations for sensitive actions, and a readable history of requests, results, and changes.
A business tool, with a defined input — an illustrative MCP request. The server checks access before returning data.
Our chat handles the conversation and presents results. MCP tools ↗ connect the agent to application services and integrations. The platform enforces permissions, records tool activity, and asks for confirmation where a workflow needs it.
Example output / structured tool data
{"order_id": "DEMO-101", "status": "Dispatched"}
The chat can turn this data into a clear answer and link to the underlying order. Tool logs let your team inspect what was requested, what came back, and what action followed.
Read data, review an action, and see the website change.
Original examples, written for this walkthrough. No client code. Copy, adapt, and explore.BUILT WITH INTENTION ↗
01 Understand the operation
Meet the people, take notes, and agree the requirements. Make assumptions and open questions visible before development starts.
02 Keep the logic together
Clear validation and reusable services. The same rules apply in the website, the admin, and background jobs.
03 Make it operable
Presentable data, searchable integration logs, and repeatable releases. Your team should be able to see what happened and what needs attention.
02 / INTEGRATIONS & YOUR ECOSYSTEM
Your systems, connected. Your data, made clear.
We connect the tools your team and partners depend on. We make the exchange traceable, then turn it into screens, reports, and decisions people can use.
Map ownership, identifiers, permissions, and update frequency. Define what a successful exchange looks like with your team and the system provider.
02 / Make exchanges traceable
Know what happened.
Validate incoming data, track each outcome, and make failures visible. Use explicit retry rules and useful logs, without storing secrets in the history.
03 / Put it in people’s hands
Make the data usable.
Searchable records, clear statuses, reconciliation views, and reports. Your team can see what is current, what changed, and what needs attention.
03 / THE TOOLBOX
Good tools. Chosen for a reason.
The stack follows the problem. We favour established tools, clear responsibilities, and fewer moving parts. Each library should earn its place.
{ }
Business applications
Django & PostgreSQL
Portals, operational tools, and business workflows. Structured data with an administration interface people can use.
Why these tools?
Django brings forms, authentication, and an admin together. PostgreSQL provides relational storage and transactions for related writes.
Readable pages, deliberate interactions, and interfaces that put the task first. Enhance where it makes a difference.
Why these tools?
HTML gives content structure; CSS shapes the experience; JavaScript adds local interactions. HTMX can update a small part of a server-rendered application without a separate client data layer.
Connect your systems, schedule background work, and trace every important exchange. Make your data consistent, visible, and useful.
Why these tools?
Background workers handle scheduled jobs and retries. Integration logs show what was sent, what came back, and what needs attention. Dashboards and admin screens make that history usable, with sensitive data redacted.