Birthday Reminder Application
Describes a full-stack birthday reminder app with React, Express, PostgreSQL, email notifications, and dark-mode UI.
What this file does
Describes a full-stack birthday reminder app with React, Express, PostgreSQL, email notifications, and dark-mode UI.
When to use it
- Building a birthday or event reminder application
- Creating a full-stack app with React, Express, and PostgreSQL
- Implementing email notifications with nodemailer and Ethereal
- Using Drizzle ORM with Neon serverless PostgreSQL
Assumes this stack
Birthday Reminder Application
Overview
This is a full-stack birthday reminder application built with React (frontend), Express (backend), and PostgreSQL (database via Drizzle ORM). The application helps users track and manage birthdays for friends, family, and colleagues, with email notification capabilities. It features a modern, dark-mode interface inspired by productivity tools like Linear and Notion, using shadcn/ui components built on Radix UI primitives.
Documentation
For detailed documentation, see the following guides in the docs/ folder:
| Document | Audience | Description |
|---|---|---|
| Developer Guide | Developers | Technical documentation covering architecture, database schema, authentication, and how to add new features |
| Product Guide | Product Managers | Feature overview, user flows, business logic, and roadmap considerations |
| API Reference | Developers | Complete API endpoint documentation with request/response examples |
| Design Guidelines | Designers/Developers | UI/UX specifications, typography, colors, and component patterns |
User Preferences
- Preferred communication style: Simple, everyday language (Spanish preferred)
- Language: Spanish as default UI language
- Date format: dd/mm/yyyy for display and input
System Architecture
Frontend Architecture
Framework & Build System
- React 18 with TypeScript for type-safe component development
- Vite as the build tool and development server with HMR (Hot Module Replacement)
- Wouter for lightweight client-side routing instead of React Router
UI Component System
- shadcn/ui component library (New York style variant) with Radix UI primitives
- Tailwind CSS for utility-first styling with custom design tokens
- CSS Variables for theming support (dark mode default)
- Components are aliased via
@/componentspath mapping
State Management
- TanStack Query (React Query) for server state management and data fetching
- Local component state with React hooks for UI state
- Custom language context provider for internationalization (Spanish/English)
- Custom hooks:
useAuth,useBirthdays,useSettings
Design System
- Custom color system with HSL-based CSS variables
- Neutral base color scheme with support for semantic colors (primary, secondary, destructive, etc.)
- Custom border radius values (9px, 6px, 3px)
- Typography using Inter font from Google Fonts CDN
- Responsive design with mobile-first approach
Key Features
- Birthday list with filtering by tag (family, friends, work, other) and time period
- Add/edit birthday forms with validation
- Excel import functionality for bulk birthday uploads
- Email settings configuration for notification preferences
- Authentication system (login/register) with session-based auth
- Toast notifications for user feedback
- Multi-language support (Spanish/English)
Backend Architecture
Server Framework
- Express.js with TypeScript for API endpoints
- Custom middleware for request logging with timestamps
- Static file serving for production builds
- Session-based authentication with Passport.js
Development vs Production
- Development mode uses Vite middleware for HMR
- Production mode serves pre-built static assets from
dist/public - Environment-aware configuration via
NODE_ENV
Build Process
- esbuild for server-side bundling with selective dependency bundling
- Allowlist approach for bundling specific dependencies (reduces syscalls for cold starts)
- Client built separately via Vite
API Structure
- Routes prefixed with
/api - Storage interface abstraction for data operations
- Implements
DatabaseStorageclass using Drizzle ORM
Storage Layer
- Interface-based design (
IStorage) for flexibility - Methods for user CRUD operations (getUser, getUserByEmail, createUser)
- Methods for birthday CRUD (getBirthdaysByUserId, createBirthday, updateBirthday, deleteBirthday)
- Integrated with Drizzle ORM for PostgreSQL persistence
Data Storage
Database Setup
- Drizzle ORM configured for PostgreSQL dialect
- Neon Database serverless driver (
@neondatabase/serverless) with HTTP transport - Migration files stored in
./migrationsdirectory - Schema defined in
shared/schema.ts
Schema Design
- Users table: email, password (hashed with bcrypt), notification settings
- Birthdays table: userId (FK), name, birthDate, tag (enum: family/friends/work/other)
- Uses
gen_random_uuid()for primary keys (UUID strings) - Zod integration via
drizzle-zodfor runtime validation - Shared schema between client and server via
@sharedalias
Database Connection
- Connection configured via
DATABASE_URLenvironment variable - Uses
drizzle({ client: sql, schema })pattern for proper Neon HTTP driver integration - Drizzle Kit configured for schema push (
db:pushscript)
Known Issues - Neon HTTP Driver
- The Neon HTTP driver has a known bug where empty query results cause
TypeError: Cannot read properties of null (reading 'map') - Workaround: Wrap queries in try-catch and handle the specific error, falling back to re-fetching data
- Affects
.returning()calls and empty.select()results
Authentication & Authorization
Authentication Strategy
- Passport.js with LocalStrategy for email/password authentication
- express-session for session management
- MemoryStore for development (consider connect-pg-simple for production)
- bcryptjs for password hashing
- SESSION_SECRET environment variable required
Admin Authorization
- Users have
isAdminboolean field (default: false) - Admin-only endpoints protected by
requireAdminmiddleware (returns 403 for non-admin) - Admin endpoints:
/api/admin/users,/api/admin/email-logs,/api/admin/upcoming-reminders - Frontend hides admin link for non-admin users
- Frontend route protection shows 404 for non-admin accessing /admin
- To make a user admin:
UPDATE users SET is_admin = true WHERE email = 'user@example.com'
External Dependencies
Database & ORM
- PostgreSQL (via Neon serverless)
- Drizzle ORM for query building and migrations
- Drizzle Kit for schema management
UI Component Libraries
- Radix UI primitives (20+ component packages)
- Tailwind CSS with PostCSS and Autoprefixer
- Lucide React for icons
- class-variance-authority (CVA) for component variants
- embla-carousel-react for carousel functionality
- react-day-picker for calendar/date selection
Form Management & Validation
- React Hook Form with Hookform Resolvers
- Zod for schema validation
- zod-validation-error for user-friendly error messages
Utilities
- date-fns for date manipulation
- clsx and tailwind-merge for className utilities
- nanoid for unique ID generation
Email Notifications
- nodemailer configured with Ethereal for development testing (captures emails without delivery)
- Production-ready with configurable SMTP (Resend, SendGrid, etc.) via environment variables
- Email templates support Spanish/English with HTML formatting
email_logstable tracks all sent emails with status, messageId, and errors- reminderService evaluates upcoming birthdays based on user preferences
- Debug endpoint
/api/debug/send-reminderfor testing (returns Ethereal preview URL) - Cron endpoint
/api/cron/process-remindersfor scheduled reminder processing - Email settings UI complete with timing and notification preferences
Development Tools
- Replit-specific plugins for error overlay, cartographer, and dev banner
- TypeScript with strict mode enabled
- Source map support via @jridgewell/trace-mapping
Potential Integrations (dependencies present but not actively used)
- Stripe for payments
- Google Generative AI
- OpenAI
- WebSocket (ws)
- Excel processing (xlsx)
- File uploads (multer)
- Rate limiting (express-rate-limit)
Build & Deployment
- Production build creates single CJS bundle for server
- Client assets bundled separately
- External dependencies not in allowlist remain as node_modules references
- Scripts:
dev(development),build(production),start(run production),db:push(schema sync)
What's inside
9 sections covering overview, architecture, frontend, backend, storage, auth, dependencies, and known issues.
Change this for your project
- Replace
Albertorela13/BirthdayReminderProwith your repository name - Replace
DATABASE_URLenvironment variable with your own Neon connection string - Replace
SESSION_SECRETenvironment variable with your own secret - Replace
user@example.comin admin SQL with your admin email
Where it goes
Keep it in your repository where the agent or team that needs it will read it.
Worth borrowing
- Interface-based storage layer (
IStorage) for swapping between database and in-memory implementations - Workaround for Neon HTTP driver empty-result bug using try-catch and re-fetch
- Admin authorization via
isAdminboolean field and middleware protecting API routes
Related Documents
GOOBY - Closing Store Marketplace
Defines a full-stack marketplace app for discovering closing retail stores in NY/NJ/CT/PA, with automated closure scanning and admin review.
Lua Code Obfuscator/Deobfuscator
Provides a full-stack web app for obfuscating and deobfuscating Roblox Lua scripts with a Monaco editor and PostgreSQL storage.
GREEN NODE - Project Overview
Describes a full-stack recycling platform with three runtime modes, provider architecture, and development scripts for Cochabamba, Bolivia.
ADN Systems DMR Peer Server
Documents a forked FreeDMR server for amateur radio DMR voice/data routing with bridges, proxies, scheduled voice announcements, and centralized security.