Skip to content

Commit 90091aa

Browse files
lesnik512claude
andauthored
docs: add Phase 4 launch playbook (#15)
Ready-to-post launch copy (Show HN, r/Python, Lobsters, staggered follow-ups, awesome-list, social) plus a full ~580-word stack announcement, with timing and etiquette. Internal asset — excluded from the published site. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 2f03259 commit 90091aa

1 file changed

Lines changed: 203 additions & 0 deletions

File tree

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
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

Comments
 (0)