Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.

Stevens

"The great butlers are great by virtue of their ability to inhabit their professional role and inhabit it to the utmost; they will not be shaken out by external events, however surprising, alarming or vexing."

— the great butler Stevens, in The Remains of the Day by Kazuo Ishiguro

Stevens is your personal digital butler, ever vigilant and ever helpful in managing the complexities of your digital life.

Much like his literary namesake, he takes great pride in his work, maintaining a dignified and professional demeanor while ensuring your affairs are in perfect order.

In the grand tradition of English butlers, Stevens has been designed to be both unobtrusive and indispensable. His primary duty is to learn about your life's context and provide you with daily briefs that keep you informed while saving you precious time.

Technical Architecture

⚠️ important caveat: the admin dashboard doesn't have auth! currently it just relies on security by obscurity of people not knowing the url to a private val. this is not very secure. if you fork this project and put sensitive data in a database you should think carefully about how to secure it.

Stevens has been designed with the utmost simplicity and extensibility, much like a well-organized household. At the heart of his operation lies a single "memories" table - a digital equivalent of a butler's meticulous records. This table serves as the foundation for all of Stevens' operations.

Core Components

  1. Memories Table: A freeform repository of all that Stevens deems worth remembering, much like a butler's mental catalog of household affairs.

    Schema:

    • id: String - Unique identifier for each memory (generated using nanoid)
    • date: String - Date in ISO format (YYYY-MM-DD)
    • text: String - Content of the memory (e.g., "weather forecast: High of 75, low of 60, partly cloudy")
    • createdBy: String - Source of the memory (e.g., "weather", "email")
    • createdDate: Number - Timestamp in milliseconds when the memory was created
    • tags: String - Categories for organizing memories (e.g., "weather")
  2. Importers: These are Stevens' eyes and ears in the digital world, gathering information from various sources:

    • Weather reports
    • Postal service updates
    • Ingesting messages from email or TElegram
    • And other sources of information that might be of interest to you
  3. Workflows: Stevens' carefully orchestrated routines that utilize his memories to assist you:

    • Morning briefs sent via Telegram or email
    • Responding to questions via text message

Folder layout

  • importers: cron jobs for importing data into the memories table
  • dashboard: the admin view for showing the memories notebook + visualizing imports
  • dailyBriefing: stuff related to sending a daily update via telegram
  • dbUtils: little one-off scripts for database stuff

Hiring your own Stevens

This project isn't intended to be runnable out of the box, but you can adapt it for yourself if you fork the code.

You'll need to set up some environment variables to make it run.

  • ANTHROPIC_API_KEY for LLM calls
  • You'll need to follow these instructions to make a telegram bot, and set TELEGRAM_TOKEN. You'll also need to get a TELEGRAM_CHAT_ID in order to have the bot remember chat contents.
  • For the Google Calendar integration you'll need GOOGLE_CALENDAR_ACCOUNT_ID and GOOGLE_CALENDAR_CALENDAR_ID. See these instuctions for details.

important caveat: the admin dashboard doesn't have auth! currently it just relies on security by obscurity of people not knowing the url to a private val. this is not very secure, if you put sensitive data in a database you should think carefully about how to secure it.

Overall it's a simple enough project that I encourage you to just copy the ideas and run in your own direction rather than try to use it as-is.

dailyBriefing
5/4/2025
dashboard
5/4/2025
dbUtils
5/4/2025
importers
5/4/2025
shared
5/4/2025
.cursorrules
5/4/2025
README.md
5/4/2025
backstory.ts
5/4/2025
file0-eadc3bf2-c38c-4d9c-9430-6bd08646473c.txt
5/4/2025
file1-9e4bf116-c620-4d07-a92e-9e59de52fd5d.txt
5/4/2025
file10-0d1aef7f-913b-40c4-a389-02c33eb5f43c.txt
5/4/2025
file11-6ef1f7b5-78f9-4372-9670-6471ffb4a073.txt
5/4/2025
file12-42a96063-a9b2-4c50-bd5e-6fc7ee6ca338.txt
5/4/2025
file13-a86fbf8f-c503-434c-969e-ca5b2f928a5f.txt
5/4/2025
file14-664b5f79-f215-43d7-9e2d-4a5ec563ef81.txt
5/4/2025
file15-ac820985-91af-4d8b-884b-a8c9fee2c4b3.txt
5/4/2025
file16-f20cae3d-6ca4-41fe-bded-3f9420ffdb6d.txt
5/4/2025
file17-31ed6764-5ddf-4c9e-b920-04d051351936.txt
5/4/2025
file18-63a4edd5-907d-42c0-be77-2870bf7cc9c3.txt
5/4/2025
file19-d819214f-79e5-41fa-8f32-962bc2cd258d.txt
5/4/2025
file2-cbd4ea03-b852-4734-8dd4-acc541992bab.txt
5/4/2025
file20-0c18a53e-c4e4-4fe2-97de-5c49f0050f3c.txt
5/4/2025
file21-6d7ee6de-5cdb-44b9-8332-f38587d51e3f.txt
5/4/2025
file22-72eb1497-894a-49ae-9a94-6ba1461c64c4.txt
5/4/2025
file23-8b84a5e4-0257-47ac-b545-398011ec3f46.txt
5/4/2025
file24-adbb17b0-4d0e-4900-a6e7-7597e17ddf5a.txt
5/4/2025
file25-1da99905-e1eb-4c80-a555-1930383a0d9b.txt
5/4/2025
file26-25237c09-043b-4055-8168-72512571437d.txt
5/4/2025
file27-28531020-4b33-4227-a689-f58fa9b88985.txt
5/4/2025
file28-1277fd0d-a275-4999-8d19-df98aa1dcc96.txt
5/4/2025
file29-0ed9066d-d7f1-419d-a596-2bebf617c2ca.txt
5/4/2025
file3-e3298de4-c305-4485-990c-853af4555688.txt
5/4/2025
file30-f669a616-d03e-4b65-ba9b-370dfc7fb0b3.txt
5/4/2025
file31-84c44a36-c992-4070-a545-0cb204c3fc43.txt
5/4/2025
file32-6e82c4c7-dde4-4ddf-a4f8-351c6076cc22.txt
5/4/2025
file33-995cbb08-d9b5-4526-a2f0-692e2c8caf4e.txt
5/4/2025
file34-910dec2a-9fab-446a-90d5-75f194f1e2a6.txt
5/4/2025
file35-1964b804-024f-403e-95d8-f400da1630fe.txt
5/4/2025
file36-6ca10c23-5dd7-42d4-8361-ee7c1c0db329.txt
5/4/2025
file37-f0deb9fa-ff02-4348-9ff6-61fcae56fce9.txt
5/4/2025
file38-221dc4ad-9865-4b7c-83ff-e2e813c89a6e.txt
5/4/2025
file39-e2adeaac-c737-4a9a-88d0-7f471761d0b7.txt
5/4/2025
file4-8c80c955-2843-45e2-9a26-2a6d2f863a8f.txt
5/4/2025
file40-c739b438-e2b2-4431-8cd4-9bd3feee1e4b.txt
5/4/2025
file41-d5a9c1fb-8d98-42c5-ac74-2c1e27afbd88.txt
5/4/2025
file42-7a58728b-2109-4ccb-95b6-1c5b02eb4481.txt
5/4/2025
file43-afab3f2c-ae0a-4ae0-9b0e-655fec2c5eed.txt
5/4/2025
file44-02000213-a43b-42cb-b824-a218a2f6b5d3.txt
5/4/2025
file45-db02ac87-621c-42eb-bb29-42a71f5e7d57.txt
5/4/2025
file46-004f49e2-1e01-42af-8557-d736bec2816d.txt
5/4/2025
file47-948b942a-686c-4cf8-90b8-6b888adaa569.txt
5/4/2025
file48-6d2d2c2b-71c4-4c15-979c-8417cb5a190b.txt
5/4/2025
file49-4740a06c-e1ba-4ab9-bab3-fac5aab5ebcd.txt
5/4/2025
file5-82b76f2c-6433-48d1-a1d2-5f6cf563de9a.txt
5/4/2025
file6-a3104149-df63-4591-b66f-4394e179244d.txt
5/4/2025
file7-50a23cd7-c7ab-443c-9c22-ec799dfe0fac.txt
5/4/2025
file8-5ced1126-47af-4cd6-b3f2-cb13b71465d1.txt
5/4/2025
file9-6a842d5d-ef2d-404b-91f5-b4b5cc7ed48f.txt
5/4/2025
memoryUtils.ts
5/4/2025
populateDemo.ts
5/4/2025