A first demo for a calm memory journal.
The prototype now includes a small built-in backend for private accounts and saved diary entries.
- Audio-first warm-friend check-in UI
- Optional local Chatterbox TTS voice for more natural open-source speech
- Browser demo live voice mode with speech recognition/synthesis where supported
- Green meditative design with a breathing canvas background
- Drafts up to five memory lines from the real conversation transcript
- Creates accounts, logs users in with HttpOnly cookie sessions, and saves entries per user
- Sends a six-digit email code before creating password accounts
- Supports Google sign-in when OAuth credentials are configured
- Lets signed-out visitors use the full diary UI with temporary in-memory entries
- Stores diary data in a local JSON database
- Shows the selected date across five years
- Adds sample same-date memories for demoing comparison
- Light and soft dark themes
Run the local web service:
npm startThen open http://127.0.0.1:3000.
To compare OpenAI Realtime voices directly, open
http://127.0.0.1:3000/voice-lab.html. The lab lets you choose a Realtime
voice, tune the personality notes, and start a live WebRTC voice test before
changing the main diary flow. It also shows a local mic meter so phone testing
can confirm that the browser is actually receiving microphone input.
By default the app writes its database to data/this-day-then-db.json. To use a
different database path, set:
DIARY_DB_PATH=/absolute/path/diary-db.json npm startCreate a Google OAuth client for a web application, then set these environment variables:
GOOGLE_CLIENT_ID=your-client-id
GOOGLE_CLIENT_SECRET=your-client-secret
GOOGLE_REDIRECT_URI=https://thisdaythen.com/api/auth/google/callback
CANONICAL_HOST=thisdaythen.comAdd the same redirect URI in Google Cloud Console. If GOOGLE_REDIRECT_URI is
not set, the server uses the current request origin plus
/api/auth/google/callback.
CANONICAL_HOST keeps www.thisdaythen.com and thisdaythen.com on the same
host so OAuth state cookies survive the Google redirect.
Password registration now sends a six-digit verification code before the account is created. Production email delivery uses Resend:
RESEND_API_KEY=your-resend-api-key
EMAIL_FROM="This Day Then <hello@thisdaythen.com>"EMAIL_FROM must be a sender address or domain verified in Resend. For local
testing only, set EMAIL_DEV_MODE=1; the server will print and return the code
instead of sending an email.
When OPENAI_API_KEY is configured, voice chat uses OpenAI Realtime WebRTC so
one tap opens a live, hands-free conversation. The app also uses the Responses
API with structured output to draft one to five lines from the user's transcript
without adding unstated details or filler. The app keeps OpenAI speech generation with the
fable voice as a fallback path when VOICE_MODE=openai-tts is set.
Useful OpenAI voice knobs:
OPENAI_API_KEY- enables OpenAI voice generationVOICE_MODE=openai-realtime- prefer live voice chat, the default when a key is configuredOPENAI_REALTIME_MODEL=gpt-realtime- model used for live voice chatOPENAI_REALTIME_VOICE=alloy- selected Realtime voiceOPENAI_SUMMARY_MODEL=gpt-5.5- primary model for memory-line summariesOPENAI_SUMMARY_FALLBACK_MODEL=gpt-4.1-mini- fallback if the primary summary model is unavailableVOICE_MODE=openai-tts- use Fable speech generation instead of live Realtime chatOPENAI_TTS_MODEL=gpt-4o-mini-tts- speech generation modelOPENAI_TTS_VOICE=fable- selected voice
Realtime voices are alloy, ash, ballad, coral, echo, sage,
shimmer, verse, marin, and cedar; marin and cedar are the best
starting points for natural quality. fable is available in the Text-to-Speech
fallback, not in Realtime live chat.
For open-source TTS, run a local Chatterbox service in one terminal:
python3 -m venv .venv-tts
. .venv-tts/bin/activate
pip install chatterbox-tts
python local_tts/chatterbox_server.pyThen run the app with the local TTS bridge enabled:
npm run start:local-ttsThe app will call POST /api/local-tts, which forwards text to
http://127.0.0.1:7861/synthesize and plays the returned WAV audio. If the local
model is unavailable, the browser voice remains as a fallback.
To clone or guide a specific voice, point Chatterbox at a short reference clip you have permission to use:
CHATTERBOX_REFERENCE_AUDIO=/absolute/path/reference.wav python local_tts/chatterbox_server.pyUseful knobs:
LOCAL_TTS_URL- local synthesis endpoint, defaults instart:local-ttsto ChatterboxVOICE_MODE=local-tts- force local TTS when Chatterbox is configuredLOCAL_TTS_EXAGGERATION=0.45- emotion intensity sent to ChatterboxCHATTERBOX_DEVICE=cuda|mps|cpu- force the model device