If you don't have Poetry installed, install it first:
curl -sSL https://install.python-poetry.org | python3 -(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | python -Initialize a new Poetry project:
poetry initFollow the interactive prompts:
- Package name:
keep-in-touch - Version:
0.1.0 - Description:
A simple contact management system with reminders - Author: Your name
- License:
MIT - Python version:
^3.10 - Define dependencies interactively:
no(we'll add them manually)
Add the required dependencies:
poetry add flask sqlalchemy apscheduler htmx-flask flask-wtf gunicorn python-dotenv jinja2 email-validatorAdd development dependencies:
poetry add --group dev pytest pytest-flask black flake8Ensure you have Node.js installed:
# Check if Node.js is installed
node -vIf not installed, download and install from nodejs.org.
Install Tailwind CSS:
# Initialize package.json if it doesn't exist
npm init -y
# Install Tailwind CSS
npm install -D tailwindcss
# Initialize Tailwind CSS configuration
npx tailwindcss initCreate the basic directory structure:
mkdir -p app/routes app/services app/templates/emails app/static/{css,js} migrations testsThe Poetry initialization will have created a pyproject.toml file, but you may want to manually edit it to ensure it has the right configuration:
[tool.poetry]
name = "keep-in-touch"
version = "0.1.0"
description = "A simple contact management system with reminders"
authors = ["Your Name <your.email@example.com>"]
readme = "README.md"
[tool.poetry.dependencies]
python = "^3.10"
flask = "^2.3.3"
sqlalchemy = "^2.0.20"
apscheduler = "^3.10.4"
htmx-flask = "^0.1.0"
flask-wtf = "^1.1.1"
gunicorn = "^21.2.0"
python-dotenv = "^1.0.0"
jinja2 = "^3.1.2"
email-validator = "^2.0.0"
[tool.poetry.group.dev.dependencies]
pytest = "^7.4.0"
pytest-flask = "^1.2.0"
black = "^23.7.0"
flake8 = "^6.1.0"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"Replace the previous docker-compose.yml with a Poetry-compatible version:
version: '3.8'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- ./app:/app/app
- ./data:/data
environment:
- FLASK_APP=run.py
- FLASK_ENV=production
- DATABASE_URL=sqlite:////data/round_again.db
- EMAIL_HOST=${EMAIL_HOST}
- EMAIL_PORT=${EMAIL_PORT}
- EMAIL_USER=${EMAIL_USER}
- EMAIL_PASSWORD=${EMAIL_PASSWORD}
- EMAIL_FROM=${EMAIL_FROM}
- USER_EMAIL=${USER_EMAIL}
restart: unless-stopped
command: poetry run gunicorn --bind 0.0.0.0:5000 run:appFROM python:3.10-slim
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV POETRY_HOME=/opt/poetry
ENV POETRY_VERSION=1.6.1
ENV PATH="$POETRY_HOME/bin:$PATH"
# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
curl \
&& rm -rf /var/lib/apt/lists/*
# Install Poetry
RUN curl -sSL https://install.python-poetry.org | python3 -
# Set working directory
WORKDIR /app
# Copy Poetry configuration files
COPY pyproject.toml poetry.lock* /app/
# Configure Poetry to not create a virtual environment
RUN poetry config virtualenvs.create false
# Install dependencies
RUN poetry install --no-interaction --no-ansi --no-dev
# Copy application code
COPY . /app/
# Create data directory for SQLite database
RUN mkdir -p /data
VOLUME /data
# Expose port
EXPOSE 5000
# Run the application
CMD ["poetry", "run", "gunicorn", "--bind", "0.0.0.0:5000", "run:app"]Create a .env.example file:
# Flask configuration
SECRET_KEY=your_secret_key_here
FLASK_APP=run.py
FLASK_ENV=development
# Database configuration
DATABASE_URL=sqlite:///data/round_again.db
# Email configuration
EMAIL_HOST=smtp.example.com
EMAIL_PORT=587
EMAIL_USER=your_email@example.com
EMAIL_PASSWORD=your_email_password
EMAIL_FROM=noreply@keepintouch.app
# User configuration
USER_EMAIL=your_email@example.com
Copy this to a .env file and fill in your actual values:
cp .env.example .env
# Edit .env with your actual valuesCreate a run.py file at the project root:
from app import create_app
app = create_app()
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')# Using make
make dev
# Directly using Python
poetry run python run.py --tailwind# Using make
make css-build
# Directly using npm
npx tailwindcss -i ./app/static/css/input.css -o ./app/static/css/styles.css --minify# Using make
make css-watch
# Directly using npm
npx tailwindcss -i ./app/static/css/input.css -o ./app/static/css/styles.css --watchpoetry shell
python run.py --tailwindpoetry run pytestpoetry run black app testsBuild and start with Docker Compose:
docker-compose build
docker-compose up -dCheck logs:
docker-compose logs -fStop containers:
docker-compose down