Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions skills/create-qwik-city-vite/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
name: create-qwik-city-vite
description: Creates a new Qwik City project with TypeScript support and installs custom AI rules.
inputs:
- id: workspace_name
name: Workspace Name
type: string
description: The name of the folder for the new project
---

## When to Use This Skill

Use this skill when the user wants to create a new Qwik City project using `create-qwik`, and wants the project configured with custom AI rules.

## Instructions

1. **Read Setup Instructions**
Review the [setup instructions](resources/setup_instructions.md) to understand how to initialize the project and install dependencies.

*Action:* Read `resources/setup_instructions.md`.

2. **Execute Setup**
Follow the steps outlined in `resources/setup_instructions.md` to:
- Create the Qwik City project (using the `workspace_name` input).
- Install dependencies.
- Create the `.agents/rules/qwik-city-vite.md` file using the content from `resources/ai_rules.md`.
- Ensure the `.agents/rules/` directory exists.

3. **Final Verification**
Check that:
- `package.json` exists in the new project.
- `.agents/rules/qwik-city-vite.md` exists.
- `src/routes/index.tsx` exists.
58 changes: 58 additions & 0 deletions skills/create-qwik-city-vite/resources/ai_rules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Gemini AI Rules for Qwik City Projects

## 1. Persona & Expertise

You are an expert front-end developer specializing in Qwik and the Qwik City meta-framework. You are highly proficient in TypeScript and building high-performance, resumable web applications. You understand:
- Qwik's component model (`component$`) and Resumability.
- Fine-grained reactivity with `useSignal()` and `useStore()`.
- Server-side data loading with `routeLoader$`.
- Server-side code execution with `server$`.
- File-system based routing.
- Secure handling of secrets and environment variables.

## 2. Project Context

This project is a Qwik City application created using `npm create qwik@latest`. It is intended to be used as a Firebase Studio (formerly Project IDX) template/workspace and is also runnable locally.

Default assumptions:
- Standard Qwik City project structure (`src/routes`, `src/components`).
- TypeScript is enabled by default.
- Vite is the development server and build tool.

## 3. Development Environment

This project is configured to run in a pre-built developer environment provided by Firebase Studio, where the environment is typically defined in `dev.nix`.

When providing instructions:
- Assume Node.js is available in the Firebase Studio environment.
- Locally, the user must have Node.js installed (version 20+ recommended).
- Running the app is done via `npm run dev` and the app is served on `http://localhost:5173`.

## 4. Coding Standards & Best Practices

### General
- Prefer TypeScript (strict typing, explicit return types for exported functions when helpful).
- Keep components small and focused.
- Avoid introducing new dependencies unless necessary.
- After suggesting new dependencies, instruct the user to run `npm install <pkg>`.

### Qwik & Qwik City Specific
- **Component Structure:** Define components with `component$()`. All code inside is potentially serializable.
- **State Management:** Use `useSignal()` for simple values (string, number, boolean) and `useStore()` for objects and arrays.
- **Data Fetching:** Use `routeLoader$` for server-side data fetching tied to a route. The data is available via a hook in the component.
- **Styling:** Use `useStylesScoped$` to define component-scoped CSS that is automatically lazy-loaded.
- **Routing:** Follow the file-based routing conventions in the `src/routes` directory.
- **Security & Secrets:**
- Never expose API keys or other secrets in client-visible code (i.e., inside `component$`).
- Use `routeLoader$` or `server$` functions to handle secrets. These functions run *only* on the server.
- Access secrets via `process.env` within these server-only functions.

## 5. Interaction Guidelines

- Provide clear, actionable steps.
- When generating code, provide complete file contents for components (`.tsx`) or routes (`routes/**/index.tsx`).
- If the request is ambiguous, ask for clarification about:
- Where state should be managed (`useSignal` vs `useStore`).
- Whether data needs to be fetched on the server (`routeLoader$`).
- Where an action should be performed (client event handler vs `server$` function).
- Keep instructions compatible with both Firebase Studio (Nix-based environment) and local setups.
68 changes: 68 additions & 0 deletions skills/create-qwik-city-vite/resources/setup_instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Qwik City Vite Workspace Setup Instructions

Follow these steps to initialize the workspace.

## 1. Install prerequisites (Node.js + npm)

This skill requires:
- Node.js (recommended 20.x+)
- npm (bundled with Node)

### 1.1 Verify
Run:
- `node -v`
- `npm -v`

If both work, go to **Step 2**.

### 1.2 Install automatically from official Node.js downloads (recommended)
Use the provided prereq installer script that:
- detects OS + CPU architecture
- fetches the latest LTS from Node’s official release index
- downloads the correct official installer/binary from nodejs.org
- installs it

Run ONE of the following depending on your OS:

#### Windows (PowerShell)
Run:
- `powershell -ExecutionPolicy Bypass -File "skills/qwik-city-vite/scripts/install_node_official.ps1"`

Then restart terminal / Antigravity session and verify:
- `node -v`
- `npm -v`

#### macOS / Linux (bash)
Run:
- `bash "skills/qwik-city-vite/scripts/install_node_official.sh"`

Then restart shell and verify:
- `node -v`
- `npm -v`

---

## 2. Create the project

Set workspace name:
- `WS_NAME="<workspace_name>"`

Then scaffold the project using the Qwik City template:

```bash
npm create qwik@latest empty "$WS_NAME"
```

## 3. Install dependencies
cd "$WS_NAME"
npm install

## 4. Configure Agent Rules

```bash
mkdir -p ".agents/rules"
cp "../skills/qwik-city-vite/resources/ai_rules.md" ".agents/rules/qwik-city-vite.md"
```

## 5. Run server
npm run dev
103 changes: 103 additions & 0 deletions skills/create-qwik-city-vite/scripts/install_node_official.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Installs the latest Node.js LTS from official nodejs.org releases (user-local install).
# - Detects CPU architecture
# - Fetches latest LTS from Node dist index.json
# - Downloads the official ZIP
# - Extracts to %LOCALAPPDATA%\Programs\nodejs\<version>
# - Adds to user PATH (no admin required)
# - Prompts to restart terminal / Antigravity

$ErrorActionPreference = "Stop"
Set-StrictMode -Version Latest

function Get-LatestLtsVersion {
$index = Invoke-RestMethod -Uri "https://nodejs.org/dist/index.json"
$lts = $index | Where-Object { $_.lts -ne $false } | Select-Object -First 1
if (-not $lts -or -not $lts.version) {
throw "Could not determine latest LTS from https://nodejs.org/dist/index.json"
}
return $lts.version # e.g., v20.11.1
}

function Get-PlatformSuffix {
$arch = $env:PROCESSOR_ARCHITECTURE
switch ($arch) {
"AMD64" { return "win-x64" }
"ARM64" { return "win-arm64" }
"x86" { return "win-x86" }
default { throw "Unsupported Windows architecture: $arch" }
}
}

function Get-MajorVersion([string]$v) {
# v like "v20.11.1"
$v = $v.Trim()
if ($v.StartsWith("v")) { $v = $v.Substring(1) }
return [int]($v.Split(".")[0])
}

# If Node already installed and >= 20, do nothing.
try {
$existing = & node -v 2>$null
if ($LASTEXITCODE -eq 0) {
$major = Get-MajorVersion $existing
if ($major -ge 20) {
Write-Host "Node is already installed ($existing). No action needed."
Write-Host "npm version: " -NoNewline; & npm -v
exit 0
}
Write-Host "Node detected ($existing) but < 20; proceeding to install latest LTS."
}
} catch {
# node not found
}

$version = Get-LatestLtsVersion
$platform = Get-PlatformSuffix
$zipName = "node-$version-$platform.zip"
$zipUrl = "https://nodejs.org/dist/$version/$zipName"

$installBase = Join-Path $env:LOCALAPPDATA "Programs\nodejs"
New-Item -ItemType Directory -Force -Path $installBase | Out-Null

$tmpDir = Join-Path $env:TEMP ("node-install-" + [guid]::NewGuid().ToString("N"))
New-Item -ItemType Directory -Force -Path $tmpDir | Out-Null
$zipPath = Join-Path $tmpDir $zipName

try {
Write-Host "Downloading $zipUrl"
Invoke-WebRequest -Uri $zipUrl -OutFile $zipPath

Write-Host "Extracting to $installBase"
Expand-Archive -Path $zipPath -DestinationPath $installBase -Force

$extractedDir = Join-Path $installBase ("node-" + $version + "-" + $platform)
if (-not (Test-Path $extractedDir)) {
throw "Extraction failed; expected folder not found: $extractedDir"
}

# Add to user PATH if not present
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
if (-not $userPath) { $userPath = "" }

$already = $userPath.Split(";") | Where-Object { $_.Trim() -ieq $extractedDir }
if (-not $already) {
$newUserPath = ($extractedDir + ";" + $userPath).TrimEnd(";")
[Environment]::SetEnvironmentVariable("Path", $newUserPath, "User")
Write-Host "Added Node to user PATH: $extractedDir"
} else {
Write-Host "Node path already present in user PATH."
}

# Also update current session PATH
$env:Path = $extractedDir + ";" + $env:Path

Write-Host "Installed Node $version"
Write-Host "Verify:"
& node -v
& npm -v

Write-Host ""
Write-Host "Restart your terminal / Antigravity session so PATH updates fully."
} finally {
if (Test-Path $tmpDir) { Remove-Item -Recurse -Force $tmpDir }
}
Loading