A modern, AI-powered daily journaling application built with Next.js, Supabase, and Google AI
- Text & Voice Input: Write or record your daily thoughts. Voice notes are transcribed locally as a placeholder until you wire an external transcription service.
- Supabase Storage: Journal entries are persisted in Supabase Postgres and fetched on demand after each create/delete operation.
- Chronological Display: Clean, organized view of your journal history
- Secure Authentication: Email/password login with Supabase Auth
- Genkit Flows (Opt-In): Google Genkit flows are implemented for sentiment analysis and weekly reflections. They require server-side execution and are currently disabled in the static Cloudflare Pages build.
- Weekly Reflection Page: Presents placeholder copy while Genkit access is re-enabled. Integrate with an external Genkit runtime to restore summaries and prompts.
- Dark/Light Theme: Toggle between themes for comfortable reading
- Responsive Design: Works perfectly on desktop, tablet, and mobile
- Minimalist UI: Clean interface that focuses on your content
- Smooth Animations: Subtle transitions for a polished experience
- Supabase Database: Authenticated CRUD access to the
journal_entriesandprofilestables - Voice Recording: Built-in audio recording and playback controls with accessibility affordances
- Entry Management: Edit, delete, and organize your entries
- Accessibility Hooks: Screen-reader announcements, skip links, and focus management utilities
Make sure you have the following installed:
- Node.js (v18 or higher)
- npm or yarn
- Supabase CLI (for database management)
-
Clone the repository
git clone <repository-url> cd EchoJournal
-
Install dependencies
npm install
-
Set up environment variables
Copy
.env.exampleto.env.localand supply the values below. The application falls back to placeholder Supabase credentials if they are missing, but authentication and storage will fail.Variable Required? Description NEXT_PUBLIC_SUPABASE_URLβ Supabase project URL NEXT_PUBLIC_SUPABASE_ANON_KEYβ Supabase anonymous client key GOOGLE_GENAI_API_KEYβ οΈ OptionalRequired when running Genkit flows locally To configure Supabase:
- Create a Supabase project at Supabase Console
- Enable Email/Password authentication
- Create the database tables in the Supabase Setup section
- Configure redirect URLs under Authentication β URL configuration so Supabase can redirect after sign-in
-
Start the development server
npm run dev
-
Open your browser
Navigate to http://localhost:9002
# Development
npm run dev # Start development server with Turbopack
npm run genkit:dev # Start Genkit AI development server
npm run genkit:watch # Start Genkit with file watching
# Building
npm run build # Build for production (static export)
# Testing
npm run test # Run Jest tests
npm run test:watch # Run tests in watch mode
npm run test:ci # Run full CI test suite
# Code Quality
npm run lint # Run ESLint
npm run typecheck # Run TypeScript type checkingEchoJournal/
βββ src/
β βββ app/ # Next.js App Router
β β βββ weekly-reflection/ # Weekly reflection page
β β βββ layout.tsx # Root layout
β β βββ page.tsx # Home page
β βββ ai/ # AI integration
β β βββ flows/ # AI workflows
β β βββ ai-instance.ts # AI configuration
β βββ components/ # React components
β β βββ ui/ # Reusable UI components
β β βββ AuthForm.tsx # Authentication forms
β β βββ theme-*.tsx # Theme components
β βββ contexts/ # React contexts
β βββ hooks/ # Custom React hooks
β βββ lib/ # Utilities and services
β βββ supabase.ts # Supabase client config
β βββ journalService.ts # Journal API service
β βββ utils.ts # Utility functions
βββ public/ # Static assets
βββ docs/ # Documentation
βββ wrangler.toml # Cloudflare Pages configuration
- Architecture Overview
- Developer Onboarding
- Component & Hook Reference
- API & Integration Reference
- Data Model Reference
- Operations Runbook
- Go to Supabase Console
- Create a new project
- Enable Authentication with Email/Password
- Set up your PostgreSQL database
-- Create journal_entries table
CREATE TABLE journal_entries (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
content TEXT NOT NULL,
sentiment_score NUMERIC,
sentiment_summary TEXT,
title TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Enable Row Level Security
ALTER TABLE journal_entries ENABLE ROW LEVEL SECURITY;
-- Create policy for users to only access their own entries
CREATE POLICY "Users can only access their own entries" ON journal_entries
FOR ALL USING (auth.uid() = user_id);
-- Create profiles table for storing user metadata
CREATE TABLE profiles (
id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
email TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can view their profile" ON profiles
FOR SELECT USING (auth.uid() = id);
CREATE POLICY "Users can upsert their profile" ON profiles
FOR INSERT WITH CHECK (auth.uid() = id)
TO authenticated;
CREATE POLICY "Users can update their profile" ON profiles
FOR UPDATE USING (auth.uid() = id)
TO authenticated;The application automatically upserts a profile record the first time a user signs in. Confirm that the authenticated role can insert and update the profiles table.
# Build the static site
npm run build
# The built files will be in the 'out' directory
# Upload to Cloudflare Pages or connect your GitHub repository
# for automatic deploymentsGenkit flows are scaffolded in src/ai/flows and can be executed when the app runs with a server runtime (e.g., Next.js server actions or an external Genkit worker). In the static Cloudflare Pages export the flows do not execute.
- Sentiment Analysis (
analyzeSentiment): Accepts a journal entry string and returns{ sentiment, summary }. Wire this flow into an API route (e.g.,/api/sentiment) and call it fromJournalService.analyzeSentimentto enrich entries. - Weekly Reflection (
analyzeWeeklyReflection): Accepts concatenated entries and returns{ summary, prompt }. The weekly reflection page currently surfaces placeholder text until this flow is restored.
Run npm run genkit:dev to start the Genkit dev server locally and test the flows with a valid GOOGLE_GENAI_API_KEY.
The app supports both light and dark themes with a smooth toggle transition. Themes are built with:
- Tailwind CSS: Utility-first styling
- CSS Variables: Dynamic theme switching
- System Preference: Automatically detects user's system theme
- Primary: Calm blue (#4682B4) for relaxation
- Secondary: Light gray (#D3D3D3) for backgrounds
- Accent: Teal (#008080) for interactive elements
- Text: High contrast for readability
Test commands are configured in package.json, but the repository does not currently include unit or integration test suites. Add tests alongside new features and execute them with:
# Run all tests (if present)
npm run test
# Type checking and linting used in CI
npm run test:ci- Responsive Layout: Tailwind CSS utility classes ensure the journal and weekly reflection pages adapt from mobile to desktop viewports.
- Voice Recording: MediaRecorder-based capture works in browsers that expose microphone APIs. Mobile Safari currently requires user interaction to begin recording.
- Accessibility Enhancements: Skip links, focus management, and toast announcements improve keyboard and assistive technology support.
- Supabase Authentication: Secure user management
- Row Level Security: Database access control
- Environment Variables: Secure API key management
- HTTPS Only: Encrypted data transmission
npm run build
# Upload the 'out' directory to Cloudflare Pages
# or connect your GitHub repository for automatic deploymentsnpm run build
# Deploy to Vercel- AI features that depend on Genkit (
src/ai/flows/*) require a server runtime and do not execute in the static Cloudflare Pages build. JournalService.analyzeSentimentexpects a/api/sentimentroute, which is not implemented. Connect it to an external service before enabling sentiment enrichment.- Voice note transcription currently returns placeholder text from the client-side mock transcription.
- Real-time Supabase subscriptions are not enabled; entries refresh after explicit CRUD operations.
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit your changes:
git commit -m 'Add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
- Code Style: Follow the existing TypeScript and React patterns
- Testing: Add tests for new features
- Documentation: Update README for significant changes
- Commits: Use conventional commit messages
This project is licensed under the MIT License - see the LICENSE file for details.
- Next.js Team: For the amazing React framework
- Supabase Team: For the backend infrastructure and database
- Cloudflare: For the fast and reliable hosting platform
- Google AI: For the sentiment analysis capabilities
- Radix UI: For the beautiful component primitives
- Tailwind CSS: For the utility-first styling approach
If you have any questions or need help:
- Documentation: Check the
/docsfolder - Issues: Open an issue on GitHub
- Discussions: Use GitHub Discussions for questions
Made with β€οΈ for better journaling
Start your mindful writing journey today!
Last updated: 2024-11-22