8.7 KiB
📅 Turmli Bar Calendar Tool
A modern, mobile-friendly web application that fetches and displays calendar events from an ICS (iCalendar) feed. Built with Python, FastAPI, and a responsive web interface.
✨ Features
- Automatic Daily Updates: Fetches calendar data automatically every day and every 4 hours
- Mobile-Responsive Design: Warm, inviting interface optimized for all devices
- Bar-Themed Colors: Cozy atmosphere with rich browns and warm earth tones
- Custom Branding: Integrated Turmli Bar logo
- Event Grouping: Events organized by date for easy viewing
- Caching: Local caching ensures calendar is available even if the source is temporarily unavailable
- API Endpoints: JSON API for programmatic access to calendar data
- Real-time Updates:
- Manual refresh button triggers actual ICS file fetch
- Auto-refresh with countdown timer (5 minutes)
- Status messages showing fetch progress and results
- Container Support: Docker and Podman compatible for easy deployment
🚀 Quick Start
Option 1: Container Deployment (Docker/Podman)
Using Docker
# Clone the repository
git clone <repository-url>
cd turmli-bar-calendar-tool
# Deploy with Docker
./deploy.sh start
# Or deploy with Podman (rootless containers)
./deploy-podman.sh start
The application will be available at http://localhost:8000
Option 2: Local Development
Prerequisites
- Python 3.13 or higher
- uv package manager (for local development only)
Installation
- Clone the repository:
git clone <repository-url>
cd turmli-bar-calendar-tool
- Install dependencies using uv:
uv sync
- Run the server:
./run.sh
Or directly with uv:
uv run uvicorn main:app --host 0.0.0.0 --port 8000 --reload
- Open your browser and navigate to:
http://localhost:8000
📱 Features & Interface
Web Interface
- Responsive Design: Optimized for mobile phones, tablets, and desktops
- Visual Calendar: Warm, inviting display with time, location, and all-day indicators
- Bar Atmosphere: Rich brown and tan colors that evoke a cozy bar environment
- Branded Experience: Features the Turmli Bar logo with subtle sepia toning
- Smart Refresh:
- Manual refresh button that fetches new data from the ICS source
- Auto-refresh countdown timer (5 minutes)
- Visual feedback showing fetch progress and results
- Displays whether data has changed since last update
Event Display
- Events grouped by date
- Shows next 30 days of events
- Clear time indicators for scheduled events
- "All Day" badges for full-day events
- Location information with map pin icons
- Smooth animations and hover effects
🔧 Configuration
Timezone
By default, the application uses Europe/Berlin timezone. To change it, modify the timezone in main.py:
tz = pytz.timezone('Europe/Berlin') # Change to your timezone
Calendar URL
The calendar ICS URL is configured in main.py. To use a different calendar:
CALENDAR_URL = "your-calendar-ics-url-here"
Update Schedule
The calendar updates:
- Daily at 2:00 AM
- Every 4 hours throughout the day
You can modify the schedule in the startup_event function in main.py.
🌐 API Endpoints
GET /
Returns the HTML interface with calendar events
GET /api/events
Returns calendar events in JSON format:
{
"events": [
{
"title": "Meeting",
"location": "Conference Room",
"start": "2024-01-15T10:00:00",
"end": "2024-01-15T11:00:00",
"all_day": false
}
],
"last_updated": "2024-01-15T08:00:00"
}
POST /api/refresh
Manually triggers a calendar refresh from the ICS source:
{
"status": "success",
"message": "Calendar refreshed successfully",
"events_count": 15,
"previous_count": 14,
"data_changed": true,
"last_updated": "2024-01-15T08:00:00"
}
The refresh button in the UI:
- Shows a loading spinner while fetching
- Displays success/error status
- Shows if data has changed
- Automatically reloads the page after successful fetch
- Resets the auto-refresh countdown timer
🎨 Customization
Logo
The application displays the Turmli Bar logo (Vektor-Logo.svg) in the header. To use a different logo:
- Place your logo file in the project root or
static/directory - Update the logo path in
main.pyif needed
Styling
The interface uses warm, bar-appropriate colors with rich browns (#2c1810, #8b4513), warm tans (#f4e4d4, #d4a574), and cream accents. The design creates a cozy, inviting atmosphere while maintaining excellent readability. Colors are easy on the eyes with subtle gradients and soft shadows. You can customize the appearance by modifying the CSS in the HTML_TEMPLATE variable in main.py.
Event Display Period
By default, shows events for the next 30 days. Change this in the fetch_calendar function:
cutoff = now + timedelta(days=30) # Modify the number of days
🚢 Deployment
🐳 Container Deployment (Docker/Podman)
Quick Start
# Deploy the application
./deploy.sh start # Start on default port 8000
PORT=8080 ./deploy.sh start # Start on custom port
# Manage the application
./deploy.sh status # Check container status
./deploy.sh logs # View application logs
./deploy.sh stop # Stop container
./deploy.sh restart # Restart container
./deploy.sh update # Pull updates and restart
Container Files Included
- Dockerfile/Containerfile: Python 3.13 container (uses pip for simplicity)
- docker-compose.yml: Docker Compose configuration
- podman-compose.yml: Podman Compose configuration
- deploy.sh: Docker deployment script
- deploy-podman.sh: Podman deployment script (supports rootless)
Note: The container uses pip for dependency installation to keep things simple. Local development still uses uv for better package management.
Podman Support
Podman is a daemonless, rootless container engine that's a drop-in replacement for Docker:
# Using Podman deployment script
./deploy-podman.sh start
# Generate systemd service (Podman only)
./deploy-podman.sh systemd
See PODMAN_README.md for detailed Podman instructions.
Container Features
- Simple Build: Straightforward Python container
- Health Checks: Built-in monitoring endpoint
- Volume Persistence: Calendar cache persists between restarts
- Auto-restart: Container restarts automatically on failure
Environment Variables
Set the port if needed (default is 8000):
PORT=8080 ./deploy.sh start
Or use compose directly:
# Docker Compose
PORT=8080 docker-compose up -d
# Podman Compose
PORT=8080 podman-compose -f podman-compose.yml up -d
Simple Container Commands
# Using the deployment script (recommended)
./deploy.sh start # Build and start
./deploy.sh stop # Stop container
./deploy.sh logs # View logs
./deploy.sh status # Check health (Docker)
./deploy-podman.sh status # Check health (Podman)
# Or use container commands directly
# Docker:
docker build -t turmli-calendar .
docker run -d -p 8000:8000 -v $(pwd)/calendar_cache.json:/app/calendar_cache.json turmli-calendar
# Podman (rootless):
podman build -t turmli-calendar .
podman run -d -p 8000:8000 -v $(pwd)/calendar_cache.json:/app/calendar_cache.json:Z turmli-calendar
Traditional Deployment
For non-container deployments, use systemd:
[Unit]
Description=Turmli Bar Calendar Tool
After=network.target
[Service]
Type=simple
User=youruser
WorkingDirectory=/path/to/turmli-bar-calendar-tool
ExecStart=/usr/bin/uv run uvicorn main:app --host 0.0.0.0 --port 8000
Restart=on-failure
[Install]
WantedBy=multi-user.target
Notes for Internal Use
- The application runs on a single port (default 8000)
- No SSL/HTTPS needed for internal network
- Simple Python server is sufficient for ~30 users
- Calendar cache persists in
calendar_cache.json - Automatic refresh every 5 minutes
📝 License
MIT License - feel free to use and modify as needed.
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
🐛 Troubleshooting
Calendar not updating
- Check the console logs for any error messages
- Verify the ICS URL is accessible
- Check the
calendar_cache.jsonfile for cached data
Events not showing
- Ensure the calendar has events in the next 30 days
- Check timezone settings match your location
- Verify the ICS file format is valid
Port already in use
- Change the port in
run.shor when running uvicorn directly - Check for other processes using port 8000:
lsof -i :8000