<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Krishnaprasad R (RK)</title>
    <description>The latest articles on DEV Community by Krishnaprasad R (RK) (@krishnaprasad_rrk_9acc).</description>
    <link>https://dev.to/krishnaprasad_rrk_9acc</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4159135%2F0fa5c39d-8bfd-4397-a503-815fd08617ee.png</url>
      <title>DEV Community: Krishnaprasad R (RK)</title>
      <link>https://dev.to/krishnaprasad_rrk_9acc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/krishnaprasad_rrk_9acc"/>
    <language>en</language>
    <item>
      <title>I Built Laravel UI Widgets That Don't Need a JavaScript Framework Called LarawellUI.</title>
      <dc:creator>Krishnaprasad R (RK)</dc:creator>
      <pubDate>Sat, 03 Oct 2026 06:48:25 +0000</pubDate>
      <link>https://dev.to/krishnaprasad_rrk_9acc/i-built-laravel-ui-widgets-that-dont-need-a-javascript-framework-called-larawellui-4c28</link>
      <guid>https://dev.to/krishnaprasad_rrk_9acc/i-built-laravel-ui-widgets-that-dont-need-a-javascript-framework-called-larawellui-4c28</guid>
      <description>&lt;p&gt;I've copied the same hand-rolled datepicker between Laravel projects more times than I want to admit. Every time, I'd look at the existing UI kits first, and every time I'd close the tab.&lt;/p&gt;

&lt;p&gt;The problem wasn't quality. It was the price of entry. Most Laravel UI kits ask you to adopt their JavaScript along with them — bring Alpine, bring Livewire, or rebuild your frontend in React or Vue. If you're running a plain server-rendered Blade app, that's a significant architectural commitment in exchange for a date field.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://larawellui.wasmer.app/" rel="noopener noreferrer"&gt;&lt;strong&gt;LarawellUI&lt;/strong&gt;&lt;/a&gt;: 34 Blade + Tailwind v4 widgets, server-rendered, with a small vanilla JS file behind each one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Copy in, don't depend on
&lt;/h2&gt;

&lt;p&gt;The install is a dev dependency, and the widgets themselves land in your app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require &lt;span class="nt"&gt;--dev&lt;/span&gt; larawellui/larawellui
php artisan larawell:add datepicker
npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;larawell:add&lt;/code&gt; copies the widget's source into your application along with anything it depends on. From that moment it's your code. Rename the classes, rip out half the markup, change the keyboard behavior — nobody's stopping you.&lt;/p&gt;

&lt;p&gt;This is the shadcn/ui model, and I think it's correct for UI components specifically. A UI widget is not a hashing library. You will need to change it. The question is whether you're fighting a package's config surface or just editing a file.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that usually breaks
&lt;/h2&gt;

&lt;p&gt;Copy-and-own has one well-known failure mode: you own it, so you never get updates again. Six months later you're on a fork of a fork and the upstream bugfixes may as well not exist.&lt;/p&gt;

&lt;p&gt;LarawellUI keeps a lock file recording the state of every file it wrote. When you update:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Files you haven't touched get replaced with the new version.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Files you've edited are skipped and listed in the output, so you know what you're now maintaining yourself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;larawell:diff&lt;/code&gt; shows exactly what upstream changed, so you can port the fix by hand if you want it.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing is overwritten silently. That was the non-negotiable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three constraints I didn't want to compromise on
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;It has to run under a strict CSP&lt;/strong&gt;. No inline &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;, no &lt;code&gt;onclick&lt;/code&gt; attributes, no &lt;code&gt;style=""&lt;/code&gt;. If you've ever tried to retrofit a Content Security Policy onto an app full of inline handlers, you know it's a nightmare that never fully ends. Every widget wires itself up from an external JS file via data attributes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It has to survive Livewire.&lt;/strong&gt; No Alpine or Livewire is required, but plenty of people use both — and DOM morphing destroys naive components. Everything is tested inside Livewire 3 and 4 against wire:model, morphs, and wire:navigate, in a real browser rather than a jsdom approximation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Accessibility and i18n aren't a later milestone.&lt;/strong&gt; Keyboard navigation, correct ARIA roles and states, RTL layouts, and dates and numbers formatted in your app's locale. A datepicker that only works with a mouse and only speaks en_US isn't a datepicker, it's a demo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's in the set&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Datepicker, date-range picker, time picker, select, phone input, OTP input, file upload, table, modal, toast, tabs, stepper, tooltips, and about twenty more.&lt;/p&gt;

&lt;p&gt;There's also an angle I didn't expect to care about but now use constantly: a built-in MCP server (&lt;code&gt;php artisan larawell:mcp&lt;/code&gt;), plus &lt;code&gt;/llms.txt&lt;/code&gt; and JSON registry endpoints. Your coding agent can list the available widgets, read the props, and run the install command itself. Telling Claude or Cursor "add a date range picker to this form" and having it pick the right widget turns out to be a reasonable workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Live previews, props and source for every widget: &lt;a href="https://larawellui.wasmer.app/" rel="noopener noreferrer"&gt;https://larawellui.wasmer.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;PHP 8.3+, Laravel 12 and 13, MIT licensed.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>tailwindcss</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
