A simple web application for coordinating team schedules. Create surveys, share them with your team, and find the best dates for meetings, events, or gatherings.
- Create Surveys: Generate unique survey codes for different events
- Mark Unavailable Dates: Team members select dates they can't attend
- Merged Calendar View: See everyone's availability at a glance with a heat map
- Find Available Dates: Automatically find consecutive date ranges that work for everyone
- Admin Dashboard: Manage surveys and submissions with password protection
- Node.js 18+
- npm or yarn
# Clone the repository
git clone https://github.com/andriuskuc/availability-finder.git
cd availability-finder
# Install all dependencies
npm run install:all
# Copy environment file and configure
cp .env.example .envEdit .env and set your admin password:
ADMIN_PASSWORD=your-secure-password
SESSION_SECRET=random-string-here
# Start both server and client in development mode
npm run dev- Frontend: http://localhost:5173
- Backend API: http://localhost:3001
# Build both client and server
npm run build
# Start production server
npm start- Navigate to
/adminand log in with your password - Create a new survey with a descriptive name
- Share the generated survey link with your team
- View submissions and use the merged calendar to find optimal dates
- Open the survey link shared with you
- Enter your name
- Click or drag on the calendar to mark dates you're NOT available
- Submit your availability
- Frontend: React, TypeScript, Tailwind CSS, Vite
- Backend: Node.js, Express, TypeScript
- Database: SQLite (via better-sqlite3)
- Authentication: Express sessions
availability-finder/
├── client/ # React frontend
│ ├── src/
│ │ ├── components/ # Reusable UI components
│ │ ├── hooks/ # Custom React hooks
│ │ ├── pages/ # Page components
│ │ ├── services/ # API client
│ │ └── types/ # TypeScript types
│ └── ...
├── server/ # Express backend
│ ├── src/
│ │ ├── config/ # Database and migrations
│ │ ├── middleware/ # Express middleware
│ │ ├── routes/ # API routes
│ │ └── types/ # TypeScript types
│ └── ...
├── data/ # SQLite database storage
└── ...
GET /api/surveys/:code- Get survey by codeGET /api/surveys/:code/check-name/:name- Check if name already submittedPOST /api/surveys/:code/submit- Submit availability
GET /api/admin/check-auth- Check authentication statusPOST /api/admin/login- Admin loginPOST /api/admin/logout- Admin logoutGET /api/admin/surveys- List all surveysPOST /api/admin/surveys- Create surveyDELETE /api/admin/surveys/:id- Delete surveyGET /api/admin/surveys/:id/submissions- Get submissionsDELETE /api/admin/surveys/:id/submissions- Reset all submissionsDELETE /api/admin/submissions/:id- Delete single submission
The project includes comprehensive tests for both frontend and backend.
# Run all tests
npm test
# Run server tests only
npm run test:server
# Run client tests only
npm run test:client
# Run tests with coverage
npm run test:coverage- Server: Jest + Supertest for API testing
- Client: Vitest + React Testing Library for component testing
Tests run automatically on every push and pull request via GitHub Actions.
The application uses a lightweight migration system built on SQLite's user_version pragma. Migrations run automatically on server startup.
- Migration files are in
server/src/config/migrations.ts - Each migration has a version number and runs exactly once
- The current schema version is tracked in the database itself
- Migrations run in transactions for safety
To add a schema change, append a new migration to the migrations array:
{
version: 3,
name: 'your_migration_name',
up: (db) => {
// Your schema changes here
db.exec(`ALTER TABLE ...`);
},
},Migrations are idempotent where possible - they check for existing columns/tables before making changes.
- Create a new project on Railway
- Connect your repository
- Set environment variables in Railway dashboard:
ADMIN_PASSWORDSESSION_SECRETNODE_ENV=production
- Add a Volume for persistent storage:
- Go to your service → Settings → Volumes
- Click + New Volume
- Set Mount Path to
/app/data - This ensures your SQLite database persists across deployments
- Deploy
Works with any Node.js hosting platform. Ensure:
- Node.js 18+ is available
- The
data/directory is writable and persistent - Environment variables are configured
| Variable | Description | Default |
|---|---|---|
PORT |
Server port | 3001 |
NODE_ENV |
Environment | development |
ADMIN_PASSWORD |
Admin login password | Required |
SESSION_SECRET |
Session encryption key | Required |
CLIENT_URL |
Frontend URL (for CORS) | http://localhost:5173 |
MIT