frontend-qwik-patterns
/frontend-qwik-patterns
Stosuje wzorce Qwik: wznawialność zamiast hydratacji, sygnały i stores, trasy Qwik City z loaderami oraz optymalne prefetchowanie.
- Autor
- j4flmao ↗
- Repozytorium
- agent-skills ↗
- Licencja
- MIT
- Ostatnia zmiana repozytorium
- 10.10.2026
Ocena i bezpieczeństwo
- Pliki w paczce
- 9
- Skrypty
- 0
- Komentarze HTML
- 0
- Adresy URL w SKILL.md
- 1
Brak sygnałów. Repozytorium zmienione 10.10.2026, bez odwołań do wycofanych modeli i API.
MIT, otwarta: można używać i zmieniać, z zachowaniem informacji o autorze.
Co robi i kiedy
Stosuje wzorce Qwik: wznawialność zamiast hydratacji, sygnały i stores, trasy Qwik City z loaderami oraz optymalne prefetchowanie.
Wyzwalacze z opisu
Oryginalny opis (EN)
Use this skill when the user says 'Qwik pattern', 'Qwik resumable', 'Qwik City route', 'useSignal', 'useStore', 'Qwik lazy loading', 'Qwik optimizer', '$()', 'component$()', 'routeLoader$', 'routeAction$'. This skill enforces: resumability over hydration, dollar-sign API for all lazy boundaries, fine-grained reactivity with useSignal/useStore, Qwik City file-based routing with lazy loaders/actions, and optimistic prefetching via PrefetchServiceWorker. Requires Qwik project (package.json with @builder.io/qwik). Do NOT use for: Qwik project setup/architecture, or non-Qwik frameworks.
Jak działa
- Purpose
- Agent Protocol
- Workflow
- Component Architecture
- State Management Patterns
- Performance Optimization
- Build & Bundle Considerations
- Testing Strategies
- Migration Patterns
- Anti-Patterns
Podgląd SKILL.md
---
name: frontend-qwik-patterns
description: >
Use this skill when the user says 'Qwik pattern', 'Qwik resumable', 'Qwik City route', 'useSignal', 'useStore', 'Qwik lazy loading', 'Qwik optimizer', '$()', 'component$()', 'routeLoader$', 'routeAction$'. This skill enforces: resumability over hydration, dollar-sign API for all lazy boundaries, fine-grained reactivity with useSignal/useStore, Qwik City file-based routing with lazy loaders/actions, and optimistic prefetching via PrefetchServiceWorker. Requires Qwik project (package.json with @builder.io/qwik). Do NOT use for: Qwik project setup/architecture, or non-Qwik frameworks.
version: "1.0.0"
author: "j4flmao"
license: "MIT"
compatibility:
claude-code: true
cursor: true
codex: true
windsurf: true
tags: [frontend, qwik, patterns, phase-10]
---
# Qwik Patterns
## Purpose
Apply production patterns to Qwik applications: resumability-driven architecture, fine-grained reactivity, lazy loading boundaries, Qwik City routing with server functions, and prefetch optimization.
## Agent Protocol
### Trigger
Exact user phrases: "Qwik pattern", "Qwik resumable", "Qwik City", "useSignal", "useStore", "Qwik lazy loading", "Qwik optimizer", "$()", "component$()", "routeLoader$", "routeAction$".
### Input Context
Before activating, verify:
- package.json has @builder.io/qwik and @builder.io/qwik-city.
- Vite config has Qwik plugins.
- Prefetch strategy is configured (PrefetchServiceWorker).
### Output Artifact
No file output. Produces resumability plan, component patterns, route design as text.
### Response Format
```
Resumability Plan: {lazy boundary map}
Component Pattern: {component$ / $() usage}
Route Design: {loaders + actions + layout}
```
No preamble. No postamble. No explanations. No filler/hedging/transitions. Compress output — why use many token when few do trick.
### Completion Criteria
- [ ] All components use component$() for lazy loading.
- [ ] Event handlers use $ suffix (onClick$, onInput$).
- [ ] Closures passed across lazy boundaries use $().
- [ ] State uses useSignal (primitive) or useStore (object).
- [ ] Data loading uses routeLoader$() with typed returns.
- [ ] Mutations use routeAction$() with Form component.
- [ ] PrefetchServiceWorker enabled in root layout.
- [ ] useVisibleTask$ used sparingly and only for client-only effects.
### Max Response Length
2560 tokens.
## Workflow
### Step 1: Resumability Pattern
```tsx
export default component$(() => {
const count = useSignal(0)
return (
<button onClick$={() => count.value++}>
{count.value}
</button>
)
})
```
No hydration: HTML contains serialized state (`data-qwik`) + QRL references to lazy-loadable chunks. Browser resumes execution without replaying component tree.
### Step 2: Dollar Sign API Boundaries
```tsx
export default component$(() => {
const state = useStore({ items: [], filter: '' })
const log = $((msg: string) => {
console.log(msg, state.items)
})
return (
<input onInput$={(_, el) => state.filter = el.value} />
)
})
```
Every `$` creates a separate lazy-loadable chunk. The optimizer extracts these into individual bundles.
### Step 3: Fine-Grained Reactivity
```tsx
export default component$(() => {
const count = useSignal(0)
const name = useSignal('')
const form = useStore({
email: '',
password: '',
errors: {} as Record<string, string>,
})
const isFormValid = useComputed$(() =>
form.email.includes('@') && form.password.length >= 8
)
return (
<div>
<p>Count: {count.value}</p>
<p>Form valid: {isFormValid.value}</p>
</div>
)
})
```
Reactivity is fine-grained — Qwik tracks reads at the property level, not via virtual DOM diffing.
### Step 4: Qwik City Routing
```
src/routes/
layout.tsx -> root layout
index.tsx -> /
about/index.tsx -> /about
blog/
layout.tsx -> blog layout
index.tsx -> /blog
[slug]/index.tsx -> /blog/:slug
dashboard/
layout.tsx -> authenticated layout
index.tsx -> /dashboard
api/
users/index.ts -> /api/users (resource route)
```
All routes, layouts, data loaders, and actions are lazy-loaded. Use `<Slot />` for layout insertion points.
### Step 5: Route Loaders and Actions
```tsx
// src/routes/dashboard/index.tsx
import { routeLoader$, routeAction$, Form } from '@builder.io/qwik-city'
export const useUserData = routeLoader$(async ({ cookie, redirect }) => {
const token = cookie.get('token')?.value
if (!token) throw redirect(302, '/login')
const user = await db.user.findUnique({ where: { token } })
return user as User
})
export const useUpdateProfile = routeAction$(async (form, { fail }) => {
const name = form.get('name')
if (!name || name.length < 2) return fail(400, { message: 'Name too short' })
await db.user.update({ data: { name } })
return { success: true }
})
export default component$(() => {
const user = useUserData()
const action = useUpdateProfile()
return (
<Form action={action}>
<input name="name" value={user.value.name} />
{action.value?.failed && <p>{action.value.fieldErrors?.message}</p>}
<button type="submit">Update</button>
</Form>
)
})
```
`routeLoader$` runs on server, serializes result into HTML. `routeAction$` handles form mutations with progressive enhancement.
### Step 6: Prefetch Optimization
```tsx
// src/root.tsx
import { PrefetchServiceWorker } from '@builder.io/qwik/prefetch-service-worker'
export default component$(() => {
return (
<html>
<head>
<PrefetchServiceWorker />
</head>
<body>
<Slot />
</body>
</html>
)
})
```
PrefetchServiceWorker preloads QRL chunks for links in viewport, enabling instant navigation without waterfall.
### Step 7: Server Functions
```tsx
// src/components/createUser.ts
import { server$ } from '@builder.io/qwik-city'
export const createUser = server$(async (data: CreateUserInput) => {
const user = await db.user.create({ data })
await email.sendWelcome(user.email)
return user
})
```
`server$()` marks a function to always run on the server. Callable from client components as if local.
### Step 8: useVisibleTask$ for Client Effects
```tsx
export default component$(() => {
const elemRef = useSignal<Element>()
useVisibleTask$(() => {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) analytics.trackView(entry.target.id)
})
})
if (elemRef.value) observer.observe(elemRef.value)
return () => observer.disconnect()
})
return <div ref={elemRef} id="tracked-element">Content</div>
})
```
## Component Architecture
### Component Decision Tree
```
Does the component need interactivity?
No -> Static HTML, no component$() needed (plain function component)
Yes -> Does it need state?
No -> Use component$() with props only
Yes -> Is the state simple (number, string)?
Yes -> useSignal
No -> useStore (object, array)
Does the component need side effects?
No -> Skip useVisibleTask$
Yes -> Is it a data fetch?
No -> Is it DOM measurement, animation, or analytics?
Yes -> useVisibleTask$ with proper cleanup
Yes -> routeLoader$ in parent, pass as props
```
### Component Composition Patterns
```tsx
// Parent provides state, children receive props
export default component$(() => {
const items = useSignal<string[]>([])
return (
<div>
<ItemList items={items.value} />
</div>
)
})
// Or use context for deep passing
import { createContextId, useContextProvider, useContext } from '@builder.io/qwik'
export const ThemeContext = createContextId<string>('theme')
export const Root = component$(() => {
useContextProvider(ThemeContext, 'dark')
return <Slot />
})
export const Child = component$(() => {
const theme = useContext(ThemeContext)
return <div class={theme}>Content</div>
})
```
### Inline Component Pattern (No $)
For non-interactive wrapper components that don't need lazy loading:
```tsx
// No component$() — this is an eager, lightweight wrapper
export function Container(props: { title: string; children?: any }) {
return (
<section>
<h2>{props.title}</h2>
{props.children}
</section>
)
}
```
### Slot Pattern with Fallback
```tsx
export const Card = component$(() => {
return (
<div class="card">
<div class="card-header">
<Slot name="header" />
</div>
<div class="card-body">
<Slot />
</div>
</div>
)
})
```
### Lazy-Loaded Third-Party Library
```tsx
export default component$(() => {
useVisibleTask$(async () => {
const Chart = await import('chart.js')
// Chart is only downloaded when this component becomes visible
new Chart(ctx, { /* options */ })
})
return <canvas ref={canvasRef} />
})
```
### Infinite Scroll Pattern
```tsx
export default component$(() => {
const items = useSignal<Item[]>([])
const page = useSignal(1)
const loading = useSignal(false)
const loadMore = $(async () => {
if (loading.value) return
loading.value = true
const newItems = await fetch(`/api/items?page=${page.value}`).then(r => r.json())
items.value = [...items.value, ...newItems]
page.value++
loading.value = false
})
return (
<div>
{items.value.map(item => <ItemCard item={item} />)}
<button onClick$={loadMore}>
{loading.value ? 'Loading...' : 'Load More'}
</button>
</div>
)
})
```
### Debounced Search Pattern
```tsx
export default component$(() => {
const query = useSignal('')
const results = useSignal<SearchResult[]>([])
const search = $(async (q: string) => {
if (q.length < 2) { results.value = []; return }
results.value = await fetch(`/api/search?q=${q}`).then(r => r.json())
})
return (
<div>
<input
onInput$={async (_, el) => {
query.value = el.value
await search(el.value)
}}
placeholder="Search..."
/>
<ul>
{results.value.map(r => <li key={r.id}>{r.title}</li>)}
</ul>
</div>
)
})
```
## State Management Patterns
### useSignal for Primitives
```tsx
const count = useSignal(0) // number
const name = useSignal('') // string
const isActive = useSignal(true) // boolean
const items = useSignal<string[]>([]) // array (replaced entirely)
```
### useStore for Objects
```tsx
const user = useStore({
id: '',
name: '',
email: '',
preferences: { theme: 'light', language: 'en' },
metadata: { createdAt: null as Date | null },
})
```
Qwik tracks property-level reads. Mutations like `user.preferences.theme = 'dark'` trigger targeted re-renders without VDOM diffing.
### Derived State
```tsx
const firstName = useSignal('John')
const lastName = useSignal('Doe')
const fullName = useComputed$(() =>
`${firstName.value} ${lastName.value}`
)
// fullName.value updates automatically when firstName or lastName changes
```
### Context-Based Shared State
```tsx
// Define context type
interface AuthState { user: User | null; login: (email: string, password: string) => Promise<void> }
// Create context ID
export const AuthContext = createContextId<AuthState>('auth')
// Provider in root layout
export const Root = component$(() => {
const authState = useStore<AuthState>({
user: null,
login: $(async (email, password) => {
const user = await loginUser(email, password)
authState.user = user
}),
})
useContextProvider(AuthContext, authState)
return <Slot />
})
// Consumer in any child
export const Profile = component$(() => {
const auth = useContext(AuthContext)
return <div>{auth.user ? `Welcome ${auth.user.name}` : 'Not logged in'}</div>
})
```
### Server State Synchronization
Use routeLoader$ + routeAction$ for server state. The client can invalidate loaders after an action:
```tsx
export const usePosts = routeLoader$(async () => {
return await db.post.findMany() as Post[]
})
export const useCreatePost = routeAction$(async (form) => {
await db.post.create({ data: { title: form.get('title') } })
// Loader automatically re-runs on next request
})
export default component$(() => {
const posts = usePosts()
const createPost = useCreatePost()
return <Form action={createPost}>...</Form>
})
```
### URL as State Source
```tsx
export default component$(() => {
const loc = useLocation()
const nav = useNavigate()
// Read state from URL
const currentPage = Number(loc.params.page) || 1
const sortBy = loc.url.searchParams.get('sort') || 'date'
// Update URL
return <button onClick$={() => nav(`/list?sort=${sortBy}&page=${currentPage + 1}`)}>Next</button>
})
```
## Performance Optimization
1. Initial load: ~10KB JS baseline, zero hydration cost, instant TTI.
2. Lazy chunks: Each $() is ~200-500 bytes, loaded on interaction only.
3. Serialized state: HTML size increases by ~2-5KB per page with serialized signals.
4. Prefetch: PrefetchServiceWorker uses idle time to download route chunks.
5. Bundle splitting: Automatic at the $ boundary — no manual code splitting.
6. Memory: Fine-grained signals use less memory than virtual DOM tree.
7. Time to interactive: Near zero because there is no hydration to wait for.
### Chunk Size Budgets
- Each $ boundary: 200-500 bytes target
- Route loader data: < 10KB serialized per page
- Total initial JS: < 15KB
- Total per-interaction JS: < 5KB
### Measuring Performance
```bash
npx qwik build --analyze # opens bundle analyzer
npm run qwik build && node dist/server/entry.mjs # test SSR perf
```
## Build & Bundle Considerations
### Entry Strategies
| Strategy | Chunks | Use Case |
|----------|--------|----------|
| `smart` | Many small chunks (default) | Most applications — optimal lazy loading |
| `hoist` | Fewer, larger chunks | Apps with many shared dependencies |
| `single` | One bundle | Small apps, no lazy benefit needed |
Configure in `vite.config.ts`:
```ts
qwikVite({ entryStrategy: { type: 'hoist' } })
```
### Tree Shaking
Qwik's optimizer automatically tree-shakes unused exports from `$()` boundaries. Only code reachable from a `$()` boundary is included in the client bundle.
### CSS Bundling
- CSS imported in components is automatically extracted and split
- Global CSS in `src/global.css` is inlined in the initial HTML
- Use CSS Modules for component-scoped styles: `import styles from './component.module.css'`
### Adapter-Specific Builds
```ts
// Cloudflare Pages
import cloudflarePages from '@builder.io/qwik-city/adapters/cloudflare-pages/vite'
// Node.js server
import nodeServer from '@builder.io/qwik-city/adapters/node-server/vite'
// Vercel Edge
import vercelEdge from '@builder.io/qwik-city/adapters/vercel-edge/vite'
```
Each adapter changes the SSR entry point and output format.
## Testing Strategies
### Component Unit Tests
```tsx
// __tests__/counter.test.tsx
import { createDOM } from '@builder.io/qwik/testing'
import { test, expect } from 'vitest'
import Counter from '../src/components/counter'
test('should increment', async () => {
const { screen, render, userEvent } = await createDOM()
await render(<Counter />)
expect(screen.querySelector('button')?.innerHTML).toBe('0')
await userEvent('button', 'click')
expect(screen.querySelector('button')?.innerHTML).toBe('1')
})
```
### Signal/Store Logic Tests
```tsx
// __tests__/state.test.ts
import { test, expect } from 'vitest'
import { useSignal, useStore } from '@builder.io/qwik'
test('signal updates reactively', () => {
const count = useSignal(0)
expect(count.value).toBe(0)
count.value = 5
expect(count.value).toBe(5)
})
test('store tracks nested mutations', () => {
const state = useStore({ user: { name: 'John' } })
expect(state.user.name).toBe('John')
state.user.name = 'Jane'
expect(state.user.name).toBe('Jane')
})
```
### Route Loader Tests
```tsx
// __tests__/loaders.test.ts
import { test, expect } from 'vitest'
import { useProductData } from '../src/routes/product/[id]'
test('loader fetches product by id', async () => {
const mockContext = {
params: { id: '1' },
request: new Request('http://localhost/product/1'),
// ... other context properties
}
const result = await useProductData(mockContext)
expect(result).toHaveProperty('name')
expect(result).toHaveProperty('price')
})
```
### E2E Testing
```tsx
// e2e/navigation.spec.ts
import { test, expect } from '@playwright/test'
test('navigates without full page reload', async ({ page }) => {
await page.goto('/')
await page.click('a[href="/about"]')
await expect(page.locator('h1')).toHaveText('About')
// Verify client-side navigation (no full page reload)
})
test('form submission with validation', async ({ page }) => {
await page.goto('/dashboard')
await page.fill('input[name="name"]', 'A')
await page.click('button[type="submit"]')
await expect(page.locator('.error')).toContainText('too short')
})
```
## Migration Patterns
### React to Qwik Migration Plan
**Phase 1 — Audit existing components:**
- Identify which components need client interactivity
- Map React hooks to Qwik equivalents
- Identify server-side data dependencies
**Phase 2 — Rewrite leaf components:**
```tsx
// React
function Toggle() {
const [on, setOn] = useState(false)
return <button onClick={() => setOn(!on)}>{on ? 'ON' : 'OFF'}</button>
}
// Qwik
export default component$(() => {
const on = useSignal(false)
return <button onClick$={() => on.value = !on.value}>{on.value ? 'ON' : 'OFF'}</button>
})
```
**Phase 3 — Migrate routing and data:**
- Replace React Router with Qwik City file-based routing
- Replace React Query/useEffect fetches with routeLoader$
- Replace API routes with resource routes or server$
**Phase 4 — Enable prefetch and optimize:**
- Add PrefetchServiceWorker
- Verify $ boundary coverage with Qwik DevTools
- Audit chunk sizes with `qwik build --analyze`
### Next.js to Qwik City
| Next.js | Qwik City |
|---------|-----------|
| `pages/[slug].tsx` | `src/routes/[slug]/index.tsx` |
| `getServerSideProps` | `routeLoader$` |
| `getStaticProps` | `routeLoader$` with SSG |
| Server Actions | `routeAction$` |
| `middleware.ts` | `plugin@name.ts` |
| `layout.tsx` | `layout.tsx` per segment |
| `next/image` | `qwik-image` or `<img>` with lazy loading |
### Incremental Strategy
1. **Route-level** — Migrate one route at a time, keeping old and new coexisting
2. **Component-level** — Embed Qwik widgets in existing pages via web components
3. **Feature-level** — Build new features in Qwik, leave legacy features in old framework
## Anti-Patterns
### Missing $ Suffix
```tsx
// Anti-pattern: onClick without $ — handler is eager, not lazy
<button onClick={() => doSomething()}>Click</button>
// Correct
<button onClick$={() => doSomething()}>Click</button>
```
### State Outside Qwik's Reactivity System
```tsx
// Anti-pattern: plain variable — changes won't trigger re-render
let count = 0
// Correct: useSignal
const count = useSignal(0)
```
### Data Fetching in useVisibleTask$
```tsx
// Anti-pattern: useVisibleTask$ for data
useVisibleTask$(async () => {
const data = await fetch('/api/data').then(r => r.json())
state.value = data
})
// Correct: routeLoader$
export const useData = routeLoader$(async () => {
return await fetch('/api/data').then(r => r.json())
})
```
### Large Serialized State
```tsx
// Anti-pattern: serializing entire data set
const allProducts = useSignal(await fetch('/api/products/10000').then(r => r.json()))
// Correct: lazy load, paginate
export const useProducts = routeLoader$(async ({ query }) => {
const page = Number(query.get('page')) || 1
return await db.product.findMany({ skip: (page-1)*20, take: 20 })
})
```
### Mixing React and Qwik in Same Component
Don't import or use React hooks inside a Qwik component. The reactivity systems are incompatible.
### Over-Serialization
```tsx
// Anti-pattern: storing non-serializable values in signals
const chartInstance = useSignal<Chart | null>(null) // Chart is a class instance
// Correct: use NoSerialize wrapper
import { NoSerialize } from '@builder.io/qwik'
const chartInstance = useSignal<NoSerialize<Chart>>()
```
## Common Pitfalls
1. **Forgetting $ on event handlers**: `onClick` instead of `onClick$` — event never gets lazy loaded.
2. **Using useState from React**: Qwik uses useSignal and useStore, not hooks from other frameworks.
3. **Heavy useVisibleTask$ usage**: Every useVisibleTask$ blocks resumability. Keep them minimal.
4. **Dynamic $() calls**: `$(someCondition ? fn1 : fn2)` breaks the optimizer. Use static boundaries.
5. **Missing PrefetchServiceWorker**: Without it, lazy navigation produces visible network waterfalls.
6. **Mutable state reassignment**: `state = newValue` instead of `state.value = newValue` for signals.
7. **Nested reactivity with useStore**: Objects inside useStore are deeply reactive — use for form state.
8. **Not using typed loaders**: routeLoader$ returns `unknown` without explicit typing.
## Best Practices
1. Every `$()` should be statically analyzable — no dynamic code inside dollar boundaries.
2. `useSignal` for primitives, `useStore` for objects. Never plain `let` or `const`.
3. Colocate routeLoader$ and routeAction$ in the route file that uses them.
4. Use `useComputed$` for derived values — avoids manual synchronization.
5. Keep useVisibleTask$ focused on a single concern — one observer per task.
6. Lazy-load heavy libraries inside `$()` callbacks, not at module level.
7. Use `NoSerialize` wrapper for non-serializable values (class instances, DOM refs).
8. Prefetch critical routes after initial render with PrefetchServiceWorker.
## Compared With
| Aspect | Qwik | React (Client) | Solid |
|--------|------|----------------|-------|
| Rendering | Resumable | Hydrating | Hydrating |
| Lazy loading | Per-event ($) | Per-component (lazy()) | Per-component (lazy()) |
| Reactivity | Signal-based, fine-grained | Virtual DOM diff | Signal-based |
| Serialization | Automatic via QRL | Manual (JSON) | Manual |
| Server functions | Built-in (server$) | Via Server Actions | Via SolidStart |
| Bundle size | ~10KB (initial) | ~40KB+ (React runtime) | ~8KB (initial) |
## Tooling
1. `npm run qwik build` — production build with Qwik optimizer.
2. `npm run qwik dev` — dev server with HMR and the Qwik DevTools panel.
3. `npm run qwik lint` — ESLint with Qwik-specific rules (ensures $ boundaries).
4. `npm run qwik qwik add` — CLI to add integrations (auth, database, UI).
5. Qwik DevTools browser extension — inspect lazy boundaries and QRL chunks.
6. `@builder.io/qwik-labs` — experimental features and utilities.
7. `qwik-speak` — internationalization library for Qwik.
8. `qwik-image` — optimized images with lazy loading.
## Rules
- No eager code — every component, event, and closure is lazy by default via `$`.
- `useSignal` for primitives, `useStore` for objects. Never use plain `let` or `const` for reactive state.
- `routeLoader$` for data fetching, `routeAction$` with `<Form>` for mutations.
- `useVisibleTask$` only for client-only effects (intersection observers, analytics) — avoid for data fetching.
- PrefetchServiceWorker is required for instant navigation — without it, lazy loading becomes waterfall.
- Qwik optimizer must be able to see `$()` boundaries — no dynamic `$` calls.
- Serialized state stays in HTML — never rely on sessionStorage for critical app state.
- Dollar boundaries must be statically analyzable — no dynamic expressions inside $().
## References
- references/qwik-city-patterns.md — Qwik City Patterns
- references/qwik-component-patterns.md — Qwik Component Patterns
- references/qwik-data.md — Qwik Data Patterns
- references/qwik-routing.md — Qwik Routing Patterns
- references/qwik-state-management.md — Qwik State Management
- references/resumable-patterns.md — Qwik Resumable Patterns
- references/qwik-component-composition.md — Qwik Component Composition Reference
- references/qwik-form-validation.md — Qwik Form Validation Reference
## Handoff
No artifact produced.
Next skill: frontend-universal-testing for Qwik component tests. Or frontend-universal-performance.
Carry forward: resumability boundaries, dollar-sign conventions, prefetch strategy.
Pliki w paczce (9)
- SKILL.md 24 KB
- references/qwik-city-patterns.md 6 KB
- references/qwik-component-composition.md 15 KB
- references/qwik-component-patterns.md 3 KB
- references/qwik-data.md 3 KB
- references/qwik-form-validation.md 22 KB
- references/qwik-routing.md 3 KB
- references/qwik-state-management.md 4 KB
- references/resumable-patterns.md 5 KB
Wersje
W bazie nie ma innych skilli o nazwie frontend-qwik-patterns.
Migawka bazy z 28.10.2026 · wersja paczki 0f056396b8ab (skrót SHA-256 całej paczki)
Pobrania w ostatnich 30 dniach: 0 · ranking
Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.
Podobne skille
- 90frontend-qwik-architecture
Projektuje aplikacje Qwik na zasadzie wznawialności bez hydratacji: leniwe granice $(), routing Qwik City i podział kodu. - 100qwik
Wspiera budowę aplikacji Qwik City bez hydracji: komponenty, signals, routeLoader$, formularze routeAction$, layouty, middleware, adaptery wdrożeniowe i wybór między Qwik 1.x a wersją 2.0. - 90qwik-core-development
Wspiera zmiany i przeglądy kodu rdzenia Qwik w packages/qwik: prymitywy reaktywne, sygnały, VNode, zachowanie kursora, QRL, zachowanie runtime pod optymalizator i testy rdzenia. - 100qwik-e2e-verification
Tworzy, zmienia, debuguje i uruchamia testy e2e Playwright Qwik w katalogu e2e, w tym zestawy routera, adapterów, dokumentacji, CLI i integracji z React. - 100cloudflare-workers-frameworks
Integruje frameworki z Cloudflare Workers: Hono, Remix, Next.js, Astro, SvelteKit, Qwik i Nuxt, w tym routing, SSR, zasoby statyczne i wdrożenie brzegowe. - 90frontend-vue-patterns
Podpowiada wzorce Vue 3: kompozyty useX, sklepy Pinia, leniwe ładowanie tras i komponenty bezrenderowe.