Inspiration
It started with a markdown file. We wanted one document that a manager, an accountant and a designer could each open and immediately see the part that mattered to them. One source, three readings.
Then one of us was scrolling a social feed and realised it was the same problem at a much larger scale. Everyone gets the same post. Almost nobody gets the part that is actually for them. You scroll for an hour to find one useful thing.
The same idea turned out to matter even more for the people on the other side. Brands and creators publish once and hope the right person stops. They pay for reach nobody asked for, and interrupt people who never wanted it. If one artifact could become the right version for each reader, both sides win at the same time.
What it does
A creator publishes one artifact, once. Each recipient opens it inside ChatGPT or Codex and gets a version compiled for them, from context that stays on their side.
The demo uses a fictional sneaker drop from a fictional creator, Luna Vale, and three audience personas:
- Alex, CEO of a tech company. An executive series page about travel, comfort and focus.
- Camille, artistic director. An editorial atelier spread about texture, softness and emotion.
- Maya, developer. A dark technical page built around a code block and durability tests.
A fourth tool, show_original_artifact, renders the artifact exactly as published, with no personalization. Putting the original next to the three versions is the whole product in one screen.
Each persona has its own tool, so asking for Alex returns Alex's artifact and never a combined gallery.
Try it in the browser with no setup, or connect the public MCP endpoint to ChatGPT or Codex in under a minute. No authentication required.
How we built it
The project was created between July 17 and July 21, 2026, entirely inside the Submission Period. Nothing in the repository predates the hackathon.
Four people: Zlata on product vision, Chrys on technical architecture, Take on development, Edith on product.
Built with Codex on GPT-5.6. We designed the architecture together with Codex, wrote an implementation plan, and executed it step by step. IMPLEMENTATION_PLAN.md and PROPOSED_STRUCTURE.md in the repository are the artifacts of that process, and the MCP integration was done the same way. Codex wrote the Streamable HTTP MCP server and its eight tools, the deterministic persona services and seed data, the MCP Apps widget resource, the browser preview, the Netlify function and deployment config, and the 39-test suite. The /feedback session ID is in the submission form, so the claim is checkable against the commit history rather than taken on trust.
What mattered was not speed but legibility. Codex wrote down what it was doing and why at every step, so at any moment we knew where we were in a project that only existed for four days, and four people could work against one shared plan.
Stack. TypeScript throughout, with a self-contained HTML widget. Two transports, a local browser preview and the MCP Apps resource, both calling the same domain service layer. Widgets are served as MCP resources and also embedded directly in the tool result, so a client never needs a second round trip to render.
Determinism, on purpose. The experience engine runs on deterministic TypeScript services rather than a live model call at render time. We kept this decision even when the easier path was available: personalisation that changes on every load is noise, and it makes attribution for the creator impossible. Someone opening the same artifact twice has to get the same experience, today and tomorrow.
Context stays on the client. Persona knowledge bases live in knowledge/ as skill files: profile.md, style.md, commands.json. They describe a person's history, taste and constraints, and they are not a server-side user profile.
Challenges we ran into
Our worst bug was the most confusing one. The MCP tool returned correct text in ChatGPT while the widget refused to render, first as an empty grey block, then as Failed to fetch template. Every change looked correct in the code and wrong in the client, so for a long time we were debugging the wrong layer entirely.
What broke the deadlock was treating the deployed server as a black box and probing it directly with raw JSON-RPC calls instead of trusting the client. resources/list was correct. resources/read returned the full widget HTML. The assets returned 200. The server was fine, so the fault had to be in what the client was being told to do.
Three things were wrong, and each of them alone was enough to break rendering:
- The tool result carried no
_meta. The template was declared on the tool descriptor but never echoed on the result, so the client received data with no instruction about how to render it. - The resource declared a custom widget domain whose root returned 404. The client tried to fetch the template from an origin that served nothing.
- The widget was reachable only through a separate
resources/readcall, which some clients never make.
The fixes were to echo _meta on the result, drop the custom domain, and embed the widget resource directly in the tool result.
Accomplishments that we're proud of
A working MCP that runs inside ChatGPT and Codex, with an inline widget, deployed publicly with no authentication so anyone can connect in under a minute. Built in four days by four people.
Determinism as a deliberate property rather than an accident.
An architecture where personalisation happens without collecting anything about the person.
You can try right now in your ChatGPT:
ChatGPT:
- Settings, Developer mode, Create a plagin
- MCP URL: https://nextbound-adaptive-media.netlify.app/mcp
- Authentication: No authentication
- Open a new chat, add Nextbound, then ask: Show Luna's original artifact. Show Luna's artifact for Alex. Show Luna's artifact for Camille. Show Luna's artifact for Maya.
What we learned
Personalisation does not require a profile. It requires context that belongs to the reader.
An MCP server is a contract, and the client is the source of truth about what actually arrived. When the two disagree, only a direct probe tells you which one is lying.
A plan written with Codex is worth more than the code it produces, because the plan is the thing four people can share.
What's next for Nextbound
Persistence and authentication, which the MVP deliberately does not have. Today state lives in memory and resets when the server restarts, and share returns a stable demo reference rather than a public URL.
A public share surface, so an experience can leave the session it was created in.
Real creators with real artifacts, and the economics that follow: brands paying for one experience made for one person, instead of paying for reach nobody asked for.
Log in or sign up for Devpost to join the conversation.