uncalledfor is a private journaling app that lets signed-in users write honest thoughts and receive a brief AI-generated reflection back in real time.
This monorepo contains:
apps/web: a React + Vite frontend with Clerk authenticationapps/api: a FastAPI backend that stores entries in PostgreSQL and streams AI responses from Groqpackages/ui: shared UI primitives for the client apppackages/eslint-configandpackages/typescript-config: shared workspace tooling
- Frontend: React, TypeScript, Vite
- Backend: FastAPI, SQLAlchemy async, PostgreSQL, Neon
- Auth: Clerk
- AI: Groq
- Tooling: TurboRepo, pnpm, uv
- Node.js 24.20+
- pnpm 11+
- Python 3.10+
- A PostgreSQL connection string (Neon is the intended setup)
- Clerk secret key and publishable key
- Groq API key
Create apps/api/.env with:
DATABASE_URL=postgresql://<user>:<password>@<host>/<database>
CLERK_SECRET_KEY=your_clerk_secret_key
GROQ_API_KEY=your_groq_api_key
GROQ_MODEL=openai/gpt-oss-120bCreate apps/web/.env.local with:
VITE_CLERK_PUBLISHABLE_KEY=your_clerk_publishable_key
VITE_API_URL=/api/v1If you want to bypass the dev proxy, you can set:
VITE_API_URL=http://127.0.0.1:8000/api/v1Apply the schema in apps/api/schema.sql once in your Neon SQL editor or PostgreSQL database:
CREATE TABLE entries (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id TEXT NOT NULL,
entry TEXT NOT NULL,
comment TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
);Install the JavaScript dependencies:
pnpm installSet up the Python API environment:
cd apps/api
uv syncStart the API:
cd apps/api
uv run fastapi dev main.py --host 127.0.0.1 --port 8000Start the web app:
pnpm --filter web devOr run both via TurboRepo:
pnpm devThe Vite dev server proxies /api requests to the FastAPI app on http://127.0.0.1:8000.
- Users sign in with Clerk.
- A journal entry is saved and immediately returned as a streaming event-source response.
- The backend streams a brief reflective message while generating it.
- Each user can retrieve their latest 10 entries with the API.
POST /api/v1/entries/— create an entry and stream the generated responseGET /api/v1/entries/— fetch the signed-in user’s most recent entries
For implementation details, see the API docs in apps/api/README.md.