DEV Community

Vineet Negi
Vineet Negi

Posted on

I built a journaling app where the AI refuses to talk on Sundays. Day 8/9 of 30.

Day 8 and 9 of building Evengood — a 60-second journaling app — for the Build with MeDo $50K hackathon.

This one took two days because I went the wrong way first.

The trap I almost fell into

By Day 7 I had what looked like a finished product. Voice capture, a calm Tomorrow line, a Kling watercolor keepsake, a 7-day streak ribbon, a Pattern detection that surfaces a one-line rhythm of your week, and a Quiet Mode that shuts the AI up entirely on grief days. v28. Working. Pretty. People could use it.

So Day 8 the obvious move was: ship a small polish feature. Maybe surface yesterday's Tomorrow line in tiny grey above the mic. Maybe a "save the week" export. Maybe a streak ribbon that pulses on the dot for today. Safe. Iterative. The kind of thing every journaling app already has.

I asked Claude to scan every competitor — Stoic, Day One, Reflectly, Daylio, Finch, Apple Journal, How We Feel, Mood Meter, Rosebud, Mindsera, Replika. Then to brainstorm a Day 8 feature that didn't exist in any of them.

The first answer was a "Yesterday's Tomorrow" line. Surfacing yesterday's prompt above the mic. Soft. Tasteful. On-brand.

I killed it.

I didn't want to ship a feature that any other journaling app could build in an afternoon. Restraint is supposed to be the thesis of this product. If the thesis is real, there should be features the category structurally cannot copy. Not because they're hard — because they're contrary to how every other product makes money.

So Day 8 became research and Day 9 became the build.

The thing nobody is building

Here is the structural observation. Every AI journaling app on the market is built around the assumption that the AI's job is to say more. Go deeper. Probe. Reframe. Suggest. Coach. Mentor. Advise.

Rosebud's UVP is literally "go deeper." Mindsera's is mental models. Stoic's is mentor advice. Replika's whole pitch is the AI talking back. Their entire business model — and their reflex to ship more from the model — is more output.

The 2025 Brown University study of LLM "therapy chatbots" catalogued fifteen distinct ethical violations across the major models. The biggest one they named was "deceptive empathy" — phrases like "I hear you" and "that sounds so hard" that mimic care without holding any. The category's failure mode is structural. The AI talks too much, in a register it doesn't actually have authority for.

Quiet Mode (v28) was my first move against that. When the user types "my dad died last week" or "I had a panic attack," Evengood doesn't reframe. The model is silenced. The screen says: "some days don't need reframing. be gentle with yourself tonight." No popup. No emoji. No analytics event. It just gets quieter.

That worked. It felt right. But it was content-triggered — only on heavy days. Calm days still got the full 2-minute reflection. Which meant Quiet Mode was a single point, not a thesis.

For Day 9, I wanted the second point on the same axis.

Witness Mode

What I shipped is called Witness Mode. It runs once a week. By default Sunday evening, but you pick the day in settings.

When you open the app on a Witness Night and reflect for 60 seconds — typed or voice — the response screen does not load a 2-minute reframe. It does not load a Tomorrow line. It does not load a theme word. It does not play TTS speech.

Instead, the AI returns one sentence. Under fifteen words. About the form of what you just said — a recurring word, a surprising word, an absence — never the meaning. Then the screen sits with you in silence for four seconds. Then the closing line reads come back tomorrow. and that is the whole evening.

Examples of what the model is allowed to return:

  • i noticed you said the word "tired" four times
  • tonight you didn't talk about work
  • what stood out was the gap between what you wanted and what you did
  • you returned to the word "ok" — three different times, three different ways

That's it. No advice. No empathy phrases. No compliments. No follow-up questions. No interpretation of meaning.

The role is borrowed almost verbatim from a forty-year-old practice in narrative therapy called outsider witnessing, formalized by Michael White and David Epston in Maps of Narrative Practice (2007). The witness's job is structurally bounded: never advise, never applaud, never interpret meaning, never offer follow-up. The witness names what resonated in the form of what the person said — and then sits with them.

The category does not have a verb for this. The verbs are: track, write, coach, chat, record, reflect-back. None of them are witness. Now one is.

Why no competitor will copy this

This is not hard to build. The whole feature is one new lib file, a few new localStorage keys, one replaced LLM system prompt, one new regex guard module, two new settings rows, and a restructured response screen. About 2,800 lines of TypeScript change in total. MeDo did the build in seven minutes.

The reason no one else has it is not technical. It is structural.

A subscription journaling app with monthly retention metrics needs the AI to talk more, not less, on the days when nothing is wrong. Calm days are when streak-driven products quietly maximize session length. A weekly evening where the AI deliberately does less than on a normal night reads as a regression on every dashboard the category lives on.

It is also philosophically backwards for them. Their pitch is the AI as coach, mentor, friend. A bounded outsider-witness role is not a brand position they can hold without rewriting their UVP.

So the moat isn't the code. It's the position the code asserts.

The calm-tech lineage

While I was building this I went back and re-read Mark Weiser, John Seely Brown, and Amber Case's calm-technology principles. Weiser and Brown wrote that "technology should communicate but doesn't need to speak" and "the right amount of technology is the minimum needed to solve the problem." Case formalized eight of these principles in 2015 and now runs a Calm Tech Certified program.

Evengood was always intuitively calm-tech. I just hadn't said it out loud. Witness Mode is the moment I'm naming the lineage. The thesis is: in 2026, an AI product that gets quieter as the user gets more vulnerable is not just a feature choice — it is a different product category from the one all my competitors are competing in.

Streak research is moving the same way. Katy Milkman's recent work argues that streak design trains people to care more about not failing than about succeeding — surveillance dressed as resilience. Evengood has a 7-day streak ribbon, but it does not show a number. It does not lecture. It just fills a dot. Witness Mode entries fill the dot the same as any other entry, with no special badge, no count, no "you witnessed three times this month" notification. That last one would be gamification, which is forbidden by the spec.

What I deliberately did not build

This list is half the work.

  • No "tonight is witness night" push notification. The reframe must be in the response, not in the prompt — pre-framing the capture screen would corrupt what the user says toward the system's expectation.
  • No streak counter as a number. Anywhere.
  • No "Witness Night" badge or progress ring.
  • No mood-trend chart, no leaderboard, no level system, no XP.
  • No popup, no toast, no red error state. Failure is silent fallback, every time. If the LLM returns something that violates any of the spec's word rules, a default line — tonight, i'm just sitting with you — is substituted on the client and the user never knows anything went wrong.
  • No login, no account, no password, no SSO. None of the previous 28 versions had auth. This one didn't add it either.
  • No Witness Mode firing on a heavy day. Quiet Mode supersedes always — a heavy-day signal must always route to Quiet, even if it happens to be Sunday. Witness is a calm-day ritual; Quiet is a heavy-day refusal. They never overlap.

The regex guards

Defense in depth. After the LLM returns its single sentence, the client runs five guards before rendering or storing:

export const FORBIDDEN_WORDS = /\b(should|must|need|ought|try|maybe|perhaps)\b/i;

export const EMPATHY_PHRASES = [
  "i hear you", "that sounds", "i'm sorry", "be kind to yourself",
  "you could", "you should", "i feel", "you feel", "must be",
];

export const ALLOWED_OPENERS = [
  "i noticed", "tonight", "what stood out was",
  "you said the word", "tonight you didn't", "you returned to",
];

export const DEFAULT_LINE = "tonight, i'm just sitting with you";

export const MAX_WORDS = 15;
Enter fullscreen mode Exit fullscreen mode

If the line exceeds 15 words, contains a forbidden word, contains an empathy phrase, doesn't start with an allowed opener, or contains CJK characters (English-only enforcement), it is silently swapped for DEFAULT_LINE. Sentry breadcrumb. No console error. No user-visible failure.

This is the part the LLM industry mostly does not do. The system prompt tells the model what the role is. The client guard refuses to render anything that violates the role even if the model drifts. Trust the model less than the spec.

What ships next

Day 10 onward, on the same spectrum:

  • A v40-ish feature called anonymous definitional ceremonies — opt-in, three users on the same day each pick the same theme word, and on Sunday evening each one sees one anonymous line from another about how that word sat with them. No content shared. No chat. No identity. Just three witnesses, one word, one Sunday. This is the long arc Witness Mode is the seed of.
  • A feature called The Wake — programmable forgetting. Reflections expire after a window the user sets unless they explicitly mark them "kept." Default: let the day go. The opposite of every product whose business model depends on the user's data accumulating forever.
  • A feature called Letter to Tomorrow — once a month, instead of a Tomorrow line, you write one to your future self. Sealed. Returned on a date you pick. No notification. No reminder. It just appears.

All three obey the same axis. Restraint as feature, not absence.

Try it

https://app-b3tuv7opfegx.appmedo.com/

Open settings. There's a new section called evening. Toggle on witness night. Pick a day. Come back that evening.

If the model returns one sentence about a word you used, and the screen sits still for four seconds, and nothing else happens, the feature worked.

That is the entire feature.

— Day 9 of 30. v29. #BuiltWithMeDo

Top comments (0)