Project case study

Talk With Jamie: a privacy-conscious personal chat app.

An AI chat that answers as me. The chat is the easy half. The half worth talking about is making sure a stranger on the public site can never pull anything private back out of it.

Overview

Talk With Jamie started as a chat interface and turned into an access-control problem. Anyone can use it, including as a guest, and it answers using context about me. So the real design question was never the chat. It was which context, for whom, and how I stop someone talking the model into handing over the rest.

What I built

  • Guest and registered chat sessions.
  • Signed HttpOnly session cookies and password hashing.
  • Persistent users, conversations, contacts and rate limits using Netlify Blobs.
  • A Netlify Functions backend with route handling, input cleaning and provider logic.
  • Private admin tools for conversation review, blocking, deletion and drafting.
  • A retrieval layer that splits context by audience, so public chat can only ever see approved chunks.
  • Automated checks covering syntax, site structure, authentication helpers, context boundaries and deployment safeguards.

Architecture

The project uses a static frontend with JavaScript handling the chat interface and account flow. Requests go through Netlify Functions, which act as the backend API. Storage is handled through Netlify Blobs, allowing the project to persist conversations and user records without running a traditional server.

Frontend Static HTML, CSS and JavaScript
API Netlify Functions routes
Storage Netlify Blobs
Testing Node syntax, site, unit and integration tests

Privacy and safety decisions

The project is clearly labelled as a chat experiment, and it warns users not to submit sensitive information. Raw personal exports and private source files are not committed or deployed. The v2 version uses a compact, redacted context pack rather than exposing original source material.

The model is also told to refuse attempts to extract its context, but I do not rely on that. A prompt is a request, not a permission system. The retrieval layer simply never puts a private chunk in front of a public user, so there is nothing sitting there for the model to leak in the first place. There is also no route in the app that reads the pack back out, including for me while signed in as admin.

Testing and deployment

The active app has automated checks covering JavaScript syntax, site structure, authentication helpers, signed sessions, username validation, message cleaning, context validation and retrieval boundaries.

What I would tell myself at the start

The first version leaned on the system prompt to keep private things private, which is not a boundary, it is a hope. Anything the model can retrieve, it can eventually be talked into repeating. Moving that decision out of the prompt and into the retrieval layer, where it is code and covered by tests, is the change that actually made this safe. The prompt now only shapes tone.