@elyracode/stack-tall 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,18 @@
1
+ # @elyracode/stack-tall
2
+
3
+ Elyra stack profile for **TALL** (Tailwind CSS, Alpine.js, Laravel, Livewire 4, Flux UI).
4
+
5
+ ## Install
6
+
7
+ ```
8
+ elyra install npm:@elyracode/stack-tall
9
+ ```
10
+
11
+ ## What's included
12
+
13
+ - **Skills**: Deep TALL stack knowledge (Livewire 4 lifecycle, attributes, hydration rules, Alpine patterns, Flux UI components, file structure conventions, common gotchas)
14
+ - **Commands**: `/tall:info` -- show stack profile status
15
+
16
+ ## Stack Detection
17
+
18
+ Elyra automatically detects TALL stack projects and suggests this package.
@@ -0,0 +1,13 @@
1
+ import type { ExtensionAPI } from "@elyracode/coding-agent";
2
+
3
+ export default function (elyra: ExtensionAPI) {
4
+ // The TALL skill is auto-loaded from the skills/ directory.
5
+ // This extension adds stack-aware commands.
6
+
7
+ elyra.registerCommand("tall:info", {
8
+ description: "Show detected TALL stack information",
9
+ handler: async (ctx) => {
10
+ ctx.ui.notify("info", "TALL stack profile loaded. Skills: tall-stack. Use /skill:tall-stack for full reference.");
11
+ },
12
+ });
13
+ }
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@elyracode/stack-tall",
3
+ "version": "0.3.0",
4
+ "description": "Elyra stack profile for TALL (Tailwind, Alpine.js, Laravel, Livewire 4, Flux UI)",
5
+ "type": "module",
6
+ "keywords": ["elyra-package", "tall", "laravel", "livewire", "tailwind", "alpine", "flux-ui"],
7
+ "license": "MIT",
8
+ "author": "Knut W. Horne",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/kwhorne/elyra.git",
12
+ "directory": "packages/stack-tall"
13
+ },
14
+ "elyra": {
15
+ "skills": ["./skills"],
16
+ "extensions": ["./extensions/index.ts"]
17
+ },
18
+ "peerDependencies": {
19
+ "@elyracode/coding-agent": "*",
20
+ "typebox": "*"
21
+ },
22
+ "scripts": {
23
+ "clean": "echo 'nothing to clean'",
24
+ "build": "echo 'nothing to build'",
25
+ "check": "echo 'nothing to check'"
26
+ }
27
+ }
@@ -0,0 +1,309 @@
1
+ ---
2
+ name: tall-stack
3
+ description: Deep knowledge about the TALL stack - Tailwind CSS, Alpine.js, Laravel, Livewire 4, and Flux UI. Use when working on TALL stack projects, Livewire components, Blade views, Alpine interactivity, or Flux UI components.
4
+ ---
5
+
6
+ # TALL Stack Reference
7
+
8
+ ## Architecture
9
+
10
+ The TALL stack connects:
11
+ - **Laravel** as the backend framework (routing, controllers, models, migrations, Eloquent)
12
+ - **Livewire 4** for reactive server-rendered components (replaces traditional AJAX)
13
+ - **Alpine.js** for lightweight client-side interactivity (toggles, dropdowns, transitions)
14
+ - **Tailwind CSS** for utility-first styling
15
+ - **Flux UI** for pre-built, accessible Livewire/Alpine components
16
+
17
+ ### When to use Livewire vs Alpine
18
+
19
+ - **Livewire**: Server state, database operations, form validation, real-time updates, anything needing PHP
20
+ - **Alpine**: Client-only UI state (dropdowns, modals, tabs, animations), no server round-trip needed
21
+ - **Both together**: Alpine handles instant UI feedback, Livewire handles persistence
22
+
23
+ ## Livewire 4
24
+
25
+ ### Component Structure
26
+
27
+ ```php
28
+ <?php
29
+
30
+ namespace App\Livewire;
31
+
32
+ use Livewire\Component;
33
+ use Livewire\Attributes\Validate;
34
+ use Livewire\Attributes\Locked;
35
+ use Livewire\Attributes\Url;
36
+ use Livewire\Attributes\Computed;
37
+ use Livewire\Attributes\On;
38
+
39
+ class EditProfile extends Component
40
+ {
41
+ #[Validate('required|string|max:255')]
42
+ public string $name = '';
43
+
44
+ #[Validate('required|email')]
45
+ public string $email = '';
46
+
47
+ #[Locked]
48
+ public int $userId;
49
+
50
+ #[Url]
51
+ public string $tab = 'general';
52
+
53
+ #[Computed]
54
+ public function user(): User
55
+ {
56
+ return User::find($this->userId);
57
+ }
58
+
59
+ public function save(): void
60
+ {
61
+ $this->validate();
62
+ $this->user->update([
63
+ 'name' => $this->name,
64
+ 'email' => $this->email,
65
+ ]);
66
+ $this->dispatch('profile-updated');
67
+ }
68
+
69
+ public function render()
70
+ {
71
+ return view('livewire.edit-profile');
72
+ }
73
+ }
74
+ ```
75
+
76
+ ### Key Livewire 4 Attributes
77
+
78
+ | Attribute | Purpose |
79
+ |-----------|---------|
80
+ | `#[Validate('rules')]` | Inline validation rules on properties |
81
+ | `#[Locked]` | Property cannot be modified from the frontend (security) |
82
+ | `#[Url]` | Syncs property with URL query string |
83
+ | `#[Computed]` | Cached computed property (auto-memoized per request) |
84
+ | `#[On('event-name')]` | Listen for dispatched events |
85
+ | `#[Layout('layouts.app')]` | Set the layout for full-page components |
86
+ | `#[Title('Page Title')]` | Set the page title |
87
+ | `#[Lazy]` | Lazy-load the component (placeholder until visible) |
88
+ | `#[Isolate]` | Prevent this component from re-rendering when sibling components update |
89
+
90
+ ### Livewire 4 Lifecycle
91
+
92
+ 1. `mount()` -- Called once when component is first instantiated
93
+ 2. `hydrate()` -- Called on every subsequent request (after deserialization)
94
+ 3. `boot()` -- Called on every request (before mount on first, before hydrate on subsequent)
95
+ 4. `updating{Property}()` / `updated{Property}()` -- Before/after property changes
96
+ 5. `render()` -- Returns the Blade view
97
+ 6. `dehydrate()` -- Called before serialization for the response
98
+
99
+ ### Common Patterns
100
+
101
+ **Form handling:**
102
+ ```php
103
+ use Livewire\Attributes\Validate;
104
+
105
+ #[Validate('required|string|max:255')]
106
+ public string $title = '';
107
+
108
+ public function save(): void
109
+ {
110
+ $this->validate();
111
+ Post::create(['title' => $this->title]);
112
+ $this->reset('title');
113
+ $this->dispatch('post-created');
114
+ }
115
+ ```
116
+
117
+ **File uploads:**
118
+ ```php
119
+ use Livewire\WithFileUploads;
120
+
121
+ class UploadPhoto extends Component
122
+ {
123
+ use WithFileUploads;
124
+
125
+ #[Validate('image|max:1024')]
126
+ public $photo;
127
+
128
+ public function save(): void
129
+ {
130
+ $this->validate();
131
+ $this->photo->store('photos');
132
+ }
133
+ }
134
+ ```
135
+
136
+ **Pagination:**
137
+ ```php
138
+ use Livewire\WithPagination;
139
+
140
+ class UserList extends Component
141
+ {
142
+ use WithPagination;
143
+
144
+ public function render()
145
+ {
146
+ return view('livewire.user-list', [
147
+ 'users' => User::paginate(10),
148
+ ]);
149
+ }
150
+ }
151
+ ```
152
+
153
+ **Real-time with events:**
154
+ ```php
155
+ // Dispatching
156
+ $this->dispatch('post-created', id: $post->id);
157
+
158
+ // Listening
159
+ #[On('post-created')]
160
+ public function handlePostCreated(int $id): void
161
+ {
162
+ // React to the event
163
+ }
164
+ ```
165
+
166
+ ### Hydration Rules (Critical)
167
+
168
+ - Only `public` properties are sent to the frontend and back
169
+ - Use `#[Locked]` for IDs and sensitive data that should not be tampered with
170
+ - Eloquent models as properties: Livewire re-fetches by ID on each request
171
+ - Collections, arrays, and simple types are serialized/deserialized directly
172
+ - If a property cannot be serialized, use `#[Computed]` instead
173
+
174
+ ## Alpine.js Patterns
175
+
176
+ ### Basic Interactivity
177
+ ```html
178
+ <div x-data="{ open: false }">
179
+ <button @click="open = !open">Toggle</button>
180
+ <div x-show="open" x-transition>
181
+ Content
182
+ </div>
183
+ </div>
184
+ ```
185
+
186
+ ### With Livewire (@entangle)
187
+ ```html
188
+ <div x-data="{ tab: @entangle('tab') }">
189
+ <button @click="tab = 'general'" :class="{ 'active': tab === 'general' }">
190
+ General
191
+ </button>
192
+ <button @click="tab = 'security'" :class="{ 'active': tab === 'security' }">
193
+ Security
194
+ </button>
195
+ </div>
196
+ ```
197
+
198
+ Note: `@entangle` syncs Alpine state with Livewire server state. Use `@entangle('property').live` for real-time sync without waiting for Livewire requests.
199
+
200
+ ### Alpine Stores (shared state)
201
+ ```html
202
+ <script>
203
+ Alpine.store('sidebar', { open: true });
204
+ </script>
205
+
206
+ <div x-data @click="$store.sidebar.open = !$store.sidebar.open">
207
+ Toggle Sidebar
208
+ </div>
209
+ ```
210
+
211
+ ## Flux UI
212
+
213
+ Flux UI provides pre-built, accessible components for TALL stack projects.
214
+
215
+ ### Common Components
216
+ ```blade
217
+ {{-- Button --}}
218
+ <flux:button>Save Changes</flux:button>
219
+ <flux:button variant="primary">Submit</flux:button>
220
+ <flux:button variant="danger" wire:click="delete">Delete</flux:button>
221
+
222
+ {{-- Input --}}
223
+ <flux:input wire:model="name" label="Full Name" />
224
+ <flux:input wire:model="email" label="Email" type="email" />
225
+
226
+ {{-- Select --}}
227
+ <flux:select wire:model="role" label="Role">
228
+ <flux:option value="admin">Admin</flux:option>
229
+ <flux:option value="user">User</flux:option>
230
+ </flux:select>
231
+
232
+ {{-- Modal --}}
233
+ <flux:modal name="confirm-delete">
234
+ <flux:heading>Delete Item?</flux:heading>
235
+ <flux:text>This action cannot be undone.</flux:text>
236
+ <flux:button variant="danger" wire:click="delete">Confirm</flux:button>
237
+ </flux:modal>
238
+
239
+ <flux:button @click="$flux.modal('confirm-delete').show()">Delete</flux:button>
240
+
241
+ {{-- Table --}}
242
+ <flux:table>
243
+ <flux:columns>
244
+ <flux:column>Name</flux:column>
245
+ <flux:column>Email</flux:column>
246
+ <flux:column>Actions</flux:column>
247
+ </flux:columns>
248
+ <flux:rows>
249
+ @foreach($users as $user)
250
+ <flux:row :key="$user->id">
251
+ <flux:cell>{{ $user->name }}</flux:cell>
252
+ <flux:cell>{{ $user->email }}</flux:cell>
253
+ <flux:cell>
254
+ <flux:button size="sm" wire:click="edit({{ $user->id }})">Edit</flux:button>
255
+ </flux:cell>
256
+ </flux:row>
257
+ @endforeach
258
+ </flux:rows>
259
+ </flux:table>
260
+
261
+ {{-- Card --}}
262
+ <flux:card>
263
+ <flux:heading>Dashboard</flux:heading>
264
+ <flux:text>Welcome back.</flux:text>
265
+ </flux:card>
266
+
267
+ {{-- Tabs --}}
268
+ <flux:tabs wire:model="tab">
269
+ <flux:tab name="general">General</flux:tab>
270
+ <flux:tab name="security">Security</flux:tab>
271
+ </flux:tabs>
272
+ ```
273
+
274
+ ### Flux UI Guidelines
275
+ - Always use Flux components when available instead of raw HTML + Tailwind
276
+ - Flux components integrate directly with Livewire via `wire:model` and `wire:click`
277
+ - Use Flux modals with the `$flux.modal()` API for programmatic control
278
+ - Flux handles accessibility (ARIA attributes, keyboard navigation) automatically
279
+
280
+ ## File Structure Conventions
281
+
282
+ ```
283
+ app/
284
+ Livewire/ # Livewire components (PHP classes)
285
+ Users/
286
+ UserTable.php
287
+ EditUser.php
288
+ Models/ # Eloquent models
289
+ resources/
290
+ views/
291
+ livewire/ # Blade views for Livewire components
292
+ users/
293
+ user-table.blade.php
294
+ edit-user.blade.php
295
+ components/ # Blade components (non-Livewire)
296
+ layouts/
297
+ app.blade.php
298
+ routes/
299
+ web.php # Routes (Livewire full-page components use Route::get)
300
+ ```
301
+
302
+ ## Common Gotchas
303
+
304
+ 1. **wire:model vs wire:model.live**: Default `wire:model` only syncs on form submit. Use `.live` for real-time sync, `.blur` for sync on blur.
305
+ 2. **Alpine + Livewire timing**: Alpine runs client-side instantly; Livewire needs a server round-trip. Use `wire:loading` for feedback.
306
+ 3. **Computed properties**: Always use `#[Computed]` for expensive queries. They're memoized per-request.
307
+ 4. **Security**: Always use `#[Locked]` on IDs and values that should not be tampered with from the browser.
308
+ 5. **Nested components**: Child Livewire components re-render independently. Use events (`dispatch`/`#[On]`) to communicate.
309
+ 6. **Flux UI + dark mode**: Flux respects Tailwind's `dark:` prefix. Ensure your layout has the dark mode class toggling.