[{"data":1,"prerenderedAt":1756},["ShallowReactive",2],{"versions":3,"blog":6},{"v3":4,"v4":5},"3.21.10","4.5.1",[7,1442],{"id":8,"title":9,"authors":10,"body":15,"category":1432,"date":1433,"description":1434,"extension":1435,"image":1436,"meta":1437,"navigation":212,"path":1438,"seo":1439,"stem":1440,"tags":1436,"__hash__":1441},"blog\u002Fblog\u002F2.v3-announcement.md","Announcing Litestar 3",[11],{"name":12,"avatar":13},"Janek Nouvertné",{"src":14},"https:\u002F\u002Fgithub.com\u002Fprovinzkraut.png",{"type":16,"value":17,"toc":1422},"minimark",[18,30,33,38,43,46,52,55,82,88,91,96,122,278,282,287,516,520,535,697,707,714,784,788,791,806,809,822,826,829,832,844,984,1003,1006,1009,1012,1015,1026,1029,1034,1041,1044,1204,1207,1312,1315,1318,1329,1333,1352,1367,1371,1378,1382,1385,1388,1391,1394,1403,1418],[19,20,21,22,29],"p",{},"A long long time ago, we released ",[23,24,28],"a",{"href":25,"rel":26},"https:\u002F\u002Fgithub.com\u002Flitestar-org\u002Flitestar\u002Freleases\u002Ftag\u002Fv2.0.0",[27],"nofollow","Litestar 2.0",",\nand with it came the promise of another major version. A version that would not be in\ndevelopment for too long, and would focus mostly on stabilising existing features,\nimproved developer experience, and removing leftovers from the 1.x -> 2.x transition.",[19,31,32],{},"Now, over 3 years later, we gotta admit that this did not go according to plan! This is\nmostly due to unforseen happenstances, and the core maintainer team not being able to\nspend as much time on the project as they would have liked. However, things have and are\nstill brewing, the project is growing, and significant progress as been made, so let's\ntake a look at some of the things Litestar 3 will bring!",[34,35,37],"h2",{"id":36},"whats-coming","What's coming",[39,40,42],"h3",{"id":41},"overwhelmingly-overhauled-and-extended-dependency-injection","Overwhelmingly overhauled and extended dependency injection",[19,44,45],{},"Yes, Litestar 3 will finally bring the most requested (and debated) feature of the past\nyears: A new dependency injection system.",[19,47,48],{},[49,50,51],"em",{},"What's new about it?",[19,53,54],{},"In a nutshell:",[56,57,58,66,69,76,79],"ul",{},[59,60,61,62,65],"li",{},"Type-based injection ",[49,63,64],{},"alongside"," the existing named-based injection",[59,67,68],{},"Native DI in guards, hooks and other places",[59,70,71,72,75],{},"Ad-hoc DI ",[49,73,74],{},"everywhere"," with access to a request \u002F application context (e.g. arbitrary ASGI middlewares)",[59,77,78],{},"Explicit registration of DI providers \u002F values",[59,80,81],{},"Nested resolution scopes",[19,83,84],{},[85,86,87],"strong",{},"What's it look like?",[19,89,90],{},"While it's currently being developed in secrecy, we can take a little peek behind the\ncurtain, and see what its API looks like:",[92,93,95],"h4",{"id":94},"type-based-di","Type-based DI",[19,97,98,99,103,104,107,108,113,114,117,118,121],{},"Litestar ",[100,101,102],"code",{},"2.23.0"," introduced ",[100,105,106],{},"NamedDependency",", as part of its move towards more\nexplicit declarations (read more ",[23,109,112],{"href":110,"rel":111},"https:\u002F\u002Fdocs.litestar.dev\u002F2\u002Ftopics\u002Fexplicit_declarations.html",[27],"here",").\nThis also laid the groundwork for the new type-based DI system: Litestar 3 will feature\n",[100,115,116],{},"TypeDependency"," alongside ",[100,119,120],{},"NameDependency","; The semantics remain the same, with the\nexception that the provider key won't be inferred from the parameter name, but will be\nthe type itself:",[123,124,129],"pre",{"className":125,"code":126,"language":127,"meta":128,"style":128},"language-python shiki shiki-themes material-theme-lighter material-theme-lighter material-theme-palenight","@get(\"\u002F\")\nasync def handler(some_service: TypeDependency[SomeService]) -> None:\n    pass\n\nrouter = Router(\n    \"\u002F\",\n    [handler],\n    dependencies={SomeService: provide_some_service},\n)\n","python","",[100,130,131,159,200,207,214,229,242,254,273],{"__ignoreMap":128},[132,133,136,140,144,147,150,154,156],"span",{"class":134,"line":135},"line",1,[132,137,139],{"class":138},"sDfIl","@",[132,141,143],{"class":142},"s3cPz","get",[132,145,146],{"class":138},"(",[132,148,149],{"class":138},"\"",[132,151,153],{"class":152},"sGFVr","\u002F",[132,155,149],{"class":138},[132,157,158],{"class":138},")\n",[132,160,162,166,169,172,174,178,181,185,188,191,194,197],{"class":134,"line":161},2,[132,163,165],{"class":164},"smZ93","async",[132,167,168],{"class":164}," def",[132,170,171],{"class":142}," handler",[132,173,146],{"class":138},[132,175,177],{"class":176},"s1nJG","some_service",[132,179,180],{"class":138},":",[132,182,184],{"class":183},"sZSNi"," TypeDependency",[132,186,187],{"class":138},"[",[132,189,190],{"class":183},"SomeService",[132,192,193],{"class":138},"])",[132,195,196],{"class":138}," ->",[132,198,199],{"class":138}," None:\n",[132,201,203],{"class":134,"line":202},3,[132,204,206],{"class":205},"s8R28","    pass\n",[132,208,210],{"class":134,"line":209},4,[132,211,213],{"emptyLinePlaceholder":212},true,"\n",[132,215,217,220,223,226],{"class":134,"line":216},5,[132,218,219],{"class":183},"router ",[132,221,222],{"class":138},"=",[132,224,225],{"class":142}," Router",[132,227,228],{"class":138},"(\n",[132,230,232,235,237,239],{"class":134,"line":231},6,[132,233,234],{"class":138},"    \"",[132,236,153],{"class":152},[132,238,149],{"class":138},[132,240,241],{"class":138},",\n",[132,243,245,248,251],{"class":134,"line":244},7,[132,246,247],{"class":138},"    [",[132,249,250],{"class":142},"handler",[132,252,253],{"class":138},"],\n",[132,255,257,260,263,265,267,270],{"class":134,"line":256},8,[132,258,259],{"class":176},"    dependencies",[132,261,262],{"class":138},"={",[132,264,190],{"class":142},[132,266,180],{"class":138},[132,268,269],{"class":142}," provide_some_service",[132,271,272],{"class":138},"},\n",[132,274,276],{"class":134,"line":275},9,[132,277,158],{"class":138},[92,279,281],{"id":280},"extended-di-availability","Extended DI availability",[19,283,284],{},[85,285,286],{},"DI in guards",[123,288,290],{"className":125,"code":289,"language":127,"meta":128,"style":128},"async def provide_user(request: TypeDependency[Request[User]]) -> User:\n    return request.user\n\nasync def require_admin_user(active_user: TypeDependency[User]) -> None:\n    if not active_user.is_admin:\n        raise NotAuthorized()\n\n@get(\"\u002F\", guards=[require_admin_user])\nasync def handler() -> None:\n    pass\n\nrouter = Router(\n    \"\u002F\",\n    [handler],\n    dependencies={User: provide_user},\n)\n",[100,291,292,331,346,350,378,396,407,411,440,455,460,465,476,487,496,511],{"__ignoreMap":128},[132,293,294,296,298,301,303,306,308,310,312,315,317,320,323,325,328],{"class":134,"line":135},[132,295,165],{"class":164},[132,297,168],{"class":164},[132,299,300],{"class":142}," provide_user",[132,302,146],{"class":138},[132,304,305],{"class":176},"request",[132,307,180],{"class":138},[132,309,184],{"class":183},[132,311,187],{"class":138},[132,313,314],{"class":183},"Request",[132,316,187],{"class":138},[132,318,319],{"class":183},"User",[132,321,322],{"class":138},"]])",[132,324,196],{"class":138},[132,326,327],{"class":183}," User",[132,329,330],{"class":138},":\n",[132,332,333,336,339,342],{"class":134,"line":161},[132,334,335],{"class":205},"    return",[132,337,338],{"class":183}," request",[132,340,341],{"class":138},".",[132,343,345],{"class":344},"sRlkE","user\n",[132,347,348],{"class":134,"line":202},[132,349,213],{"emptyLinePlaceholder":212},[132,351,352,354,356,359,361,364,366,368,370,372,374,376],{"class":134,"line":209},[132,353,165],{"class":164},[132,355,168],{"class":164},[132,357,358],{"class":142}," require_admin_user",[132,360,146],{"class":138},[132,362,363],{"class":176},"active_user",[132,365,180],{"class":138},[132,367,184],{"class":183},[132,369,187],{"class":138},[132,371,319],{"class":183},[132,373,193],{"class":138},[132,375,196],{"class":138},[132,377,199],{"class":138},[132,379,380,383,386,389,391,394],{"class":134,"line":216},[132,381,382],{"class":205},"    if",[132,384,385],{"class":138}," not",[132,387,388],{"class":183}," active_user",[132,390,341],{"class":138},[132,392,393],{"class":344},"is_admin",[132,395,330],{"class":138},[132,397,398,401,404],{"class":134,"line":231},[132,399,400],{"class":205},"        raise",[132,402,403],{"class":142}," NotAuthorized",[132,405,406],{"class":138},"()\n",[132,408,409],{"class":134,"line":244},[132,410,213],{"emptyLinePlaceholder":212},[132,412,413,415,417,419,421,423,425,428,431,434,437],{"class":134,"line":256},[132,414,139],{"class":138},[132,416,143],{"class":142},[132,418,146],{"class":138},[132,420,149],{"class":138},[132,422,153],{"class":152},[132,424,149],{"class":138},[132,426,427],{"class":138},",",[132,429,430],{"class":176}," guards",[132,432,433],{"class":138},"=[",[132,435,436],{"class":142},"require_admin_user",[132,438,439],{"class":138},"])\n",[132,441,442,444,446,448,451,453],{"class":134,"line":275},[132,443,165],{"class":164},[132,445,168],{"class":164},[132,447,171],{"class":142},[132,449,450],{"class":138},"()",[132,452,196],{"class":138},[132,454,199],{"class":138},[132,456,458],{"class":134,"line":457},10,[132,459,206],{"class":205},[132,461,463],{"class":134,"line":462},11,[132,464,213],{"emptyLinePlaceholder":212},[132,466,468,470,472,474],{"class":134,"line":467},12,[132,469,219],{"class":183},[132,471,222],{"class":138},[132,473,225],{"class":142},[132,475,228],{"class":138},[132,477,479,481,483,485],{"class":134,"line":478},13,[132,480,234],{"class":138},[132,482,153],{"class":152},[132,484,149],{"class":138},[132,486,241],{"class":138},[132,488,490,492,494],{"class":134,"line":489},14,[132,491,247],{"class":138},[132,493,250],{"class":142},[132,495,253],{"class":138},[132,497,499,501,503,505,507,509],{"class":134,"line":498},15,[132,500,259],{"class":176},[132,502,262],{"class":138},[132,504,319],{"class":142},[132,506,180],{"class":138},[132,508,300],{"class":142},[132,510,272],{"class":138},[132,512,514],{"class":134,"line":513},16,[132,515,158],{"class":138},[92,517,519],{"id":518},"ad-hoc-di","Ad-hoc DI",[19,521,522,523,526,527,530,531,534],{},"The ",[100,524,525],{},"Litestar"," and ",[100,528,529],{},"ASGIConnection"," instances will expose a ",[100,532,533],{},"di_context"," attribute,\nwhich can be used to dynamically resolve dependencies:",[123,536,538],{"className":125,"code":537,"language":127,"meta":128,"style":128},"class SomeMiddleware(ASGIMiddleware):\n    async def handle(self, scope: Scope, send: Send, receive: Receive, next_app: ASGIApp) -> None:\n        litestar_app = Litestar.from_scope(scope)\n        db_session =  await litestar_app.di_context.solve(AsyncSession)\n        ...\n        await next_app(scope, send, receive)\n",[100,539,540,557,620,642,671,676],{"__ignoreMap":128},[132,541,542,545,549,551,554],{"class":134,"line":135},[132,543,544],{"class":164},"class",[132,546,548],{"class":547},"s52Pk"," SomeMiddleware",[132,550,146],{"class":138},[132,552,553],{"class":547},"ASGIMiddleware",[132,555,556],{"class":138},"):\n",[132,558,559,562,564,567,569,573,575,578,580,583,585,588,590,593,595,598,600,603,605,608,610,613,616,618],{"class":134,"line":161},[132,560,561],{"class":164},"    async",[132,563,168],{"class":164},[132,565,566],{"class":142}," handle",[132,568,146],{"class":138},[132,570,572],{"class":571},"seDIv","self",[132,574,427],{"class":138},[132,576,577],{"class":176}," scope",[132,579,180],{"class":138},[132,581,582],{"class":183}," Scope",[132,584,427],{"class":138},[132,586,587],{"class":176}," send",[132,589,180],{"class":138},[132,591,592],{"class":183}," Send",[132,594,427],{"class":138},[132,596,597],{"class":176}," receive",[132,599,180],{"class":138},[132,601,602],{"class":183}," Receive",[132,604,427],{"class":138},[132,606,607],{"class":176}," next_app",[132,609,180],{"class":138},[132,611,612],{"class":183}," ASGIApp",[132,614,615],{"class":138},")",[132,617,196],{"class":138},[132,619,199],{"class":138},[132,621,622,625,627,630,632,635,637,640],{"class":134,"line":202},[132,623,624],{"class":183},"        litestar_app ",[132,626,222],{"class":138},[132,628,629],{"class":183}," Litestar",[132,631,341],{"class":138},[132,633,634],{"class":142},"from_scope",[132,636,146],{"class":138},[132,638,639],{"class":142},"scope",[132,641,158],{"class":138},[132,643,644,647,649,652,655,657,659,661,664,666,669],{"class":134,"line":209},[132,645,646],{"class":183},"        db_session ",[132,648,222],{"class":138},[132,650,651],{"class":205},"  await",[132,653,654],{"class":183}," litestar_app",[132,656,341],{"class":138},[132,658,533],{"class":344},[132,660,341],{"class":138},[132,662,663],{"class":142},"solve",[132,665,146],{"class":138},[132,667,668],{"class":142},"AsyncSession",[132,670,158],{"class":138},[132,672,673],{"class":134,"line":216},[132,674,675],{"class":183},"        ...\n",[132,677,678,681,683,685,687,689,691,693,695],{"class":134,"line":231},[132,679,680],{"class":205},"        await",[132,682,607],{"class":142},[132,684,146],{"class":138},[132,686,639],{"class":142},[132,688,427],{"class":138},[132,690,587],{"class":142},[132,692,427],{"class":138},[132,694,597],{"class":142},[132,696,158],{"class":138},[19,698,699,700,703,704,341],{},"when using type-based DI, this has the added benefit of being type-safe, e.g.\n",[100,701,702],{},".resolve"," has a signature of ",[100,705,706],{},"async def resolve[T](type_: type[T]) -> T",[19,708,709,710,713],{},"Using the same DI context, you can dynamically ",[49,711,712],{},"provide"," values:",[123,715,717],{"className":125,"code":716,"language":127,"meta":128,"style":128},"@contextlib.asynccontextmanager\nasync def lifespan(app: Litestar) -> AsyncGenerator[None]:\n    app.di_context.provide(MySettings, my_settings)\n",[100,718,719,731,759],{"__ignoreMap":128},[132,720,721,723,726,728],{"class":134,"line":135},[132,722,139],{"class":138},[132,724,725],{"class":142},"contextlib",[132,727,341],{"class":138},[132,729,730],{"class":142},"asynccontextmanager\n",[132,732,733,735,737,740,742,745,747,749,751,753,756],{"class":134,"line":161},[132,734,165],{"class":164},[132,736,168],{"class":164},[132,738,739],{"class":142}," lifespan",[132,741,146],{"class":138},[132,743,744],{"class":176},"app",[132,746,180],{"class":138},[132,748,629],{"class":183},[132,750,615],{"class":138},[132,752,196],{"class":138},[132,754,755],{"class":183}," AsyncGenerator",[132,757,758],{"class":138},"[None]:\n",[132,760,761,764,766,768,770,772,774,777,779,782],{"class":134,"line":202},[132,762,763],{"class":183},"    app",[132,765,341],{"class":138},[132,767,533],{"class":344},[132,769,341],{"class":138},[132,771,712],{"class":142},[132,773,146],{"class":138},[132,775,776],{"class":142},"MySettings",[132,778,427],{"class":138},[132,780,781],{"class":142}," my_settings",[132,783,158],{"class":138},[39,785,787],{"id":786},"a-whole-new-logging-experience","A whole new logging experience",[19,789,790],{},"Litestar's logging integration has been greatly simplified. And by simplified I mean\n\"mostly removed\". While it had a noble goal (providing a unified interface for different\nlogging libraries, suited for the needs of usage in a web framework environment), it\noften fell short of them, and users and developers alike ended up frustrated. And filing\nand fixing a lot of bugs.",[19,792,793,794,797,798,801,802,805],{},"So we went back to the drawing board and came up with an integration that's reduced the\nlogging interface to the bare minimum Litestar ",[49,795,796],{},"actually"," needs, for the few logging\nfeatures it has: You can provide an object conforming to the stdlibs ",[100,799,800],{},"logging.Logger","\ninterface or, alternatively, to structlog's logger interface, which can be toggle via a\n",[100,803,804],{},"log_structured=True"," parameter.",[19,807,808],{},"But that's about it. Nothing more to it.",[19,810,811,812,816,817,341],{},"You can read more about it ",[23,813,112],{"href":814,"rel":815},"https:\u002F\u002Fdocs.litestar.dev\u002Fmain\u002Frelease-notes\u002Fchangelog.html#3.0.0-remove%20logging%20config%20and%20related%20constructs",[27],"\nand ",[23,818,821],{"href":819,"rel":820},"https:\u002F\u002Fdocs.litestar.dev\u002Fmain\u002Fusage\u002Flogging.html",[27],"there",[39,823,825],{"id":824},"redesigning-handler-registration","Redesigning handler registration",[19,827,828],{},"One of the major changes is something that has no visible effects above the surface;\nIn 3.0, Litestar's layer system, i.e. how route handlers, controllers, routers and\napplications are wired togehter, has been completely rewritten.",[19,830,831],{},"Litestar's routing generally works top-down:",[56,833,834,837],{},[59,835,836],{},"An application register a router, a router registers a handler, etc.",[59,838,839,840,843],{},"A handler will receive configuration from the layers ",[49,841,842],{},"above"," it",[123,845,847],{"className":125,"code":846,"language":127,"meta":128,"style":128},"class SomeController(Controller):\n    path = \"\u002Fcontroller\"\n    guards = [controller_guard]\n\n    @get(\"\u002Fhandler\", guards=[handler_guard])\n    async def handler(self) -> None:\n        pass\n\n\napp = Litestar([SomeController], guards=[app_guard])\n",[100,848,849,863,879,895,899,926,944,949,953,957],{"__ignoreMap":128},[132,850,851,853,856,858,861],{"class":134,"line":135},[132,852,544],{"class":164},[132,854,855],{"class":547}," SomeController",[132,857,146],{"class":138},[132,859,860],{"class":547},"Controller",[132,862,556],{"class":138},[132,864,865,868,870,873,876],{"class":134,"line":161},[132,866,867],{"class":183},"    path ",[132,869,222],{"class":138},[132,871,872],{"class":138}," \"",[132,874,875],{"class":152},"\u002Fcontroller",[132,877,878],{"class":138},"\"\n",[132,880,881,884,886,889,892],{"class":134,"line":202},[132,882,883],{"class":183},"    guards ",[132,885,222],{"class":138},[132,887,888],{"class":138}," [",[132,890,891],{"class":183},"controller_guard",[132,893,894],{"class":138},"]\n",[132,896,897],{"class":134,"line":209},[132,898,213],{"emptyLinePlaceholder":212},[132,900,901,904,906,908,910,913,915,917,919,921,924],{"class":134,"line":216},[132,902,903],{"class":138},"    @",[132,905,143],{"class":142},[132,907,146],{"class":138},[132,909,149],{"class":138},[132,911,912],{"class":152},"\u002Fhandler",[132,914,149],{"class":138},[132,916,427],{"class":138},[132,918,430],{"class":176},[132,920,433],{"class":138},[132,922,923],{"class":142},"handler_guard",[132,925,439],{"class":138},[132,927,928,930,932,934,936,938,940,942],{"class":134,"line":231},[132,929,561],{"class":164},[132,931,168],{"class":164},[132,933,171],{"class":142},[132,935,146],{"class":138},[132,937,572],{"class":571},[132,939,615],{"class":138},[132,941,196],{"class":138},[132,943,199],{"class":138},[132,945,946],{"class":134,"line":244},[132,947,948],{"class":205},"        pass\n",[132,950,951],{"class":134,"line":256},[132,952,213],{"emptyLinePlaceholder":212},[132,954,955],{"class":134,"line":275},[132,956,213],{"emptyLinePlaceholder":212},[132,958,959,962,964,966,969,972,975,977,979,982],{"class":134,"line":457},[132,960,961],{"class":183},"app ",[132,963,222],{"class":138},[132,965,629],{"class":142},[132,967,968],{"class":138},"([",[132,970,971],{"class":142},"SomeController",[132,973,974],{"class":138},"],",[132,976,430],{"class":176},[132,978,433],{"class":138},[132,980,981],{"class":142},"app_guard",[132,983,439],{"class":138},[19,985,986,987,989,990,992,993,995,996,998,999,1002],{},"In this example, ",[100,988,744],{}," registers ",[100,991,971],{},", which in turn registers ",[100,994,250],{},",\nwhile ",[100,997,250],{}," receives ",[100,1000,1001],{},"guards"," from all levels above it.",[19,1004,1005],{},"At least on the API surface this is the case. Underneath, it poses a bit of a technical\nchallenge: If components (handlers, controllers, routers) are meant to be standalone,\nhow can e.g. a handler know about guards registered above it? The usual solution to this\nwould be to make them active elements of the routing process; When a request comes in,\nit is first handled by the app, which resolves its guards, then if the request path\nmatches a subcomponent, further routing is handed down to it, in this instance the\ncontroller, and the same process repeats all the way down until a leaf node in the\nrouting tree is hit, and a response can be generated.",[19,1007,1008],{},"This approach though comes with its own downsides: It requires distributing a lot of\nthe dispatch logic into components, compared to a more centralised design, and it also\nremoves opportunities for optimisation (e.g. if we know all guards \u002F dependencies \u002F\netc. a request will hit at once, we can resolve them concurrently or skip those we know\ncan't be reached).",[19,1010,1011],{},"For these reasons, in Litestar 2, a different design was chosen: During the\nregistration process, a component kept track of its parent layers, providing access to\nthem through the handler. The handler could then resolve them lazily whenever needed.",[19,1013,1014],{},"However convenient, this design had a few downsides mainly that:",[56,1016,1017,1020,1023],{},[59,1018,1019],{},"It required keeping all the layers around, which were basically just static\nconfiguration except the parent tracking",[59,1021,1022],{},"It had to (deep)copy things frequently, causing complicated workarounds, hampered\nstartup performance and lead to unexpected behaviour in some cases",[59,1024,1025],{},"Handlers were stateful, opening the door to race conditions and other issues stemming\nfrom what's now effectively global state (this was mitigated somewhat by the copying though)",[19,1027,1028],{},"And there were a few things that we could not do with this, for example caching resolved\ncomponents statically.",[19,1030,1031],{},[85,1032,1033],{},"The new approach",[19,1035,1036,1037,1040],{},"The new component registration in Litestar 3 departs from the dynamic nature, and\nfully embraces static configuration; Transient components (i.e. controllers and routers)\ncompletely disappear at runtime, and purely function as an intermediate configuration\nlayer. When a handler is added to a router, nothing happens immediately - only a\nreference to the handler is stored there. The actual registration happens after a\ncomponent is added to an application. On startup, the application recursively walks all\ncomponents, bottom-up, and ",[49,1038,1039],{},"merges"," them into a new handler. That is, a completely new\nhandler instance will be created, from the merged values of all the layers above it.",[19,1042,1043],{},"In practice this means that",[123,1045,1047],{"className":125,"code":1046,"language":127,"meta":128,"style":128},"class SomeController(Controller):\n    path = \"\u002Fcontroller\"\n    guards = [controller_guard]\n\n    @get(\"\u002Fhandler\", guards=[handler_guard])\n    async def handler(self) -> None:\n        pass\n\n\nrouter = Router(\"\u002Frouter\", [SomeController], guards=[router_guard])\n\napp = Litestar([router], guards=[app_guard])\n",[100,1048,1049,1061,1073,1085,1089,1113,1131,1135,1139,1143,1177,1181],{"__ignoreMap":128},[132,1050,1051,1053,1055,1057,1059],{"class":134,"line":135},[132,1052,544],{"class":164},[132,1054,855],{"class":547},[132,1056,146],{"class":138},[132,1058,860],{"class":547},[132,1060,556],{"class":138},[132,1062,1063,1065,1067,1069,1071],{"class":134,"line":161},[132,1064,867],{"class":183},[132,1066,222],{"class":138},[132,1068,872],{"class":138},[132,1070,875],{"class":152},[132,1072,878],{"class":138},[132,1074,1075,1077,1079,1081,1083],{"class":134,"line":202},[132,1076,883],{"class":183},[132,1078,222],{"class":138},[132,1080,888],{"class":138},[132,1082,891],{"class":183},[132,1084,894],{"class":138},[132,1086,1087],{"class":134,"line":209},[132,1088,213],{"emptyLinePlaceholder":212},[132,1090,1091,1093,1095,1097,1099,1101,1103,1105,1107,1109,1111],{"class":134,"line":216},[132,1092,903],{"class":138},[132,1094,143],{"class":142},[132,1096,146],{"class":138},[132,1098,149],{"class":138},[132,1100,912],{"class":152},[132,1102,149],{"class":138},[132,1104,427],{"class":138},[132,1106,430],{"class":176},[132,1108,433],{"class":138},[132,1110,923],{"class":142},[132,1112,439],{"class":138},[132,1114,1115,1117,1119,1121,1123,1125,1127,1129],{"class":134,"line":231},[132,1116,561],{"class":164},[132,1118,168],{"class":164},[132,1120,171],{"class":142},[132,1122,146],{"class":138},[132,1124,572],{"class":571},[132,1126,615],{"class":138},[132,1128,196],{"class":138},[132,1130,199],{"class":138},[132,1132,1133],{"class":134,"line":244},[132,1134,948],{"class":205},[132,1136,1137],{"class":134,"line":256},[132,1138,213],{"emptyLinePlaceholder":212},[132,1140,1141],{"class":134,"line":275},[132,1142,213],{"emptyLinePlaceholder":212},[132,1144,1145,1147,1149,1151,1153,1155,1158,1160,1162,1164,1166,1168,1170,1172,1175],{"class":134,"line":457},[132,1146,219],{"class":183},[132,1148,222],{"class":138},[132,1150,225],{"class":142},[132,1152,146],{"class":138},[132,1154,149],{"class":138},[132,1156,1157],{"class":152},"\u002Frouter",[132,1159,149],{"class":138},[132,1161,427],{"class":138},[132,1163,888],{"class":138},[132,1165,971],{"class":142},[132,1167,974],{"class":138},[132,1169,430],{"class":176},[132,1171,433],{"class":138},[132,1173,1174],{"class":142},"router_guard",[132,1176,439],{"class":138},[132,1178,1179],{"class":134,"line":462},[132,1180,213],{"emptyLinePlaceholder":212},[132,1182,1183,1185,1187,1189,1191,1194,1196,1198,1200,1202],{"class":134,"line":467},[132,1184,961],{"class":183},[132,1186,222],{"class":138},[132,1188,629],{"class":142},[132,1190,968],{"class":138},[132,1192,1193],{"class":142},"router",[132,1195,974],{"class":138},[132,1197,430],{"class":176},[132,1199,433],{"class":138},[132,1201,981],{"class":142},[132,1203,439],{"class":138},[19,1205,1206],{},"is, after registration, the same as",[123,1208,1210],{"className":125,"code":1209,"language":127,"meta":128,"style":128},"@get(\n    \"\u002Frouter\u002Fcontroller\u002Fhandler\",\n    guards=[\n        app_guard,\n        router_guard,\n        controller_guard,\n        handler_guard,\n    ]\n)\nasync def handler() -> None:\n    pass\n\napp = Litestar([handler])\n",[100,1211,1212,1220,1231,1239,1246,1253,1260,1267,1272,1276,1290,1294,1298],{"__ignoreMap":128},[132,1213,1214,1216,1218],{"class":134,"line":135},[132,1215,139],{"class":138},[132,1217,143],{"class":142},[132,1219,228],{"class":138},[132,1221,1222,1224,1227,1229],{"class":134,"line":161},[132,1223,234],{"class":138},[132,1225,1226],{"class":152},"\u002Frouter\u002Fcontroller\u002Fhandler",[132,1228,149],{"class":138},[132,1230,241],{"class":138},[132,1232,1233,1236],{"class":134,"line":202},[132,1234,1235],{"class":176},"    guards",[132,1237,1238],{"class":138},"=[\n",[132,1240,1241,1244],{"class":134,"line":209},[132,1242,1243],{"class":142},"        app_guard",[132,1245,241],{"class":138},[132,1247,1248,1251],{"class":134,"line":216},[132,1249,1250],{"class":142},"        router_guard",[132,1252,241],{"class":138},[132,1254,1255,1258],{"class":134,"line":231},[132,1256,1257],{"class":142},"        controller_guard",[132,1259,241],{"class":138},[132,1261,1262,1265],{"class":134,"line":244},[132,1263,1264],{"class":142},"        handler_guard",[132,1266,241],{"class":138},[132,1268,1269],{"class":134,"line":256},[132,1270,1271],{"class":138},"    ]\n",[132,1273,1274],{"class":134,"line":275},[132,1275,158],{"class":138},[132,1277,1278,1280,1282,1284,1286,1288],{"class":134,"line":457},[132,1279,165],{"class":164},[132,1281,168],{"class":164},[132,1283,171],{"class":142},[132,1285,450],{"class":138},[132,1287,196],{"class":138},[132,1289,199],{"class":138},[132,1291,1292],{"class":134,"line":462},[132,1293,206],{"class":205},[132,1295,1296],{"class":134,"line":467},[132,1297,213],{"emptyLinePlaceholder":212},[132,1299,1300,1302,1304,1306,1308,1310],{"class":134,"line":478},[132,1301,961],{"class":183},[132,1303,222],{"class":138},[132,1305,629],{"class":142},[132,1307,968],{"class":138},[132,1309,250],{"class":142},[132,1311,439],{"class":138},[19,1313,1314],{},"These are not just semantically the same, but also technically. The original handler\nsupplied by the user is left completely untouched, only the reference to the function is\nkept. Everything else is re-created with the merged values.",[19,1316,1317],{},"With this change, routers, controllers and handlers now contain virtually no runtime\nlogic any more, and serve purely as configuration objects. It has also proven to provide\nsome modest startup time improvements for larger apps, but the main benefit is\nmaintainability; The code is much more concise, tightly grouped and split by\nresponsibility. Components are now truly independent, and they need not and cannot know\nanything about the context they're included in.",[19,1319,1320,1321,1324,1325,615],{},"An exemplary payoff of this redesign is the new zero-overhead middleware exclusions;\nMiddlewares that are statically excluded from a component (e.g. via an ",[100,1322,1323],{},"opt"," key or a\npath filter) won't be applied to that component at all, instead of dynamically checking\nif the middleware should be skipped at runtime.\n(Read more about this ",[23,1326,112],{"href":1327,"rel":1328},"https:\u002F\u002Fdocs.litestar.dev\u002Fmain\u002Frelease-notes\u002Fchangelog.html#3.0.0-zero%20cost%20excluded%20middlewares",[27],[39,1330,1332],{"id":1331},"more-exciting-things","More exciting things",[19,1334,1335,1336,241,1341,241,1346,1351],{},"There are many more changes, such as\n",[23,1337,1340],{"href":1338,"rel":1339},"https:\u002F\u002Fdocs.litestar.dev\u002Fmain\u002Fusage\u002Fmiddleware\u002Fcreating-middleware.html#configuration-constraints",[27],"middleware configuration constraints",[23,1342,1345],{"href":1343,"rel":1344},"https:\u002F\u002Fdocs.litestar.dev\u002Fmain\u002Frelease-notes\u002Fwhats-new-3.html#improved-file-system-handling-fsspec-integration",[27],"improved cloud file system integration",[23,1347,1350],{"href":1348,"rel":1349},"https:\u002F\u002Fdocs.litestar.dev\u002Fmain\u002Frelease-notes\u002Fchangelog.html#3.0.0-make",[27],"async native test client"," and many more.",[19,1353,1354,1355,1360,1361,1366],{},"See ",[23,1356,1359],{"href":1357,"rel":1358},"https:\u002F\u002Fdocs.litestar.dev\u002Fmain\u002Frelease-notes\u002Fchangelog.html",[27],"3.x changelog"," and\n",[23,1362,1365],{"href":1363,"rel":1364},"https:\u002F\u002Fdocs.litestar.dev\u002Fmain\u002Frelease-notes\u002Fwhats-new-3.htm",[27],"What's changed in 3.0"," for an overview.",[34,1368,1370],{"id":1369},"release-when","Release when?",[19,1372,1373,1374,1377],{},"Litestar 3.0 will probably release some time within 2026. There's one major feature\nstill waiting for completion before going into beta (DI overhaul). This is currently\nblocked by a lack of maintainer resources (i.e. I - Janek - do not have enough time at\nthe moment to consistently work on it). The groundwork is laid though, the core is\nworking, all preparations have been made. I currently expect the beta to land by the\nend of this summer. After that, the final release date for 3.0 depends on how the beta\ngoes. Since 3.0 has been developed on ",[100,1375,1376],{},"main"," for quite a while now, and people have been\ntest-driving it, we currently don't expect any major surprises, so we're aiming for ~3\nmonths after the beta release.",[34,1379,1381],{"id":1380},"and-beyond","And beyond",[19,1383,1384],{},"Technical details aside, what's the future like for Litestar? What are the long term\ngoals? Where are we headed conceptually? How are we doing emotionally? What does\nLitestar want?",[19,1386,1387],{},"It's been a long time since Litestar 2.0 released, and a lot has changed since then. The\nproject has grown, maintainers came and went, and the project has seen a steady increase\nin usage.",[19,1389,1390],{},"The project is in a good shape now. Much better than it was when 2.0 was released. There\nare fewer \"big things\" on our to-do lists, to the point where I expect that after 3.0,\nwe can put our maintenance focus (even) more on minor improvements, documentation\nupdates and other auxiliary resources.",[19,1392,1393],{},"Furthermore, Litestar has managed to establish a niche in the well satiated web\nframework space for itself, comfortably placing it as a viable alternative to well known\nnames, albeit not rivalling them in sheer popularity. The Litestar of today has a unique\nflavour and style to it, that we, I, and a growing community of users have come to\ncherish. I'm hoping beyond 3.0, we can explore this even further, but I would not expect\na major release any time soon after.",[19,1395,1396,1397,1402],{},"Once 3.0 is released and well, I will take some time to focus on\n",[23,1398,1401],{"href":1399,"rel":1400},"https:\u002F\u002Fmsgspec.dev\u002F",[27],"msgspec",", a project that Litestar relies on a great deal for many\nof its internals, and where I've recently joined the maintainer team. Keeping Litestar's\necosystem and foundations alive is equally important as the core-framework-work itself,\nand I'm more than happy about the opportunity for all of this work.",[19,1404,1405,1406,1411,1412,1417],{},"Well then, I hope you feel a bit more informed after reading this. If on the other hand\nit raised more questions than it answered, don't hesitate to pop over to our\n",[23,1407,1410],{"href":1408,"rel":1409},"https:\u002F\u002Fgithub.com\u002Forgs\u002Flitestar-org\u002Fdiscussions",[27],"discussions page"," or\n",[23,1413,1416],{"href":1414,"rel":1415},"https:\u002F\u002Fdiscord.gg\u002Flitestar",[27],"discord"," and ask away!",[1419,1420,1421],"style",{},"html pre.shiki code .sDfIl, html code.shiki .sDfIl{--shiki-light:#39ADB5;--shiki-default:#39ADB5;--shiki-dark:#89DDFF}html pre.shiki code .s3cPz, html code.shiki .s3cPz{--shiki-light:#6182B8;--shiki-default:#6182B8;--shiki-dark:#82AAFF}html pre.shiki code .sGFVr, html code.shiki .sGFVr{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}html pre.shiki code .smZ93, html code.shiki .smZ93{--shiki-light:#9C3EDA;--shiki-default:#9C3EDA;--shiki-dark:#C792EA}html pre.shiki code .s1nJG, html code.shiki .s1nJG{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sZSNi, html code.shiki .sZSNi{--shiki-light:#90A4AE;--shiki-default:#90A4AE;--shiki-dark:#BABED8}html pre.shiki code .s8R28, html code.shiki .s8R28{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#39ADB5;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sRlkE, html code.shiki .sRlkE{--shiki-light:#E53935;--shiki-default:#E53935;--shiki-dark:#F07178}html pre.shiki code .s52Pk, html code.shiki .s52Pk{--shiki-light:#E2931D;--shiki-default:#E2931D;--shiki-dark:#FFCB6B}html pre.shiki code .seDIv, html code.shiki .seDIv{--shiki-light:#E53935;--shiki-light-font-style:italic;--shiki-default:#E53935;--shiki-default-font-style:italic;--shiki-dark:#F07178;--shiki-dark-font-style:italic}",{"title":128,"searchDepth":161,"depth":161,"links":1423},[1424,1430,1431],{"id":36,"depth":161,"text":37,"children":1425},[1426,1427,1428,1429],{"id":41,"depth":202,"text":42},{"id":786,"depth":202,"text":787},{"id":824,"depth":202,"text":825},{"id":1331,"depth":202,"text":1332},{"id":1369,"depth":161,"text":1370},{"id":1380,"depth":161,"text":1381},"Announcement","2026-07-26","Litestar 3 is afoot. Have a look at what awaits you","md",null,{},"\u002Fblog\u002Fv3-announcement",{"title":9,"description":1434},"blog\u002F2.v3-announcement","Hy3ZincXjdz2Vhqvvil71MRNCFfGir2HpP69FM5w1rw",{"id":1443,"title":1444,"authors":1445,"body":1450,"category":1432,"date":1749,"description":1750,"extension":1435,"image":1436,"meta":1751,"navigation":212,"path":1752,"seo":1753,"stem":1754,"tags":1436,"__hash__":1755},"blog\u002Fblog\u002F1.new-website-and-v3.md","Introducing the New Litestar Website and the upcoming 3.0 release",[1446],{"name":1447,"avatar":1448},"Julien Courtès",{"src":1449},"https:\u002F\u002Fgithub.com\u002FKumzy.png",{"type":16,"value":1451,"toc":1732},[1452,1455,1459,1462,1466,1469,1473,1476,1494,1497,1501,1504,1508,1511,1528,1531,1535,1541,1545,1548,1551,1555,1563,1577,1581,1584,1588,1596,1610,1614,1617,1643,1652,1656,1659,1667,1671,1674,1708,1726,1729],[19,1453,1454],{},"We are thrilled to announce the launch of our new website along a preview of the upcoming v3 version of Litestar. This major update is the result of years of hard work and dedication from our team, and we can't wait to share it with you!",[34,1456,1458],{"id":1457},"website","Website",[19,1460,1461],{},"With the upcoming v3, we wanted to have a new website that would reflect evolution of the project and the ecosystem around the framework.",[39,1463,1465],{"id":1464},"plugin-directory","Plugin Directory",[19,1467,1468],{},"We wired a page to list all the plugins available for the Litestar framework. It includes official plugins maintained by the Litestar team as well as plugins developped by the community.",[92,1470,1472],{"id":1471},"submit-your-plugin","Submit Your Plugin",[19,1474,1475],{},"If you want to develop or register your plugin, you can have it listed there by submitting your plugin:",[1477,1478,1479,1488,1491],"ol",{},[59,1480,1481,1482,1487],{},"Fork the ",[23,1483,1486],{"href":1484,"rel":1485},"https:\u002F\u002Fgithub.com\u002Flitestar-org\u002Fplugin-registry",[27],"litestar-org\u002Fplugin-registry"," repository",[59,1489,1490],{},"Add your plugin information following our submission guidelines",[59,1492,1493],{},"Create a pull request with your plugin details",[19,1495,1496],{},"We will then merge our submission and you will be listed in the plugin page.",[39,1498,1500],{"id":1499},"blog-section","Blog Section",[19,1502,1503],{},"We decided to add a blog to share some exciting news about the litestar framework and the ecosystem. We will be posting release announcements and updates.",[39,1505,1507],{"id":1506},"next-improvements","Next improvements",[19,1509,1510],{},"We have a ton of ideas for the website, not sure all the things we have in mind will make it one day, but here is a list of some of the things:",[56,1512,1513,1516,1519,1522,1525],{},[59,1514,1515],{},"Deployment guide (how to deploy your Litestar application in production)",[59,1517,1518],{},"Tutorials (interactive tutorials to learn Litestar hands-on)",[59,1520,1521],{},"Starter templates (boilerplates to kickstart your projects or create a plugin)",[59,1523,1524],{},"Docker and containerization best practices",[59,1526,1527],{},"Performance optimization tips",[19,1529,1530],{},"This section will help you take your Litestar applications from development to production with confidence.",[34,1532,1534],{"id":1533},"litestar-v3","Litestar v3",[19,1536,1537,1538,341],{},"Litestar 3 is on its way! Read all about what's coming in the ",[23,1539,1540],{"href":1438},"Litestar 3 announcement",[39,1542,1544],{"id":1543},"new-documentation","New documentation",[19,1546,1547],{},"We have revamped the documentation for the v3 release, making it more comprehensive and easier to navigate. But writing good documentation is hard and takes a lot of time, so we are still working on it and we will keep improving it as we get closer to the release.",[19,1549,1550],{},"Do not hesitate to check it out and give us feedback on how we can improve it, or even better, contribute to it if you want to help us!",[34,1552,1554],{"id":1553},"europython-2026","EuroPython 2026",[19,1556,1557,1558,1562],{},"We will be attending ",[23,1559,1554],{"href":1560,"rel":1561},"https:\u002F\u002Fep2026.europython.eu\u002F",[27]," in Kraków in July. This is a great opportunity for us to connect with the community, share our progress on Litestar v3, and gather feedback.",[19,1564,1565,1566,1571,1572,1576],{},"Cody and Julien gave a ",[23,1567,1570],{"href":1568,"rel":1569},"https:\u002F\u002Fep2026.europython.eu\u002Fsession\u002Fdesigning-performant-apis-with-litestar",[27],"talk"," about how to design performant APIs with Litestar, make sure to check it out! Also Jacob gave also a ",[23,1573,1570],{"href":1574,"rel":1575},"https:\u002F\u002Fep2026.europython.eu\u002Fsession\u002Fsupercharging-litestar-extensibility-through-plugins",[27]," about supercharging litestar with plugins.",[34,1578,1580],{"id":1579},"join-our-community","Join our community",[19,1582,1583],{},"The Litestar project lives because of our community. Here's how you can get involved:",[39,1585,1587],{"id":1586},"connect-on-discord","Connect on Discord",[19,1589,1590,1591,1595],{},"Join our vibrant ",[23,1592,1594],{"href":1414,"rel":1593},[27],"Discord community"," where you can:",[56,1597,1598,1601,1604,1607],{},[59,1599,1600],{},"Get help with your projects",[59,1602,1603],{},"Share your creations",[59,1605,1606],{},"Discuss new features and ideas",[59,1608,1609],{},"Connect with other Litestar developers",[39,1611,1613],{"id":1612},"contribute-to-the-project","Contribute to the project",[19,1615,1616],{},"Litestar is open source and welcomes contributors! Whether you're interested in:",[56,1618,1619,1625,1631,1637],{},[59,1620,1621,1624],{},[85,1622,1623],{},"Code contributions",": Bug fixes, new features, performance improvements",[59,1626,1627,1630],{},[85,1628,1629],{},"Documentation",": Writing guides, improving examples, fixing typos",[59,1632,1633,1636],{},[85,1634,1635],{},"Community support",": Helping others on Discord and GitHub",[59,1638,1639,1642],{},[85,1640,1641],{},"Plugin development",": Creating tools that extend Litestar's capabilities",[19,1644,1645,1646,1651],{},"Every contribution makes a difference. Check out our ",[23,1647,1650],{"href":1648,"rel":1649},"https:\u002F\u002Fdocs.litestar.dev\u002Flatest\u002Fcontribution-guide",[27],"contribution guide"," to get started.",[39,1653,1655],{"id":1654},"talk-about-litestar","Talk about Litestar",[19,1657,1658],{},"If you enjoy using Litestar, consider sharing your experience with others, you can:",[56,1660,1661,1664],{},[59,1662,1663],{},"Write blog posts or tutorials about your projects",[59,1665,1666],{},"Talk to others about your experience with Litestar",[34,1668,1670],{"id":1669},"get-started-today","Get started today",[19,1672,1673],{},"If you want to try out Litestar, you can install it using pip or uv (or any package manager of your choice):",[123,1675,1679],{"className":1676,"code":1677,"language":1678,"meta":128,"style":128},"language-bash shiki shiki-themes material-theme-lighter material-theme-lighter material-theme-palenight","pip install litestar\n# or\nuv add litestar\n","bash",[100,1680,1681,1692,1698],{"__ignoreMap":128},[132,1682,1683,1686,1689],{"class":134,"line":135},[132,1684,1685],{"class":547},"pip",[132,1687,1688],{"class":152}," install",[132,1690,1691],{"class":152}," litestar\n",[132,1693,1694],{"class":134,"line":161},[132,1695,1697],{"class":1696},"sWuyu","# or\n",[132,1699,1700,1703,1706],{"class":134,"line":202},[132,1701,1702],{"class":547},"uv",[132,1704,1705],{"class":152}," add",[132,1707,1691],{"class":152},[19,1709,1710,1711,1716,1717,1721,1722,1725],{},"Visit our ",[23,1712,1715],{"href":1713,"rel":1714},"https:\u002F\u002Fdocs.litestar.dev",[27],"documentation"," for comprehensive guides, explore the ",[23,1718,1720],{"href":1719},"\u002Fplugins","plugin directory"," for useful extensions, and join our ",[23,1723,1594],{"href":1414,"rel":1724},[27]," to connect with fellow developers.",[19,1727,1728],{},"We can't wait to see what you'll build with Litestar!",[1419,1730,1731],{},"html pre.shiki code .s52Pk, html code.shiki .s52Pk{--shiki-light:#E2931D;--shiki-default:#E2931D;--shiki-dark:#FFCB6B}html pre.shiki code .sGFVr, html code.shiki .sGFVr{--shiki-light:#91B859;--shiki-default:#91B859;--shiki-dark:#C3E88D}html pre.shiki code .sWuyu, html code.shiki .sWuyu{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#90A4AE;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":128,"searchDepth":161,"depth":161,"links":1733},[1734,1739,1742,1743,1748],{"id":1457,"depth":161,"text":1458,"children":1735},[1736,1737,1738],{"id":1464,"depth":202,"text":1465},{"id":1499,"depth":202,"text":1500},{"id":1506,"depth":202,"text":1507},{"id":1533,"depth":161,"text":1534,"children":1740},[1741],{"id":1543,"depth":202,"text":1544},{"id":1553,"depth":161,"text":1554},{"id":1579,"depth":161,"text":1580,"children":1744},[1745,1746,1747],{"id":1586,"depth":202,"text":1587},{"id":1612,"depth":202,"text":1613},{"id":1654,"depth":202,"text":1655},{"id":1669,"depth":161,"text":1670},"2026-07-25","We are proud to announce the launch of our new Litestar website, and some hints at the beta of Litestar 3.0.",{},"\u002Fblog\u002Fnew-website-and-v3",{"title":1444,"description":1750},"blog\u002F1.new-website-and-v3","XP5mqDAA9--L_R9SXDgNL_91kLb7WgiFjGXLUX0UWas",1785155663549]