DEV Community

Cover image for Skip Livewire? Why Laravel Blade + AQC + Alpine Might Be All You Need
Raheel Shan
Raheel Shan

Posted on • Originally published at raheelshan.com

Skip Livewire? Why Laravel Blade + AQC + Alpine Might Be All You Need

Introduction

Livewire is a popular choice in the Laravel ecosystem for building reactive UIs without writing a full frontend in Vue or React. It brings the frontend and backend together beautifully — but that doesn’t mean it’s always the right tool.

I’ve spent the last few years refining a Laravel architecture that puts business logic first. It’s clean, testable, reusable, and doesn't depend on extra frameworks. My approach combines three core tools:

  • AQC (Atomic Query Construction) — for business logic encapsulation
  • Blade Partials + Fetch API — for dynamic UI updates
  • Alpine.js — for lightweight interactivity

And here's my argument: when done right, this stack makes Livewire unnecessary.


The Backend: Laravel + AQC

I introduced the AQC pattern to organize backend logic into small, atomic classes. Every form, table, and UI interaction corresponds to a class that handles just one concern — from fetching filtered posts to submitting a form.

Livewire forces you to push logic into component methods. But AQC separates it cleanly and lets controllers, APIs, and even Blade fetchers reuse it without duplication.

So why rewrite the same logic again inside a Livewire class?


The View: Blade Partials + AJAX

In my approach, partial views are returned via controller routes. These partials are already:

  • Authenticated
  • Validated
  • Conditionalized through Blade
  • Ready to inject into the DOM

This means:

  • You write normal Laravel.
  • You don’t invent Livewire syntax (wire:model, etc.).
  • You can debug it like any other route.

A simple fetch() replaces the entire need for wire:click, wire:model, wire:submit, etc.


The UI: Alpine.js (When You Need It)

For tabs, modals, dropdowns, dynamic counters — Alpine is more than enough.

No virtual DOM. No lifecycle hooks. Just HTML with behavior sprinkled on top.

And the best part? Alpine doesn’t interfere with Blade or fetch-injected content. It just works.


But Doesn’t Livewire Do All This?

It does, but at a cost:

Livewire comparision


A Laravel Developer’s Perspective

Livewire adds an extra layer. That layer is helpful for people who:

  • Don’t want to write JS
  • Are okay putting logic in component classes
  • Don’t already follow a backend-first design like AQC

But if you're already structuring your app cleanly — Livewire is just duplication. You do more work to avoid JavaScript, while losing the power of your existing Laravel structure.


Improving My Approach Further

This isn't static either — here’s how I continue to improve it:

  • Use IntersectionObserver for lazy-fetching partials only when visible
  • Cache rendered partials for repeated DOM sections (e.g. dropdown options)
  • Combine AQC with Jobs for background-heavy operations
  • Use Turbo/Hotwire if you want pushState navigation with HTML partials

Conclusion

I’m not saying Livewire is bad. It’s brilliant for teams who need something between Blade and Vue. But if you’re already writing Laravel the clean way — if you already have proper separation of concerns — then Livewire might just be solving problems you don’t have.

Your controller + AQC + Blade + Alpine stack is:

  • Faster to understand
  • Easier to test
  • Native to Laravel
  • Fully under your control

That’s why I skipped Livewire — and maybe you should too.


If you found this post helpful, consider supporting my work — it means a lot.

Support my work

Top comments (3)

Collapse
 
xwero profile image
david duymelinck

I hate this type of posts because the only thing it does is making the solution you don't like look bad.

Comparison table rebuttal:

  • Why are components a bad thing? they are a part of Blade.
  • Nobody is stopping you to call methods that contain the business logic.
  • The directives are there to help you. If you don't want to use them, Livewire doesn't care.
  • You need to know the solution if you want to use it efficiently (ajax calls and db hits)
  • if you choose a solution there are consequences, that is the same with your choice for alpine.js

Use Turbo/Hotwire if you want pushState navigation with HTML partials

This is the funniest sentence of the post. So to do what Livewire does you add another javascript library.

I agree that Livewire shouldn't be a default choice. See what your application needs and decide what the best solution is to make it work.

Collapse
 
raheelshan profile image
Raheel Shan • Edited

I appreciate the feedback. To be clear, I’m not saying Blade components or Livewire directives are bad. My point is that for many apps, you can cover the same needs with Blade partials, Alpine, and clean backend design—without bringing in the full Livewire layer.

I agree with you that every tool has tradeoffs. Livewire helps a lot but some developers feel it as adding additional layer. These are the layers that have been introduced, but

with a clever combination of backend and lightweight JavaScript we already have everything needed.

The problem is we often get hyped into adding new tools and abstractions when simpler patterns already cover most needs.

So we actually agree on the bottom line, Livewire shouldn’t be a default assumption. The best choice depends on your app’s needs, and my post was simply making the case that developers often have more than one viable path forward.

Collapse
 
xwero profile image
david duymelinck • Edited

The problem is we often get hyped into adding new tools and abstractions when simpler patterns already cover most needs.

I think this has more to do with Laravel as an ecosystem. Quite a few solutions in the ecosystem use Livewire or Vue because it are the defaults, which means the compatibility with other parts of the ecosystem is guaranteed.

It is our decision to opt in the ecosystem or use Laravel just as a framework.