Journaling apps are graveyards of text. Day One, Notion, even physical journals — they store your thoughts with perfect fidelity and then do absolutely nothing with them. You can journal every day for five years and have no clearer picture of your emotional patterns, cognitive loops, or recurring themes than when you started. You're generating data with no analysis layer.
Therapists do the analysis — but they're expensive, available one hour a week, and work from the tiny fraction of what you say out loud. The rest of the signal is lost.
Pratyaksha (Sanskrit: "direct perception" or "clear seeing") is my attempt to answer that. Not a chatbot. Not a mood tracker. A multi-agent AI system that reads your entries the same way a skilled analyst would — looking for intent, emotion, themes, and contradictions — and then makes them visible.
The central design decision was multi-agent over monolithic. A single LLM prompt like "analyse this journal entry" produces shallow, generic output — it tries to do everything and does nothing well. Instead, I decomposed the problem into four specialised concerns and gave each its own agent.
Critically, agents don't share state. Each agent receives the raw journal entry plus the structured output of the previous agent — nothing else. This keeps the reasoning chain clean, traceable, and debuggable. If the Emotion Agent produces a wrong classification, you can see exactly what it received and why it concluded what it did.
The marketing site was built to be a portfolio piece in itself — an interactive 3D brain that responds to emotional keywords typed in real-time (React Three Fiber), Apple-style scroll storytelling that walks through each agent's function (GSAP ScrollTrigger), and a Bento Grid displaying all 21 chart types with live sample data.
The 4-agent pipeline — each agent receives raw entry + previous agent's structured output:
┌──────────────────────────────────────────────────────────────────┐
│ PRATYAKSHA AGENT PIPELINE │
└──────────────────────────────────────────────────────────────────┘
INPUT: Raw journal entry text (free-form, any length)
│
▼
┌─────────────────────────────────────────────────────────────┐
│ AGENT 01: INTENT AGENT │
│ Input: raw entry │
│ Output: { type: "Emotional|Cognitive|Work|Health", │
│ confidence: 0.94, │
│ primary_concern: "...", │
│ context_tags: ["..."] } │
└──────────────────────────┬──────────────────────────────────┘
│ (raw entry + intent output)
▼
┌─────────────────────────────────────────────────────────────┐
│ AGENT 02: EMOTION AGENT │
│ Input: raw entry + intent classification │
│ Output: { mood: "Anxious|Calm|Hopeful|...", │
│ energy_level: 0-100, │
│ patterns: ["avoidance", "catastrophising"], │
│ mode: "Anxious|Calm|Hopeful" } │
└──────────────────────────┬──────────────────────────────────┘
│ (raw entry + intent + emotion)
▼
┌─────────────────────────────────────────────────────────────┐
│ AGENT 03: THEME AGENT │
│ Input: raw entry + intent + emotion + history │
│ Output: { recurring_themes: ["..."], │
│ contradictions: ["..."], │
│ cognitive_loops: ["..."], │
│ narrative_shift: bool } │
└──────────────────────────┬──────────────────────────────────┘
│ (all above outputs)
▼
┌─────────────────────────────────────────────────────────────┐
│ AGENT 04: INSIGHT AGENT │
│ Input: all previous outputs │
│ Output: { summary: "...", │
│ recommendations: ["..."], │
│ next_action: "...", │
│ cbt_reframe: "..." } │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ 21 VISUALISATIONS (Next.js Dashboard) │
│ React Query + aggressive caching + live data │
│ Emotional Timeline · Energy Radar · Heatmap │
│ Sankey Flow · Contradiction Tracker · + 15 more │
└─────────────────────────────────────────────────────┘
Marketing: R3F 3D Brain + GSAP Scroll + Bento Grid
The marketing site hero has a 3D brain that reacts as a user types — activating different lobes, changing glow intensity, and pulsing based on the emotional valence of detected keywords. The challenge: keystrokes fire at human typing speed (6–12 chars/sec), WebGL is expensive, and a naive approach causes visible jank on every keystroke.
21 charts on a single dashboard, each making independent data requests, with some requiring the full history of journal entries — the naive implementation made 21 separate API calls on mount and the dashboard was unusable for users with more than a few months of data.
Solution: React Query with a carefully designed cache key strategy. All charts that share a data dependency use the same cache key — the first chart to mount fetches, every subsequent chart reads from cache. Charts that don't need live data are rendered server-side in Next.js App Router and hydrated statically.
The marketing site's Apple-style scroll section pins a section and animates through the 4-agent pipeline as you scroll. Desktop was smooth. Mobile was a disaster: pinned sections have known interaction with iOS Safari's elastic bounce scroll, and touch event timing caused frames to drop during fast swipes.
Solution: replaced the pin approach on mobile with a standard scroll-triggered opacity/translateY
animation (no pinning). Used GSAP's
ScrollTrigger.normalizeScroll(true) to handle iOS
momentum scroll. Separate animation timelines for mobile vs desktop, detected via a media query
matcher at ScrollTrigger.create time.
Core product metrics at the end of the build:
-
Multi-agent pipelines are more maintainable than monolithic LLM prompts.
When the Emotion Agent produces a wrong output, I can test it in isolation with known inputs. With a monolithic prompt, a regression anywhere in the reasoning chain is nearly impossible to localise.
-
3D on the web is more accessible than expected with React Three Fiber.
R3F's declarative model means you write 3D scenes the way you write React components. The learning curve is the 3D geometry concepts — not the WebGL API. The brain model went from concept to interactive in under a week.
-
GSAP ScrollTrigger on mobile needs careful pinning configuration.
Pin-based scroll storytelling is a desktop-first pattern. Building mobile-first and treating the pinned version as a progressive enhancement would have saved significant debugging time.
-
React Query cache key design is architecture, not an implementation detail.
Getting cache key strategy right from the beginning is the difference between a dashboard that loads in 300ms and one that makes 21 API calls every time a user switches tabs.
-
The marketing site is part of the product.
The interactive 3D brain demo communicates what Pratyaksha does more effectively than any paragraph of copy. Time invested in the marketing site experience directly converts to user trust.