[{"data":1,"prerenderedAt":1827},["ShallowReactive",2],{"\u002Fblog\u002Ftresjs-rapier-v1":3,"author-nathan-mande":1762,"author-jaime-bboyjt":1781,"author-alvarosabu":1798,"formatted-blog-post-\u002Fblog\u002Ftresjs-rapier-v1":1815},{"id":4,"title":5,"author":6,"body":10,"category":1746,"date":1747,"description":1748,"draft":203,"extension":1749,"meta":1750,"navigation":203,"path":1751,"readingTime":1752,"seo":1757,"stem":1758,"thumbnail":1759,"url":1760,"__hash__":1761},"blog\u002Fblog\u002Ftresjs-rapier-v1.md","Rapier Physics v1",[7,8,9],"nathan-mande","jaime-bboyjt","alvarosabu",{"type":11,"value":12,"toc":1732},"minimark",[13,17,47,52,57,114,125,468,480,484,491,506,569,576,592,596,605,648,655,662,669,838,853,857,863,1078,1089,1095,1099,1109,1127,1130,1134,1137,1189,1196,1202,1307,1312,1318,1322,1325,1348,1355,1359,1372,1437,1444,1451,1460,1577,1582,1590,1597,1601,1615,1619,1688,1692,1706,1719,1728],[14,15,16],"p",{},"Since we launched Tres some years ago, I was looking specially to the moment we release a Physics module because the big majority of games out there, needs some level of collision handling and, honestly, because a scene where nothing ever falls, bounces or bumps into anything else stops being fun very quickly.",[14,18,19,20,34,35,40,41,46],{},"Today that moment is here: ",[21,22,23,33],"strong",{},[24,25,29],"a",{"href":26,"rel":27},"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@tresjs\u002Frapier",[28],"nofollow",[30,31,32],"code",{},"@tresjs\u002Frapier"," v1.0.0 is stable"," 🎉. Declarative physics for TresJS, powered by ",[24,36,39],{"href":37,"rel":38},"https:\u002F\u002Frapier.rs\u002F",[28],"Rapier",", the Rust physics engine compiled to WASM by the folks at ",[24,42,45],{"href":43,"rel":44},"https:\u002F\u002Fdimforge.com\u002F",[28],"Dimforge",".",[48,49],"blog-embed-lab",{"src":50,"title":51},"https:\u002F\u002Flab.tresjs.org\u002Fexperiments\u002Frapier-object-clump\u002F","Rapier object clump physics demo",[53,54,56],"h2",{"id":55},"getting-started","Getting started",[58,59,60,85,100],"code-group",{},[61,62,68],"pre",{"className":63,"code":64,"filename":65,"language":66,"meta":67,"style":67},"language-bash shiki shiki-themes catppuccin-latte catppuccin-latte catppuccin-frappe","npm install @tresjs\u002Frapier\n","npm","bash","",[30,69,70],{"__ignoreMap":67},[71,72,75,78,82],"span",{"class":73,"line":74},"line",1,[71,76,65],{"class":77},"s0faT",[71,79,81],{"class":80},"s9Zht"," install",[71,83,84],{"class":80}," @tresjs\u002Frapier\n",[61,86,89],{"className":63,"code":87,"filename":88,"language":66,"meta":67,"style":67},"yarn add @tresjs\u002Frapier\n","yarn",[30,90,91],{"__ignoreMap":67},[71,92,93,95,98],{"class":73,"line":74},[71,94,88],{"class":77},[71,96,97],{"class":80}," add",[71,99,84],{"class":80},[61,101,104],{"className":63,"code":102,"filename":103,"language":66,"meta":67,"style":67},"pnpm add @tresjs\u002Frapier\n","pnpm",[30,105,106],{"__ignoreMap":67},[71,107,108,110,112],{"class":73,"line":74},[71,109,103],{"class":77},[71,111,97],{"class":80},[71,113,84],{"class":80},[14,115,116,117,120,121,124],{},"Wrap your world in a ",[30,118,119],{},"\u003CPhysics>"," provider, mark the things that should be simulated with ",[30,122,123],{},"\u003CRigidBody>"," and that's it, no physics loop to hand-wire, no manual syncing between the simulation and the scene graph:",[61,126,130],{"className":127,"code":128,"language":129,"meta":67,"style":67},"language-vue shiki shiki-themes catppuccin-latte catppuccin-latte catppuccin-frappe","\u003Cscript setup lang=\"ts\">\nimport { Physics, RigidBody } from '@tresjs\u002Frapier'\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CTresCanvas>\n    \u003CSuspense>\n      \u003CPhysics>\n        \u003CRigidBody collider=\"ball\" :restitution=\"0.5\">\n          \u003CTresMesh :position=\"[0, 8, 0]\">\n            \u003CTresSphereGeometry \u002F>\n            \u003CTresMeshNormalMaterial \u002F>\n          \u003C\u002FTresMesh>\n        \u003C\u002FRigidBody>\n\n        \u003CRigidBody type=\"fixed\">\n          \u003CTresMesh :rotation=\"[-Math.PI \u002F 2, 0, 0]\">\n            \u003CTresPlaneGeometry :args=\"[20, 20]\" \u002F>\n            \u003CTresMeshBasicMaterial color=\"#f4f4f4\" \u002F>\n          \u003C\u002FTresMesh>\n        \u003C\u002FRigidBody>\n      \u003C\u002FPhysics>\n    \u003C\u002FSuspense>\n  \u003C\u002FTresCanvas>\n\u003C\u002Ftemplate>\n","vue",[30,131,132,158,188,198,205,215,226,237,248,275,294,306,316,326,336,341,358,375,393,411,420,429,439,449,459],{"__ignoreMap":67},[71,133,134,138,142,146,149,152,155],{"class":73,"line":74},[71,135,137],{"class":136},"sWdzt","\u003C",[71,139,141],{"class":140},"slJ5s","script",[71,143,145],{"class":144},"s1cdE"," setup",[71,147,148],{"class":144}," lang",[71,150,151],{"class":136},"=",[71,153,154],{"class":80},"\"ts\"",[71,156,157],{"class":136},">\n",[71,159,161,165,169,173,176,179,182,185],{"class":73,"line":160},2,[71,162,164],{"class":163},"sZyUJ","import",[71,166,168],{"class":167},"spKPg"," {",[71,170,172],{"class":171},"s9Av-"," Physics",[71,174,175],{"class":167},",",[71,177,178],{"class":171}," RigidBody ",[71,180,181],{"class":167},"}",[71,183,184],{"class":163}," from",[71,186,187],{"class":80}," '@tresjs\u002Frapier'\n",[71,189,191,194,196],{"class":73,"line":190},3,[71,192,193],{"class":136},"\u003C\u002F",[71,195,141],{"class":140},[71,197,157],{"class":136},[71,199,201],{"class":73,"line":200},4,[71,202,204],{"emptyLinePlaceholder":203},true,"\n",[71,206,208,210,213],{"class":73,"line":207},5,[71,209,137],{"class":136},[71,211,212],{"class":140},"template",[71,214,157],{"class":136},[71,216,218,221,224],{"class":73,"line":217},6,[71,219,220],{"class":136},"  \u003C",[71,222,223],{"class":140},"TresCanvas",[71,225,157],{"class":136},[71,227,229,232,235],{"class":73,"line":228},7,[71,230,231],{"class":136},"    \u003C",[71,233,234],{"class":140},"Suspense",[71,236,157],{"class":136},[71,238,240,243,246],{"class":73,"line":239},8,[71,241,242],{"class":136},"      \u003C",[71,244,245],{"class":140},"Physics",[71,247,157],{"class":136},[71,249,251,254,257,260,262,265,268,270,273],{"class":73,"line":250},9,[71,252,253],{"class":136},"        \u003C",[71,255,256],{"class":140},"RigidBody",[71,258,259],{"class":144}," collider",[71,261,151],{"class":136},[71,263,264],{"class":80},"\"ball\"",[71,266,267],{"class":144}," :restitution",[71,269,151],{"class":136},[71,271,272],{"class":80},"\"0.5\"",[71,274,157],{"class":136},[71,276,278,281,284,287,289,292],{"class":73,"line":277},10,[71,279,280],{"class":136},"          \u003C",[71,282,283],{"class":140},"TresMesh",[71,285,286],{"class":144}," :position",[71,288,151],{"class":136},[71,290,291],{"class":80},"\"[0, 8, 0]\"",[71,293,157],{"class":136},[71,295,297,300,303],{"class":73,"line":296},11,[71,298,299],{"class":136},"            \u003C",[71,301,302],{"class":140},"TresSphereGeometry",[71,304,305],{"class":136}," \u002F>\n",[71,307,309,311,314],{"class":73,"line":308},12,[71,310,299],{"class":136},[71,312,313],{"class":140},"TresMeshNormalMaterial",[71,315,305],{"class":136},[71,317,319,322,324],{"class":73,"line":318},13,[71,320,321],{"class":136},"          \u003C\u002F",[71,323,283],{"class":140},[71,325,157],{"class":136},[71,327,329,332,334],{"class":73,"line":328},14,[71,330,331],{"class":136},"        \u003C\u002F",[71,333,256],{"class":140},[71,335,157],{"class":136},[71,337,339],{"class":73,"line":338},15,[71,340,204],{"emptyLinePlaceholder":203},[71,342,344,346,348,351,353,356],{"class":73,"line":343},16,[71,345,253],{"class":136},[71,347,256],{"class":140},[71,349,350],{"class":144}," type",[71,352,151],{"class":136},[71,354,355],{"class":80},"\"fixed\"",[71,357,157],{"class":136},[71,359,361,363,365,368,370,373],{"class":73,"line":360},17,[71,362,280],{"class":136},[71,364,283],{"class":140},[71,366,367],{"class":144}," :rotation",[71,369,151],{"class":136},[71,371,372],{"class":80},"\"[-Math.PI \u002F 2, 0, 0]\"",[71,374,157],{"class":136},[71,376,378,380,383,386,388,391],{"class":73,"line":377},18,[71,379,299],{"class":136},[71,381,382],{"class":140},"TresPlaneGeometry",[71,384,385],{"class":144}," :args",[71,387,151],{"class":136},[71,389,390],{"class":80},"\"[20, 20]\"",[71,392,305],{"class":136},[71,394,396,398,401,404,406,409],{"class":73,"line":395},19,[71,397,299],{"class":136},[71,399,400],{"class":140},"TresMeshBasicMaterial",[71,402,403],{"class":144}," color",[71,405,151],{"class":136},[71,407,408],{"class":80},"\"#f4f4f4\"",[71,410,305],{"class":136},[71,412,414,416,418],{"class":73,"line":413},20,[71,415,321],{"class":136},[71,417,283],{"class":140},[71,419,157],{"class":136},[71,421,423,425,427],{"class":73,"line":422},21,[71,424,331],{"class":136},[71,426,256],{"class":140},[71,428,157],{"class":136},[71,430,432,435,437],{"class":73,"line":431},22,[71,433,434],{"class":136},"      \u003C\u002F",[71,436,245],{"class":140},[71,438,157],{"class":136},[71,440,442,445,447],{"class":73,"line":441},23,[71,443,444],{"class":136},"    \u003C\u002F",[71,446,234],{"class":140},[71,448,157],{"class":136},[71,450,452,455,457],{"class":73,"line":451},24,[71,453,454],{"class":136},"  \u003C\u002F",[71,456,223],{"class":140},[71,458,157],{"class":136},[71,460,462,464,466],{"class":73,"line":461},25,[71,463,193],{"class":136},[71,465,212],{"class":140},[71,467,157],{"class":136},[469,470,471],"prose-note",{},[14,472,473,475,476,479],{},[30,474,119],{}," loads the Rapier WASM binary asynchronously, so it needs a ",[30,477,478],{},"\u003CSuspense>"," boundary around it. If you are using Nuxt, the module handles the auto-imports for you.",[53,481,483],{"id":482},"frame-rate-independent-stepping","Frame-rate independent stepping",[14,485,486,487,490],{},"This is the change that earned the ",[30,488,489],{},"1.0.0"," more than any other. In the alpha, the simulation advanced once per rendered frame, which meant your physics behaved differently on a 60Hz laptop than on a 144Hz monitor: bodies fell faster, bounces were snappier and anything tuned on one machine felt wrong on another.",[14,492,493,494,497,498,501,502,505],{},"v1 steps the world on a ",[21,495,496],{},"fixed timestep with an accumulator",". The renderer runs at whatever rate the display gives it, each frame's delta goes into an accumulator, and the world is stepped in exact ",[30,499,500],{},"timeStep"," sized chunks (",[30,503,504],{},"1\u002F60"," by default) as many times as fit. The delta is also clamped before it goes in, so a long hitch (a background tab, a GC pause) can't hand the solver half a second of catch-up and spiral the frame budget into the ground.",[61,507,509],{"className":127,"code":508,"language":129,"meta":67,"style":67},"\u003CPhysics :time-step=\"1 \u002F 120\" :time-scale=\"0.5\">\n  \u003C!-- slow motion, simulated at 120Hz -->\n\u003C\u002FPhysics>\n",[30,510,511,556,561],{"__ignoreMap":67},[71,512,513,515,517,520,523,525,528,532,535,538,540,542,545,547,549,552,554],{"class":73,"line":74},[71,514,137],{"class":136},[71,516,245],{"class":140},[71,518,519],{"class":167}," :",[71,521,522],{"class":144},"time-step",[71,524,151],{"class":136},[71,526,527],{"class":80},"\"",[71,529,531],{"class":530},"sREMW","1",[71,533,534],{"class":136}," \u002F",[71,536,537],{"class":530}," 120",[71,539,527],{"class":80},[71,541,519],{"class":167},[71,543,544],{"class":144},"time-scale",[71,546,151],{"class":136},[71,548,527],{"class":80},[71,550,551],{"class":530},"0.5",[71,553,527],{"class":80},[71,555,157],{"class":136},[71,557,558],{"class":73,"line":160},[71,559,560],{"class":171},"  \u003C!-- slow motion, simulated at 120Hz -->\n",[71,562,563,565,567],{"class":73,"line":190},[71,564,193],{"class":136},[71,566,245],{"class":140},[71,568,157],{"class":136},[14,570,571,572,575],{},"If you actually want the old behaviour, ",[30,573,574],{},"timeStep=\"vary\""," steps once per frame with the raw delta. It's cheaper, and fine for purely decorative physics, just don't expect two machines to agree on the outcome.",[14,577,578,580,581,580,584,587,588,591],{},[30,579,500],{},", ",[30,582,583],{},"timeScale",[30,585,586],{},"pause"," and ",[30,589,590],{},"debug"," are all reactive, so you can wire them straight to a UI control and tweak them at runtime.",[53,593,595],{"id":594},"all-the-collider-shapes","All the collider shapes",[14,597,598,600,601,604],{},[30,599,123],{}," derives a collider from the geometry it wraps. Pass ",[30,602,603],{},"collider"," to pick the shape:",[606,607,608],"prose-list",{},[609,610,611,630,636,642],"ul",{},[612,613,614,617,618,580,621,580,624,580,627],"li",{},[30,615,616],{},"cuboid"," (default), ",[30,619,620],{},"ball",[30,622,623],{},"capsule",[30,625,626],{},"cone",[30,628,629],{},"cylinder",[612,631,632,635],{},[30,633,634],{},"convexHull"," for convex approximations of arbitrary meshes",[612,637,638,641],{},[30,639,640],{},"trimesh"," for exact geometry",[612,643,644,647],{},[30,645,646],{},"heightfield"," for terrain",[649,650,652],"blog-rapier-demo",{"label":651},"collider shapes demo",[653,654],"blog-embed-scene-rapier-shapes",{},[14,656,657,658,661],{},"One body per shape, dropped into a box. Hit ",[21,659,660],{},"Show colliders"," to see the difference between the mesh you rendered and the shape Rapier is actually solving against.",[14,663,664,665,668],{},"When the automatic shape isn't what you want, drop in ",[21,666,667],{},"custom colliders"," as standalone components and compose several of them inside a single body:",[61,670,672],{"className":127,"code":671,"language":129,"meta":67,"style":67},"\u003Cscript setup lang=\"ts\">\nimport { BallCollider, CuboidCollider, Physics, RigidBody } from '@tresjs\u002Frapier'\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CRigidBody :collider=\"false\">\n    \u003CCuboidCollider :args=\"[1, 0.5, 1]\" :position=\"[0, 0.5, 0]\" \u002F>\n    \u003CBallCollider :args=\"[0.5]\" :position=\"[0, 1.5, 0]\" \u002F>\n    \u003CTresMesh>\n      \u003C!-- your visual mesh, decoupled from the collision shape -->\n    \u003C\u002FTresMesh>\n  \u003C\u002FRigidBody>\n\u003C\u002Ftemplate>\n",[30,673,674,690,718,726,730,738,754,777,800,808,814,822,830],{"__ignoreMap":67},[71,675,676,678,680,682,684,686,688],{"class":73,"line":74},[71,677,137],{"class":136},[71,679,141],{"class":140},[71,681,145],{"class":144},[71,683,148],{"class":144},[71,685,151],{"class":136},[71,687,154],{"class":80},[71,689,157],{"class":136},[71,691,692,694,696,699,701,704,706,708,710,712,714,716],{"class":73,"line":160},[71,693,164],{"class":163},[71,695,168],{"class":167},[71,697,698],{"class":171}," BallCollider",[71,700,175],{"class":167},[71,702,703],{"class":171}," CuboidCollider",[71,705,175],{"class":167},[71,707,172],{"class":171},[71,709,175],{"class":167},[71,711,178],{"class":171},[71,713,181],{"class":167},[71,715,184],{"class":163},[71,717,187],{"class":80},[71,719,720,722,724],{"class":73,"line":190},[71,721,193],{"class":136},[71,723,141],{"class":140},[71,725,157],{"class":136},[71,727,728],{"class":73,"line":200},[71,729,204],{"emptyLinePlaceholder":203},[71,731,732,734,736],{"class":73,"line":207},[71,733,137],{"class":136},[71,735,212],{"class":140},[71,737,157],{"class":136},[71,739,740,742,744,747,749,752],{"class":73,"line":217},[71,741,220],{"class":136},[71,743,256],{"class":140},[71,745,746],{"class":144}," :collider",[71,748,151],{"class":136},[71,750,751],{"class":80},"\"false\"",[71,753,157],{"class":136},[71,755,756,758,761,763,765,768,770,772,775],{"class":73,"line":228},[71,757,231],{"class":136},[71,759,760],{"class":140},"CuboidCollider",[71,762,385],{"class":144},[71,764,151],{"class":136},[71,766,767],{"class":80},"\"[1, 0.5, 1]\"",[71,769,286],{"class":144},[71,771,151],{"class":136},[71,773,774],{"class":80},"\"[0, 0.5, 0]\"",[71,776,305],{"class":136},[71,778,779,781,784,786,788,791,793,795,798],{"class":73,"line":239},[71,780,231],{"class":136},[71,782,783],{"class":140},"BallCollider",[71,785,385],{"class":144},[71,787,151],{"class":136},[71,789,790],{"class":80},"\"[0.5]\"",[71,792,286],{"class":144},[71,794,151],{"class":136},[71,796,797],{"class":80},"\"[0, 1.5, 0]\"",[71,799,305],{"class":136},[71,801,802,804,806],{"class":73,"line":250},[71,803,231],{"class":136},[71,805,283],{"class":140},[71,807,157],{"class":136},[71,809,810],{"class":73,"line":277},[71,811,813],{"class":812},"sMnCH","      \u003C!-- your visual mesh, decoupled from the collision shape -->\n",[71,815,816,818,820],{"class":73,"line":296},[71,817,444],{"class":136},[71,819,283],{"class":140},[71,821,157],{"class":136},[71,823,824,826,828],{"class":73,"line":308},[71,825,454],{"class":136},[71,827,256],{"class":140},[71,829,157],{"class":136},[71,831,832,834,836],{"class":73,"line":318},[71,833,193],{"class":136},[71,835,212],{"class":140},[71,837,157],{"class":136},[469,839,840],{},[14,841,842,843,845,846,849,850,852],{},"Avoid ",[30,844,640],{}," colliders on ",[21,847,848],{},"dynamic"," bodies. They are exact but expensive, and Rapier can't compute a reliable mass distribution from them. Use ",[30,851,634],{}," for moving objects and keep trimeshes for static geometry.",[53,854,856],{"id":855},"reacting-to-impacts","Reacting to impacts",[14,858,859,860,862],{},"A physics engine that you can't listen to is just an animation. ",[30,861,123],{}," emits events for the four things you usually care about:",[61,864,866],{"className":127,"code":865,"language":129,"meta":67,"style":67},"\u003Cscript setup lang=\"ts\">\nimport { RigidBody } from '@tresjs\u002Frapier'\n\nfunction onHit({ totalForceMagnitude }) {\n  if (totalForceMagnitude > 50) {\n    playSound('crash')\n  }\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CRigidBody\n    @collision-enter=\"onCollisionEnter\"\n    @collision-exit=\"onCollisionExit\"\n    @contact-force=\"onHit\"\n  >\n    \u003CTresMesh>\n      \u003CTresBoxGeometry \u002F>\n      \u003CTresMeshNormalMaterial \u002F>\n    \u003C\u002FTresMesh>\n  \u003C\u002FRigidBody>\n\u003C\u002Ftemplate>\n",[30,867,868,884,898,902,923,943,957,962,967,975,979,987,994,1004,1014,1024,1029,1037,1046,1054,1062,1070],{"__ignoreMap":67},[71,869,870,872,874,876,878,880,882],{"class":73,"line":74},[71,871,137],{"class":136},[71,873,141],{"class":140},[71,875,145],{"class":144},[71,877,148],{"class":144},[71,879,151],{"class":136},[71,881,154],{"class":80},[71,883,157],{"class":136},[71,885,886,888,890,892,894,896],{"class":73,"line":160},[71,887,164],{"class":163},[71,889,168],{"class":167},[71,891,178],{"class":171},[71,893,181],{"class":167},[71,895,184],{"class":163},[71,897,187],{"class":80},[71,899,900],{"class":73,"line":190},[71,901,204],{"emptyLinePlaceholder":203},[71,903,904,907,910,913,917,920],{"class":73,"line":200},[71,905,906],{"class":163},"function",[71,908,909],{"class":77}," onHit",[71,911,912],{"class":167},"({",[71,914,916],{"class":915},"sQnVB"," totalForceMagnitude",[71,918,919],{"class":167}," })",[71,921,922],{"class":167}," {\n",[71,924,925,928,931,934,937,940],{"class":73,"line":207},[71,926,927],{"class":163},"  if",[71,929,930],{"class":171}," (totalForceMagnitude ",[71,932,933],{"class":136},">",[71,935,936],{"class":530}," 50",[71,938,939],{"class":171},") ",[71,941,942],{"class":167},"{\n",[71,944,945,948,951,954],{"class":73,"line":217},[71,946,947],{"class":77},"    playSound",[71,949,950],{"class":171},"(",[71,952,953],{"class":80},"'crash'",[71,955,956],{"class":171},")\n",[71,958,959],{"class":73,"line":228},[71,960,961],{"class":167},"  }\n",[71,963,964],{"class":73,"line":239},[71,965,966],{"class":167},"}\n",[71,968,969,971,973],{"class":73,"line":250},[71,970,193],{"class":136},[71,972,141],{"class":140},[71,974,157],{"class":136},[71,976,977],{"class":73,"line":277},[71,978,204],{"emptyLinePlaceholder":203},[71,980,981,983,985],{"class":73,"line":296},[71,982,137],{"class":136},[71,984,212],{"class":140},[71,986,157],{"class":136},[71,988,989,991],{"class":73,"line":308},[71,990,220],{"class":136},[71,992,993],{"class":140},"RigidBody\n",[71,995,996,999,1001],{"class":73,"line":318},[71,997,998],{"class":144},"    @collision-enter",[71,1000,151],{"class":136},[71,1002,1003],{"class":80},"\"onCollisionEnter\"\n",[71,1005,1006,1009,1011],{"class":73,"line":328},[71,1007,1008],{"class":144},"    @collision-exit",[71,1010,151],{"class":136},[71,1012,1013],{"class":80},"\"onCollisionExit\"\n",[71,1015,1016,1019,1021],{"class":73,"line":338},[71,1017,1018],{"class":144},"    @contact-force",[71,1020,151],{"class":136},[71,1022,1023],{"class":80},"\"onHit\"\n",[71,1025,1026],{"class":73,"line":343},[71,1027,1028],{"class":136},"  >\n",[71,1030,1031,1033,1035],{"class":73,"line":360},[71,1032,231],{"class":136},[71,1034,283],{"class":140},[71,1036,157],{"class":136},[71,1038,1039,1041,1044],{"class":73,"line":377},[71,1040,242],{"class":136},[71,1042,1043],{"class":140},"TresBoxGeometry",[71,1045,305],{"class":136},[71,1047,1048,1050,1052],{"class":73,"line":395},[71,1049,242],{"class":136},[71,1051,313],{"class":140},[71,1053,305],{"class":136},[71,1055,1056,1058,1060],{"class":73,"line":413},[71,1057,444],{"class":136},[71,1059,283],{"class":140},[71,1061,157],{"class":136},[71,1063,1064,1066,1068],{"class":73,"line":422},[71,1065,454],{"class":136},[71,1067,256],{"class":140},[71,1069,157],{"class":136},[71,1071,1072,1074,1076],{"class":73,"line":431},[71,1073,193],{"class":136},[71,1075,212],{"class":140},[71,1077,157],{"class":136},[14,1079,1080,1081,1084,1085,1088],{},"Mark a body as a sensor and you get ",[30,1082,1083],{},"intersection-enter"," \u002F ",[30,1086,1087],{},"intersection-exit"," instead: overlap detection without a physical response, which is what you want for trigger zones, checkpoints and pickups.",[14,1090,1091,1094],{},[30,1092,1093],{},"contact-force"," is the one I'm most excited about. It gives you the magnitude of the impact, so \"played a soft thud\" versus \"shattered the crate\" becomes a threshold check rather than a guess.",[53,1096,1098],{"id":1097},"collision-and-solver-groups","Collision and solver groups",[14,1100,1101,1102,587,1105,1108],{},"Not everything should collide with everything. Both ",[30,1103,1104],{},"collisionGroups",[30,1106,1107],{},"solverGroups"," take a bitmask, and they are separate on purpose:",[606,1110,1111],{},[609,1112,1113,1120],{},[612,1114,1115,1119],{},[21,1116,1117],{},[30,1118,1104],{}," decides which pairs are even tested for contact",[612,1121,1122,1126],{},[21,1123,1124],{},[30,1125,1107],{}," decides which pairs actually generate a physical response",[14,1128,1129],{},"That split is what lets you build things like a player that passes through enemies but still triggers their hitboxes.",[53,1131,1133],{"id":1132},"joints","Joints",[14,1135,1136],{},"Six joint types ship in v1, each connecting two rigid bodies:",[606,1138,1139],{},[609,1140,1141,1149,1157,1165,1173,1181],{},[612,1142,1143,1148],{},[21,1144,1145],{},[30,1146,1147],{},"RevoluteJoint",": a hinge, for doors, wheels and levers",[612,1150,1151,1156],{},[21,1152,1153],{},[30,1154,1155],{},"PrismaticJoint",": a slider along one axis",[612,1158,1159,1164],{},[21,1160,1161],{},[30,1162,1163],{},"SphericalJoint",": ball-and-socket, for ragdolls and chains",[612,1166,1167,1172],{},[21,1168,1169],{},[30,1170,1171],{},"SpringJoint",": elastic, with stiffness and damping",[612,1174,1175,1180],{},[21,1176,1177],{},[30,1178,1179],{},"RopeJoint",": a maximum distance constraint",[612,1182,1183,1188],{},[21,1184,1185],{},[30,1186,1187],{},"GenericJoint",": configure the locked axes yourself",[14,1190,1191,1192,1195],{},"Three balls hanging off a kinematic anchor, each link tied to the next with a ",[30,1193,1194],{},"\u003CSphericalJoint>",":",[649,1197,1199],{"label":1198},"joint chain demo",[1200,1201],"blog-embed-scene-rapier-joints",{},[61,1203,1205],{"className":127,"code":1204,"language":129,"meta":67,"style":67},"\u003CSphericalJoint\n  :bodies=\"[anchorRef?.instance, linkRef?.instance]\"\n  :params=\"[[0, -0.7, 0], [0, 0.7, 0]]\"\n\u002F>\n",[30,1206,1207,1214,1248,1302],{"__ignoreMap":67},[71,1208,1209,1211],{"class":73,"line":74},[71,1210,137],{"class":136},[71,1212,1213],{"class":140},"SphericalJoint\n",[71,1215,1216,1219,1222,1224,1226,1229,1232,1235,1237,1240,1242,1245],{"class":73,"line":160},[71,1217,1218],{"class":167},"  :",[71,1220,1221],{"class":144},"bodies",[71,1223,151],{"class":136},[71,1225,527],{"class":80},[71,1227,1228],{"class":171},"[anchorRef",[71,1230,1231],{"class":136},"?.",[71,1233,1234],{"class":171},"instance",[71,1236,175],{"class":167},[71,1238,1239],{"class":171}," linkRef",[71,1241,1231],{"class":136},[71,1243,1244],{"class":171},"instance]",[71,1246,1247],{"class":80},"\"\n",[71,1249,1250,1252,1255,1257,1259,1262,1265,1267,1270,1273,1275,1278,1281,1283,1286,1288,1290,1293,1295,1297,1300],{"class":73,"line":190},[71,1251,1218],{"class":167},[71,1253,1254],{"class":144},"params",[71,1256,151],{"class":136},[71,1258,527],{"class":80},[71,1260,1261],{"class":171},"[[",[71,1263,1264],{"class":530},"0",[71,1266,175],{"class":167},[71,1268,1269],{"class":136}," -",[71,1271,1272],{"class":530},"0.7",[71,1274,175],{"class":167},[71,1276,1277],{"class":530}," 0",[71,1279,1280],{"class":171},"]",[71,1282,175],{"class":167},[71,1284,1285],{"class":171}," [",[71,1287,1264],{"class":530},[71,1289,175],{"class":167},[71,1291,1292],{"class":530}," 0.7",[71,1294,175],{"class":167},[71,1296,1277],{"class":530},[71,1298,1299],{"class":171},"]]",[71,1301,1247],{"class":80},[71,1303,1304],{"class":73,"line":200},[71,1305,1306],{"class":171},"\u002F>\n",[14,1308,1309,1311],{},[30,1310,1254],{}," are the anchor points in each body's local space, so the chain hangs from the bottom of one link and the top of the next.",[14,1313,1314,1315,1317],{},"Scale that exact pattern up and you get a wrecking ball: a fixed pole, six dynamic links and a ball 25 times heavier than any of them, all strung together with ",[30,1316,1163],{},". Grab the ball, pull it back and let go.",[48,1319],{"src":1320,"title":1321},"https:\u002F\u002Flab.tresjs.org\u002Fexperiments\u002Frapier-wrecking-ball\u002F","Rapier wrecking ball physics demo",[14,1323,1324],{},"Three details are what make that chain read as steel instead of rubber:",[606,1326,1327],{},[609,1328,1329,1336,1342],{},[612,1330,1331,587,1333,1335],{},[30,1332,1104],{},[30,1334,1107],{}," on the links, so they swing through each other instead of fighting over the same space",[612,1337,1338,1341],{},[30,1339,1340],{},"setAdditionalSolverIterations(8)"," on the chain bodies, because Rapier's default four iterations let a long joint chain stretch visibly",[612,1343,1344,1347],{},[30,1345,1346],{},"enableCcd"," on the ball, so all that mass at speed can't tunnel straight through a brick",[14,1349,1350,1351,1354],{},"The chain links themselves are invisible ball colliders. What you see is a single ",[30,1352,1353],{},"TresInstancedMesh"," of torus rings, positioned along each link every frame, which is a good reminder that the simulation and the thing you render don't have to be the same object.",[53,1356,1358],{"id":1357},"hundreds-of-bodies-with-instancedrigidbody","Hundreds of bodies with InstancedRigidBody",[14,1360,1361,1362,1364,1365,1368,1369,1371],{},"Simulating a thousand individual ",[30,1363,123],{}," components means a thousand Vue components and a thousand draw calls. ",[30,1366,1367],{},"\u003CInstancedRigidBody>"," pairs the simulation with a ",[30,1370,1353],{},", so a whole crowd of objects sharing one geometry and one material stays cheap.",[61,1373,1375],{"className":127,"code":1374,"language":129,"meta":67,"style":67},"\u003CInstancedRigidBody collider=\"ball\" :args=\"[0.25]\" :restitution=\"0.5\">\n  \u003CTresInstancedMesh ref=\"instanceRef\" :args=\"[geometry, material, 500]\" \u002F>\n\u003C\u002FInstancedRigidBody>\n",[30,1376,1377,1424,1429],{"__ignoreMap":67},[71,1378,1379,1381,1384,1386,1388,1390,1392,1395,1397,1399,1402,1405,1407,1409,1411,1414,1416,1418,1420,1422],{"class":73,"line":74},[71,1380,137],{"class":136},[71,1382,1383],{"class":140},"InstancedRigidBody",[71,1385,259],{"class":144},[71,1387,151],{"class":136},[71,1389,264],{"class":80},[71,1391,519],{"class":167},[71,1393,1394],{"class":144},"args",[71,1396,151],{"class":136},[71,1398,527],{"class":80},[71,1400,1401],{"class":171},"[",[71,1403,1404],{"class":530},"0.25",[71,1406,1280],{"class":171},[71,1408,527],{"class":80},[71,1410,519],{"class":167},[71,1412,1413],{"class":144},"restitution",[71,1415,151],{"class":136},[71,1417,527],{"class":80},[71,1419,551],{"class":530},[71,1421,527],{"class":80},[71,1423,157],{"class":136},[71,1425,1426],{"class":73,"line":160},[71,1427,1428],{"class":171},"  \u003CTresInstancedMesh ref=\"instanceRef\" :args=\"[geometry, material, 500]\" \u002F>\n",[71,1430,1431,1433,1435],{"class":73,"line":190},[71,1432,193],{"class":136},[71,1434,1383],{"class":140},[71,1436,157],{"class":136},[14,1438,1439,1440,1443],{},"You seed the starting transforms with ",[30,1441,1442],{},"setMatrixAt"," like any other instanced mesh; Rapier takes over the matrix buffer from there.",[53,1445,1447,1448],{"id":1446},"dropping-into-the-world-with-userapier","Dropping into the world with ",[30,1449,1450],{},"useRapier",[14,1452,1453,1454,580,1456,1459],{},"Anywhere inside ",[30,1455,119],{},[30,1457,1458],{},"useRapier()"," hands you the underlying world:",[61,1461,1465],{"className":1462,"code":1463,"language":1464,"meta":67,"style":67},"language-ts shiki shiki-themes catppuccin-latte catppuccin-latte catppuccin-frappe","import { useRapier } from '@tresjs\u002Frapier'\n\nconst { world, rapier, isDebug, isPaused, timeStep, timeScale, step, onBeforeStep } = useRapier()\n\nonBeforeStep((timestep) => {\n  \u002F\u002F runs once per physics substep, not per rendered frame\n})\n","ts",[30,1466,1467,1482,1486,1542,1546,1566,1571],{"__ignoreMap":67},[71,1468,1469,1471,1473,1476,1478,1480],{"class":73,"line":74},[71,1470,164],{"class":163},[71,1472,168],{"class":167},[71,1474,1475],{"class":171}," useRapier ",[71,1477,181],{"class":167},[71,1479,184],{"class":163},[71,1481,187],{"class":80},[71,1483,1484],{"class":73,"line":160},[71,1485,204],{"emptyLinePlaceholder":203},[71,1487,1488,1491,1493,1496,1498,1501,1503,1506,1508,1511,1513,1516,1518,1521,1523,1526,1528,1531,1533,1536,1539],{"class":73,"line":190},[71,1489,1490],{"class":163},"const",[71,1492,168],{"class":167},[71,1494,1495],{"class":171}," world",[71,1497,175],{"class":167},[71,1499,1500],{"class":171}," rapier",[71,1502,175],{"class":167},[71,1504,1505],{"class":171}," isDebug",[71,1507,175],{"class":167},[71,1509,1510],{"class":171}," isPaused",[71,1512,175],{"class":167},[71,1514,1515],{"class":171}," timeStep",[71,1517,175],{"class":167},[71,1519,1520],{"class":171}," timeScale",[71,1522,175],{"class":167},[71,1524,1525],{"class":171}," step",[71,1527,175],{"class":167},[71,1529,1530],{"class":171}," onBeforeStep ",[71,1532,181],{"class":167},[71,1534,1535],{"class":136}," =",[71,1537,1538],{"class":77}," useRapier",[71,1540,1541],{"class":171},"()\n",[71,1543,1544],{"class":73,"line":200},[71,1545,204],{"emptyLinePlaceholder":203},[71,1547,1548,1551,1553,1555,1558,1561,1564],{"class":73,"line":207},[71,1549,1550],{"class":77},"onBeforeStep",[71,1552,950],{"class":171},[71,1554,950],{"class":167},[71,1556,1557],{"class":915},"timestep",[71,1559,1560],{"class":167},")",[71,1562,1563],{"class":136}," =>",[71,1565,922],{"class":167},[71,1567,1568],{"class":73,"line":217},[71,1569,1570],{"class":812},"  \u002F\u002F runs once per physics substep, not per rendered frame\n",[71,1572,1573,1575],{"class":73,"line":228},[71,1574,181],{"class":167},[71,1576,956],{"class":171},[14,1578,1579,1581],{},[30,1580,1458],{}," is exported as well and is the exact same composable, so whichever name you picked up during the alpha keeps working.",[469,1583,1584],{},[14,1585,1586,1587,1589],{},"Put your physics logic in ",[30,1588,1550],{},", not in the render loop. With a fixed timestep the two no longer run at the same rate, and applying forces from the render loop means applying them an inconsistent number of times per second.",[14,1591,1592,1593,1596],{},"And when things misbehave, ",[30,1594,1595],{},"\u003CPhysics debug>"," draws every collider wireframe so you can see the difference between what you rendered and what Rapier is actually simulating. It's usually a two second fix once you can see it.",[53,1598,1600],{"id":1599},"one-gotcha-worth-repeating","One gotcha worth repeating",[14,1602,1603,1604,1607,1608,1611,1612,1614],{},"Don't mutate ",[30,1605,1606],{},"position"," or ",[30,1609,1610],{},"rotation"," directly on a mesh wrapped by a dynamic ",[30,1613,123],{},". Rapier owns those transforms, and writing to them fights the solver: you'll get teleporting, jitter, or bodies tunnelling through the floor. Use forces, impulses, or a kinematic body type if you need direct control.",[53,1616,1618],{"id":1617},"resources","Resources",[606,1620,1621],{},[609,1622,1623,1636,1648,1657,1669],{},[612,1624,1625,1632,1633,1635],{},[21,1626,1627],{},[24,1628,1631],{"href":1629,"rel":1630},"https:\u002F\u002Frapier.tresjs.org\u002F",[28],"rapier.tresjs.org",": the full ",[30,1634,32],{}," reference, every component and every prop",[612,1637,1638,1644,1645,1647],{},[21,1639,1640],{},[24,1641,1643],{"href":37,"rel":1642},[28],"rapier.rs",": the engine underneath. Worth a read whenever you need something we don't wrap yet, since ",[30,1646,1458],{}," gives you the raw world anyway",[612,1649,1650,1656],{},[21,1651,1652],{},[24,1653,1655],{"href":50,"rel":1654},[28],"Object clump",": the one at the top of this post. Forty instanced spheres pulled toward the centre, with a kinematic body following your pointer to shove them around",[612,1658,1659,1665,1666,1668],{},[21,1660,1661],{},[24,1662,1664],{"href":1320,"rel":1663},[28],"Wrecking ball",": a six link ",[30,1667,1163],{}," chain and a very heavy ball, against a wall you can resize",[612,1670,1671,1678,1679,1682,1683,1685,1686],{},[21,1672,1673],{},[24,1674,1677],{"href":1675,"rel":1676},"https:\u002F\u002Flab.tresjs.org\u002Fexperiments\u002Frapier-car\u002F",[28],"Car",": Rapier's own ",[30,1680,1681],{},"DynamicRayCastVehicleController",", driven from ",[30,1684,1458],{}," inside ",[30,1687,1550],{},[53,1689,1691],{"id":1690},"thanks","Thanks",[14,1693,1694,1695,587,1700,1705],{},"This release exists because of ",[24,1696,1699],{"href":1697,"rel":1698},"https:\u002F\u002Fgithub.com\u002FNeosoulink",[28],"Nathan Mande",[24,1701,1704],{"href":1702,"rel":1703},"https:\u002F\u002Fgithub.com\u002FJaimeTorrealba",[28],"Jaime Torrealba"," who did the heavy lifting on colliders, joints and the reactivity work that makes all of this feel like Vue instead of like a physics API with a Vue costume on. 🙌",[14,1707,1708,1709,1714,1715,46],{},"Full release notes are on ",[24,1710,1713],{"href":1711,"rel":1712},"https:\u002F\u002Fgithub.com\u002FTresjs\u002Ftres\u002Freleases\u002Ftag\u002F%40tresjs%2Frapier%401.0.0",[28],"GitHub"," and the docs live at ",[24,1716,1631],{"href":1717,"rel":1718},"https:\u002F\u002Frapier.tresjs.org",[28],[14,1720,1721,1722,1727],{},"Now go make something fall over. Share it with us on ",[24,1723,1726],{"href":1724,"rel":1725},"https:\u002F\u002Fdiscord.gg\u002Ftresjs",[28],"Discord",", we want to see it 🚀.",[1729,1730,1731],"style",{},"html pre.shiki code .s0faT, html code.shiki .s0faT{--shiki-light:#1E66F5;--shiki-light-font-style:italic;--shiki-default:#1E66F5;--shiki-default-font-style:italic;--shiki-dark:#8CAAEE;--shiki-dark-font-style:italic}html pre.shiki code .s9Zht, html code.shiki .s9Zht{--shiki-light:#40A02B;--shiki-default:#40A02B;--shiki-dark:#A6D189}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 .sWdzt, html code.shiki .sWdzt{--shiki-light:#179299;--shiki-default:#179299;--shiki-dark:#81C8BE}html pre.shiki code .slJ5s, html code.shiki .slJ5s{--shiki-light:#1E66F5;--shiki-default:#1E66F5;--shiki-dark:#8CAAEE}html pre.shiki code .s1cdE, html code.shiki .s1cdE{--shiki-light:#DF8E1D;--shiki-default:#DF8E1D;--shiki-dark:#E5C890}html pre.shiki code .sZyUJ, html code.shiki .sZyUJ{--shiki-light:#8839EF;--shiki-default:#8839EF;--shiki-dark:#CA9EE6}html pre.shiki code .spKPg, html code.shiki .spKPg{--shiki-light:#7C7F93;--shiki-default:#7C7F93;--shiki-dark:#949CBB}html pre.shiki code .s9Av-, html code.shiki .s9Av-{--shiki-light:#4C4F69;--shiki-default:#4C4F69;--shiki-dark:#C6D0F5}html pre.shiki code .sREMW, html code.shiki .sREMW{--shiki-light:#FE640B;--shiki-default:#FE640B;--shiki-dark:#EF9F76}html pre.shiki code .sMnCH, html code.shiki .sMnCH{--shiki-light:#7C7F93;--shiki-light-font-style:italic;--shiki-default:#7C7F93;--shiki-default-font-style:italic;--shiki-dark:#949CBB;--shiki-dark-font-style:italic}html pre.shiki code .sQnVB, html code.shiki .sQnVB{--shiki-light:#E64553;--shiki-light-font-style:italic;--shiki-default:#E64553;--shiki-default-font-style:italic;--shiki-dark:#EA999C;--shiki-dark-font-style:italic}",{"title":67,"searchDepth":160,"depth":160,"links":1733},[1734,1735,1736,1737,1738,1739,1740,1741,1743,1744,1745],{"id":55,"depth":160,"text":56},{"id":482,"depth":160,"text":483},{"id":594,"depth":160,"text":595},{"id":855,"depth":160,"text":856},{"id":1097,"depth":160,"text":1098},{"id":1132,"depth":160,"text":1133},{"id":1357,"depth":160,"text":1358},{"id":1446,"depth":160,"text":1742},"Dropping into the world with useRapier",{"id":1599,"depth":160,"text":1600},{"id":1617,"depth":160,"text":1618},{"id":1690,"depth":160,"text":1691},"release","2026-07-29","@tresjs\u002Frapier hits stable v1. Declarative physics for TresJS, powered by Rapier and WASM.","md",{},"\u002Fblog\u002Ftresjs-rapier-v1",{"text":1753,"minutes":1754,"time":1755,"words":1756},"7 min read",6.73,403800,1346,{"title":5,"description":1748},"blog\u002Ftresjs-rapier-v1","\u002Fblog\u002Ftresjs-rapier-v1\u002Ftresjs-rapier-v1.png",null,"_lBURhmA5lg-4t0kjAdwTQwp2UlcB2P-h0EkQaphdJ8",{"id":1763,"title":1699,"avatar":1764,"body":1765,"description":67,"email":1769,"extension":1749,"github":1770,"meta":1771,"name":1699,"navigation":203,"path":1775,"seo":1776,"slug":7,"stem":1777,"twitter":1778,"website":1779,"__hash__":1780},"authors\u002Fauthors\u002Fnathan-mande.md","\u002Favatars\u002Fnathan-mande.png",{"type":11,"value":1766,"toc":1767},[],{"title":67,"searchDepth":160,"depth":160,"links":1768},[],"nathaninbusiness2.0@gmail.com","Neosoulink",{"readingTime":1772},{"text":1773,"minutes":1774,"time":1774,"words":1774},"0 min read",0,"\u002Fauthors\u002Fnathan-mande",{"description":67},"authors\u002Fnathan-mande","nsl_nathan","https:\u002F\u002Fnathan-mande.netlify.app","vNCq28bi7CggsWaoqUWFqb7wR8yMyAADMCNS29UbFQk",{"id":1782,"title":1704,"avatar":1783,"body":1784,"description":67,"email":1788,"extension":1749,"github":1789,"meta":1790,"name":1704,"navigation":203,"path":1792,"seo":1793,"slug":8,"stem":1794,"twitter":1795,"website":1796,"__hash__":1797},"authors\u002Fauthors\u002Fjaime-torrealba.md","\u002Favatars\u002Fjaime-torrealba.png",{"type":11,"value":1785,"toc":1786},[],{"title":67,"searchDepth":160,"depth":160,"links":1787},[],"solucionesinformaticasjtc@gmail.com","JaimeTorrealba",{"readingTime":1791},{"text":1773,"minutes":1774,"time":1774,"words":1774},"\u002Fauthors\u002Fjaime-torrealba",{"description":67},"authors\u002Fjaime-torrealba","jaimebboyjt","https:\u002F\u002Fjaimetorrealba.com\u002F","T_y_ohx58b5LQ_km9jn0_15mj_nzMBb2Ts3GBGNXpNY",{"id":1799,"title":1800,"avatar":1801,"body":1802,"description":67,"email":1806,"extension":1749,"github":9,"meta":1807,"name":1809,"navigation":203,"path":1810,"seo":1811,"slug":9,"stem":1812,"twitter":9,"website":1813,"__hash__":1814},"authors\u002Fauthors\u002Falvarosabu.md","Alvarosabu","\u002Favatars\u002Falvarosabu.png",{"type":11,"value":1803,"toc":1804},[],{"title":67,"searchDepth":160,"depth":160,"links":1805},[],"hola@alvarosaburido.dev",{"readingTime":1808},{"text":1773,"minutes":1774,"time":1774,"words":1774},"Alvaro Saburido","\u002Fauthors\u002Falvarosabu",{"description":67},"authors\u002Falvarosabu","https:\u002F\u002Falvarosaburido.dev","CmwieKa4qc2RGTVr4mry8wF-8Mb9vtJoJrhpP_Qz5kk",{"id":4,"title":5,"author":6,"body":10,"category":1746,"date":1747,"description":1748,"draft":203,"extension":1749,"meta":1750,"navigation":203,"path":1751,"readingTime":1752,"seo":1757,"stem":1758,"thumbnail":1759,"url":1760,"__hash__":1761,"authors":1816},[1817,1821,1824],{"name":1699,"description":1818,"avatar":1819,"to":1779,"target":1820},"@Neosoulink",{"src":1764},"_blank",{"name":1704,"description":1822,"avatar":1823,"to":1796,"target":1820},"@JaimeTorrealba",{"src":1783},{"name":1809,"description":1825,"avatar":1826,"to":1813,"target":1820},"@alvarosabu",{"src":1801},1785402821931]