Skip to content
Skillv1.0.0

qwik

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

by terminalskills(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from terminalskills/skills (skills/qwik/SKILL.md). Install upstream with npx skills add terminalskills/skills --skill qwik. Copyright stays with the author (Apache-2.0).

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

# 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

// 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>((props) => {
  return (
    <article>
      <Link href={`/articles/${props.slug}`}>
        <h2>{props.title}</h2>
      </Link>
      <p>{props.excerpt}</p>
    </article>
  );
});

Signals and State

// 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 (
    <div>
      <p>Count: {count.value} (doubled: {doubled.value})</p>
      <button onClick$={() => count.value++}>+1</button>
    </div>
  );
});

Data Loading with routeLoader$

// 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<Article[]>;
});

export default component$(() => {
  const articles = useArticles();

  return (
    <div>
      <h1>Articles</h1>
      {articles.value.map((article) => (
        <ArticleCard key={article.id} title={article.title} slug={article.slug} excerpt={article.excerpt} />
      ))}
    </div>
  );
});

Server Actions

// 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 (
    <Form action={action}>
      <input name="title" placeholder="Title" required />
      <textarea name="body" placeholder="Body" required />
      <button type="submit">Create</button>
      {action.value?.error && <p>{action.value.error}</p>}
    </Form>
  );
});

Layouts

// src/routes/layout.tsx — root layout
import { component$, Slot } from '@builder.io/qwik';
import { Link } from '@builder.io/qwik-city';

export default component$(() => {
  return (
    <div>
      <header>
        <nav>
          <Link href="/">Home</Link>
          <Link href="/articles">Articles</Link>
        </nav>
      </header>
      <main>
        <Slot />
      </main>
    </div>
  );
});

Middleware

// src/routes/admin/layout.tsx — auth middleware via onRequest
import { type RequestHandler } from '@builder.io/qwik-city';

export const onRequest: RequestHandler = async ({ cookie, redirect }) => {
  const token = cookie.get('session')?.value;
  if (!token) throw redirect(302, '/login');
};

useStore for Complex State

// src/routes/dashboard/index.tsx — store for nested reactive state
import { component$, useStore, $ } from '@builder.io/qwik';

export default component$(() => {
  const state = useStore({
    articles: [] as Article[],
    filter: '',
    loading: false,
  });

  const fetchArticles = $(async () => {
    state.loading = true;
    const res = await fetch('/api/articles');
    state.articles = await res.json();
    state.loading = false;
  });

  return (
    <div>
      <button onClick$={fetchArticles}>Load</button>
      <input bind:value={state.filter} placeholder="Filter..." />
      {state.loading ? <p>Loading...</p> : (
        state.articles
          .filter((a) => a.title.includes(state.filter))
          .map((a) => <div key={a.id}>{a.title}</div>)
      )}
    </div>
  );
});

Deployment

# Add deployment adapter
npm run qwik add cloudflare-pages  # or: vercel, netlify, node-server, deno
npm run build
npm run deploy

Key Patterns

  • Use $ suffix on functions (onClick$, component$, routeLoader$) — it marks serialization boundaries
  • Use useSignal for primitives, useStore for objects — similar to Solid's signal/store split
  • routeLoader$ runs on the server during SSR — data is serialized into HTML
  • routeAction$ handles form submissions server-side with Zod validation
  • JavaScript loads lazily per interaction — no hydration step
  • Use onRequest handlers in layouts for server-side middleware (auth, redirects)
  • Deploy anywhere: Cloudflare, Vercel, Netlify, Deno, Node — via adapters

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/terminalskills-skills-qwik/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

terminalskills-skills-qwik.ocm.jsonjson
{
  "ocm": "1",
  "id": "terminalskills-skills-qwik",
  "kind": "skill",
  "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.",
  "publisher": "terminalskills",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "coding"
    ],
    "tags": [
      "skill-md",
      "typescript",
      "frontend",
      "ssr",
      "resumable",
      "edge",
      "performance",
      "skills-sh"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "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."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "skills.sh",
      "repository": "https://github.com/terminalskills/skills",
      "path": "skills/qwik/SKILL.md",
      "ref": "HEAD",
      "url": "https://github.com/terminalskills/skills/blob/HEAD/skills/qwik/SKILL.md",
      "key": "terminalskills/skills/skills/qwik/SKILL.md"
    },
    "compatibility": "node >= 18, npm or yarn or pnpm",
    "license": "Apache-2.0"
  },
  "instructions": "# Qwik\n\nQwik 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.\n\n## Installation\n\n```bash\n# Create Qwik project with Qwik City (meta-framework)\nnpm create qwik@latest\ncd my-app\nnpm install\nnpm run dev\n```\n\n## Project Structure\n\n```\n# Qwik City project layout\nsrc/\n├── entry.ssr.tsx         # SSR entry\n├── root.tsx              # Root component\n├── global.css\n├── routes/               # File-based routing\n│   ├── layout.tsx        # Root layout\n│ ",
  "cost": {
    "context_tokens": 1516
  }
}

Fetch it by URL: GET /api/v1/registry/terminalskills-skills-qwik/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.