Get your machine and your repository ready.
By the end you’ll have a working development environment, the
opentrash repository created and cloned, an empty documentation site
skeleton ready to grow, and the package name claimed. Works on macOS, Windows, and
Linux. Plan about 90 minutes the first time.
opentrash as the package
and repository name throughout. Name yours anything — wherever you see
opentrash, substitute your own name. Just be consistent.
1 Development environment
Five tools: Python (via miniforge), VS Code, git, the GitHub CLI, and UV. If you already have any, skip that step.
1 Install miniforge (Python 3.11)
Miniforge is a minimal Python distribution using conda-forge by default — lighter and cleaner than full Anaconda.
curl -L -O "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-MacOSX-arm64.sh"
bash Miniforge3-MacOSX-arm64.sh
When prompted: accept the license (yes), accept the default location, answer yes to initialize. Then close and reopen Terminal.
curl -L -O "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-MacOSX-x86_64.sh"
bash Miniforge3-MacOSX-x86_64.sh
Download Miniforge3-Windows-x86_64.exe from the miniforge releases page and run it. Choose Just Me, and on Advanced Options check “Add Miniforge3 to my PATH.” Afterwards use the Miniforge Prompt from the Start menu.
curl -L -O "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-x86_64.sh"
bash Miniforge3-Linux-x86_64.sh
conda --version
Shows conda 24.x.x or similar. “Command not found” means the terminal didn’t reload — close it completely and reopen.
2 Install VS Code
Download from code.visualstudio.com and install. Open the Extensions panel and install:
- Python (Microsoft)
- Jupyter (Microsoft)
- GitLens (GitKraken) — optional but helpful
macOS: make the code command available — press Cmd+Shift+P, run “Shell Command: Install 'code' command in PATH.” Windows/Linux installers handle this.
code --version
3 Install git (and Homebrew on macOS)
Homebrew is the standard macOS package manager and makes the rest easy.
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Follow the on-screen instructions to add Homebrew to your PATH (the installer prints the exact lines). Then:
brew install git
Download from git-scm.com. Choose VS Code as default editor if offered, and “Git from the command line and also from 3rd-party software” for PATH.
sudo apt install git
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
git --version
4 Install the GitHub CLI and sign in
The GitHub CLI (gh) is the fastest way to authenticate — no manual SSH keys. It handles credentials through a quick browser login.
brew install gh
winget install --id GitHub.cli
Or download from cli.github.com.
Follow the steps at cli/cli install guide.
gh auth login
Choose GitHub.com → HTTPS → Yes (authenticate Git) → Login with a web browser. Copy the one-time code, press Enter, approve in your browser. Far simpler than SSH keys.
ssh-keygen -t ed25519 -C "you@example.com", add the public key at github.com/settings/keys, verify with ssh -T git@github.com. The gh HTTPS path is recommended for most people.gh auth status
5 Install UV
UV is a fast Python package manager for project dependencies.
curl -LsSf https://astral.sh/uv/install.sh | sh
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
Restart your terminal, then verify:
uv --version
2 Create the repository
The opentrash package lives in its own repository,
separate from any website repo. This keeps it clean, independently versioned, and
ready for PyPI — the standard layout for a real Python package.
6 Create and clone the repo
Create it on GitHub with the CLI (replace opentrash with your chosen name; set the owner to your user or org):
mkdir -p ~/Projects && cd ~/Projects
gh repo create opentrash --public --description "Cloud-native geospatial tools for residential waste operations" --clone
mkdir %USERPROFILE%\Projects
cd %USERPROFILE%\Projects
gh repo create opentrash --public --description "Cloud-native geospatial tools for residential waste operations" --clone
Use --private instead of --public while you work. For an org repo: gh repo create YOUR-ORG/opentrash .... --clone downloads it locally.
Then enter the repo and open it in VS Code:
cd opentrash
code .
3 The package skeleton + docs site
Create a minimal but complete skeleton: the Python package folder, a documentation site (MkDocs Material), packaging config, and a workflow that auto-builds the docs to GitHub Pages. Every later lesson grows this.
7 Build the skeleton structure
This is the target layout. Starter files are provided with the course materials — drop them into your cloned repo so it looks like this:
In plain terms: your code lives in opentrash/. Your docs pages live in docs/. Config sits at the root. The .github/workflows/docs.yml file publishes the docs site automatically on every push.
8 Create the environment and install tools
Create a dedicated conda environment, then install MkDocs Material and build tooling:
conda create -n opentrash python=3.11 -y
conda activate opentrash
pip install mkdocs-material build twine
mkdocs-material is the docs theme, build creates the package distribution, twine uploads to PyPI (Part 4).
9 Preview the docs site locally
From the repo root:
mkdocs serve
Open http://127.0.0.1:8000. You’ll see the skeleton docs homepage. Edits to anything in docs/ reload live. Ctrl+C stops it.
10 Enable GitHub Pages for the docs
The included docs.yml workflow builds the site and pushes it to a gh-pages branch on every commit to main. After your first push (Step 12), enable Pages:
- Repo → Settings → Pages.
- Under Build and deployment, set Source to “Deploy from a branch.”
- Branch
gh-pages, folder/ (root). Save.
Docs go live at https://<owner>.github.io/opentrash/. Nothing else to do.
If you own a domain (e.g. opentrash.app), point it at this repo’s Pages site. Each repo supports one custom domain, so a dedicated package repo can use its own independently of any other site you host.
- Settings → Pages → Custom domain: enter the domain, Save (writes a
CNAMEfile). - At your DNS provider, add the records GitHub specifies — a
CNAMEpointing to<owner>.github.io(and/orArecords for an apex domain). - After DNS propagates, enable “Enforce HTTPS.”
You can switch between default URL and custom domain any time — it’s a setting, not a one-way door. Start with the default if unsure.
4 Claim the package name on PyPI
PyPI names are first-come, first-served, claimed by uploading a release. Publishing a
tiny 0.0.0 placeholder now reserves your name while it’s available.
(You’ll learn the full publishing workflow in Lesson 12 — this just holds
the name.)
11 Build and upload a placeholder release
Create a free account at pypi.org and check your name is free at https://pypi.org/project/opentrash/.
With pyproject.toml set to name = "opentrash" and version = "0.0.0", from the repo root:
python -m build
twine upload dist/*
twine prompts for PyPI credentials (use an API token from your account settings). Once uploaded, the name is yours. Verify at https://pypi.org/project/opentrash/.
pyproject.toml, the repo, and the package folder all match it.5 Commit and verify
12 First commit and push
git add .
git commit -m "Phase 0: package skeleton, docs scaffold, packaging config"
git push origin main
If your default branch is master, use that instead of main.
Final checklist
conda,code,git,gh,uvall report a versiongh auth statusshows you signed in- Repo created and cloned locally
- Skeleton structure in place (package folder, docs, mkdocs.yml, pyproject.toml, workflow)
mkdocs serverenders the docs homepage locally- First push succeeded; GitHub Pages enabled (default URL or custom domain)
- Package name claimed on PyPI
Troubleshooting
conda: command not found— the terminal didn’t reload. Close it completely and open a fresh one.gh: command not found— reopen the terminal; on macOS confirmbrewfinished and is on your PATH.- Auth fails in browser — rerun
gh auth loginand copy the full one-time code. - Pages shows 404 — check Settings → Pages: source is the
gh-pagesbranch, root folder. First build takes a couple minutes. twinerejects upload — the name may be taken, or that version already exists. Bump the version or pick another name.- Anything else — capture the exact error text and ask. A clear question is half the fix.