> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hiveku.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Workflow Recipe: Send a Weekly Team Digest

> Send your team a weekly summary of new leads, orders, and top content

Keep stakeholders in the loop without forcing them to log in. A Monday-morning email with last week's numbers, insights, and a recommendation.

<Info>
  Before you start: make sure you have tables to query (CRM contacts, orders, analytics) and a sending domain configured. See [Send Emails](/how-tos/send-emails) if you haven't set up email sending yet.
</Info>

## The Flow at a Glance

<CardGroup cols={4}>
  <Card title="1. Weekly schedule" icon="calendar-days">
    Monday 9 AM UTC
  </Card>

  <Card title="2. Query stats" icon="database">
    Leads, orders, views
  </Card>

  <Card title="3. AI summary" icon="wand-magic-sparkles">
    Friendly prose digest
  </Card>

  <Card title="4. Email team" icon="envelope">
    Send to the list
  </Card>
</CardGroup>

## Step 1: Build the Workflow

<Steps>
  <Step title="Start a new workflow">
    **Workflows** > **New Workflow**. Name it `Weekly Team Digest`.
  </Step>

  <Step title="Add a Schedule trigger">
    Click **Add Trigger** > **Schedule**. Use cron:

    ```
    cron(0 9 ? * MON *)
    ```

    Monday 9:00 AM UTC. Adjust to your team's timezone by shifting the hour.
  </Step>

  <Step title="Add database queries">
    Add three **Database Query** actions, one per metric:

    * **new\_leads** — `SELECT count(*) FROM crm_contacts WHERE created_at > now() - interval '7 days'`
    * **new\_orders** — `SELECT count(*), sum(total) as revenue FROM orders WHERE created_at > now() - interval '7 days' AND status = 'paid'`
    * **top\_content** — `SELECT title, slug, views FROM blog_posts ORDER BY views DESC LIMIT 3`

    Name each output (e.g., `new_leads`, `new_orders`, `top_content`) so you can reference them later.
  </Step>

  <Step title="Add an AI Generation action">
    Click **+ Add Action** > **AI Generation**. Prompt:

    ```
    Generate a friendly weekly digest email for an internal team.
    Tone: warm, concise, a little conversational. ~150 words.
    Include one insight and one recommendation.

    Data:
    - New leads this week: {{new_leads.count}}
    - New paid orders: {{new_orders.count}} (${{new_orders.revenue}})
    - Top blog posts:
      {{#each top_content}}- {{title}} ({{views}} views)
      {{/each}}

    Output format: subject line on line 1, blank line, then body.
    Wrap the body in HTML for email (use <p>, <h3>, <ul>).
    ```

    Name the output `digest`.
  </Step>

  <Step title="Add a Send Email action">
    Click **+ Add Action** > **Send Email**. Configure:

    * **To:** `team@yourcompany.com` (or a distribution list)
    * **From:** your verified sending address
    * **Subject:** `{{digest.subject}}`
    * **HTML Body:** `{{digest.body}}`
  </Step>

  <Step title="Save and enable">
    Save and flip the **Enabled** toggle. The first digest goes out next Monday at 9 AM UTC.
  </Step>
</Steps>

<Tip>
  Want to test sooner? Change the schedule temporarily to `rate(5 minutes)`, enable, wait one run, verify, then switch back to the weekly cron. Digest workflows are safe to test this way because they're read-only.
</Tip>

## Simple Alternative (No AI)

If you don't want AI copy, replace the AI action with a plain HTML template in the Send Email body:

```html theme={null}
<h2>Weekly digest — {{format_date(now, 'MMM D, YYYY')}}</h2>

<h3>By the numbers</h3>
<ul>
  <li><strong>New leads:</strong> {{new_leads.count}}</li>
  <li><strong>New orders:</strong> {{new_orders.count}} (${{new_orders.revenue}})</li>
</ul>

<h3>Top content</h3>
<ul>
  {{#each top_content}}<li>{{title}} — {{views}} views</li>{{/each}}
</ul>
```

Cheaper, deterministic, but less engaging than the AI version.

## Customize What's in the Digest

Every team cares about different things. Swap out queries to match. Examples:

* **New sign-ups:** `SELECT count(*) FROM users WHERE created_at > now() - interval '7 days'`
* **Active subscribers:** `SELECT count(*) FROM subscriptions WHERE status = 'active'`
* **Churn this week:** `SELECT count(*) FROM subscriptions WHERE cancelled_at > now() - interval '7 days'`
* **Support tickets:** `SELECT count(*) FROM tickets WHERE created_at > now() - interval '7 days' AND status = 'open'`
* **Top pages by views:** pulled from your analytics table

Add as many Database Query actions as you need, reference them in the AI prompt, and the digest picks them up.

## Test It

<Steps>
  <Step title="Change the trigger to every 5 minutes">
    Temporarily set the cron to `rate(5 minutes)` so you don't wait a week.
  </Step>

  <Step title="Enable and wait">
    Flip the toggle on. A run should appear in the **Runs** tab within 5 minutes.
  </Step>

  <Step title="Check your inbox">
    The digest lands at the **To:** address. Verify the numbers match what you expect, and that the AI copy reads naturally.
  </Step>

  <Step title="Switch back to weekly">
    Change the trigger back to `cron(0 9 ? * MON *)` and save. Forgetting this step means you get a digest every 5 minutes until you turn it off.
  </Step>
</Steps>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Digest not sending">
    Check the workflow's **Runs** tab. If the run shows a failure on the Send Email step, it's usually one of: the sending API key is revoked (rotate it in env vars), the From address isn't verified with your email provider, or the To address has hard-bounced in the past and is on the suppression list.
  </Accordion>

  <Accordion title="Numbers look wrong">
    Timezone is usually the culprit. `now()` on Postgres is UTC by default, which can throw off "this week" calculations if your team operates in another timezone. Specify explicitly: `WHERE created_at > now() AT TIME ZONE 'America/New_York' - interval '7 days'`.
  </Accordion>

  <Accordion title="AI copy too generic">
    Prompts that say "write a digest" get generic output. Improve by: giving a voice example ("Sound like Patrick from Basecamp's launch emails"), listing what NOT to include ("no fluff, no emoji, no corporate speak"), and providing a past digest as a reference.
  </Accordion>

  <Accordion title="Recipients aren't getting it">
    Check spam folders first. Then verify the sending domain is authenticated (SPF, DKIM, DMARC) — unauthenticated emails to corporate Gmail/Outlook often get silently dropped. See [Send Emails](/how-tos/send-emails) for domain setup.
  </Accordion>

  <Accordion title="Database query times out">
    Large tables without indexes can make the query slow. Add an index on `created_at`, or use a materialized view that's refreshed daily. Your workflow reads the view instead of the raw table.
  </Accordion>
</AccordionGroup>

## What's Next?

<CardGroup cols={2}>
  <Card title="Send Emails" icon="envelope" href="/how-tos/send-emails">
    Set up verified sending for reliable delivery
  </Card>

  <Card title="SEO Rank Alerts" icon="chart-line" href="/how-tos/workflow-seo-rank-alert">
    Add SEO changes to your digest
  </Card>

  <Card title="Workflows Basics" icon="diagram-project" href="/how-tos/workflows">
    More on triggers, actions, and runs
  </Card>
</CardGroup>
