Skip to content

My portfolio, blog, and mini-projects website, revamped for 2024

License

Notifications You must be signed in to change notification settings

VerdantFox/code-with-teddy

Repository files navigation

code-with-teddy

My portfolio, blog, and mini-projects website, revamped for 2024

Setup

You'll need to install a few things to get the website running locally. The website is built with Python and FastAPI for the backend, and uses TailwindCSS, Alpine.js and HTMX on the front end. The database is Postgres with the SQLAlchemy ORM.

Python

First, install uv for package management. I recommend installing pipx and then:

pipx install uv

Then install python environment:

# Create a virtual environment
uv venv --python=3.12 venv
source venv/bin/activate

# Install DEV dependencies
uv pip install -r requirements-dev.txt

Update requirements with:

./scripts/update-requirements.sh

Node

First, install the latest versions of npm and node. Then install the node environment:

# Install node environment
npm install

Docker

You'll need to install Docker to run the website locally. Even if not running the app itself in Docker, its used for running the Postgres database. You can install Docker from here. Deployments use Docker and Docker Compose, so you'll need to install Docker Compose as well. You can install Docker Compose from here.

Docker and Docker Compose configurations are in docker_config.

Tools

Install xdotool for run-dev script

ubuntu:

sudo apt-get install xdotool

Install npx for updating node dependencies.

Running the app

Start the database locally

To start up the local database for development, run:

python -m scripts.start_local_postgres

👆 By default this creates a Postgres docker container and populates it with dummy data.

Start the app locally

To run the app locally, you can use the following command:

python -m scripts.run_dev

This will start an instance of tailwind that will build the CSS and watch for changes. It will also update the Python requirements, start up the Postgres database docker container if it is not already running, and start the FastAPI server.

Run the app locally with Docker

To run the app in Docker, use the following command:

./scripts/deploy.sh

This command assumes that the Postgres database is not already started by scripts/start_local_postgres.py, and that the app is already running locally. You'll need to stop those processes before running the deploy script.

./scripts/deploy.sh deploys the dev environment by default which doesn't set up SSL for nginx and doesn't write the crontab.

To stop the app, use:

./scripts/deploy.sh --down

For more options, use:

./scripts/deploy.sh --help

Testing

Tests are written in Python with pytest. They include functional tests against the FastAPI endpoints, unit tests against key functions, and end-to-end tests using Playwright.

To run the playwright tests, you'll need to first install the playwright browsers:

playwright install

To run tests use one of the following commands:

# Standard run of functional and unit tests
pytest

# Run the playwright tests against localhost (requires a running instance of the app)
pytest --playwright local

# Run all tests (end-to-end against localhost), including the playwright tests
pytest --all

# To see test coverage:
pytest --cov --cov-report=term --cov-report=html

Linting

I use pre-commit to run linting and formatting checks before every commit. Install the pre-commit hooks with:

pre-commit install

To run the checks manually, use:

pre-commit run --all-files

Lint checks include (but are not limited to):

  • ruff (lots of Python lint checks, auto-fixes, and autoformatting)
  • mypy (static Python type checking)
  • prettier (HTML, CSS, JS, YAML formatting)

Updating dependencies

To update dependencies, run:

# Update Python dependencies
./scripts/update-requirements.sh --python

# Update Node dependencies
./scripts/update-requirements.sh --node

# Update static dependencies
./scripts/update-requirements.sh --static

# Update pre-commit hooks
./scripts/update-requirements.sh --pre-commit

# Update all dependencies
./scripts/update-requirements.sh --all

Settings and secrets

Settings and secrets for the Python app are handled by the app.settings module, using the Pydantic BaseSettings class. The settings are loaded from environment variables, which can be set in a .env file in the root of the project. The .env file is not checked into version control, but a .env.local file is provided as a template. Secrets are stored in the secrets directory, which is not checked into version control. Secrets are files who's name is the secret key and they contain just the secret value. Secrets are loaded onto the settings object at runtime.

Database migrations

Database migrations are handled by Alembic. See the README.md in the migrations directory for more information.

Deployment

CI/CT/CD pipeline deployment

The CI/CT/CD pipeline is set up with GitHub Actions. The pipeline is defined in .github/workflows/run-full-ci.yml. You can find the GitHub action pipeline here.

On every push to the main branch, the CI/CD pipeline will run the tests and linting. If all checks pass, the pipeline will update the release-branch branch to the latest commit on main. This branch is used for deployment to the production server.

Server-side, a cron job runs every 5 minutes to check for new commits on the release-branch. If a new commit is found, the server will pull the latest changes and restart the FastAPI server with ./scripts/deploy.sh --prod.

Manual deployment

To deploy the app manually, SSH into the server, go to the project, and use the following command:

./scripts/deploy.sh --prod

This will deploy the app in production mode, which includes setting up SSL for nginx and write to the crontab to set up the server to restart the app daily and run further deployments by the CI/CD pipeline.

SSL

SSL certificates are generated by the domain registrar and are stored in the certs directory. The certificates are not checked into version control. The SSL cert files will need to be stored at certs/<DOMAIN>/ with the following names:

  • domain.cert.pem
  • intermediate.cert.pem
  • private.key.pem
  • public.key.pem

In addition to the SSL certificates, you'll need to generate a Diffie-Hellman key exchange file for nginx. You can generate this file with the following command:

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

The resulting file will need to be stored at certs/certs/dhparam.pem.

About

My portfolio, blog, and mini-projects website, revamped for 2024

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published