A small Flask application that provides cost calculators for resin and FDM 3D printing. Built with uv for reproducible Python environments and designed to run locally or in a container.
- Overview
- Architecture at a glance
- Features
- Prerequisites
- Quick start
- Docker
- Configuration
- Health
- Endpoints
- Production notes
- Development
- Troubleshooting
- Licence
- Security
- Contributing
- Support
This service exposes simple web pages to calculate material and job costs for resin and FDM 3D prints. It includes a basic health endpoint for orchestration systems and uses a plain Flask entry point that works with Flask’s dev server or Gunicorn in production.
- Flask app factory with a top level
app:appWSGI target - Stateless HTTP endpoints and HTML templates
- Optional branding via environment variables
- Health endpoint
GET /healthfor liveness checks
- Resin and FDM cost calculators with simple and advanced views
- Configurable branding, logo and favicon
- Single business control for default profit margin
- Clean
app:appentry point compatible with Flask and Gunicorn /healthendpoint for liveness checks- Reproducible local development with uv
- Ready to run via a prebuilt container image
- Docker / Kubernetes
- Alternatively uv and Python 3.13 for local development
Local development with uv
uv sync --all-extras
uv run flask --app app:app run --host 0.0.0.0 --port ${PORT:-6969}Pull and run
docker pull ghcr.io/sudo-kraken/3d-printing-cost-calculators:latest
docker run --rm -p 6969:6969 \
-e PORT=6969 \
ghcr.io/sudo-kraken/3d-printing-cost-calculators:latestYou can deploy the app on Kubernetes using the published Helm chart:
helm install 3d-printing-cost-calculators oci://ghcr.io/sudo-kraken/helm-charts/3d-printing-cost-calculators \
--namespace 3d-printing-cost-calculators --create-namespaceDocker Compose example
services:
calculators:
image: ghcr.io/sudo-kraken/3d-printing-cost-calculators:latest
environment:
PORT: 6969
WEB_CONCURRENCY: 2
ports:
- "6969:6969"
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:6969/health"]
interval: 30s
timeout: 5s
retries: 3| Variable | Required | Default | Description |
|---|---|---|---|
| PORT | no | 6969 | Port to bind |
| WEB_CONCURRENCY | no | 2 | Gunicorn worker processes |
| APP_BRAND_NAME | no | Branding string used in templates | |
| APP_LOGO_URL | no | Logo URL used in templates | |
| APP_FAVICON_URL | no | Favicon URL | |
| APP_DEFAULT_PROFIT_MARGIN | no | Default profit margin percentage |
.env example
PORT=6969
WEB_CONCURRENCY=2
APP_BRAND_NAME="My Print Shop"
APP_DEFAULT_PROFIT_MARGIN=20GET /healthreturns{ "ok": true }
GET /homeGET /resin-calculatorandGET /resin-simpleGET /fdm-calculatorandGET /fdm-simplePOST /calculate-resinPOST /calculate-fdm
- Prefer Gunicorn with multiple workers for CPU bound tasks. For simple IO bound routes the default of 2 workers is fine.
- Expose the
/healthendpoint to your load balancer or orchestrator for liveness checks.
uv run ruff check --fix .
uv run ruff format .
uv run pytest --cov- If templates fail to load, ensure the
templates/andstatic/folders are included in the container image. - If you change dependencies, regenerate
uv.lockwithuv lockand commit it.
This project is licensed under the MIT Licence. See the LICENCE file for details.
If you discover a security issue, please review and follow the guidance in SECURITY.md, or open a private security-focused issue with minimal details and request a secure contact channel.
Feel free to open issues or submit pull requests if you have suggestions or improvements.
See CONTRIBUTING.md
Open an issue with as much detail as possible, including your environment details and relevant logs or output.
