|
| 1 | +# Launch playbook (Phase 4) |
| 2 | + |
| 3 | +Internal asset — **not published** (excluded from the site via `exclude_docs`). |
| 4 | +Ready-to-post copy for the coordinated launch, plus timing and etiquette. |
| 5 | + |
| 6 | +**Design principles** |
| 7 | +- **Single-focus posts** on link aggregators (HN/Reddit/Lobsters) outperform one |
| 8 | + sprawling "look at my org" post. Stagger one project per week. |
| 9 | +- **Greenfield:** research found no prior HN/Reddit/Lobsters threads for these |
| 10 | + projects, so each post gets a clean first thread. |
| 11 | +- **Honest, calibrated voice:** "new but sharp," first-person (maintainer). The |
| 12 | + "when *not* to use this" framing is the credibility play — keep it. |
| 13 | +- One equal-billing **announcement** carries the whole-stack story. |
| 14 | + |
| 15 | +Suggested order: **modern-di (HN+Reddit)** → **stack announcement** → |
| 16 | +**faststream-outbox** → **httpware**, ~one per week. |
| 17 | + |
| 18 | +--- |
| 19 | + |
| 20 | +## 1. Show HN — modern-di (lead) |
| 21 | + |
| 22 | +**Title:** `Show HN: modern-di – Typed dependency injection for Python, with scopes` |
| 23 | + |
| 24 | +**Body:** |
| 25 | + |
| 26 | +> Hi HN. I'm the author of modern-di, a dependency-injection framework for Python. |
| 27 | +> |
| 28 | +> I kept building a FastAPI API, a FastStream worker, and a Typer CLI that all shared the same business logic — and rewiring the same dependencies three times, once per entrypoint. modern-di is my attempt at *one* typed wiring shared across all of them. |
| 29 | +> |
| 30 | +> What it does: |
| 31 | +> - **Type-based autowiring** — your constructor type hints *are* the graph; no `Provide[...]` markers or string keys. |
| 32 | +> - **Explicit scopes** (APP → REQUEST → …) with **build-time** cycle- and scope-violation checks. |
| 33 | +> - **Sync resolution by design** — async setup/teardown lives in the framework lifespan, not in resolution. This is deliberate and permanent, not a missing feature. |
| 34 | +> - **Official integrations** for FastAPI, Litestar, FastStream, and Typer, plus a first-party pytest plugin that turns any dependency into a fixture. |
| 35 | +> - Zero-dependency core, MIT, 100+ releases. |
| 36 | +> |
| 37 | +> Where it honestly stands: |
| 38 | +> - If you're building a single FastAPI service and everything is request-scoped, FastAPI's `Depends` is enough — you don't need this. |
| 39 | +> - The closest library is **Dishka**, which is more established, has many more integrations, and supports async resolution + custom scopes. If you need those, use Dishka. modern-di's bets are a simpler sync-only model, the first-party pytest plugin, and being one consistent small stack. |
| 40 | +> - It's young but actively developed. |
| 41 | +> |
| 42 | +> Docs include a full comparison and a "do you even need a DI container?" page: https://modern-di.modern-python.org |
| 43 | +> Repo: https://github.com/modern-python/modern-di |
| 44 | +> |
| 45 | +> Happy to dig into the design — especially the sync-only decision. |
| 46 | +
|
| 47 | +Etiquette: post Tue–Thu ~8–10am ET; never ask for upvotes; reply to every |
| 48 | +comment; the honest "when not to use it" is what earns goodwill. |
| 49 | + |
| 50 | +--- |
| 51 | + |
| 52 | +## 2. r/Python (Showcase format — three required sections) |
| 53 | + |
| 54 | +**Title:** `modern-di – typed dependency injection with scopes and one wiring across FastAPI, Litestar, FastStream, and Typer` |
| 55 | + |
| 56 | +**Body:** |
| 57 | + |
| 58 | +> **What My Project Does** |
| 59 | +> modern-di is a dependency-injection framework. You declare providers once (type-based autowiring from constructor hints), and resolve them with explicit scopes (APP → REQUEST → …) and build-time cycle/scope checks. The same container wires your FastAPI app, your FastStream workers, your Typer CLI, and your tests — via official integrations and a first-party pytest plugin that turns any dependency into a fixture. Sync resolution by design; async lives in the framework lifespan. |
| 60 | +> |
| 61 | +> **Target Audience** |
| 62 | +> Python teams whose business logic runs behind *more than one entrypoint* (an API plus workers/CLIs) and who want one wiring instead of three. It's production-intended but young — early adopters welcome. If you have a single web service where everything is request-scoped, framework-native `Depends`/`Provide` is enough and modern-di is overkill. |
| 63 | +> |
| 64 | +> **Comparison** |
| 65 | +> - **vs FastAPI `Depends` / Litestar `Provide`:** great inside one app, but don't span workers/CLIs or give typed app-scoped singletons; modern-di shares one wiring across all entrypoints. |
| 66 | +> - **vs `dependency-injector`:** type-based autowiring instead of `Provide[...]` markers; nested request scopes; first-party pytest plugin. |
| 67 | +> - **vs Dishka** (the closest library): Dishka is more established, has more integrations, and supports async resolution + custom scopes — pick it if you need those. modern-di bets on a simpler sync-only model and a first-party pytest plugin. |
| 68 | +> - **vs `that-depends`** (my earlier framework): modern-di adds explicit scopes and drops global state; that-depends stays maintained for async resolution. |
| 69 | +> |
| 70 | +> Docs + comparison: https://modern-di.modern-python.org |
| 71 | +
|
| 72 | +--- |
| 73 | + |
| 74 | +## 3. Lobsters |
| 75 | + |
| 76 | +Submit the link **https://modern-di.modern-python.org** (the docs, not the bare |
| 77 | +repo), tag `python`. Authored comment: |
| 78 | + |
| 79 | +> Typed DI for Python with explicit scopes, built so one container wires a FastAPI app, FastStream workers, and a Typer CLI together. Sync-only by design. The docs include an honest comparison vs dependency-injector/Dishka and a "do you even need DI?" section. Author here — happy to discuss the sync-only call. |
| 80 | +
|
| 81 | +Only post if you have a Lobsters account with karma; it's allergic to drive-by |
| 82 | +self-promo. |
| 83 | + |
| 84 | +--- |
| 85 | + |
| 86 | +## 4. Org-story announcement (equal billing) |
| 87 | + |
| 88 | +For a blog / dev.to / GitHub Discussion "Announcements" post — the one place the |
| 89 | +whole stack shares billing. Full ~580-word draft: |
| 90 | + |
| 91 | +--- |
| 92 | + |
| 93 | +### The modern-python stack: production Python services without the boilerplate |
| 94 | + |
| 95 | +Every production Python service I build needs roughly the same scaffolding. A |
| 96 | +sensible project structure. A way to wire dependencies that doesn't turn into a |
| 97 | +tangle. Resilient calls to other services. Reliable event publishing when a |
| 98 | +database write and a message have to happen together. And observability, so I can |
| 99 | +actually see what's happening in production. |
| 100 | + |
| 101 | +None of that is the interesting part of the product — but all of it has to be |
| 102 | +there, and getting it right repeatedly is tedious. Over the last couple of years |
| 103 | +I've been factoring these concerns into a small family of MIT-licensed libraries, |
| 104 | +each independently usable, built with the same tooling |
| 105 | +([uv](https://github.com/astral-sh/uv), [ruff](https://github.com/astral-sh/ruff), |
| 106 | +[ty](https://github.com/astral-sh/ty)). Collectively they're the *modern-python* |
| 107 | +stack. Here's how the pieces fit. |
| 108 | + |
| 109 | +**Start from a template.** |
| 110 | +[`fastapi-sqlalchemy-template`](https://github.com/modern-python/fastapi-sqlalchemy-template) |
| 111 | +and [`litestar-sqlalchemy-template`](https://github.com/modern-python/litestar-sqlalchemy-template) |
| 112 | +are dockerized, batteries-included starting points: FastAPI or Litestar, |
| 113 | +SQLAlchemy 2, PostgreSQL, dependency injection already wired, with linting, |
| 114 | +typing, and tests configured. Clone, rename, and you have a service that runs — |
| 115 | +instead of spending the first day assembling boilerplate. |
| 116 | + |
| 117 | +**Wire your dependencies with [`modern-di`](https://modern-di.modern-python.org).** |
| 118 | +The thing that tends to rot first in a growing service is dependency wiring. |
| 119 | +modern-di is a typed DI container built around one idea: *one wiring shared across |
| 120 | +every entrypoint.* The same container resolves dependencies in your FastAPI |
| 121 | +handlers, your FastStream workers, and your Typer CLI — instead of three parallel |
| 122 | +copies that drift apart. It uses type-based autowiring (your constructor hints are |
| 123 | +the graph), explicit scopes with build-time validation, and a first-party pytest |
| 124 | +plugin that turns any dependency into a fixture. It's deliberately sync-only: |
| 125 | +async setup and teardown belong in the framework lifespan, not in resolution. If |
| 126 | +you only have a single web service, your framework's own `Depends` is enough — |
| 127 | +modern-di earns its place when you have a second entrypoint. (The docs include an |
| 128 | +honest comparison with dependency-injector and Dishka, and a "do you even need |
| 129 | +DI?" page.) |
| 130 | + |
| 131 | +**Call other services with [`httpware`](https://httpware.modern-python.org).** |
| 132 | +As soon as a service talks to other services, you need more than a bare HTTP |
| 133 | +client. httpware wraps httpx with the things you'd otherwise assemble yourself: |
| 134 | +typed errors (4xx/5xx become a status-keyed exception tree, no more |
| 135 | +`raise_for_status`), typed response bodies (decode straight to your pydantic or |
| 136 | +msgspec model), and resilience as composable middleware — retry with budget, |
| 137 | +bulkhead, and circuit breaker, ordered explicitly. |
| 138 | + |
| 139 | +**Publish events reliably with |
| 140 | +[`faststream-outbox`](https://faststream-outbox.modern-python.org).** |
| 141 | +If your service writes to a database and publishes an event, you have a dual-write |
| 142 | +problem: a crash between the two leaves them inconsistent. faststream-outbox |
| 143 | +solves it with the transactional outbox pattern for FastStream and Postgres — |
| 144 | +write your domain row and an outbox row in the same transaction, and a relay |
| 145 | +forwards each row to your broker (Kafka, RabbitMQ, NATS, Redis) with a single |
| 146 | +decorator. At-least-once delivery, with a dead-letter option. |
| 147 | + |
| 148 | +**Instrument everything with |
| 149 | +[`lite-bootstrap`](https://lite-bootstrap.modern-python.org).** |
| 150 | +Finally, observability. lite-bootstrap wires OpenTelemetry, Prometheus, Sentry, |
| 151 | +and structlog into a FastAPI, Litestar, or FastStream service in a few lines — |
| 152 | +each instrument opt-in, each skipped automatically if you don't configure it. |
| 153 | +Consistent instrumentation across a fleet of services, without copy-pasting 150 |
| 154 | +lines of setup into every repo. |
| 155 | + |
| 156 | +**Use one, or all of them.** The point isn't to adopt everything. Each library |
| 157 | +stands alone — use httpware without modern-di, or lite-bootstrap with a framework |
| 158 | +of your own. But together they cover the unglamorous 20% of a service that you'd |
| 159 | +otherwise rebuild every time. [modern-python.org](https://modern-python.org) ties |
| 160 | +it together, and everything is open to issues, ideas, and contributions. These are |
| 161 | +young, actively-developed projects — I'd genuinely like your feedback on what's |
| 162 | +missing. |
| 163 | + |
| 164 | +--- |
| 165 | + |
| 166 | +## 5. Staggered follow-up posts (own thread each, later weeks) |
| 167 | + |
| 168 | +- **Show HN: faststream-outbox** — "the transactional outbox pattern for |
| 169 | + FastStream + Postgres." Outbox is a respected, technical topic. Honest framing: |
| 170 | + the pattern is battle-tested, the library is ~weeks old. |
| 171 | +- **Show HN / r/Python: httpware** — "httpx clients with typed errors + composable |
| 172 | + resilience (retry/bulkhead/circuit-breaker)." Resilience patterns draw |
| 173 | + discussion. Beta; pin versions. |
| 174 | + |
| 175 | +(Reuse the modern-di structures above: HN = honest "what/where-it-stands"; |
| 176 | +r/Python = What-it-does / Target-audience / Comparison.) |
| 177 | + |
| 178 | +## 6. awesome-list submissions (one-liners) |
| 179 | + |
| 180 | +- **awesome-python** (DI section): `modern-di — typed dependency injection with scopes and framework integrations.` |
| 181 | +- **awesome-fastapi**: `modern-di-fastapi — dependency injection for FastAPI via modern-di.` |
| 182 | +- **awesome-asyncio / FastStream lists**: `faststream-outbox — transactional outbox for FastStream + Postgres.` |
| 183 | + |
| 184 | +## 7. Social one-liners (X / Mastodon / Bluesky) |
| 185 | + |
| 186 | +- "One typed DI wiring for your FastAPI app, FastStream workers, and Typer CLI — not three. modern-di, sync-by-design: https://modern-di.modern-python.org" |
| 187 | +- "Dual-write problem in your event-driven service? faststream-outbox does the transactional outbox for FastStream + Postgres in one decorator." |
| 188 | +- "httpx, but your 404s are typed exceptions and retry/bulkhead/circuit-breaker are composable middleware. httpware." |
| 189 | + |
| 190 | +--- |
| 191 | + |
| 192 | +## Posting playbook (timing & etiquette) |
| 193 | + |
| 194 | +- **Stagger** one launch item per week (modern-di → announcement → |
| 195 | + faststream-outbox → httpware). Greenfield, so each gets a clean first thread. |
| 196 | +- **Don't** simultaneously cross-post the same project to HN + Reddit; space by a |
| 197 | + day or more. |
| 198 | +- **Engage** every comment — that feedback is your Phase 5 roadmap input; route it |
| 199 | + to the modern-di **Ideas Discussion**. |
| 200 | +- **HN/Reddit:** never solicit votes; lead with the honest "when *not* to use |
| 201 | + this." That candor is the credibility play. |
| 202 | +- **Reddit r/Python:** follow the Showcase rules (the three required sections); |
| 203 | + post and engage, don't drop-and-run. |
0 commit comments