What should a weekly owner report actually include?
Two report messages from a system in production, field by field, in the order they print. The order is the design, and so is everything the message leaves out.
By Eugene Romanov·Published
The short answer
A weekly owner report is a short list printed in a fixed order: one headline figure, what arrived since the last one, what has not moved, what the system tried and failed at, and the errors last. In the production system these fields come from, every line is conditional. A count of zero prints nothing, the error list is capped at five with the rest counted, and the report gets shorter on a quiet week.
SHT-02What drives the number
The field order of a real daily report, top to bottom
lib/followups/digest.ts builds one message and the order never varies. A heading with the date. How many messages went out, and whether the daily cap was reached. A warning line, but only when the throttle actually moved. The count of real replies. Then opt-outs, bounces, automatic out-of-office replies, and leads the engine marked dead by itself. After the counts come the blocks: replies awaiting action, queue health, and a subject-line leaderboard. Errors go last. None of that ordering is accidental. The figure you act on is at the top, the diagnostics sit in the middle, and the section that will ruin your morning is at the bottom, where you will still read it and will not read it first.
A zero prints nothing, and that is the most important rule in the file
Every count line in that digest is wrapped in a condition. Opt-outs appear only if there were opt-outs. Bounces only if there were bounces. The throttle warning only when the cap really moved. A report that prints a zero next to every label every day trains you to skim it, and a reader who skims will skim on the day the number is not zero. The error section follows the same rule twice over: absent entirely when nothing failed, and capped at five entries with the remainder counted when something did. Length carries information here. A short message means a quiet day, and you can read that from the shape before you read a word of it.
The weekly money report, and the two places it counts from
app/api/cron/weekly-revenue/route.ts prints a monthly recurring total rounded to whole dollars, the number of active subscriptions with trials shown inside that count rather than beside it, what arrived in the last seven days, and a breakdown by plan sorted so the largest contribution is first. Two decisions in it are worth copying. It reads each subscription's price live from the payment provider instead of a table of plan identifiers, so somebody on an older or custom price is counted at what they actually pay rather than mapped onto the current plan. And it counts new signups from the database as well, because a signup that has not opened a subscription yet is invisible to a provider-only count, and one was missed exactly that way.
The report has to be a pure function before it is a message
buildDigestMessage in lib/followups/digest.ts takes a plain object of counts and returns a string. No database, no chat client, no request context. That is not tidiness for its own sake. It means the wording, the suppression rules and the ordering can be exercised against made-up numbers without a mail server, a scheduler or a live account, so the part most likely to be wrong is the part easiest to check. If you are commissioning reporting, ask where the message body is assembled and whether it can be run on invented input. If the only way to see the report is to wait until Monday and hope, the wording will never improve, because nobody can afford a week per correction.
Thirteen endpoints existed, five run on a clock, and the eight that stopped are the lesson
Thirteen job directories sit under app/api/cron/ in that system, and five paths are actually scheduled: four in vercel.json and one added by a GitHub Actions workflow. The other eight came off the schedule on 2026-05-15, written up in docs/paused-crons-2026-05-15.md, because between them they were delivering six to eight messages a weekday into one chat, which in that system is this studio's own founder chat and not any client's. No code was deleted; a line pasted back re-enables any of them. For your own template the useful part is not that reports get switched off. It is what survived: a job lives when it does work rather than describes it, or when it reaches somebody who has to act that day.
What to leave out, and when to commission nothing
Leave out anything you cannot act on the day you read it. Leave out any figure typed in one place and printed in another, because a number written twice will disagree with itself eventually, and which copy reaches you is decided by whichever code happened to run last. Leave out ratios computed over small counts, since a ratio hides how small the counts were. And do not commission reporting while half the work still lives in a spreadsheet, because a summary built over half the jobs reads exactly like one built over all of them, which turns an honest uncertainty into a confident wrong figure. Where the records already sit in one system this is a retainer rather than a build: Maintain at $300 a month, Grow at $750, Scale at $1,500.
SHT-03General notes
The questions people actually ask.
- N01What should a weekly owner report include?
- One headline figure, what arrived since the last report, what has not moved with the oldest first, what the system tried and failed at, and a comparison with the week before. Print them in that order every week, because a fixed order is what lets somebody read the report in ten seconds instead of parsing it.
- N02How long should a weekly report be?
- Shorter on a quiet week than on a busy one, which only happens if lines are conditional. In the digest described here a count of zero prints no line at all, so the length of the message is itself a signal. A report that is the same length every week is a form, and people stop reading forms.
- N03Where should the numbers in a report come from?
- Recomputed from the records at send time, never from a figure typed somewhere else. The weekly money job here reads each subscription's price live from the payment provider rather than from a table of plan identifiers, so somebody paying a legacy price is reported at the price they actually pay rather than at whatever that table would have said.
- N04Should errors be in the owner report or in a log?
- In the report, and last. A log is somewhere you go on purpose, and going on purpose lasts about a fortnight. Putting failures at the bottom of a message you already read means you see them without them crowding out the number you opened the message for, and capping the list at five keeps one bad night from burying everything else.
- N05Which lines belong in the daily message and which in the weekly one?
- Split them by how fast a line goes stale rather than by how important it feels. What went out today and what failed today is worthless by tomorrow morning and belongs in the daily message, and anything you can only read by comparing it with last week, money and totals, belongs in the weekly one. A line that appears in both teaches you to skim the second copy, and skimming is not a habit that stays confined to one line.
- N06How do I find out whether a report is still being read?
- Take it off the schedule and see whether anybody asks for it. That is the cheapest test available, and it is safe as long as the code stays in place, so the job comes back by pasting one line into the schedule, which is exactly how the paused jobs in the system described here were left. Write the recipient at the top of the template too, before the first line of content: a message with no named reader is a message nobody is responsible for opening.
- N07Should the weekly report contain a chart?
- Not inside the message. A chart is for exploring something you already suspect, and the weekly message exists to tell you whether to suspect anything at all. Text lines survive a lock screen, a forward to your accountant, and a search of your own chat history months later, and an image does none of those. Keep the chart on a page you open deliberately, on the few occasions the message has given you a reason to.
SHT-04Evidence
The systems this argument comes from.
Everything above was learned building these. Each sheet names the business, what the trade's arithmetic actually is, and the file in the repository that proves the capability. No client revenue and no client's customers appear on any of them.

