Look, I'll be honest with you. I spent way too many nights doom-scrolling through random confession pages, and one thought kept bugging me: what if these people could get actual support instead of just reactions? That's how Confessly was bornβa place where you can spill your thoughts anonymously and get genuine, thoughtful AI-powered guidance back.
This isn't just another confession board. It's what happens when you mix the raw honesty of anonymous platforms with the empathy of modern AI. And yeah, I'm building it completely open-source because why gatekeep?
What Makes Confessly Different?
The concept is simple but powerful:
- Anonymous by default β No accounts, no tracking, just pure honesty
- AI Advisor β Every confession gets a supportive, non-judgmental response from GPT
- Community-driven β Trending confessions, reactions, and shared experiences
- Moderation tools β Because we all know the internet needs guardrails
Think Whisper meets ChatGPT, but actually useful.
The Tech Stack (And Why I Chose It)
Let me walk you through what's under the hood:
Frontend:
- Next.js 14 (App Router) β Server components, edge runtime, the whole nine yards
- React 18 β Because duh
- TypeScript β Sanity is underrated
- Tailwind CSS β Fast styling without the CSS headaches
- Framer Motion β Smooth animations that don't feel overdone
- Zustand β State management that doesn't make me cry
Backend & Services:
- Next.js API Routes β Keeping it simple with serverless functions
- Firebase Firestore β Real-time database for confessions and reactions
- Firebase Auth β For the admin dashboard
- OpenAI GPT-4 β The brain behind our AI advisor
- Vercel β Deployment that just works
Dev Tools:
- ESLint + Prettier β Because consistency matters
- Husky β Git hooks for pre-commit checks
Architecture Deep Dive
Here's how everything connects:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Client Layer β
β (Next.js 14 App Router + React Components) β
ββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β API Routes Layer β
β /api/confessions/* | /api/ai/* | /api/moderation/* β
ββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββ
β
ββββββββββββ΄βββββββββββ
βΌ βΌ
ββββββββββββββββ ββββββββββββββββββββ
β Firebase β β OpenAI API β
β Firestore β β GPT-4 Turbo β
ββββββββββββββββ ββββββββββββββββββββ
Data Flow:
- User posts anonymous confession
- Firebase stores confession with metadata
- AI Advisor endpoint receives confession
- GPT-4 generates empathetic response
- Response stored and displayed to user
- Real-time updates via Firebase listeners
File Structure That Makes Sense
This took me a few iterations to get right. Here's the final structure:
confessly/
βββ src/
β βββ app/
β β βββ (main)/
β β β βββ page.tsx # Home - confession feed
β β β βββ trending/
β β β β βββ page.tsx # Trending confessions
β β β βββ confession/
β β β β βββ [id]/
β β β β βββ page.tsx # Single confession view
β β β βββ layout.tsx # Main layout wrapper
β β βββ admin/
β β β βββ page.tsx # Admin dashboard
β β β βββ moderation/
β β β β βββ page.tsx # Moderation queue
β β β βββ layout.tsx # Admin layout
β β βββ api/
β β β βββ confessions/
β β β β βββ route.ts # POST new confession
β β β β βββ [id]/
β β β β β βββ route.ts # GET single confession
β β β β β βββ react/
β β β β β βββ route.ts # POST reaction
β β β β βββ trending/
β β β β βββ route.ts # GET trending
β β β βββ ai/
β β β β βββ advisor/
β β β β β βββ route.ts # POST get AI response
β β β β βββ therapist/
β β β β βββ route.ts # POST therapist mode
β β β βββ moderation/
β β β βββ flag/
β β β β βββ route.ts # POST flag confession
β β β βββ review/
β β β βββ route.ts # POST review decision
β β βββ layout.tsx # Root layout
β β βββ globals.css # Global styles
β βββ components/
β β βββ confession/
β β β βββ ConfessionCard.tsx # Single confession display
β β β βββ ConfessionFeed.tsx # Feed container
β β β βββ ConfessionForm.tsx # New confession form
β β β βββ AIResponse.tsx # AI response display
β β βββ ui/
β β β βββ Button.tsx # Reusable button
β β β βββ Card.tsx # Card component
β β β βββ Modal.tsx # Modal wrapper
β β β βββ Input.tsx # Form inputs
β β β βββ Badge.tsx # Status badges
β β βββ layout/
β β β βββ Header.tsx # Site header
β β β βββ Footer.tsx # Site footer
β β β βββ Sidebar.tsx # Admin sidebar
β β βββ admin/
β β βββ ModerationQueue.tsx # Moderation interface
β β βββ StatsCard.tsx # Dashboard stats
β βββ lib/
β β βββ firebase/
β β β βββ config.ts # Firebase initialization
β β β βββ firestore.ts # Firestore helpers
β β β βββ auth.ts # Auth helpers
β β βββ openai/
β β β βββ client.ts # OpenAI client setup
β β β βββ prompts.ts # AI prompt templates
β β βββ utils/
β β β βββ formatDate.ts # Date formatting
β β β βββ sanitize.ts # Content sanitization
β β β βββ analytics.ts # Analytics helpers
β β βββ constants.ts # App constants
β βββ store/
β β βββ confessionStore.ts # Confession state
β β βββ uiStore.ts # UI state
β βββ types/
β β βββ confession.ts # Confession types
β β βββ user.ts # User types
β β βββ api.ts # API response types
β βββ hooks/
β βββ useConfessions.ts # Confession data hook
β βββ useAIResponse.ts # AI interaction hook
β βββ useInfiniteScroll.ts # Infinite scroll hook
βββ public/
β βββ images/
β βββ favicon.ico
βββ .env.local # Environment variables
βββ .eslintrc.json # ESLint config
βββ .prettierrc # Prettier config
βββ next.config.js # Next.js config
βββ tailwind.config.ts # Tailwind config
βββ tsconfig.json # TypeScript config
βββ package.json # Dependencies
Database Schema (Firestore)
Keep it simple, stupid. Here's what the data looks like:
Collections:
// confessions collection
{
id: string,
content: string,
category: 'relationship' | 'work' | 'mental-health' | 'other',
aiResponse: string | null,
reactions: {
heart: number,
hug: number,
support: number
},
flags: number,
status: 'active' | 'flagged' | 'removed',
createdAt: timestamp,
trending_score: number, // calculated based on time + reactions
anonymous_id: string // hashed IP for rate limiting
}
// reactions collection (subcollection under each confession)
{
id: string,
confessionId: string,
type: 'heart' | 'hug' | 'support',
createdAt: timestamp,
anonymous_id: string
}
// moderation collection
{
id: string,
confessionId: string,
reason: string,
status: 'pending' | 'approved' | 'removed',
reviewedAt: timestamp | null,
reviewerId: string | null
}
The UI/UX Philosophy
I wanted Confessly to feel like a safe space, not another cold tech product. Here's the vibe:
Design Principles:
- Minimalist β Remove everything that doesn't serve the user
- Soft colors β Purples and blues that feel calming, not aggressive
- Generous whitespace β Let the content breathe
- Smooth animations β Transitions that feel natural, not jarring
- Mobile-first β Because most people confess at 2 AM on their phones
Key UI Components:
Confession Card:
- Soft gradient background
- No profile pictures (obviously)
- Emoji reactions instead of likes
- "Get AI Support" button prominently displayed
- Flag option tucked in the corner
AI Response Section:
- Distinct visual treatment (lighter card, different border)
- Warm, conversational tone in the design
- "This is AI-generated" disclaimer (transparency matters)
- Option to regenerate response
Feed Layout:
- Infinite scroll with skeleton loaders
- Filter chips at the top (category, trending, recent)
- Floating action button for new confession
- Smooth card entrance animations
Core Features Breakdown
1. Anonymous Confession Posting
// Simplified version of the submission flow
const submitConfession = async (content: string, category: string) => {
// Generate anonymous ID (hashed IP + session)
const anonymousId = await generateAnonymousId();
// Check rate limit (max 3 per hour per anonymous ID)
await checkRateLimit(anonymousId);
// Sanitize content
const sanitized = sanitizeContent(content);
// Create confession
const confession = await db.collection('confessions').add({
content: sanitized,
category,
anonymous_id: anonymousId,
status: 'active',
reactions: { heart: 0, hug: 0, support: 0 },
flags: 0,
createdAt: serverTimestamp(),
aiResponse: null
});
// Trigger AI response generation
generateAIResponse(confession.id);
return confession.id;
};
2. AI Advisor Mode
The magic sauce. Here's how the AI responds:
// AI prompt engineering
const generateAdvicePrompt = (confession: string) => {
return `You are a compassionate AI advisor for an anonymous confession platform.
A user has shared: "${confession}"
Provide a supportive, non-judgmental response that:
- Validates their feelings
- Offers perspective or gentle advice
- Suggests actionable steps if appropriate
- Encourages professional help for serious issues
- Uses warm, conversational language
- Keeps it under 150 words
Remember: This is anonymous, so focus on the emotion and situation, not identity.`;
};
The AI is prompted to be empathetic, concise, and helpfulβnot preachy or robotic.
3. Trending Algorithm
Simple but effective:
const calculateTrendingScore = (confession) => {
const age = Date.now() - confession.createdAt.toMillis();
const ageHours = age / (1000 * 60 * 60);
const reactionCount =
confession.reactions.heart * 1 +
confession.reactions.hug * 1.5 +
confession.reactions.support * 2;
// Decay score over time (gravity)
const gravity = 1.8;
return reactionCount / Math.pow(ageHours + 2, gravity);
};
New confessions with lots of reactions rise fast. Old ones fade gracefully.
4. Moderation Dashboard
Admins get a clean interface to review flagged content:
- Queue of flagged confessions
- Context about why it was flagged
- One-click approve/remove actions
- Stats dashboard (total confessions, active users, flags)
Viral Features That Hook Users
1. AI Therapist Mode
Toggle between quick advice and deeper, therapy-style conversations. Costs more tokens but provides richer responses.
2. Trending Confessions Leaderboard
Shows the most-reacted confessions of the day/week. Gamification without being toxic.
3. Category-Based Exploration
Filter by relationship, work, mental health, or general confessions.
4. Reaction System
Instead of generic likes: β€οΈ (Heart), π€ (Hug), πͺ (Support)
5. Anonymous Sharing
Generate shareable links to specific confessions (with AI responses included).
Environment Setup
Create a .env.local file:
# Firebase
NEXT_PUBLIC_FIREBASE_API_KEY=your_api_key
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your_domain
NEXT_PUBLIC_FIREBASE_PROJECT_ID=your_project_id
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your_bucket
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
NEXT_PUBLIC_FIREBASE_APP_ID=your_app_id
# OpenAI
OPENAI_API_KEY=your_openai_key
# App
NEXT_PUBLIC_APP_URL=http://localhost:3000
NEXT_PUBLIC_MAX_CONFESSIONS_PER_HOUR=3
Getting Started
# Clone and install
git clone https://github.com/yourusername/confessly
cd confessly
npm install
# Set up environment
cp .env.example .env.local
# Fill in your API keys
# Run development server
npm run dev
# Build for production
npm run build
npm start
Deployment Strategy
Vercel is the obvious choice here:
- Connect your GitHub repo
- Add environment variables in Vercel dashboard
- Deploy
- Done
Firebase handles:
- Database scaling automatically
- Real-time updates without extra config
- Security rules to prevent abuse
Cost estimates (for moderate traffic):
- Vercel: Free tier handles ~100K requests/month
- Firebase: ~$25/month with generous free tier
- OpenAI: ~$50/month (depends on usage)
Security & Privacy Considerations
This is crucial for a confession app:
Firestore Rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /confessions/{confession} {
// Anyone can read active confessions
allow read: if resource.data.status == 'active';
// Anyone can create (with rate limiting in code)
allow create: if request.auth == null;
// Only admins can update/delete
allow update, delete: if request.auth.token.admin == true;
}
}
}
Additional Measures:
- Content sanitization on both client and server
- Rate limiting per anonymous ID
- IP hashing (never store raw IPs)
- Profanity filter with manual review for edge cases
- Clear terms of service and privacy policy
Performance Optimizations
Client Side:
- Image lazy loading with Next.js Image component
- Infinite scroll with intersection observer
- Optimistic UI updates for reactions
- Debounced search and filters
Server Side:
- API route caching with proper headers
- Firestore indexes for common queries
- Edge functions for low latency
- OpenAI streaming responses for faster perceived performance
Future Roadmap
What's next for Confessly:
- [ ] PWA support for mobile app feel
- [ ] Voice confession option (transcribed to text)
- [ ] Follow-up conversations with AI
- [ ] Community support threads
- [ ] Multilingual support
- [ ] Dark mode (always dark mode)
- [ ] Export your confessions (therapy journal)
Lessons Learned
Building Confessly taught me a few things:
Keep it simple β My first version had way too many features. Users just want to confess and get support.
AI prompts matter β I spent more time on prompt engineering than I expected. The difference between robotic and empathetic AI responses is all in the prompt.
Moderation is hard β You can't automate everything. Human review is necessary for edge cases.
Performance obsession pays off β Users bounce if your app feels slow. Optimize early.
Privacy builds trust β Being genuinely anonymous (not "we promise not to look" anonymous) is the whole point.
Why Open Source?
I'm open-sourcing Confessly because I think we need more compassionate tech in the world. If someone builds something better using this code, that's a win. If someone learns from my mistakes, even better.
The repo will be on GitHub with full documentation, deployment guides, and contribution guidelines.
Final Thoughts
Confessly isn't just a side project for meβit's an experiment in building technology that actually helps people. We're all carrying something, and sometimes the best first step is just getting it out there, even if anonymously.
If you build this or something inspired by it, I'd love to see what you create. Tag me, send a DM, whatever. Let's make the internet a slightly less terrible place.
That's a wrap π
Now go touch some code π¨βπ»
Top comments (0)