<?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>Try Bladewell in a Laravel App: Install, Customize, and Update Your First Component</title>
      <dc:creator>Krishnaprasad R (RK)</dc:creator>
      <pubDate>Mon, 26 Oct 2026 06:12:09 +0000</pubDate>
      <link>https://dev.to/krishnaprasad_rrk_9acc/try-bladewell-in-a-laravel-app-install-customize-and-update-your-first-component-4518</link>
      <guid>https://dev.to/krishnaprasad_rrk_9acc/try-bladewell-in-a-laravel-app-install-customize-and-update-your-first-component-4518</guid>
      <description>&lt;p&gt;In my first post, I introduced &lt;a href="https://www.bladewellui.com/" rel="noopener noreferrer"&gt;Bladewell&lt;/a&gt; and explained why I wanted Laravel UI components that work without adopting another JavaScript framework.&lt;/p&gt;

&lt;p&gt;This time, let's look at what happens when you actually bring a component into an app.&lt;/p&gt;

&lt;p&gt;The useful test for a UI library comes after the demo: can you make it fit your project, and can you still maintain it after you do?&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with one component
&lt;/h2&gt;

&lt;p&gt;Use an existing Blade application with PHP 8.3+, Laravel 12 or 13, Tailwind CSS 4.1+, and Vite. The datepicker also requires PHP's intl extension.&lt;/p&gt;

&lt;p&gt;From your project directory:&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; bladewell/bladewell
php artisan bladewell:add datepicker
npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The installer brings in the datepicker and its supporting components. You don't need to install the entire catalogue to try one field.&lt;/p&gt;

&lt;p&gt;Use it in a Blade view:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;x-widget.datepicker&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"start_date"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your page should load your application's Vite assets as usual.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open the files it added
&lt;/h2&gt;

&lt;p&gt;The source lives inside your application. With the default paths, look here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resources/views/components/widget/datepicker/
resources/js/widget/datepicker/
resources/css/widget/theme.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Blade files control the markup, the JavaScript handles interaction, and the theme file contains shared design tokens.&lt;/p&gt;

&lt;p&gt;Try a small change first. Adjust a theme value, rebuild your assets, and see how it looks alongside the rest of your app.&lt;/p&gt;

&lt;p&gt;For a more specific change, edit the component itself. That is the point of copying the source into your project: customization becomes an ordinary code change you can review and commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens when an update arrives?
&lt;/h2&gt;

&lt;p&gt;Owning the source also means taking responsibility for your changes.&lt;/p&gt;

&lt;p&gt;Bladewell records installed file hashes in bladewell.lock. Commit that file alongside your component changes.&lt;/p&gt;

&lt;p&gt;After updating the package, refresh installed components with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer update bladewell/bladewell
php artisan bladewell:add &lt;span class="nt"&gt;--installed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The installer updates eligible unedited files and reports edited files it skips. Shared theme and base CSS are preserved.&lt;/p&gt;

&lt;p&gt;To inspect differences:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan bladewell:diff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Review relevant upstream fixes and merge them into your customized files. This doesn't remove maintenance work, but it makes the decisions visible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it in the app you already have
&lt;/h2&gt;

&lt;p&gt;Bladewell uses vanilla JavaScript for interaction. Alpine and Livewire aren't prerequisites, and the widgets also support Livewire 3 and 4.&lt;/p&gt;

&lt;p&gt;It is designed for Blade and Tailwind v4 projects. If your pages are React or Vue through Inertia, this isn't the component layer for those pages.&lt;/p&gt;

&lt;p&gt;My suggestion is to start with one field on an existing form. Check it against your own layout, validation flow, and keyboard interactions before adopting more components.&lt;/p&gt;

&lt;p&gt;Bladewell is free and MIT licensed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.bladewellui.com/" rel="noopener noreferrer"&gt;Explore the components and documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Browse the source or report an issue&lt;/li&gt;
&lt;li&gt;View the package on Packagist&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Which UI component takes the most work to customize in your Laravel projects—and what do you usually need to change?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>laravel</category>
      <category>php</category>
    </item>
    <item>
      <title>I Built Laravel UI Widgets That Don't Need a JavaScript Framework Called Bladewell.</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;Bladewell UI (bladewellui.com) is a free, MIT-licensed library of Blade and Tailwind CSS v4 components for Laravel. Install it from Packagist as bladewell/bladewell.&lt;/p&gt;

&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://www.bladewellui.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;Bladewell&lt;/strong&gt;&lt;/a&gt;: 36 Blade + Tailwind CSS 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 package 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; bladewell/bladewell
php artisan bladewell:add datepicker
npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;bladewell:add&lt;/code&gt; copies the widget's source into your application, along with anything it depends on (the date picker brings its field frame, icons and validation rules like &lt;code&gt;MinimumAge&lt;/code&gt;). From that moment it's your code. Rename the classes, rip out half the markup, change the keyboard behaviour. Nobody's stopping you, and nothing of mine runs in production.&lt;/p&gt;

&lt;p&gt;This is the shadcn/ui model, and I think it's the right one 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;Bladewell keeps a lock file, &lt;code&gt;bladewell.lock&lt;/code&gt;, with a hash of every file it wrote. Commit it like &lt;code&gt;composer.lock&lt;/code&gt;. When you update with &lt;code&gt;php artisan bladewell:add --installed&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Files you haven't touched get the new version.&lt;/li&gt;
&lt;li&gt;Files you've edited are skipped and listed in the output, so you know what you're now maintaining yourself.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;php artisan bladewell:diff&lt;/code&gt; shows how your copy differs from the new version, so you can port a fix by hand if you want it.&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 Content Security Policy.&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;, so your policy never needs &lt;code&gt;'unsafe-inline'&lt;/code&gt;. If you've ever tried to retrofit a CSP 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 &lt;code&gt;data-*&lt;/code&gt; attributes. (The one exception is opt-in: the accordion menu's "remember scroll position" script, which carries your nonce.)&lt;/p&gt;

&lt;p&gt;You don't have to take my word for it: the docs site itself is served with &lt;code&gt;default-src 'self'&lt;/code&gt; and a per-request nonce, and every live example runs under it. &lt;a href="https://www.bladewellui.com/why" rel="noopener noreferrer"&gt;The Why page&lt;/a&gt; prints the exact policy it was sent with, so you can hold it against DevTools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It has to survive Livewire.&lt;/strong&gt; Alpine and Livewire aren't required, but plenty of people use both, and DOM morphing destroys naive components. The widgets are checked inside Livewire 3 and 4 components in a real browser, not a jsdom approximation: inputs bind with &lt;code&gt;wire:model&lt;/code&gt; and keep focus while you type, an open modal or menu stays open through a render, file uploads go to Livewire's temporary uploads, and toasts fired with &lt;code&gt;$this-&amp;gt;dispatch()&lt;/code&gt; survive &lt;code&gt;wire:navigate&lt;/code&gt;.&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, focus management, RTL layouts, and dates and numbers in your app's locale. Every example is checked with axe-core against WCAG 2.2 A and AA, in light and dark, closed and with each popover and dialog opened, on every change. 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;h2&gt;
  
  
  What's in the set
&lt;/h2&gt;

&lt;p&gt;Datepicker, date-range picker, time picker, select, phone input, OTP and verification-code inputs, file upload, table, pagination, modal, toast, dropdown, tabs, stepper, accordion, tooltips, captcha, and more: 36 in all.&lt;/p&gt;

&lt;p&gt;Starting a new app instead? There's a starter kit, a Laravel 13 app with sign-in, registration, password reset, email verification, account settings and a dashboard, built from these components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer create-project bladewell/starter-kit my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  For your coding agent
&lt;/h2&gt;

&lt;p&gt;An angle I didn't expect to care about but now use constantly: a built-in MCP server (&lt;code&gt;php artisan bladewell:mcp&lt;/code&gt;), plus &lt;code&gt;/llms.txt&lt;/code&gt; and JSON registry endpoints. Your agent can list the widgets, read their props and examples, see what's installed and what you've edited, and run the install with a dry run first. 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;
  
  
  Where it isn't a fit
&lt;/h2&gt;

&lt;p&gt;Being honest saves you an afternoon: it's not for Tailwind v3 or Bootstrap projects, not for Inertia apps whose pages are React or Vue, and not if you'd rather never see a component's code. An installed package you only &lt;code&gt;composer update&lt;/code&gt; suits that better.&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://www.bladewellui.com/" rel="noopener noreferrer"&gt;https://www.bladewellui.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;PHP 8.3+, Laravel 12 and 13, Tailwind CSS 4.1+. Free and MIT licensed. Feedback and issues welcome on &lt;a href="https://github.com/rkwebforge/bladewell" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

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