IKAREMIKAREM v1.1.0

MIGRATE / FROM ANYWHERE

Two lines for Meraki.
A day for the rest.

Pick your framework below — every guide has a mapping table, the honest deltas, and a plan. Full guides live in the repo under docs/MIGRATING_FROM_*.md.

$ pip uninstall meraki -y && pip install ikarem
- from meraki import Meraki
+ from ikarem.meraki_compat import Meraki

That's the whole migration. Same decorators, same add_middleware, same 404/405 plain-text bodies, same byte-pair headers, same Response(body, status_code). Your uvicorn example:app invocation keeps working. Run your test suite — it passes unchanged.

01 / API MAP

Same shape. More underneath.

MerakiIKAREM native
Response(body=b"…", status_code=201)Same shape — or just return {...}, 201
request.path, request.methodSame, plus query, cookies, path_params, await body()/json()/form()
request.query_params (tuples)request.query (dict)
request.headers (byte pairs)request.headers (lowercased dict)
Static paths only{uid:int/float/uuid/path}, 404 vs 405, url_for
pipeline.add(mw)app.use(...): CORS, security headers, rate limit, sessions, CSRF
plugins/ (empty), config/ (empty)Working plugins + layered Config + DatabasePlugin
Note. Meraki's Request never stores receive, so it cannot read POST bodies at all. Any endpoint reading a body is new capability, not ported code.

02 / CASH IN

Highest ROI first.

1. Path params. Meraki has none — GET /users/{uid:int} starts working the moment you use the compat layer (request.ikarem.path_params inside old handlers).

2. Return dicts. Replace Response(body=json.dumps(...).encode()) with return {...}.

3. Kill validation boilerplate with Schema + Field() — invalid bodies become 400s and document themselves in OpenAPI.

4. Run ikarem check myapp:app — circular deps and bad Depends() surface before traffic does.

03 / GO NATIVE

One file at a time.

app = Meraki().ikarem   # the full Ikarem app under your compat app

Meraki().ikarem exposes the engine: include_router, exception_handler, mount_static, websocket, mcp_tools(). Both styles coexist on one app. You're done when grep -r meraki_compat is empty. Worked example: the Ledger app was built exactly this way.

04 / FROM FASTAPI

A day. Mostly mechanical.

FastAPIIKAREM
@app.get("/users/{uid}") + uid: int@app.get("/users/{uid:int}") + uid: int
class Item(BaseModel)class Item(Schema) + Field()
x=Depends(fn)x=Depends(fn) — same spelling
BackgroundTasksBackgroundTasks — same name
TestClient, /docs, /openapi.jsonSame names, same paths

Converters move into the route, there is no response_model filtering, and advanced Pydantic types become plain fields plus handler checks. Full guide: docs/MIGRATING_FROM_FASTAPI.md.

05 / FROM STARLETTE

Hours. The closest cousin.

StarletteIKAREM
Route("/users/{uid:int}", endpoint)@app.get("/users/{uid:int}")
JSONResponse, PlainTextResponseSame names
Middleware(...)app.use(mw)
StaticFilesapp.mount_static(url, dir)
TestClient, lifespanTestClient, on_startup/shutdown

Swap the router file, keep handler bodies, then add Schema bodies where you used to parse await request.json() by hand. Full guide: docs/MIGRATING_FROM_STARLETTE.md.

06 / FROM LITESTAR

A day. Controller by controller.

LitestarIKAREM
Controller with path=Blueprint(name, url_prefix=)
Provide(dep)Depends(dep)
DTOsSchema + Field()
guards=[...]require_roles() / require_scopes()
(data, StatusCode.CREATED_201)(data, 201)

Keep paths identical per controller, diff the 400s, replay the auth tests. Full guide: docs/MIGRATING_FROM_LITESTAR.md.

07 / FROM FLASK

A day. Half the API already crossed over.

FlaskIKAREM
@app.route("/x", methods=["POST"])@app.post("/x")
Global request proxyExplicit req param — no magic
jsonify, abort, flashreturn {...}, abort, flash — same names
Blueprint, MethodViewSame names, full DI per method
render_templateTemplates(dir) (ikarem[jinja])

The real work is globals → req and sync → async (blocking DB drivers first). Blueprint + MethodView + abort + flash already shipped as Flask takes. Full guide: docs/MIGRATING_FROM_FLASK.md.

08 / FROM DJANGO

A week. A rewrite of views, stated plainly.

DjangoIKAREM
urls.py treeRoutes + include_router(prefix)
Models + ORMDatabaseConnector strategy + Schema (SQL stays yours)
contrib.auth + sessionsJWT + signed-cookie sessions + CSRF
MIDDLEWARE settingapp.use(...) order, fail-fast at boot
manage.pyikarem run|check|mcp|new|migrate|worker|inspect

No ORM and no admin are standing decisions, not gaps. Freeze the URL tree, port models to SQL with the suite green between, cut over one subtree at a time behind mount_asgi(). Full guide: docs/MIGRATING_FROM_DJANGO.md.