This project generates a PDF calendar with tide information for a specified tide station, year, and month. It includes a web interface built with Flask, and the application can be containerized using Docker.
- Python 3.9 or later
- Docker
- Git (for version control)
-
Clone the repository:
git clone https://github.com/matt-the-ogre/tide-calendar-site.git cd tide-calendar-site -
Create and activate a virtual environment:
python3 -m venv venv source venv/bin/activate # On Windows use `venv\Scripts\activate`
-
Install the required Python packages:
pip install -r requirements.txt
-
Install system dependencies:
Linux:
sudo apt-get update sudo apt-get install -y pcal ghostscript
macOS:
brew update; brew upgrade brew install pcal ghostscript
-
Set environment variables:
Create a
.envfile in the project root with the following content:FLASK_APP=run.py FLASK_ENV=development -
Run the Flask app:
cd app flask run --debug --host 0.0.0.0 --port 5001 -
Access the app:
Open your web browser and go to
http://127.0.0.1:5001/.
-
Build the Docker image:
docker build -t tide-calendar-app .
-
Run the Docker container:
docker run -p 5001:5001 tide-calendar-app
-
Access the app:
Open your web browser and go to
http://127.0.0.1:5001/.
tide_calendar/
├── app/
│ ├── __init__.py
│ ├── routes.py # Web routes with form validation and API endpoints
│ ├── get_tides.py # Tide data processing and PDF generation
│ ├── database.py # SQLite operations and station search functions
│ ├── tide_stations_new.csv # Canonical tide station database (2,900+ stations)
│ ├── tide-stations-raw-new.md # Raw NOAA station data source
│ ├── tide_station_ids.db # SQLite database with usage tracking
│ ├── templates/
│ │ ├── index.html # Main interface with autocomplete
│ │ └── tide_station_not_found.html
│ └── static/
│ ├── style.css
│ ├── favicon.ico
│ └── tide-calendar-example.webp
├── convert_stations_final.py # Utility to convert MD to CSV with proper formatting
├── run.py # Application entry point
├── requirements.txt
├── Dockerfile
├── CLAUDE.md # Development documentation
└── README.md
- app/init.py: Initializes the Flask app and database.
- app/routes.py: Web routes with form validation, API endpoints for autocomplete, and cookie management.
- app/get_tides.py: Script to generate the PDF calendar with tide information.
- app/database.py: SQLite operations including station search, autocomplete, and usage tracking.
- app/tide_stations_new.csv: Canonical database of 2,900+ tide stations with proper place names.
- app/templates/index.html: Main web interface with intelligent autocomplete and responsive design.
- app/static/: Contains CSS styling, favicon, and example images.
- convert_stations_final.py: Utility script to convert raw NOAA data to properly formatted CSV.
- run.py: Entry point to run the Flask app with automatic database initialization.
- CLAUDE.md: Development documentation and architecture overview.
- requirements.txt: List of Python dependencies.
- Dockerfile: Instructions to build the Docker image.
- Smart Autocomplete: Search tide stations by place name with intelligent suggestions
- Comprehensive Database: 2,900+ USA and Canadian tide stations with proper geographic disambiguation
- Country Filter: Easy radio button selection to filter by USA, Canada, or view all stations
- User-Friendly Interface: Type place names like "Point Roberts, WA" or use station IDs
- Remember Last Used: Automatically remembers your last successful location
- PDF Generation: Creates downloadable monthly tide calendars
- Start typing a place name (e.g., "Seattle", "Miami", "San Francisco")
- Select from the autocomplete dropdown suggestions
- Choose your desired year and month
- Click "Generate and download the PDF"
- Type a complete place name (e.g., "Point Roberts, WA")
- Choose your desired year and month
- Click "Generate and download the PDF"
- Enter a 7-digit NOAA tide station ID directly
- Choose your desired year and month
- Click "Generate and download the PDF"
- Ensure
pcalandghostscriptare installed on your system if running locally. - The app defaults to "Point Roberts, WA" for demonstration purposes.
- All tide stations are sourced from NOAA's official tide station database.
- The application automatically tracks popular stations for better autocomplete suggestions.
For deployment, it's common practice to use standard HTTP (port 80) or HTTPS (port 443) ports to make the application accessible over the web without specifying a port number in the URL. Here’s how you can set this up in your Docker deployment.
-
Modify the Docker Run Command
To use port 80 or 443, map the internal port 5001 to the desired external port.
For HTTP (port 80):
docker run -p 80:5001 tide-calendar-app
For HTTPS (port 443):
docker run -p 443:5001 tide-calendar-app
-
Using HTTPS (port 443)
If you are using HTTPS, you'll need to set up SSL/TLS certificates. This is typically done using a reverse proxy like Nginx or a cloud provider's load balancer that handles SSL termination.
-
Nginx Configuration
Create an Nginx configuration file to proxy requests to your Flask app running inside Docker.
nginx.conf:
server { listen 80; server_name yourdomain.com; location / { proxy_pass http://localhost:5001; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
-
Docker Compose
You can use Docker Compose to run both your Flask app and Nginx.
docker-compose.yml:
version: '3' services: app: build: . ports: - "5001:5001" environment: FLASK_ENV: production nginx: image: nginx:latest ports: - "80:80" volumes: - ./nginx.conf:/etc/nginx/conf.d/default.conf depends_on: - app
-
Building and Running with Docker Compose
docker-compose up --build
If you are using port 443, you’ll need to set up SSL certificates. Let’s Encrypt is a popular free option. Here’s a basic setup using Certbot with Nginx.
-
Install Certbot
Install Certbot and the Nginx plugin on your server.
For Ubuntu:
sudo apt-get update sudo apt-get install certbot python3-certbot-nginx
-
Obtain and Install SSL Certificate
sudo certbot --nginx -d yourdomain.com
Follow the prompts to obtain and install the certificate.
-
Automatic Renewal
Certbot automatically installs a cron job for certificate renewal. You can test the renewal process with:
sudo certbot renew --dry-run
- For production deployment, map port 5001 to port 80 for HTTP or port 443 for HTTPS in your Docker run command.
- Use Nginx as a reverse proxy to manage incoming traffic and SSL termination.
- Obtain and configure SSL certificates if using HTTPS, using tools like Certbot and Let's Encrypt.
- If you encounter a
500 Internal Server Error, check the Flask console output for detailed error messages. - Ensure all environment variables are set correctly, and dependencies are installed.
Contributions are welcome! Please fork the repository and submit a pull request for review.
This project is licensed under the GNU GPL v3 License.