GrowCast is a Next.js web app for publishing a live garden dashboard with an optional gallery and a protected panel.
GrowCast lets you share your grow in real time. Visitors can view the live stream, some details and media (setup/snapshots/timelapse). Admin users can update all metadata from a web dashboard.
- Live stream embed on the homepage (RTSP camera via MediaMTX (RTSP -> HLS))
- Public grow dashboard
- Markdown support for notes/setup text
- Optional gallery page for snapshots + timelapse video (GrowCast Timelapse plugin)
To see a live demo, visit my instance. The official project site is growcast.0xmarcel.com.
- npm
- Node.js 20 LTS or newer
- An IP camera with RTSP support
- MediaMTX server (to convert RTSP input into HLS output)
- Cloudflare account +
cloudflared(for encrypted public access)
- Clone the repository.
- Install dependencies:
npm install- Create admin credentials:
npm run setup:adminThis script creates .env.local with required admin variables.
Required for admin login:
ADMIN_USERNAME=your_admin_username
ADMIN_PASSWORD_HASH=scrypt$...$...
ADMIN_SESSION_SECRET=at_least_32_chars_random_secretnpm run devOpen http://localhost:3000.
npm run build
npm run startapp/
page.tsx # Public dashboard
gallery/page.tsx # Gallery page
admin/page.tsx # Admin login + dashboard
admin/logout/route.ts # Logout endpoint
api/snapshots/[filename]/ # Serves snapshot images
api/timelapse/[filename]/ # Serves timelapse video
components/
site-header.tsx
site-footer.tsx
snapshot-gallery.tsx
timelapse-player.tsx
lib/
db.ts # JSON data store + types
admin-auth.ts # Auth/session/rate-limit logic
extension-status.ts # Timelapse plugin file discovery
getSetupImages.ts # Reads public/setup images
scripts/
admin-creator.mjs # Interactive .env.local generator
data/
current-grow.json # Persisted grow data
public/
setup/ # Optional setup photos shown on homepage
yourPictures/ # Optional user uploaded pictures shown on dashboard
extensions/
GrowCast-Timelapse/ # Optional plugin folder
My App doesnt need much configuration to get started, but i have tested some optimizations for MediaMTX. The default MediaMTX configuration caused issues on iOS devices and significant stuttering on some Windows systems. Below i have included how i configured my MediaMTX server.
hlsAlwaysRemux: true
hlsVariant: fmp4
hlsSegmentCount: 7
hlsSegmentDuration: 1s
hlsPartDuration: 200ms
hlsSegmentMaxSize: 50M
hlsDirectory: ''
hlsMuxerCloseAfter: 60s
paths:
growcam:
source: rtsp://USER:PASSWORD@IP.OF.YOUR.CAM/stream1
sourceProtocol: tcp
sourceOnDemand: no
If you still have issues, make sure your camera is not set to a high frame rate, (i set mine to 15fps, but feel free to try other values).
GrowCast expects a browser-playable stream URL in the admin dashboard. Since some cameras expose RTSP, use MediaMTX to convert RTSP to HLS:
- Configure your RTSP camera (RTSP source looks somewhat like this:
rtsp://<camera-ip>:554/<path>). - Run MediaMTX and create a path that ingests RTSP.
- Use MediaMTX HLS output URL as the stream URL in GrowCast admin (
/admin), for example:http://<mediamtx-host>:8888/<path>/index.m3u8
- Save in GrowCast settings.
This app uses Next.js route handlers and local filesystem storage.
- Primary source:
data/current-grow.json - Read/write logic:
lib/db.ts - If file is missing, default data is generated.
GET /api/snapshots/[filename]- Serves image files from
extensions/GrowCast-Timelapse/snapshots
- Serves image files from
GET /api/timelapse/[filename]- Serves timelapse video from
extensions/GrowCast-Timelapse/timelapse/latest_timelapse.mp4
- Serves timelapse video from
POST /admin/logout- Clears admin session and redirects to
/admin
- Clears admin session and redirects to
- Username + scrypt password hash from env vars
- Signed cookie-based sessions
- In-memory session store
To make the HLS source and app publicly accessible without exposing your home network, publish both services through Cloudflare Tunnel:
- Run GrowCast (example:
http://localhost:3000). - Run MediaMTX (example: HLS endpoint on
http://localhost:8888). - Create tunnel routes with
cloudflared:- One public hostname for GrowCast (example:
growcast.example.com->http://localhost:3000) - One public hostname for MediaMTX HLS (example:
stream.example.com->http://localhost:8888)
- One public hostname for GrowCast (example:
- In GrowCast admin, set
Stream URLto your public MediaMTX HLS URL:https://stream.example.com/<path>/
- Verify both endpoints are reachable through Cloudflare.
Important:
- Keep admin credentials strong (
ADMIN_*env vars). - Restrict access where possible, bot protection is recommended.
Cause:
- Missing/invalid
ADMIN_*env variables.
Fix:
- Run
npm run setup:adminand restart the app.
Cause:
extensions/GrowCast-Timelapsefolder missing or no media generated.
Fix:
- Install/run the timelapse plugin and ensure snapshots/timelapse files exist.
Cause:
- Stale page cache after edits.
Fix:
- Restart dev server.
