--- name: qwik description: | Qwik is a resumable web framework that delivers instant-loading applications by eliminating hydration. It serializes application state on the server and lazily loads JavaScript on interaction, making it ideal for edge deployment. license: Apache-2.0 compatibility: 'node >= 18, npm or yarn or pnpm' metadata: author: terminal-skills version: 1.0.0 category: development tags: - typescript - frontend - ssr - resumable - edge - performance --- # Qwik Qwik eliminates hydration by serializing the application state into HTML. JavaScript loads lazily on user interaction, not on page load. This means near-zero JS on initial load regardless of app complexity. ## Installation ```bash # Create Qwik project with Qwik City (meta-framework) npm create qwik@latest cd my-app npm install npm run dev ``` ## Project Structure ``` # Qwik City project layout src/ ├── entry.ssr.tsx # SSR entry ├── root.tsx # Root component ├── global.css ├── routes/ # File-based routing │ ├── layout.tsx # Root layout │ ├── index.tsx # / page │ └── articles/ │ ├── index.tsx # /articles │ └── [slug]/ │ └── index.tsx # /articles/:slug ├── components/ # Reusable components │ └── article-card/ │ └── article-card.tsx └── lib/ # Utilities ``` ## Components ```tsx // src/components/article-card/article-card.tsx — Qwik component import { component$ } from '@builder.io/qwik'; import { Link } from '@builder.io/qwik-city'; interface Props { title: string; slug: string; excerpt: string; } export const ArticleCard = component$((props) => { return (

{props.title}

{props.excerpt}

); }); ``` ## Signals and State ```tsx // src/routes/counter/index.tsx — signals and reactivity import { component$, useSignal, useComputed$, useTask$ } from '@builder.io/qwik'; export default component$(() => { const count = useSignal(0); const doubled = useComputed$(() => count.value * 2); useTask$(({ track }) => { track(() => count.value); console.log(`Count changed to ${count.value}`); }); return (

Count: {count.value} (doubled: {doubled.value})

); }); ``` ## Data Loading with routeLoader$ ```tsx // src/routes/articles/index.tsx — server-side data loading import { component$ } from '@builder.io/qwik'; import { routeLoader$ } from '@builder.io/qwik-city'; import { ArticleCard } from '~/components/article-card/article-card'; export const useArticles = routeLoader$(async ({ env }) => { const res = await fetch(`${env.get('API_URL')}/articles`); return res.json() as Promise; }); export default component$(() => { const articles = useArticles(); return (

Articles

{articles.value.map((article) => ( ))}
); }); ``` ## Server Actions ```tsx // src/routes/articles/new/index.tsx — form with server action import { component$ } from '@builder.io/qwik'; import { routeAction$, Form, zod$, z } from '@builder.io/qwik-city'; export const useCreateArticle = routeAction$( async (data, { redirect, env }) => { const res = await fetch(`${env.get('API_URL')}/articles`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data), }); if (!res.ok) return { success: false, error: 'Failed to create' }; throw redirect(302, '/articles'); }, zod$({ title: z.string().min(1).max(200), body: z.string().min(1), }) ); export default component$(() => { const action = useCreateArticle(); return (