<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vineet Negi</title>
    <description>The latest articles on DEV Community by Vineet Negi (@vineetnegi0101).</description>
    <link>https://dev.to/vineetnegi0101</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3889849%2F28d7fb02-a338-405e-8712-73f4eeedbe9b.jpeg</url>
      <title>DEV Community: Vineet Negi</title>
      <link>https://dev.to/vineetnegi0101</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vineetnegi0101"/>
    <language>en</language>
    <item>
      <title>I built a journaling app where the database deletes your letter the day after we send it. Day 13 of 30.</title>
      <dc:creator>Vineet Negi</dc:creator>
      <pubDate>Sun, 03 May 2026 14:36:31 +0000</pubDate>
      <link>https://dev.to/vineetnegi0101/i-built-a-journaling-app-where-the-database-deletes-your-letter-the-day-after-we-send-it-day-13-of-3g3b</link>
      <guid>https://dev.to/vineetnegi0101/i-built-a-journaling-app-where-the-database-deletes-your-letter-the-day-after-we-send-it-day-13-of-3g3b</guid>
      <description>&lt;p&gt;FutureMe has 15 million letters in its database. They've been there since 2002. Some of them will be there in 2050.&lt;/p&gt;

&lt;p&gt;Evengood will have zero.&lt;/p&gt;

&lt;p&gt;This week I shipped The Quiet Letter — a feature where you write to your future self today, we email it on a date you pick, and we hard-delete the row from our database within 24 hours of sending it. The email is the only artifact. We don't keep a copy.&lt;/p&gt;

&lt;p&gt;Every feature in Evengood is built around a question: what would a journaling app look like if it weren't trying to maximize for retention?&lt;/p&gt;

&lt;h2&gt;
  
  
  What I shipped this week
&lt;/h2&gt;

&lt;p&gt;A new page at /letter. You write a letter to yourself. Voice or text. You pick a delivery date between 7 days and 5 years from now. You enter your email. You hit seal.&lt;/p&gt;

&lt;p&gt;We send a confirmation email — double opt-in, same as our Sunday pattern email. You confirm. The letter sits in our database in exactly the state you wrote it.&lt;/p&gt;

&lt;p&gt;On the date you picked, an hourly cron job picks it up and emails it to you. The subject line is &lt;em&gt;a letter you wrote on [the day you sealed it]&lt;/em&gt;. The body is the letter, verbatim, plus one footer line: &lt;em&gt;this letter has now been deleted from our server.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A daily cron job at 3am UTC hard-deletes every row whose sent_at is more than 24 hours old. Unverified drafts get purged after 7 days.&lt;/p&gt;

&lt;p&gt;One table. Four edge functions. Three new pages. One small new link on the home page that says &lt;em&gt;or write a letter to a future you →&lt;/em&gt;. That's it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we deliberately did NOT build
&lt;/h2&gt;

&lt;p&gt;No letter inbox. No list view of pending letters. There is no screen anywhere in Evengood where you can see what you've written. The only place the letter exists, between sealing and delivery, is in a Postgres row you can't read.&lt;/p&gt;

&lt;p&gt;No edit-after-seal. No "oh wait, I changed my mind." Once you hit seal, the letter is committed.&lt;/p&gt;

&lt;p&gt;No public letters wall. FutureMe has one. We deliberately do not.&lt;/p&gt;

&lt;p&gt;No reminder emails. No "you have a letter coming in 30 days!" notification. The whole point is that you forget you wrote it. The surprise IS the feature.&lt;/p&gt;

&lt;p&gt;No analytics on the body content. We don't read your letter. We just hold it long enough to deliver it.&lt;/p&gt;

&lt;p&gt;No account, no login. The verification token IS the only identity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this took a full week
&lt;/h2&gt;

&lt;p&gt;The code itself is small — maybe 500 lines across the whole feature. What took the time was the deletion architecture.&lt;/p&gt;

&lt;p&gt;Most "send me a letter in the future" features that already exist treat the database as permanent. The letter sits forever. The user data accumulates. That's the default in Postgres because nothing deletes itself.&lt;/p&gt;

&lt;p&gt;To make deletion the actual default required:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Two separate cron jobs (one for delivered letters, one for unverified drafts)&lt;/li&gt;
&lt;li&gt;A clean separation between &lt;em&gt;verified&lt;/em&gt; and &lt;em&gt;unverified&lt;/em&gt; state, so unconfirmed drafts also get purged&lt;/li&gt;
&lt;li&gt;Copy on every screen that says, in plain language, what gets deleted and when&lt;/li&gt;
&lt;li&gt;An email body that ends with the deletion confirmation, so the user has receipts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The email is the only artifact. That sentence is the whole product.&lt;/p&gt;

&lt;h2&gt;
  
  
  The weird part
&lt;/h2&gt;

&lt;p&gt;FutureMe — which I love and respect — has been operating since 2002 and has delivered over 15 million letters. The site is still standalone. It's never been integrated into a daily reflection practice. You can't write a letter on FutureMe and also do anything else with your day there.&lt;/p&gt;

&lt;p&gt;Evengood is the opposite shape. The Quiet Letter sits inside a daily reflection app, but the letter itself doesn't accumulate. It passes through. The only thing that stays is the practice.&lt;/p&gt;

&lt;p&gt;Day One can't ship this. Their pricing is justified by lifetime data retention. A feature whose primary verb is &lt;em&gt;delete&lt;/em&gt; would directly undermine the upsell.&lt;/p&gt;

&lt;p&gt;Reflectly and Stoic can't ship this. Their growth model is daily re-engagement. A feature that says &lt;em&gt;we'll be quiet for 6 months and then send you one email&lt;/em&gt; destroys their DAU.&lt;/p&gt;

&lt;p&gt;Apple Journal can't ship this. Apple doesn't run scheduled outbound email infrastructure for users.&lt;/p&gt;

&lt;p&gt;It's a feature only an app with the wrong incentives would build.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Evengood stands at Day 13
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;60-second voice or text reflection. No account. Nothing saved server-side.&lt;/li&gt;
&lt;li&gt;Witness Mode: one quiet sentence as tomorrow's invitation.&lt;/li&gt;
&lt;li&gt;A Quiet Pattern: weekly summary detecting heavier and lighter days.&lt;/li&gt;
&lt;li&gt;The Pattern by email: 52 sentences a year, one every Sunday morning. Double opt-in. One-click unsubscribe.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Quiet Letter (new this week): write to your future self. We deliver once. Then we forget.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Five features. Zero notifications. Zero streaks. Zero "you haven't journaled in 3 days."&lt;/p&gt;

&lt;p&gt;The live app is here: &lt;a href="https://app-b3tuv7opfegx.appmedo.com" rel="noopener noreferrer"&gt;https://app-b3tuv7opfegx.appmedo.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The letter compose page is here: &lt;a href="https://app-b3tuv7opfegx.appmedo.com/letter" rel="noopener noreferrer"&gt;https://app-b3tuv7opfegx.appmedo.com/letter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;17 days left. One more weekly feature to go.&lt;/p&gt;

&lt;p&gt;Built entirely on &lt;a href="https://medo.dev" rel="noopener noreferrer"&gt;MeDo&lt;/a&gt;. The whole feature shipped in a single Deep Build turn — 30 credits, ~500 lines of new code, zero edits to existing reflection or pattern code.&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>hackathon</category>
      <category>nocode</category>
      <category>writing</category>
    </item>
    <item>
      <title>I built a journaling app where the only email it sends is 52 sentences a year. Day 12 of 30.</title>
      <dc:creator>Vineet Negi</dc:creator>
      <pubDate>Sat, 02 May 2026 11:56:56 +0000</pubDate>
      <link>https://dev.to/vineetnegi0101/i-built-a-journaling-app-where-the-only-email-it-sends-is-52-sentences-a-year-day-12-of-30-49k7</link>
      <guid>https://dev.to/vineetnegi0101/i-built-a-journaling-app-where-the-only-email-it-sends-is-52-sentences-a-year-day-12-of-30-49k7</guid>
      <description>&lt;p&gt;Day 10, 11, and 12 of building Evengood — a 60-second journaling app — for the Build with MeDo $50K hackathon.&lt;/p&gt;

&lt;p&gt;If you've read &lt;a href="https://dev.to/vineetnegi0101"&gt;my previous posts&lt;/a&gt;, you know the spine of this project: every product decision is a fight to NOT add the thing every journaling app already has. No streaks. No gamification. No therapy voice. No human face in any generated image. No auto-play audio. No "you've been quiet for 3 days, are you okay?" notification.&lt;/p&gt;

&lt;p&gt;This week the fight was about email.&lt;/p&gt;

&lt;h2&gt;
  
  
  The default email behavior of every wellness app
&lt;/h2&gt;

&lt;p&gt;Open any journaling or wellness app and look at what lands in your inbox after a month. You'll find:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A weekly digest you didn't ask for.&lt;/li&gt;
&lt;li&gt;A "your week in numbers" report with charts.&lt;/li&gt;
&lt;li&gt;Streak reminders ("don't lose your 14-day streak!").&lt;/li&gt;
&lt;li&gt;"We noticed you've been quiet" check-ins.&lt;/li&gt;
&lt;li&gt;Promotional emails for the premium tier.&lt;/li&gt;
&lt;li&gt;Affiliate emails for meditation apps.&lt;/li&gt;
&lt;li&gt;Surveys, NPS prompts, "how are we doing?".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The unsubscribe link is usually 9-point grey on grey at the bottom, behind a confirmation page that asks if you're sure, with a final "are you really sure?" modal.&lt;/p&gt;

&lt;p&gt;Email is the unwell part of wellness apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I shipped this week
&lt;/h2&gt;

&lt;p&gt;Evengood now has exactly one email surface, and it's called &lt;strong&gt;The Pattern, by email&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here's the entire copy on the home screen, verbatim:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The Pattern, by email.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;One sentence about your week, every Sunday morning. Nothing else.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's the feature. That's the whole feature.&lt;/p&gt;

&lt;p&gt;If you opt in, you get one email per week. The email contains exactly one sentence — the same Pattern sentence the app generates for you on Sunday morning, the one that reads something like &lt;em&gt;"there is a rhythm of late meetings leaving you drained, followed by quiet walks that steady you."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Header in Georgia italic. Body in a single Helvetica paragraph. The app's locked palette in a soft gradient. No subject-line cleverness. No "hey [first name]". No tracking pixel. No unsubscribe footer in 9-point grey.&lt;/p&gt;

&lt;p&gt;52 sentences a year if you stay opted in for the full year. Most people won't. That's fine.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I deliberately did NOT build
&lt;/h2&gt;

&lt;p&gt;Here's the email-feature backlog I rejected this week, in the order it was tempting:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Streak reminders.&lt;/strong&gt; Easy engagement win. Rejected because shame is not a habit loop I want to build for someone closing their laptop at midnight.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. "You haven't reflected in 3 days" emails.&lt;/strong&gt; Rejected because if someone stops using the app, the app should be okay with that. Notifications-as-guilt is the entire problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Weekly digest with multiple sentences, bullet points, and charts.&lt;/strong&gt; Rejected because the Pattern is one sentence. The email is the same one sentence. Adding anything dilutes it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. A welcome email when you opt in.&lt;/strong&gt; Rejected because every app does this and nobody wants it. If you opted in, you already know what the app is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Tracking pixel for open-rate analytics.&lt;/strong&gt; Rejected because I don't need to know if you read it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. An unsubscribe confirmation page.&lt;/strong&gt; Rejected because if you click unsubscribe, you've unsubscribed. No confirmation. No "are you sure?". No survey about why.&lt;/p&gt;

&lt;p&gt;The unsubscribe link is at the top of the email in the same font size as the body. One click via signed token and you're out. No login. No "sign in to manage your preferences."&lt;/p&gt;

&lt;h2&gt;
  
  
  What I did build
&lt;/h2&gt;

&lt;p&gt;Four edge functions and one table:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;subscribe-pattern&lt;/code&gt; — validates the email, stores it as unconfirmed, generates a confirmation token, sends the one-time confirmation email.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;confirm-pattern-subscription&lt;/code&gt; — verifies the token, flips the row to confirmed. That's the only thing it does.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;send-pattern-emails&lt;/code&gt; — runs Sunday morning. Pulls confirmed subscribers. Generates each person's Pattern from the most recent week of reflections. Sends one email per subscriber.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;unsubscribe-pattern&lt;/code&gt; — verifies the unsubscribe token, marks the row unsubscribed. Token is one-click, no auth required.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The table has row-level security so the anon key can write new subscriptions but can't read anyone else's email — not even its own row after insert. The server doesn't store your reflections. It only knows your email and a device ID, in separate tables that don't join.&lt;/p&gt;

&lt;p&gt;Total bytes the server stores about you per year if you opt in: your email address, plus 52 timestamps of when emails went out. That's it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this took a full week
&lt;/h2&gt;

&lt;p&gt;It didn't take a week to build. The four edge functions are maybe 200 lines of TypeScript total. The email template is 60 lines of HTML.&lt;/p&gt;

&lt;p&gt;It took a week to NOT build the seven other features I kept wanting to add. To delete the welcome email I wrote on Tuesday. To delete the digest format I prototyped on Wednesday. To delete the &lt;em&gt;"you used the word 'tired' three times this week"&lt;/em&gt; insight email I wrote on Thursday and was very proud of.&lt;/p&gt;

&lt;p&gt;Every deleted feature was a feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Evengood stands at Day 12
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Days 1–3:&lt;/strong&gt; built the 60-second reflection loop and the watercolor keepsake.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Days 4–7:&lt;/strong&gt; shipped Pattern detection — heavier-day words in peach, lighter-day words in lavender, one quiet sentence about the rhythm of your week.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Days 8–9:&lt;/strong&gt; shipped Witness Mode (the once-a-week night the app refuses to reflect on your day).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Days 10–12:&lt;/strong&gt; shipped The Pattern, by email — one sentence, every Sunday, that's the whole feature.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;18 days remain.&lt;/p&gt;

&lt;p&gt;The list of things I'm not going to build is longer than the list of things I am.&lt;/p&gt;

&lt;p&gt;That's still the whole product.&lt;/p&gt;




&lt;p&gt;Live: &lt;a href="https://app-b3tuv7opfegx.appmedo.com" rel="noopener noreferrer"&gt;https://app-b3tuv7opfegx.appmedo.com&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  BuiltWithMeDo
&lt;/h1&gt;

</description>
      <category>showdev</category>
      <category>hackathon</category>
      <category>nocode</category>
      <category>writing</category>
    </item>
    <item>
      <title>I built a journaling app where the AI refuses to talk on Sundays. Day 8/9 of 30.</title>
      <dc:creator>Vineet Negi</dc:creator>
      <pubDate>Mon, 27 Apr 2026 03:49:08 +0000</pubDate>
      <link>https://dev.to/vineetnegi0101/i-built-a-journaling-app-where-the-ai-refuses-to-talk-on-sundays-day-89-of-30-2ohn</link>
      <guid>https://dev.to/vineetnegi0101/i-built-a-journaling-app-where-the-ai-refuses-to-talk-on-sundays-day-89-of-30-2ohn</guid>
      <description>&lt;p&gt;Day 8 and 9 of building &lt;a href="https://app-b3tuv7opfegx.appmedo.com/" rel="noopener noreferrer"&gt;Evengood&lt;/a&gt; — a 60-second journaling app — for the &lt;a href="https://medo.devpost.com/" rel="noopener noreferrer"&gt;Build with MeDo&lt;/a&gt; $50K hackathon.&lt;/p&gt;

&lt;p&gt;This one took two days because I went the wrong way first.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trap I almost fell into
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The first answer was a "Yesterday's Tomorrow" line. Surfacing yesterday's prompt above the mic. Soft. Tasteful. On-brand.&lt;/p&gt;

&lt;p&gt;I killed it.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;So Day 8 became research and Day 9 became the build.&lt;/p&gt;

&lt;h2&gt;
  
  
  The thing nobody is building
&lt;/h2&gt;

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

&lt;p&gt;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 &lt;em&gt;more output&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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: &lt;em&gt;"some days don't need reframing. be gentle with yourself tonight."&lt;/em&gt; No popup. No emoji. No analytics event. It just gets quieter.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;For Day 9, I wanted the second point on the same axis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Witness Mode
&lt;/h2&gt;

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

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Instead, the AI returns one sentence. Under fifteen words. About the &lt;em&gt;form&lt;/em&gt; 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 &lt;code&gt;come back tomorrow.&lt;/code&gt; and that is the whole evening.&lt;/p&gt;

&lt;p&gt;Examples of what the model is allowed to return:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;i noticed you said the word "tired" four times&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;tonight you didn't talk about work&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;what stood out was the gap between what you wanted and what you did&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;you returned to the word "ok" — three different times, three different ways&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's it. No advice. No empathy phrases. No compliments. No follow-up questions. No interpretation of meaning.&lt;/p&gt;

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

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

&lt;h2&gt;
  
  
  Why no competitor will copy this
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The reason no one else has it is not technical. It is structural.&lt;/p&gt;

&lt;p&gt;A subscription journaling app with monthly retention metrics needs the AI to talk &lt;em&gt;more&lt;/em&gt;, 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 &lt;em&gt;less&lt;/em&gt; than on a normal night reads as a regression on every dashboard the category lives on.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;So the moat isn't the code. It's the position the code asserts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The calm-tech lineage
&lt;/h2&gt;

&lt;p&gt;While I was building this I went back and re-read Mark Weiser, John Seely Brown, and Amber Case's &lt;a href="https://calmtech.com" rel="noopener noreferrer"&gt;calm-technology principles&lt;/a&gt;. 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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I deliberately did not build
&lt;/h2&gt;

&lt;p&gt;This list is half the work.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;li&gt;No streak counter as a number. Anywhere.&lt;/li&gt;
&lt;li&gt;No "Witness Night" badge or progress ring.&lt;/li&gt;
&lt;li&gt;No mood-trend chart, no leaderboard, no level system, no XP.&lt;/li&gt;
&lt;li&gt;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 — &lt;em&gt;tonight, i'm just sitting with you&lt;/em&gt; — is substituted on the client and the user never knows anything went wrong.&lt;/li&gt;
&lt;li&gt;No login, no account, no password, no SSO. None of the previous 28 versions had auth. This one didn't add it either.&lt;/li&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The regex guards
&lt;/h2&gt;

&lt;p&gt;Defense in depth. After the LLM returns its single sentence, the client runs five guards before rendering or storing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FORBIDDEN_WORDS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\b(&lt;/span&gt;&lt;span class="sr"&gt;should|must|need|ought|try|maybe|perhaps&lt;/span&gt;&lt;span class="se"&gt;)\b&lt;/span&gt;&lt;span class="sr"&gt;/i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;EMPATHY_PHRASES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;i hear you&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;that sounds&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;i'm sorry&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;be kind to yourself&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;you could&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;you should&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;i feel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;you feel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;must be&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ALLOWED_OPENERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;i noticed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tonight&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;what stood out was&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;you said the word&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tonight you didn't&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;you returned to&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT_LINE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tonight, i'm just sitting with you&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MAX_WORDS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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 &lt;code&gt;DEFAULT_LINE&lt;/code&gt;. Sentry breadcrumb. No console error. No user-visible failure.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  What ships next
&lt;/h2&gt;

&lt;p&gt;Day 10 onward, on the same spectrum:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A v40-ish feature called &lt;strong&gt;anonymous definitional ceremonies&lt;/strong&gt; — 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.&lt;/li&gt;
&lt;li&gt;A feature called &lt;strong&gt;The Wake&lt;/strong&gt; — 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.&lt;/li&gt;
&lt;li&gt;A feature called &lt;strong&gt;Letter to Tomorrow&lt;/strong&gt; — 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.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All three obey the same axis. Restraint as feature, not absence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://app-b3tuv7opfegx.appmedo.com/" rel="noopener noreferrer"&gt;https://app-b3tuv7opfegx.appmedo.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open settings. There's a new section called &lt;em&gt;evening&lt;/em&gt;. Toggle on &lt;code&gt;witness night&lt;/code&gt;. Pick a day. Come back that evening.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;That is the entire feature.&lt;/p&gt;

&lt;p&gt;— Day 9 of 30. v29. #BuiltWithMeDo&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>ai</category>
      <category>calmtech</category>
      <category>hackathon</category>
    </item>
    <item>
      <title>The most important feature in our AI journaling app is the one where the AI shuts up. Day 6/7 of 30. 🌿</title>
      <dc:creator>Vineet Negi</dc:creator>
      <pubDate>Sat, 25 Apr 2026 06:56:11 +0000</pubDate>
      <link>https://dev.to/vineetnegi0101/the-most-important-feature-in-our-ai-journaling-app-is-the-one-where-the-ai-shuts-up-day-7-of-30-2loh</link>
      <guid>https://dev.to/vineetnegi0101/the-most-important-feature-in-our-ai-journaling-app-is-the-one-where-the-ai-shuts-up-day-7-of-30-2loh</guid>
      <description>&lt;p&gt;Day 7 of building Evengood — a 60-second end-of-day reflection app — in public on the &lt;a href="https://medo.dev" rel="noopener noreferrer"&gt;Build with MeDo hackathon&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Today I shipped the feature I'm most proud of in seven days of building.&lt;/p&gt;

&lt;p&gt;It's the feature where the AI &lt;strong&gt;doesn't do anything&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Every AI journaling app I've ever tried has the same failure mode. You type something heavy — &lt;em&gt;"my dad died last week," "I had a panic attack on the train," "I think I'm getting fired Monday"&lt;/em&gt; — and the LLM cheerfully reframes it into a growth-mindset Hallmark card. &lt;em&gt;"What a meaningful day of self-reflection! Here are three things to be grateful for..."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It's the worst possible response. It tells the user the product wasn't built by anyone who has ever had a hard day.&lt;/p&gt;

&lt;p&gt;And it's the default behavior of every "wrap GPT in a textarea" app shipped this year.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I shipped today
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Quiet Mode.&lt;/strong&gt; A pure-function detector that runs on the user's reflection text &lt;em&gt;before&lt;/em&gt; it ever leaves the device. If the text contains signals from four categories — grief (&lt;code&gt;died&lt;/code&gt;, &lt;code&gt;funeral&lt;/code&gt;, &lt;code&gt;passed away&lt;/code&gt;), crisis (&lt;code&gt;panic attack&lt;/code&gt;, &lt;code&gt;breakdown&lt;/code&gt;, &lt;code&gt;can't breathe&lt;/code&gt;, &lt;code&gt;want to die&lt;/code&gt;), breakup/loss (&lt;code&gt;broke up&lt;/code&gt;, &lt;code&gt;divorce&lt;/code&gt;, &lt;code&gt;fired&lt;/code&gt;, &lt;code&gt;miscarriage&lt;/code&gt;, &lt;code&gt;diagnosis&lt;/code&gt;), or extreme overwhelm (&lt;code&gt;I can't do this anymore&lt;/code&gt;, &lt;code&gt;I give up&lt;/code&gt;) — the app does &lt;strong&gt;less&lt;/strong&gt;, not more.&lt;/p&gt;

&lt;p&gt;Specifically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Gemini reframe call is &lt;strong&gt;skipped entirely&lt;/strong&gt;. No API hit, no token spend, no AI rewriting your grief into a productivity tip.&lt;/li&gt;
&lt;li&gt;The text-to-speech call is skipped too.&lt;/li&gt;
&lt;li&gt;Instead, a soft acknowledgment card replaces the reframe card:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Some days don't need reframing.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Be gentle with yourself tonight. This one's saved, untouched.&lt;br&gt;&lt;br&gt;
&lt;em&gt;Quiet Mode · we noticed this might be a heavy day&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;The entry is saved to history with &lt;code&gt;isQuiet: true&lt;/code&gt;. Original text preserved exactly. No reframe text stored.&lt;/li&gt;
&lt;li&gt;The weekly Pattern detection (also a Gemini call, runs over the last 7 entries) &lt;strong&gt;excludes&lt;/strong&gt; quiet entries from its corpus. The pattern is about your rhythms, not your tragedies.&lt;/li&gt;
&lt;li&gt;Streak still counts. Quiet days are still days you showed up.&lt;/li&gt;
&lt;li&gt;For self-harm signals only, one calm line appears below the card: &lt;em&gt;"If you need to talk to someone right now: text or call 988 (US) or befrienders.org (global)."&lt;/em&gt; No emoji, no red, no popup, no urgency styling. One line.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The whole thing is invisible until it's needed. There's no banner saying "Quiet Mode protects you," no settings tour, no onboarding card. It just sits there silently and does nothing 99% of the time. The 1% it does something, it does the smallest possible thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is the most important feature
&lt;/h2&gt;

&lt;p&gt;Hackathon judges in 2026 have watched a thousand "we wrapped an LLM" demos this season. The thing that cuts through is a product that demonstrates &lt;strong&gt;judgment about when not to use the LLM&lt;/strong&gt;. Quiet Mode is that demonstration in a single 15-second beat:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Type &lt;em&gt;"my dad died last week"&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Hit share
&lt;/li&gt;
&lt;li&gt;App goes quieter, not louder&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's the demo. That's the whole pitch.&lt;/p&gt;

&lt;p&gt;It's also the thing that makes the product feel like it was made by humans who have thought about humans.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it's built
&lt;/h2&gt;

&lt;p&gt;The detector is a 40-line pure function in &lt;code&gt;src/lib/quietMode.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;detectQuietMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;quiet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;quiet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lower&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;QUIET_SIGNALS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;re&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;b&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;.*+?^${}()|[&lt;/span&gt;&lt;span class="se"&gt;\]\\]&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;$&amp;amp;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;b`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;i&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;quiet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;quiet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No LLM. No external call. Word-boundary regex against a hand-curated signal list. Runs in microseconds. Costs zero. Privacy-respecting (the matched signal is stored only in the local entry, never logged or sent anywhere).&lt;/p&gt;

&lt;p&gt;The submit handler in &lt;code&gt;App.tsx&lt;/code&gt; checks the detector before deciding what to do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;quiet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;detectQuietMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reflectionText&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quiet&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;quietModeEnabled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;saveQuietEntry&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;reflectionText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;today&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nf"&gt;showQuietAcknowledgment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// no Gemini call&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// otherwise: normal reframe flow&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reframe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;callGemini&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reflectionText&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Pattern detection edge function (Supabase) added a single filter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;entries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;allEntries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isQuiet&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the whole feature. ~80 lines of code. Half a day of work. The hardest part was deciding what &lt;em&gt;not&lt;/em&gt; to add.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I deliberately didn't build
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No popup or modal. Quiet Mode never interrupts you to congratulate itself.&lt;/li&gt;
&lt;li&gt;No emoji on the acknowledgment card. This isn't a moment for sparkles.&lt;/li&gt;
&lt;li&gt;No red or alarming colors. The card uses the same calm lavender→peach gradient as the rest of the app.&lt;/li&gt;
&lt;li&gt;No "we detected crisis keywords" language. The user-facing copy says "we noticed this might be a heavy day." One word change, completely different feeling.&lt;/li&gt;
&lt;li&gt;No analytics event when Quiet Mode triggers. We don't need to know.&lt;/li&gt;
&lt;li&gt;No required settings tour. It's on by default and you can find the toggle if you want to turn it off.&lt;/li&gt;
&lt;li&gt;No fancy ML classifier. A regex list curated by hand is more honest about what we're doing — looking for specific words — than a black-box model that might silently change behavior.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The restraint &lt;em&gt;is&lt;/em&gt; the feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's live right now
&lt;/h2&gt;

&lt;p&gt;Evengood, Day 7 of 30:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;60-second voice or text reflection (whisper for transcription)&lt;/li&gt;
&lt;li&gt;Calm AI reframe via Gemini (when not in Quiet Mode)&lt;/li&gt;
&lt;li&gt;Weekly Pattern detection — your last 7 reflections turn into one sentence&lt;/li&gt;
&lt;li&gt;Moment of the Week — one keepsake auto-pulled from the week&lt;/li&gt;
&lt;li&gt;Save-as-image keepsake (lavender/peach card with your moment)&lt;/li&gt;
&lt;li&gt;Streak counter, history view, ambient sound (rain / piano / silence)&lt;/li&gt;
&lt;li&gt;Email opt-in for the Sunday Pattern&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quiet Mode (today's ship)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No account. No password. Nothing about you leaves the device except an anonymous &lt;code&gt;device_id&lt;/code&gt; and (if you opt in) your email for the Sunday note.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Live: &lt;a href="https://app-b3tuv7opfegx.appmedo.com" rel="noopener noreferrer"&gt;https://app-b3tuv7opfegx.appmedo.com&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Built entirely on &lt;a href="https://medo.dev" rel="noopener noreferrer"&gt;@MeDo&lt;/a&gt; with Supabase + Gemini.&lt;/p&gt;

&lt;p&gt;If you build AI products: I think the next year of differentiation isn't going to be about which model you wrapped. It's going to be about whether you have the judgment to &lt;em&gt;not&lt;/em&gt; call the model.&lt;/p&gt;

&lt;p&gt;More tomorrow.&lt;/p&gt;

&lt;p&gt;— Day 7 / 30 🌿  &lt;/p&gt;

&lt;h1&gt;
  
  
  BuildInPublic #BuildWithMeDo
&lt;/h1&gt;

</description>
      <category>ai</category>
      <category>buildinpublic</category>
      <category>mentalhealth</category>
      <category>ux</category>
    </item>
    <item>
      <title>I built an app to help myself end the day without spiraling. Day 4 of 30. 🌿</title>
      <dc:creator>Vineet Negi</dc:creator>
      <pubDate>Thu, 23 Apr 2026 19:08:11 +0000</pubDate>
      <link>https://dev.to/vineetnegi0101/i-built-an-app-to-help-myself-end-the-day-without-spiraling-day-4-of-30-4pp5</link>
      <guid>https://dev.to/vineetnegi0101/i-built-an-app-to-help-myself-end-the-day-without-spiraling-day-4-of-30-4pp5</guid>
      <description>&lt;h2&gt;
  
  
  11:47 PM. Again.
&lt;/h2&gt;

&lt;p&gt;I was lying in bed, staring at the ceiling, running the day on loop.&lt;/p&gt;

&lt;p&gt;The meeting I should’ve pushed back on. The message I left on read. The three tabs of “I’ll think about this later” that quietly piled up.&lt;/p&gt;

&lt;p&gt;I’ve tried the things. Journaling apps that felt like homework. Meditation timers that felt like a second job. Notion templates with seventeen sections I abandoned by day three.&lt;/p&gt;

&lt;p&gt;What I actually wanted was something that took &lt;strong&gt;60 seconds&lt;/strong&gt;, left me with a small, quiet gift, and then got out of the way.&lt;/p&gt;

&lt;p&gt;So on Day 1 of the MeDo hackathon, I decided to just build the thing.&lt;/p&gt;

&lt;p&gt;The result is &lt;strong&gt;Evengood&lt;/strong&gt;. It’s live here: &lt;a href="https://app-b3tuv7opfegx.appmedo.com/" rel="noopener noreferrer"&gt;https://app-b3tuv7opfegx.appmedo.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the story of the four days it took to go from “60-second voice note” to “a week that remembers you.” Including the three disasters that almost made me ship nothing.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Evengood actually does
&lt;/h2&gt;

&lt;p&gt;One screen. A soft lavender-to-peach gradient. One prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How was today?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You tap once. You talk for up to 60 seconds — or type instead if you’re somewhere quiet.&lt;/p&gt;

&lt;p&gt;Then Evengood does four small things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It &lt;strong&gt;holds space&lt;/strong&gt; for a few seconds (now with a gentle “writing your tomorrow…” line, more on that in a minute).&lt;/li&gt;
&lt;li&gt;It plays back a &lt;strong&gt;calming Tomorrow prompt&lt;/strong&gt; in a soft TTS voice — not advice, not a to-do, just one small thing to notice tomorrow. Things like &lt;em&gt;“Notice the way the steam rises and curls from a warm cup.”&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;It paints you a &lt;strong&gt;watercolor keepsake&lt;/strong&gt; of the feeling behind your day using the Kling image plugin.&lt;/li&gt;
&lt;li&gt;It drops a dot into a 7-day streak ribbon, so you come back tomorrow.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No login. No account. Nothing saved to a server. Just your browser, your 60 seconds, and one tiny thing to notice tomorrow.&lt;/p&gt;




&lt;h2&gt;
  
  
  The stack (and why each piece)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Piece&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;th&gt;Why I picked it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MeDo&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full-stack scaffolding, routing, deploy&lt;/td&gt;
&lt;td&gt;I didn’t want to spend day 1 on Vite config&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Speech-to-Text plugin&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Turns the 60-sec voice note into text&lt;/td&gt;
&lt;td&gt;Whisper-grade, no API key juggling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;LLM (2 calls)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;One for the Tomorrow prompt, one for the theme word&lt;/td&gt;
&lt;td&gt;Split keeps each call small + retries cheap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Text-to-Speech plugin&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Plays the Tomorrow prompt back in a soft voice&lt;/td&gt;
&lt;td&gt;The voice is the whole feel of the app&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Kling image plugin&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Watercolor keepsake card&lt;/td&gt;
&lt;td&gt;Softer than DALL·E, fits the palette&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tailwind + Playfair Display + Inter&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The visual calm&lt;/td&gt;
&lt;td&gt;Serifs make reflection feel like reflection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;localStorage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Keeps reflections + keepsakes, keyed by ISO date&lt;/td&gt;
&lt;td&gt;No DB, no account — your week lives in your browser&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Total backend code I wrote myself: &lt;strong&gt;zero lines.&lt;/strong&gt; MeDo’s agent wired the plugin calls and I focused on the feel.&lt;/p&gt;




&lt;h2&gt;
  
  
  Three disasters
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Disaster 1: The silent 15 seconds
&lt;/h3&gt;

&lt;p&gt;Day 2, first real user test. I handed my phone to a friend, she talked for 45 seconds about her day, tapped submit…&lt;/p&gt;

&lt;p&gt;and the screen went &lt;strong&gt;silent.&lt;/strong&gt; A soft spinner. Ten seconds. Twelve seconds. Fifteen seconds.&lt;/p&gt;

&lt;p&gt;She looked up and said: &lt;em&gt;“Did it break?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It hadn’t. The TTS + watercolor were cooking in the background. But in a reflection app, silence reads as “we lost your thoughts.” That’s the exact opposite of what I was trying to build.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Lesson: in a calm app, every second of silence has to &lt;em&gt;feel intentional&lt;/em&gt;. Silence without a cue reads as a bug, not peace.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Fix (shipped Day 4):&lt;/strong&gt; During the wait, the screen now says &lt;em&gt;“writing your tomorrow…”&lt;/em&gt; in soft Playfair italic, with &lt;em&gt;“(usually about 10 seconds)”&lt;/em&gt; underneath at 60% opacity. Same wait. Completely different feeling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Disaster 2: The keepsake that spoke Mandarin
&lt;/h3&gt;

&lt;p&gt;Day 3. Everything was working. I was happy.&lt;/p&gt;

&lt;p&gt;Then a fellow hackathon builder flagged a bug: the LLM was occasionally slipping Chinese characters into the keepsake text for English input.&lt;/p&gt;

&lt;p&gt;The model I’m using has a multilingual base. Every few calls, it would decide today was a Mandarin day.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Lesson: multilingual models don’t need you to &lt;em&gt;ask&lt;/em&gt; for another language — they just vibe into one. You have to actively clamp the output.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Fix (shipped Day 4):&lt;/strong&gt; A strict English-only system instruction + a CJK-unicode validator that re-generates the response once if any non-Latin script is detected. Logs the retry to the console so I can see how often it happens.&lt;/p&gt;

&lt;h3&gt;
  
  
  Disaster 3: The streak that lied
&lt;/h3&gt;

&lt;p&gt;The 7-day streak ribbon under YOUR WEEK was gorgeous. Seven little dots. One pulsing for today.&lt;/p&gt;

&lt;p&gt;And it did absolutely nothing.&lt;/p&gt;

&lt;p&gt;Tap a past dot? Nothing. Hover? Nothing. It was pure decoration. Which, in an app whose entire emotional promise is “the week is building you something,” felt like a lie.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Lesson: if you’re going to visualize continuity, the visualization has to be a door, not a sticker.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Fix (shipped Day 4):&lt;/strong&gt; Tap any filled dot → the reflection text from that day slides in on top, the Keepsake Card (tomorrow prompt + watercolor) below, little back arrow to return. Every reflection is persisted in localStorage keyed by ISO date, so the week actually accumulates. The streak finally does what it was pretending to do.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I learned about building small things
&lt;/h2&gt;

&lt;p&gt;A journaling app is mostly &lt;em&gt;feel&lt;/em&gt;. The LLM does 5% of the work. The other 95% is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The soft gradient.&lt;/li&gt;
&lt;li&gt;The serif on the prompt.&lt;/li&gt;
&lt;li&gt;The breathing animation on the spinner.&lt;/li&gt;
&lt;li&gt;The fact that nothing is saved to a server.&lt;/li&gt;
&lt;li&gt;The one small thing to notice tomorrow, instead of a list of things to fix.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I could have spent Day 4 adding “emotional trends” charts, or a share-as-long-image export, or an AI coach tab. All impressive. None of it would’ve fixed the three things that actually made the app feel broken.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 The best Day-4 features are usually the ones that make Day 1 finally feel finished.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Try it (60 seconds, no account)
&lt;/h2&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://app-b3tuv7opfegx.appmedo.com/" rel="noopener noreferrer"&gt;https://app-b3tuv7opfegx.appmedo.com/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Talk or type for a minute about your day. You’ll get back one small thing to notice tomorrow, a watercolor of the feeling behind it, and a dot on your week.&lt;/p&gt;

&lt;p&gt;If it leaves you slightly calmer than it found you, I’ve done my job.&lt;/p&gt;

&lt;p&gt;And if you’re also building something small for the MeDo hackathon — drop your link in the comments, I’ll genuinely try it. The builders on this one are absurdly good.&lt;/p&gt;

&lt;p&gt;🌿&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Built with &lt;a href="https://medo.dev" rel="noopener noreferrer"&gt;MeDo&lt;/a&gt;. Day 4 of 30.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>mentalhealth</category>
      <category>productivity</category>
      <category>showdev</category>
    </item>
    <item>
      <title>I built a 60-second reflection app that paints you a watercolor keepsake. Days 2 + 3 of the $50K MeDo hackathon.</title>
      <dc:creator>Vineet Negi</dc:creator>
      <pubDate>Thu, 23 Apr 2026 04:40:09 +0000</pubDate>
      <link>https://dev.to/vineetnegi0101/i-built-a-60-second-reflection-app-that-paints-you-a-watercolor-keepsake-day-2-of-the-50k-medo-5065</link>
      <guid>https://dev.to/vineetnegi0101/i-built-a-60-second-reflection-app-that-paints-you-a-watercolor-keepsake-day-2-of-the-50k-medo-5065</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;I spent the weekend building &lt;strong&gt;Evengood&lt;/strong&gt; — a 60-second end-of-day reflection app — on &lt;a href="https://medo.dev" rel="noopener noreferrer"&gt;MeDo&lt;/a&gt;, a no-code AI platform. You talk or type how your day was, it plays back a calming Tomorrow prompt in a soft voice, and it paints you a watercolor keepsake from the feeling behind your words.&lt;/p&gt;

&lt;p&gt;Live: &lt;a href="https://app-b3tuv7opfegx.appmedo.com/" rel="noopener noreferrer"&gt;https://app-b3tuv7opfegx.appmedo.com/&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The idea
&lt;/h2&gt;

&lt;p&gt;Every journaling app I've tried feels like homework. Notebooks full of dashboards, streaks I fail at, prompts I resent. I wanted the opposite: a tiny ritual that takes under a minute, leaves you with something beautiful, and then gets out of the way. No login. Nothing saved on a server. Come back tomorrow if you want to.&lt;/p&gt;

&lt;p&gt;The aesthetic target: a soft lavender-to-peach gradient, Playfair Display for the headings, deep-indigo text, a single breathing microphone circle. Feel, not features.&lt;/p&gt;

&lt;h2&gt;
  
  
  The MeDo stack
&lt;/h2&gt;

&lt;p&gt;For non-builders reading this: MeDo is a chat-driven platform where you describe the app you want and it generates the full React + Vite + Tailwind codebase, wires in plugins, and hosts it. You iterate by sending follow-up prompts. It's not a template tool — it writes real code you can inspect and edit.&lt;/p&gt;

&lt;p&gt;Evengood uses four MeDo plugins:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Speech-to-Text&lt;/strong&gt; — captures the 60-second reflection when the user chooses to talk&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Large Language Model&lt;/strong&gt; (x2) — one call generates the Tomorrow prompt, a second call extracts a one-word "theme" like &lt;em&gt;peaceful&lt;/em&gt;, &lt;em&gt;proud&lt;/em&gt;, &lt;em&gt;tender&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text-to-Speech&lt;/strong&gt; — reads the Tomorrow prompt back in a calm voice&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kling (image generation)&lt;/strong&gt; — paints the watercolor keepsake card using the theme word&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The keepsake card — the part I'm proudest of
&lt;/h2&gt;

&lt;p&gt;The theme word drives a Kling image prompt like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;soft dreamy watercolor, lavender to peach gradient, abstract calm feeling of peaceful, no text, no people, serene, ethereal, minimal&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For my test reflection about finishing hard work and noticing the light through a kitchen window, the LLM picked &lt;em&gt;peaceful&lt;/em&gt; and Kling painted me a field of lavender dissolving into a peach watercolor sky. The Tomorrow line ("Notice the way the air feels when you first open a window.") overlays in white serif. It's the kind of image you'd actually screenshot and keep.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bugs, and how I debugged them without writing code
&lt;/h2&gt;

&lt;p&gt;On v8, the Kling image silently fell back to a CSS gradient every time. Turned out the timeout was 15 seconds; Kling typically needs 20–40. I sent MeDo a fix prompt: &lt;em&gt;bump the timeout to 45 seconds and add console.log statements before the call, on success, and on error&lt;/em&gt;. Next build, the logs made the whole flow observable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[keepsake] calling Kling with prompt: soft dreamy watercolor, lavender to peach gradient, abstract calm feeling of peaceful...
[keepsake] Kling returned image url: https://...keepsake-ea752a84-....jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;22 seconds end-to-end, and the watercolor rendered. That's the pattern I keep returning to on MeDo: &lt;em&gt;ask for observability first, then debug.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Three things I learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Feel is a spec.&lt;/strong&gt; The best prompt I wrote wasn't a feature list — it was a paragraph describing how the app should feel when you use it. MeDo builds noticeably better when you give it emotional direction alongside technical constraints.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persist client-side, aggressively.&lt;/strong&gt; No-account apps live or die by &lt;code&gt;localStorage&lt;/code&gt;. The 7-day streak and ambient soundscape choice both persist without a backend, and that keeps the app feeling lightweight.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One bundled prompt beats five small ones.&lt;/strong&gt; I grouped my v8 changes (keepsake card + streak + soundscape) into a single well-scoped prompt with an explicit "DO NOT" list, and the output was dramatically cleaner than when I'd tried incremental changes.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Day 3 update — three things actually shipped
&lt;/h2&gt;

&lt;p&gt;Between Day 2 and Day 3 I did one tight fix pass on MeDo (30 credits, one prompt, 38 tasks) and all three v8 rough edges are now solid:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Kling watercolor keepsake works end-to-end.&lt;/strong&gt; Timeout bumped from 15s to 45s, console logs wrapped around the call. The image is now generated from the single theme word inferred from your reflection (calm, peaceful, hopeful, grateful…) and renders in ~22 seconds. No more gradient fallback.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Ambient soundscape toggle is wired.&lt;/strong&gt; A small pill above the microphone lets you switch between Silent, Rain, and Soft piano. Choice persists in localStorage so it carries over between sessions. Audio fades in when the reflection starts and fades out on Tomorrow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Streak tracker is real.&lt;/strong&gt; Seven dots along the bottom of the keepsake card, today filled in deep indigo, past days filled in lavender, future days faded. Powered by a tiny localStorage array of ISO dates — no account, no server, still works.&lt;/p&gt;

&lt;p&gt;The meta-lesson: on a no-code platform, &lt;strong&gt;observability is the superpower&lt;/strong&gt;. One prompt asking for console.log before, on-success, and on-error made the Kling bug diagnosable in a single build cycle. I keep returning to that pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://app-b3tuv7opfegx.appmedo.com/" rel="noopener noreferrer"&gt;https://app-b3tuv7opfegx.appmedo.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It takes 60 seconds. If it leaves you with a watercolor you actually want to keep, I'd love to hear about it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built for the &lt;a href="https://medo.devpost.com" rel="noopener noreferrer"&gt;Build with MeDo Hackathon&lt;/a&gt; — $50K in prizes, submissions open until May 20, 2026.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>ai</category>
      <category>nocode</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I joined a $50K no-code hackathon with zero coding experience. Day 1.</title>
      <dc:creator>Vineet Negi</dc:creator>
      <pubDate>Tue, 21 Apr 2026 01:01:39 +0000</pubDate>
      <link>https://dev.to/vineetnegi0101/i-joined-a-50k-no-code-hackathon-with-zero-coding-experience-day-1-ed6</link>
      <guid>https://dev.to/vineetnegi0101/i-joined-a-50k-no-code-hackathon-with-zero-coding-experience-day-1-ed6</guid>
      <description>&lt;p&gt;So here's what I did today.&lt;/p&gt;

&lt;p&gt;I signed up for the Build with MeDo Hackathon on Devpost. $50,000 in prizes. 30 days. 2,343 people already registered before me. And my coding experience is basically: I once changed the background color on a Wordpress site and felt like a hacker for a week.&lt;/p&gt;

&lt;p&gt;The twist: MeDo is a no-code platform. You describe what you want in plain English, an AI builds the app. So technically you don't need to know how to code. In theory.&lt;/p&gt;

&lt;p&gt;I figured the smartest play wasn't to compete for the grand prize — 2,000+ developers with years of experience are going after that. There's also a Creative Content Award (10 winners × $500) for blog posts and videos about your project. And a Community Choice Award (5 × $500) voted on by the MeDo Discord. Those are way more winnable if you show up consistently and actually document the journey.&lt;/p&gt;

&lt;p&gt;So I'm documenting the journey. That's what this post is.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'm building
&lt;/h2&gt;

&lt;p&gt;It's called &lt;strong&gt;Evengood&lt;/strong&gt;. The pitch is one sentence: &lt;em&gt;end every day on an even, good note.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You open it at night, spend 60 seconds typing how your day went — the rough parts, the wins, whatever. Evengood gives you back a short, calm 2-minute audio reflection that actually mentions what you said, names one real win, and gives you one clear thing to carry into tomorrow. It saves a one-line journal entry automatically. Over a month you end up with a readable year-in-sentences thing.&lt;/p&gt;

&lt;p&gt;I picked this because (a) I'd actually use it, (b) it's small enough to be buildable in 30 days of evening work, and (c) the story is easier to tell than "I built another todo app."&lt;/p&gt;

&lt;h2&gt;
  
  
  The plan
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Week 1: post publicly every day (you're reading day 1), set up the scaffolding in MeDo, don't over-scope.&lt;/li&gt;
&lt;li&gt;Week 2: build the three core features. One per day. No heroics.&lt;/li&gt;
&lt;li&gt;Week 3: polish, deploy, record a demo video.&lt;/li&gt;
&lt;li&gt;Week 4: write the retrospective, rally the community, submit on Devpost.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why I'm writing this on day zero of code
&lt;/h2&gt;

&lt;p&gt;Because by the end of 30 days this is either a story about a no-code beginner who shipped a real app and won some money, or it's a story about a no-code beginner who tried and flamed out on day 11. Both are useful. Both are worth writing down.&lt;/p&gt;

&lt;p&gt;If you want to watch what happens, I'll be posting on X too (I won't link it here to keep this post tag-compliant — you can find me from my profile). Or just follow along on DEV.&lt;/p&gt;

&lt;p&gt;Back tomorrow with day 2.&lt;/p&gt;

&lt;h1&gt;
  
  
  BuiltWithMeDo
&lt;/h1&gt;

</description>
      <category>buildinpublic</category>
      <category>nocode</category>
      <category>ai</category>
      <category>hackathon</category>
    </item>
  </channel>
</rss>
