VibeHost

Daily reports

Cron-driven HTML reports. Same URL every day. Always current.

The pattern: your data pipeline generates an HTML report (charts, tables, narrative). Deploy it to a stable VibeHost URL on a schedule. Stakeholders bookmark once; the URL always reflects the latest data.

Real-world: Dcard's growth team runs ~19+ date-stamped report apps (gr-report-20260521-k7qz, gr-report-20260520-a7k2, ...) plus rolling apps (growth-daily, dcard-kpi-2026).

Two patterns

PatternURLUse when
Rolling — same URL, latest datahttps://growth-daily.vibehost.spaceStakeholders want a bookmark that's always current
Date-stamped — new app each dayhttps://gr-report-20260521.vibehost.spaceYou need historical snapshots and want each URL to be permanent

Rolling is simpler; date-stamped gives you a permanent "this was the state on day X" archive without relying on rollback.

Rolling pattern

# Pipeline produces report-output/index.html (+ assets/) every morning
vibehost deploy ./report-output --app growth-daily

That's the whole thing. The bookmark https://growth-daily.vibehost.space always shows the latest deploy.

Wrap it in your cron / scheduler:

#!/usr/bin/env bash
# /opt/reports/daily-deploy.sh
set -euo pipefail

cd /opt/reports
export VIBEHOST_TOKEN="$(cat /run/secrets/vibehost_pat)"

# 1. Run the pipeline
python3 generate.py --date "$(date +%Y-%m-%d)" --out ./report-output

# 2. Deploy
vibehost deploy ./report-output --app growth-daily --json > /var/log/deploys/$(date +%F).json

# 3. Smoke check
URL="https://growth-daily.vibehost.space"
curl -fsS -o /dev/null "$URL"
echo "[$(date -u +%FT%TZ)] deployed: $URL" >> /var/log/deploys/history.log

systemd timer:

[Unit]
Description=Daily growth report deploy
[Timer]
OnCalendar=*-*-* 07:00:00
Persistent=true
[Install]
WantedBy=timers.target
[Unit]
Description=Daily growth report
[Service]
Type=oneshot
ExecStart=/opt/reports/daily-deploy.sh
User=reports
StandardOutput=journal
StandardError=journal

Date-stamped pattern

DATE=$(date +%Y%m%d)
APP="gr-report-$DATE"

vibehost app create "$APP"
vibehost deploy ./report-output --app "$APP"
vibehost app visibility "$APP" workspace

Each day = new app. URLs stay live indefinitely; you can reference "the report on May 21, 2026" forever by its URL.

Trade-offs:

  • ✓ Each historical snapshot has its own permanent URL.
  • ✓ Easy to A/B compare "today vs yesterday" by opening two tabs.
  • ✗ Apps accumulate. Free tier caps at 100 apps per workspace; you'll want to vibehost app delete old ones periodically (or move to the rolling pattern + use immutableUrl for archives).
  • ✗ The bookmark changes daily — stakeholders need a meta-page that lists "today's report" pointing at the latest.

Best of both:

# Rolling app — the always-current bookmark
vibehost deploy ./report-output --app growth-daily

# Date-stamped immutable URL for archives
DEPLOY_ID=$(vibehost deploy ./report-output --app growth-daily --json | jq -r '.data.id')
IMMUTABLE_URL="https://${DEPLOY_ID}.vibehost.space"

# Log the immutable URL in your wiki / sheet
echo "$(date -u +%F): $IMMUTABLE_URL" >> /opt/reports/archive-urls.tsv

Stakeholders bookmark growth-daily.vibehost.space. Anyone who wants to point at "the May 21 report specifically" links the immutable URL from your archive sheet. No per-day app proliferation.

CI variant

.github/workflows/daily-report.yml
name: Daily report
on:
  schedule:
    - cron: '0 7 * * *'   # 07:00 UTC daily
  workflow_dispatch:

jobs:
  report:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: '3.12' }
      - run: pip install -r requirements.txt
      - run: python generate.py --out ./report-output
      - run: curl -fsSL https://vibehost.com/install.sh | sh
      - env: { VIBEHOST_TOKEN: ${{ secrets.VIBEHOST_TOKEN }} }
        run: ~/.vibehost/bin/vibehost deploy ./report-output --app growth-daily

Pros over a self-hosted cron: no server to maintain; logs in GitHub Actions; can re-run any day on demand.

Cons: GitHub-hosted runners have data egress, so if your pipeline pulls 10GB of raw data daily, it's faster to run on a beefier self-hosted box.

Access control

Reports usually shouldn't be public.

# Workspace-only (everyone signed into your workspace can view)
vibehost app visibility growth-daily workspace

# Or invite specific stakeholders
vibehost app grants add-email vp@acme.com viewer --app growth-daily

# Or stakeholders outside your workspace, via Google sign-in
vibehost app grants add-email partner@vc.com viewer --app growth-daily

For external review without sign-up, use a share link.

Why not Notion / Sheets / a BI tool

SheetsNotionTableauVibeHost report
Interactive chartsLimitedNoAny JS lib
Mobile layoutBrokenPassableSlowYour HTML
Load timeSlow at scaleSlow at scaleSlowStatic HTML — instant
BrandingGoogleNotionTableauYours
Auth modelGoogle sharingNotion sharingLicense-basedVibeHost grants
Embed in emailLimitediframe-friendly
Cost$$$$$$$$

If your data team already has a BI tool, that's probably the right answer. VibeHost reports are best when you want full control over the visual (specific chart library, custom layout, brand polish) and low overhead (no server, no DB connection to manage).

See also

On this page