This project provides a complete full-stack application setup using:
- Frontend: Vite with React and Tailwind CSS 4.0
- Backend: Self-hosted Convex with PostgreSQL
- Authentication: Keycloak OAuth 2.0
Everything is configured to run in a one-step Docker Compose setup with a clean separation between frontend and backend.
project/
├── frontend/ # React+Vite frontend (client-side)
│ ├── src/ # React application code
│ ├── public/ # Static assets
│ ├── convex.json # Convex client config
│ └── package.json # Frontend dependencies
│
├── backend/ # Convex backend (server-side)
│ ├── convex/ # Convex functions and schema
│ ├── .env.local # Environment variables for Convex
│ └── package.json # Backend dependencies
│
├── docker-compose.yml # Docker Compose configuration
├── init-all.sh # Linux/Docker initialization script
└── README.md # This documentation file
-
Clone this repository
-
Start the Docker services:
docker compose up -d- Generate a Convex admin key:
docker compose exec backend bash -c "cd /convex && ./generate_admin_key.sh"- Create a
.env.localfile in thebackenddirectory with the generated admin key:
CONVEX_SELF_HOSTED_URL=http://localhost:3210
CONVEX_SELF_HOSTED_ADMIN_KEY=your_admin_key_here
-
Manually configure Keycloak with the following steps:
- Access Keycloak admin console at http://localhost:8080/admin
- Default admin credentials: username
admin, passwordadmin - Create a new realm or use the default "master" realm
- Create a client with Client ID
vite-app - Configure client settings:
- Set Access Type to
public - Set Valid Redirect URIs to
http://localhost:3000/* - Set Web Origins to
http://localhost:3000(or*for development)
- Set Access Type to
- Create a test user in the realm
-
Create a
.env.localfile in thefrontenddirectory with your Keycloak settings:
VITE_KEYCLOAK_URL=http://localhost:8080
VITE_KEYCLOAK_REALM=master
VITE_KEYCLOAK_CLIENT_ID=vite-app
- Deploy Convex schema:
cd backend
npm install
npx convex deploy- Install frontend dependencies:
cd frontend
npm install
npm run dev- PostgreSQL: Shared database for both Convex and Keycloak
- Keycloak: Open source identity and access management
- Convex: Real-time backend with automatic API generation
- Vite: Next generation frontend tooling
- React: UI library with TypeScript support (client-side only)
- Tailwind CSS 4.0: Utility-first CSS framework
- Convex: Backend-as-a-service with real-time data sync
- PostgreSQL: Relational database for persistent storage
- TypeScript: Strongly typed schema and functions
| Service | URL | Description |
|---|---|---|
| Frontend App | http://localhost:3000 | The main application |
| Convex Dashboard | http://localhost:6791 | Convex admin dashboard |
| Convex Backend | http://localhost:3210 | Convex API endpoint |
| Keycloak | http://localhost:8080 | Authentication server |
| PostgreSQL | localhost:5432 | Database (not directly accessible) |
Keycloak does not come with pre-configured settings. You need to manually create and configure it:
- Access Keycloak admin console at http://localhost:8080/admin
- Default admin credentials: username
admin, passwordadmin - Configure the Keycloak realm and client:
- Create a new realm or use the "master" realm
- Create a new client ID (e.g.,
vite-app) - Configure client settings:
- Set Access Type to
public - Set Valid Redirect URIs to
http://localhost:3000/* - Set Web Origins to
http://localhost:3000or*for development
- Set Access Type to
- Create test users as needed in the realm
After configuring Keycloak, you need to create the following environment files:
Backend .env.local:
# Convex configuration
CONVEX_SELF_HOSTED_URL=http://localhost:3210
CONVEX_SELF_HOSTED_ADMIN_KEY=your_generated_admin_key
# Keycloak configuration for backend validation
KEYCLOAK_URL=http://localhost:8080
KEYCLOAK_REALM=master
KEYCLOAK_CLIENT_ID=vite-app
# Token validation settings
TOKEN_EXPIRATION_GRACE_PERIOD_SECONDS=30
MAX_TOKEN_AGE_SECONDS=86400
# Rate limiting settings
RATE_LIMITING_WINDOW_MS=60000
RATE_LIMITING_MAX_REQUESTS=5
# Valid issuers for token validation
VALID_ISSUERS=http://localhost:8080/realms/master,http://keycloak:8080/realms/master,https://localhost:8443/realms/master
# Valid clients, audiences and sources
VALID_CLIENT_IDS=vite-app
VALID_AUDIENCES=master-realm,account
VALID_SOURCES=vite-app,master-realm
Frontend .env.local:
# Convex URL for client connection
VITE_CONVEX_URL=http://localhost:3210
# Keycloak configuration for frontend authentication
VITE_KEYCLOAK_URL=http://localhost:8080
VITE_KEYCLOAK_REALM=master
VITE_KEYCLOAK_CLIENT_ID=vite-app
To access the Convex dashboard:
- Go to http://localhost:6791
- Enter the admin key when prompted (generated during setup)
- Frontend: The frontend code is mounted as a volume, so changes will be automatically reflected after a page refresh
- Backend: After making changes to functions in the
backend/convexdirectory, run:
cd backend
npx convex deploy┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Browser │────▶│ Frontend │────▶│ Convex │
│ │◀────│ (Vite+React)│◀────│ Backend │
└─────────────┘ └─────────────┘ └──────┬──────┘
│ │ │
│ │ │
│ ┌────▼────┐ ┌────▼────┐
└──────────────▶│ Keycloak │──────▶│ Postgres │
│ (Auth) │ │ DB │
└──────────┘ └─────────┘
- Ensure you've created the proper
.env.localfiles in both backend and frontend directories - Make sure the Convex admin key generated is correctly copied to the backend
.env.localfile - If Keycloak configuration fails, check that you've properly set up the client in the Keycloak admin console
- Check Docker Compose logs with
docker compose logs <service-name> - Ensure all ports are available on your host machine
- Make sure Keycloak is properly configured with the correct redirect URIs
- Check that your
.env.localfiles contain the correct Keycloak settings - Verify that the client ID matches between Keycloak setup and your environment files
- Check the browser console for any CORS or OAuth-related errors
- If the frontend can't connect to Convex, check that the backend is running
- Verify that the
CONVEX_URLenvironment variable is set correctly - Make sure the admin key is properly set in
.env.local
If you see errors like Could not find public function for 'tasks:get':
- Make sure your Convex schema was properly deployed
- Check if the function exists in your
/backend/convexdirectory - Run a manual deployment:
cd backend npx convex deploy
MIT



