← Back to list

I Missed Laravel’s Debugbar in AdonisJS, So I Built One

I’ve spent years in the Laravel world, and one of the small comforts I never appreciated enough was the debug bar sitting at the bottom of…

Syed Abdullah · 2026-05-19 12:47 · 0 claps · 3.5 min read
#adonisjs #software-development #laravel #debugging #full-stack
Open on Medium ↗
Wiki topics: 💻 · Programming

I Missed Laravel’s Debugbar in AdonisJS, So I Built One

I’ve spent years in the Laravel world, and one of the small comforts I never appreciated enough was the debug bar sitting at the bottom of every page in development. SQL queries, route info, session data, timing, all there. You stop noticing it until it’s gone.

More recently, I started using AdonisJS instead for my projects, since my frontends were mostly in React.js and I wanted to get rid of context switching between two languages, while still keeping the same comfort and ecosystem I got with Laravel.

I got almost everything I wanted and liked about Laravel, in Adonis, except for the Debugbar. There simply wasn’t one.

I felt the urge to build a new one, but my internal gut told me not to get distracted and just work around it. So I did, until I couldn’t, because every time I had to debug something, it took far more effort than I felt it should have.

That’s when I decided to gear up, plan it out, and get it over with.

What it does

adonis-debugbar is a development tool for AdonisJS 6 and 7. It adds a debug bar to the bottom of your pages that shows you, per request:

  • Queries: Every SQL query executed, with bindings, duration, and a one-click EXPLAIN ANALYZE button (works with Postgres, MySQL, and SQLite)
  • Timeline: full request timeline from start to response, with the ability to add named markers and labelled measure spans for any operation you want to track
  • Messages & Console logs: Automatic capture of backend console.log/warn/error logs, including the file and line where they were called
  • Exceptions: Handle a single exception manually or wire into the global exception handler to capture all errors.
  • Route Details: Including full middleware chain and controller
  • Basic Data: Request headers & data, session object, and Inertia
  • Copy option: Option to copy all the tab for each tab with a single click

Everything is scoped to the individual request using AsyncLocalStorage, which means even with concurrent requests flying in, you see exactly what happened in the one you’re looking at. No mixing, no guessing.

adonis-debugbar

adonis-debugbar

Why I choose per-request scoping

This is where Adonis and Laravel actually diverge in practice, and it’s the part that took me the longest to figure out.

In most Laravel apps I worked on, the page and its data came from the same place. You hit a route, the controller pulled the data, the Blade template rendered it, done. One request, one debug bar at the bottom showing everything that happened. Simple.

Adonis apps don’t really work that way. Because it’s a JavaScript framework, and most people pair it with React or Vue, the patterns I kept seeing in real projects were different. Most projects built with Adonis were SPA style apps, that loaded initial HTML as a blank template, everything loads through API calls after.

So a single “page” in an Adonis app might be five or ten separate API requests. Each one runs its own queries, its own middleware, its own logic. A traditional debug bar that just shows “the current request” would only ever show the first one that rendered the bar, which is almost never the one you’re trying to debug.

I went back and forth on this for a while. The cleanest solution I could land on was to capture every request independently, full page loads, XHR, fetch, all of them, and let you flip between them in the bar. So when something on the page misbehaves, you can pick the exact request that did it and see its queries, its timing, its exceptions, in isolation.

AsyncLocalStorage made the implementation clean. Each request gets its own store, all the collectors write into that store, and the bar in the browser fetches the data for whichever request you click on. Concurrent requests stay completely isolated from each other, no shared state, no leaks between them.

Zero overhead when disabled

The whole thing is gated behind a single environment variable, DEBUG_BAR=true. When it’s not set, the provider exits immediately on boot. No middleware registered, no listeners attached, no routes added, nothing allocated.

This matters because debug tools that leak into production are a real problem. I wanted something I could leave registered in adonisrc.ts unconditionally and never worry about. Forget to turn it off in staging? It’s already off unless you explicitly opt in.

What’s next

I’m using it daily on my own project and it’s already saved me a lot of console.log hunts. But I built it for myself first, and now I’m trying to figure out whether the broader AdonisJS community would actually use it.

If you’re an Adonis developer who has felt the same pain, I’d love feedback. Are there any usecases that I missed, or any tab that can add value to it. Just let me know.

Repo: https://github.com/imsyedabdullah/adonis-debugbar

If it’s useful to you, a star on GitHub helps me know it’s worth the time to keep polishing. And if you’ve built something similar, or know of a tool I missed, please tell me, I’d rather use yours than maintain mine.

Thanks for reading.


메타데이터
post_id
86ce5d694bc0
slug
i-missed-laravels-debugbar-in-adonisjs-so-i-built-one-86ce5d694bc0
url
https://medium.com/@2syedabdullah/i-missed-laravels-debugbar-in-adonisjs-so-i-built-one-86ce5d694bc0
canonical_url
https://medium.com/@2syedabdullah/i-missed-laravels-debugbar-in-adonisjs-so-i-built-one-86ce5d694bc0
author_url
https://medium.com/@2syedabdullah
status
ok
fetched_at
2026-06-09 15:37:30