Part 1: Setup¶
Scaffold the project¶
python -m venv .venv && source .venv/bin/activate
pip install zeython
zeython new "TaskFlow"
cd task_flow
pip install -e ".[dev]"
cp .env.example .env
zeython new generated a real, runnable project — not a single-file demo.
(The [dev] extra pulls in pytest, pytest-asyncio, and httpx — the
project ships with a passing test in tests/test_home.py already, and
you'll write more of your own starting in
Part 6.) Look at what's there:
task_flow/
├── app/
│ ├── Controllers/ # request handlers
│ ├── Models/ # async Active Record models
│ ├── Middleware/ # ASGI middleware
│ ├── Providers/ # your own service providers
│ ├── Jobs/ # background jobs
│ └── Console/Commands/ # custom `zeython command <name>` CLI commands
├── database/
│ ├── factories/ # model factories for tests/seeding
│ └── seeders/ # `zeython db seed`
├── routes/
│ └── web.py # route definitions
├── migrations/ # Alembic migrations
├── tests/
├── main.py # application entry point -- start here
├── alembic.ini
└── .env.example
main.py is worth opening now. It's not hidden framework magic — it's
plain Python that constructs an Application, registers the providers
your app needs (AuthServiceProvider, DatabaseServiceProvider,
RouteServiceProvider, ...), and a dozen more commented out that you can
turn on later (rate limiting, an admin panel, localization). Everything
your generated app does, it does because a line in main.py says so —
see Architecture when you're ready for the full
picture of how the container and providers fit together. For now, the
short version: a service provider is where a piece of functionality
(auth, the database, routing) gets wired into the app, and main.py is
the list of which pieces you're using.
Run it¶
A fresh scaffold ships with the User model already written but no
migration file for it yet — revision autogenerates one by diffing your
models against the (empty) database, migrate applies it:
Visit http://127.0.0.1:8000 — you'll get a small JSON welcome payload.
zeython serve auto-reloads on file changes, so leave it running for the
rest of this tutorial.
Try the auth that's already there¶
A generated project ships with a working User model and session
authentication out of the box (see Authentication
for the full picture later) — you get to use it for free instead of
building login from scratch:
curl -sS -c cookies.txt -X POST http://127.0.0.1:8000/register \
-H 'Content-Type: application/json' \
-d '{"name": "Ada", "email": "ada@example.com", "password": "hunter2222"}'
{"name":"Ada","email":"ada@example.com","id":1,"created_at":"...","updated_at":"...","is_deleted":false,"deleted_at":null}
-c cookies.txt saves the session cookie /register sets — you're now
logged in as Ada, and every following curl in this tutorial that
passes -b cookies.txt will be authenticated as her. Confirm it:
{"name":"Ada","email":"ada@example.com","id":1,"created_at":"...","updated_at":"...","is_deleted":false,"deleted_at":null}
That's the whole account system you'd otherwise hand-roll — password hashing, a signed session cookie, CSRF protection on every unsafe request from here on (you'll deal with that directly in Part 5, when it's TaskFlow's own routes that need protecting) — already wired up, already tested, already documented.
Next: Part 2 — Models, where TaskFlow actually starts.