A full-stack React application with Vercel serverless functions backend, demonstrating Airbyte Embedded integration. For an overview and guided tutorial of using this sample app, please check out the Airbyte Embedded docs home
- React 19 with Vite build tool
- Airbyte Embedded Widget integration
- Cookie-based authentication
- Responsive design with modern CSS
The application uses Vercel Serverless Functions instead of a traditional Express server for better performance and scalability:
api/
βββ health.js # GET /api/health - Health check
βββ logout.js # POST /api/logout - User logout
βββ users/
β βββ index.js # POST /api/users - Create/login user
β βββ me.js # GET /api/users/me - Get current user
βββ airbyte/
β βββ token.js # POST /api/airbyte/token - Generate widget token
βββ _lib/ # Shared utilities
βββ auth.js # Authentication & CORS helpers
βββ db.js # Database operations
βββ airbyte.js # Airbyte API integration
- Serverless Architecture: Each API endpoint is an independent function
- Auto-scaling: Functions scale automatically based on demand
- Cookie-based Authentication: Secure HTTP-only cookies
- CORS Support: Configured for cross-origin requests
- File-based Database: Simple JSON storage (upgradeable to Vercel KV)
- Node.js 18+
- npm or yarn
- Airbyte workspace with Embedded enabled
- AWS S3 bucket (for data destination)
-
Clone the repository
git clone <repository-url> cd sonar-demoapp
-
Install dependencies
npm install
-
Set up environment variables Create a
.env.local
file in the root directory:# Frontend origin SONAR_ALLOWED_ORIGIN=http://localhost:5173 # Airbyte Embedded credentials (from Settings > Embedded) SONAR_AIRBYTE_ORGANIZATION_ID=your_organization_id SONAR_AIRBYTE_CLIENT_ID=your_client_id SONAR_AIRBYTE_CLIENT_SECRET=your_client_secret # AWS Credentials SONAR_AWS_ACCESS_KEY=your_aws_access_key SONAR_AWS_SECRET_ACCESS_KEY=your_aws_secret_access_key # S3 Configuration SONAR_S3_BUCKET=your_s3_bucket_name SONAR_S3_BUCKET_REGION=your_s3_bucket_region SONAR_S3_BUCKET_PREFIX=your_s3_bucket_prefix
-
Run the development server
# Start the frontend (React + Vite) npm run dev
The app will be available at
http://localhost:5173
-
Install Vercel CLI
npm install -g vercel
-
Run locally with serverless functions
vercel dev
This runs both the frontend and serverless functions locally, simulating the production environment.
npm run dev
- Start Vite development servernpm run build
- Build for productionnpm run preview
- Preview production build locallynpm run lint
- Run ESLint
SONAR_AIRBYTE_ORGANIZATION_ID=your_organization_id
SONAR_AIRBYTE_CLIENT_ID=your_client_id
SONAR_AIRBYTE_CLIENT_SECRET=your_client_secret
SONAR_AWS_ACCESS_KEY=your_aws_access_key
SONAR_AWS_SECRET_ACCESS_KEY=your_aws_secret_access_key
SONAR_S3_BUCKET=your_s3_bucket_name
SONAR_S3_BUCKET_REGION=your_s3_bucket_region
SONAR_S3_BUCKET_PREFIX=your_s3_bucket_prefix
SONAR_ALLOWED_ORIGIN=https://sonar-demoapp.vercel.app # Production
# or
SONAR_ALLOWED_ORIGIN=http://localhost:5173 # Development
SONAR_WEBAPP_PASSWORD=your_secure_password # Optional: Protect entire app with password
For production deployment, configure these environment variables in your Vercel dashboard.
POST /api/users
- Create new user or login existing userGET /api/users/me
- Get current authenticated userPOST /api/logout
- Logout user (clear auth cookie)
POST /api/airbyte/token
- Generate widget token for authenticated user
GET /api/health
- Health check endpoint
- User submits email via login form
- Backend creates user record (if new) or finds existing user
- Sets HTTP-only authentication cookie
- Frontend can now access protected endpoints
- Widget token generated on-demand for Airbyte integration
Uses a hybrid approach for data persistence:
- Primary storage for active user sessions
- Persists during serverless function warm state
- Automatically caches users from database lookups
- Provides fast access for authenticated operations
- Fallback storage in
/tmp
directory - Used when cache misses occur
- Provides persistence during function execution
Note: For production use, upgrade to:
- Vercel KV (Redis-based, recommended)
- Vercel Postgres (for relational data)
- External database (MongoDB, PostgreSQL, etc.)
{
"id": "timestamp_string",
"email": "user@example.com",
"createdAt": "2024-01-01T00:00:00.000Z"
}
- HTTP-only Cookies: Prevents XSS attacks
- CORS Configuration: Restricts cross-origin requests
- Environment Variables: Sensitive data not in code
- Input Validation: Email validation and sanitization
- Optional Password Protection: Protect entire application with a password
The application supports optional password protection to restrict access to the entire webapp. When enabled, users must enter the correct password before they can access any part of the application.
To enable password protection:
- Set the
SONAR_WEBAPP_PASSWORD
environment variable to your desired password - Deploy or restart your application
Features:
- Password is stored securely in environment variables
- Authentication persists for 24 hours via HTTP-only cookies
- Automatic fallback when password protection is disabled
- Clean, user-friendly password entry interface
To disable password protection:
- Remove or leave empty the
SONAR_WEBAPP_PASSWORD
environment variable
API Endpoints:
POST /api/auth/password
- Verify password and set authentication cookieGET /api/auth/check
- Check current password authentication status
- Connect your GitHub repository to Vercel
- Configure environment variables in Vercel dashboard
- Deploy automatically on git push
# Build the project
npm run build
# Deploy to Vercel
vercel --prod
If you encounter runtime errors during deployment:
- Ensure all serverless functions use ES module syntax (
export default
andimport
) - Remove any
vercel.json
file - Vercel auto-detects Node.js functions - Check that environment variables are properly configured in Vercel dashboard
- Verify all API functions are in the
/api
directory with.js
extension - Ensure
package.json
contains"type": "module"
for ES module support
If you see "Failed to fetch" errors in the browser:
- Ensure all frontend API calls use relative URLs (
/api/...
nothttp://localhost:3001/api/...
) - Check browser developer tools Network tab for actual HTTP status codes
- Verify CORS headers are properly set in serverless functions
- Confirm environment variables are configured in Vercel dashboard
βββ api/ # Serverless functions
β βββ _lib/ # Shared utilities
β βββ users/ # User management endpoints
β βββ airbyte/ # Airbyte integration endpoints
βββ src/ # React frontend source
β βββ components/ # React components
β βββ contexts/ # React contexts
β βββ hooks/ # Custom hooks
β βββ services/ # API service layer
βββ public/ # Static assets
βββ server/ # Legacy Express server (deprecated)
βββ package.json # Dependencies and scripts
- Create new file in
api/
directory - Export default async function handler
- Use shared utilities from
api/_lib/
- Follow existing patterns for CORS and error handling
Example:
import { setCorsHeaders } from './_lib/auth.js';
export default async function handler(req, res) {
if (setCorsHeaders(res, req)) return;
if (req.method !== 'GET') {
return res.status(405).json({ error: 'Method not allowed' });
}
res.json({ message: 'Hello World' });
}