Etu is an interstitial journaling platform that helps you capture life's moments through quick, tagged markdown notes called "blips."
This is the webapp for Etu. For more reading on our ideas see:
- Quick Capture: Write notes in Markdown with live preview (Cmd+Enter to save)
- Tag System: Organize notes with custom tags and autocomplete
- Search & Filter: Find notes by content, tags, or date
- Timeline View: Browse notes chronologically with date grouping
- History: Review past notes
- Settings: Manage account, profile image, Notion integration, view stats, and manage API keys
- Keyboard Shortcuts:
nfor new note,/to search - Mobile Support: Responsive design with bottom navigation
- API Keys: Generate keys for CLI and mobile app access
- Stripe Subscriptions: $5/year with Stripe integration
- Theme Toggle: Light/dark mode support
- Framework: Next.js 16 (App Router)
- Backend: Connect RPC client for etu-backend service
- Proto Types:
@icco/etu-protopackage (shared TypeScript types) - Auth: Auth.js v5 (NextAuth) with credentials via gRPC backend
- Styling: Tailwind CSS 4 + daisyUI 5
- Icons: Heroicons
- Markdown: marked + DOMPurify
- Payments: Stripe
- Node.js 25+ (see
.nvmrc) - Yarn
- Running etu-backend gRPC service
- GitHub Packages authentication (for
@icco/etu-proto)
# Configure npm for @icco scope (if not already done)
# Add to ~/.npmrc: //npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN
# Install dependencies
yarn install
# Set up environment variables (see below)
# Create .env.local with your gRPC backend URL and secrets
# Start development server
yarn dev# Auth.js
AUTH_SECRET="your-secret-key"
AUTH_URL="http://localhost:3000"
# gRPC Backend (Connect RPC)
GRPC_BACKEND_URL="http://localhost:50051"
GRPC_API_KEY="your-service-api-key" # Required
# Stripe (optional)
STRIPE_SECRET_KEY="sk_..."
STRIPE_WEBHOOK_SECRET="whsec_..."
STRIPE_PRICE_ID="price_..."# Development with docker-compose
docker-compose up -d
# Production build (requires GitHub token for @icco/etu-proto)
docker build --secret id=npm_token,env=GITHUB_TOKEN -t etu-server .
docker run -p 3000:3000 \
-e AUTH_SECRET="..." \
-e GRPC_BACKEND_URL="http://backend:50051" \
-e GRPC_API_KEY="..." \
etu-server├── app/
│ ├── (auth)/ # Login/register pages
│ ├── (app)/ # Protected app pages
│ │ ├── notes/ # Notes timeline
│ │ ├── history/ # Note history
│ │ ├── search/ # Full-text search
│ │ ├── tags/ # Tag browser
│ │ └── settings/ # Account, API keys, stats, subscription
│ ├── api/
│ │ ├── auth/ # NextAuth handlers
│ │ └── stripe/ # Stripe webhooks
│ ├── docs/ # Proto API documentation
│ └── page.tsx # Landing page
├── components/ # Shared UI (nav, note cards, dialogs, theme toggle)
├── lib/
│ ├── actions/ # Server actions (notes, auth, user, api-keys)
│ ├── grpc/
│ │ ├── client.ts # Connect RPC client + proto type converters
│ │ └── mock.ts # Mock services for e2e testing
│ ├── auth.ts # Auth.js config
│ ├── types.ts # View-layer types (proto Timestamp → Date)
│ └── stripe.ts
└── middleware.ts # Auth middleware
This webapp follows a microservice architecture:
- etu-web (this repo): Frontend webapp (no direct database access)
- etu-backend: gRPC service for all data storage (users, notes, tags, API keys)
The webapp communicates with the backend via Connect RPC. TypeScript types are shared via the @icco/etu-proto package (published from etu-backend).
For programmatic access to notes and tags, use:
Generate API keys in Settings to use with these clients.
The proto definitions documentation is available at /docs when the app is running. This documentation is automatically generated from the @icco/etu-proto package and describes the gRPC API contract between the frontend and backend services.