Now playing

Inhabit

Austin Johnson

Album art
00:0000:00
By icelemontees4 min read
— views··

About Tea with Jesus

Introduction

Tea with Jesus

Tea with Jesus started as a passion project from my "when life gives you lemon, make lemonade" season but i like ice lemon tea better and this was birthed as part of.

This started off as a very simple project but have developed into something more with a blog space, a curated synced music player (on the main page and bottom right.. it was so hard to do!!), a fun brew with tea, and listening aids. There were so much details that went into this. i.e the Music Player was always cut when you navigate into a post, so I put in a persistent Music Player on the dock (bottom right) and kept it in sync with the main Music Player~


Overview

Notion-powered, Next.js blog focused on slow, reflective reading with a few delightful touches. The below is mostly AI generated and summarizes the core features that was implemented and how to use/customize them. PM me if you want access to the project :)

  • Tech Stack: Built on Next.js App Router, JavaScript / TypeScript, TailwindCSS, backed using Notion API (Data are stored here!), and Upstash Redis for fast caching
  • Primary content storage: Undeer the hood, the content (posts) are stored on Notion's database (posts, status, dates, etc.) which is brilliant because I didn't use a conventional database such as MySQL but something that I can edit directly on Notion as a post

Reader Experience

Homepage

  • Verse with Tea

    • Random scripture with a short reflection prompt.
    • Shared context via VerseProvider so the same verse appears inside the submission flow.
    • “Brew another” to reshuffle client-side.
  • Post grid

    • Clean, accessible post cards with date and reading time.
    • Author derived from Notion (fallbacks included).
    • A “Write a post” card to open public submission.

Post page

  • Listen to post (TTS)

    • Text-to-speech controls using Web Speech API (ListenControls).
    • Strips markdown and reads content aloud.
  • Reading aids

    • Reading time based on word count.
    • TableOfContents auto-generates anchors for long posts.
    • ScriptureAnnotator upgrades inline scripture references into interactive components.
  • Engagement

    • ViewsCounter: increments and displays total views per post.
    • Reactions: lightweight reactions (Amen, Pray, Heart) with live counts.

Music Player System

  • Persistent dock

    • MusicDock mounts once in Layout and acts as the single playback host.
    • Audio continues playing across page changes.
  • Full/Mirror UIs

    • Homepage MusicPlayer is a mirror (non-host) UI.
    • Host/mirror sync via BroadcastChannel keeps state in sync (play/pause/seek/track).
      • Hopefully there is no more bug here.
  • YouTube playback

    • Uses YouTube Iframe API, robust multi-instance loader with a global callback queue.
    • Resumes correctly when gaining host role: seeks to last time and continues if playing.
  • State persistence

    • Restores last known track/time and infers elapsed time when resuming.

Community Submissions

  • Public submissions

    • Share your tea with Jesus
    • Saved to Notion with status set to “In Review” before it is published.
  • Rate limiting

    • Basic IP-based limit (default: 3 submissions/hour). Adjustable in src/app/api/submissions/route.ts.
  • Validation & sanitization

    • Input sanitized (src/lib/sanitize.ts) and length-checked.
    • Tags trimmed, capped in count and length.
  • Notion mapping

    • Status: In Review
    • Dates: Published Date + optional rich text timestamp
    • Author priority: rich_text AuthorSubmitted ByAuthor Name → People Author

Content Pipeline

  • Notion integration

    • Loads posts filtered by Status = Published.
    • Slugs from title; description from first non-empty paragraph.
    • Word count and reading time calculated at render.
  • Caching

    • Upstash Redis caching for lists/summaries.
    • Safe withLock helper to prevent overlapping refresh jobs.

Public APIs

These are mainly for developers. But if you want to use: https://icelemontees.danielninetyfour.com/api/verse/random

  • Verse

    • GET /api/verse/random: { text, reference, version, prompt }
    • GET /api/verse/lookup: resolve references (used by ScriptureReference)
    • GET /api/verse/daily: daily verse (for future scheduling)
  • Views

    • POST /api/views/[slug]: increments and returns { views }
    • GET /api/views/[slug]: returns { views }
  • Reactions

    • GET /api/reactions/[slug]: { counts }
    • POST /api/reactions/[slug]: body { type: "amen" | "pray" | "heart" }, returns updated { counts }
  • Submissions

    • POST /api/submissions: create a Notion row with validations and rate limiting
  • Posts

    • GET /api/posts/[slug]: server-side helper endpoint (used for internal/SSR fetches if needed)
  • Drafts/Admin (optional)

    • GET /api/drafts: list drafts (auth/secret-gated)
    • GET /api/drafts/[slug]: fetch a draft
    • POST /api/admin/sync-views: sync view counts back to Notion (requires secret)
    • GET /api/admin/debug-views: debug view data
    • GET /api/cron and GET /api/cron/ping: heartbeat/background triggers

SEO & Metadata

  • Global metadata in src/app/layout.tsx:

    • Open Graph and Twitter cards
    • NEXT_PUBLIC_SITE_URL for canonical URLs
    • OG image at /public/opengraph-image.png
  • robots.ts and sitemap.ts included.


Accessibility & UX

  • Semantic HTML and focusable controls.
  • Tailwind utility classes for contrast and responsive design.
  • Dark mode via ThemeProvider.
  • TTS for readers who prefer listening.
  • Keyboard-friendly buttons and inputs.

Configuration

Set environment variables:

  • NOTION_TOKEN
  • NOTION_DATABASE_ID
  • NEXT_PUBLIC_SITE_URL
  • Optional (Redis caching): UPSTASH_REDIS_REST_URL, UPSTASH_REDIS_REST_TOKEN
  • Optional admin endpoints: ADMIN_POST_SECRET

Development

  • Install: npm install
  • Run: npm run dev
  • Source directories:
    • src/app: routes, pages, and API handlers
    • src/components: UI components (music player, verse, reactions, etc.)
    • src/lib: Notion, Redis, utilities

Roadmap Ideas

  • Shareable verse/quote image generation (but honestly it would be very expensive for the AI generation cost)
  • User authentications via SSO?
    • Customisable Playlist management UI for the music player.

If you have any suggestion, let me know!

  • Made with Tea :)