Skip to content
Draft
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
2 changes: 1 addition & 1 deletion e2e/docs-e2e/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"name": "docs-e2e",
"description": "",
"private": true,
"author": "",
"devDependencies": {
"@playwright/test": "1.54.1",
Expand All @@ -10,6 +9,7 @@
"keywords": [],
"license": "ISC",
"main": "index.js",
"private": true,
"scripts": {
"test": "pnpm exec playwright test --config=playwright.config.ts --project=chromium",
"test-ui": "pnpm exec playwright test --config=playwright.config.ts --project=chromium --ui"
Expand Down
5 changes: 5 additions & 0 deletions e2e/docs-e2e/tests/Docs/integrations-pages-load.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ test('Integrations Drizzle page loads', async ({ page }) => {
await expect(page).toHaveTitle('Drizzle | Integrations 📚 Qwik Documentation');
});

test('Integrations Gel page loads', async ({ page }) => {
await page.goto('/docs/integrations/gel/');
await expect(page).toHaveTitle('Gel | Integrations 📚 Qwik Documentation');
});

test('Integrations Internationalization page loads', async ({ page }) => {
await page.goto('/docs/integrations/i18n/');
await expect(page).toHaveTitle('Internationalization | Integrations 📚 Qwik Documentation');
Expand Down
1 change: 1 addition & 0 deletions e2e/docs-e2e/tests/Docs/pages-load-test.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ test('docs page loads', async ({ page }) => {
'Builder.io',
'Cypress',
'Drizzle',
'Gel',
'i18n',
'Icons',
'Image Optimization',
Expand Down
8 changes: 4 additions & 4 deletions e2e/qwik-react-e2e/package.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
{
"name": "qwik-react-test-app",
"description": "Qwik react test app",
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"private": true,
"devDependencies": {
"@builder.io/qwik-react": "workspace:^",
"@types/react": "18.3.3",
"@types/react-dom": "18.3.0",
"react": "18.3.1",
"react-dom": "18.3.1"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"private": true,
"scripts": {
"build": "qwik build",
"build.client": "vite build",
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -235,17 +235,18 @@
"serve.debug": "tsx --require ./scripts/runBefore.ts --inspect-brk --conditions=development starters/dev-server.ts 3300",
"start": "pnpm run --stream \"/.*\\.watch/\"",
"test": "pnpm build.full && pnpm test.unit && pnpm test.e2e",
"test.e2e": "pnpm test.e2e.chromium && pnpm test.e2e.webkit && test.e2e.integrations",
"test.e2e": "pnpm test.e2e.chromium && pnpm test.e2e.webkit && pnpm test.e2e.integrations",
"test.e2e.chromium": "playwright test starters --browser=chromium --config starters/playwright.config.ts",
"test.e2e.chromium.debug": "PWDEBUG=1 playwright test starters --browser=chromium --config starters/playwright.config.ts",
"test.e2e.city": "playwright test starters/e2e/qwikcity --browser=chromium --config starters/playwright.config.ts",
"test.e2e.cli": "pnpm --filter qwik-cli-e2e e2e",
"test.e2e.firefox": "playwright test starters --browser=firefox --config starters/playwright.config.ts",
"test.e2e.integrations": "pnpm test.e2e.integrations.chromium && pnpm test.e2e.integrations.webkit",
"test.e2e.integrations.chromium": "playwright test e2e/adapters-e2e/tests --project=chromium --config e2e/adapters-e2e/playwright.config.ts",
"test.e2e.integrations.webkit": "playwright test e2e/adapters-e2e/tests --project=webkit --config e2e/adapters-e2e/playwright.config.ts",
"test.e2e.webkit": "playwright test starters --browser=webkit --config starters/playwright.config.ts",
"test.e2e.qwik-react.chromium": "playwright test e2e/qwik-react-e2e/tests --project=chromium --config e2e/qwik-react-e2e/playwright.config.ts",
"test.e2e.qwik-react.webkit": "playwright test e2e/qwik-react-e2e/tests --project=webkit --config e2e/qwik-react-e2e/playwright.config.ts",
"test.e2e.webkit": "playwright test starters --browser=webkit --config starters/playwright.config.ts",
"test.rust": "make test",
"test.rust.update": "make test-update",
"test.unit": "vitest packages",
Expand Down
2 changes: 1 addition & 1 deletion packages/docs/src/routes/api/qwik/api.json
Original file line number Diff line number Diff line change
Expand Up @@ -1774,7 +1774,7 @@
}
],
"kind": "Function",
"content": "> This API is provided as an alpha preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.\n> \n\n> Warning: This API is now obsolete.\n> \n> This is no longer needed as the preloading happens automatically in qrl-class.ts. Leave this in your app for a while so it uninstalls existing service workers, but don't use it for new projects.\n> \n\n\n```typescript\nPrefetchServiceWorker: (opts: {\n base?: string;\n scope?: string;\n path?: string;\n verbose?: boolean;\n fetchBundleGraph?: boolean;\n nonce?: string;\n}) => JSXNode<'script'>\n```\n\n\n<table><thead><tr><th>\n\nParameter\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\nopts\n\n\n</td><td>\n\n{ base?: string; scope?: string; path?: string; verbose?: boolean; fetchBundleGraph?: boolean; nonce?: string; }\n\n\n</td><td>\n\n\n</td></tr>\n</tbody></table>\n\n**Returns:**\n\n[JSXNode](#jsxnode)<!-- -->&lt;'script'&gt;",
"content": "> This API is provided as an alpha preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.\n> \n\n> Warning: This API is now obsolete.\n> \n> This is no longer needed as the preloading happens automatically in qrl-class.ts. Leave this in your app for a while so it uninstalls existing service workers, but don't use it for new projects.\n> \n\n\n```typescript\nPrefetchServiceWorker: (opts: {\n base?: string;\n scope?: string;\n path?: string;\n verbose?: boolean;\n fetchBundleGraph?: boolean;\n nonce?: string;\n}) => JSXNode<'script'>\n```\n\n\n<table><thead><tr><th>\n\nParameter\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\nopts\n\n\n</td><td>\n\n{ base?: string; scope?: string; path?: string; verbose?: boolean; fetchBundleGraph?: boolean; nonce?: string; }\n\n\n</td><td>\n\n\n</td></tr>\n</tbody></table>\n\n**Returns:**\n\nJSXNode&lt;'script'&gt;",
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/components/prefetch.ts",
"mdFile": "qwik.prefetchserviceworker.md"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/docs/src/routes/api/qwik/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3667,7 +3667,7 @@ opts

**Returns:**

[JSXNode](#jsxnode)&lt;'script'&gt;
JSXNode&lt;'script'&gt;

[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/components/prefetch.ts)

Expand Down
240 changes: 240 additions & 0 deletions packages/docs/src/routes/docs/integrations/gel/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
---
title: Gel | Integrations
keywords: 'Gel, EdgeDB, database, data, postgres'
contributors:
- nabrams
updated_at: '2025-10-10T18:53:23Z'
created_at: '2025-08-01T23:00:50Z'
---

import PackageManagerTabs from '~/components/package-manager-tabs/index.tsx';

# Gel Data

[GelDB](https://www.geldata.com/) Gel is a scalable, integrated data platform on top of Postgres.

Gel gives the relational model a fresh facelift, solves n+1, simplifies migrations, and streamlines your entire database workflow.

Gel can be used in Qwik with `routeLoader$`, `routeAction$` and `server$` functions. These are Qwik APIs to allow code to execute only on the server-side.

The simplest way to add Gel to your Qwik project is by running the Qwik CLI command. This will automatically install all necessary dependencies, set up a basic schema in the `dbschema` folder, and generate a `queries` directory to help you start building your own API queries. Additionally, it will scaffold an `actions` folder with example routes and files, giving you a ready-to-use foundation for working with Gel in your app.

It will also create a `gel.toml` file to configure the gel instance. Everything you need to start building your app with Gel is there.

<PackageManagerTabs>
<span q:slot="pnpm">

```shell
pnpm run qwik add gel
```
</span>
<span q:slot="npm">
```shell
npm run qwik add gel
```
</span>
<span q:slot="yarn">
```shell
yarn run qwik add gel
```
</span>
<span q:slot="bun">
```shell
bun run qwik add gel
```
</span>
</PackageManagerTabs>

> Gel is a modern data platform built on PostgreSQL that provides a unified interface for managing, querying, and scaling your data. It offers features like real-time analytics, seamless migrations, and integrated workflows to simplify database operations for developers and teams.

## Auto-generating queries

Gel lets you automatically generate queries for your database schema by using their query language EdgeQL.
It is already installed for you and you can use the following scripts to utilize it:

*** Before you start, make sure you have run the following command:
```shell
pnpm gel:generate:queries &&
pnpm gel:generate:types
```

The following `<generator>`s are currently supported:

- Command: `gel:generate:queries` >
- `queries`: Generate typed functions from *.edgeql files
- Command: `gel:generate:types` >
- `interfaces`: Generate interfaces for your schema types
- `edgeql-js`: Generate the query builder



## Gel UI

You can also use the Gel UI to view and edit your database schema, query your data, among other things.
To do so, run the following command:
<PackageManagerTabs>
<span q:slot="pnpm">

```shell
pnpm gel:ui
```
</span>
<span q:slot="npm">
```shell
npm gel:ui
```
</span>
<span q:slot="yarn">
```shell
yarn gel:ui
```
</span>
<span q:slot="bun">
```shell
bun gel:ui
```
</span>
</PackageManagerTabs>

## Client user actions

We will use these client actions to query and insert users in the DB below.

```tsx {7} /Gel/ title="src/actions/client.tsx"
import { server$ } from "@builder.io/qwik-city";
import { executeQuery } from "../../actions/client";
import * as queries from "../../../dbschema/queries";

export const getAllUsers = server$(async () => {
return await executeQuery(queries.getAllUsers);
});

export const insertUser = server$(
async (name: string, email: string, has_profile: boolean) => {
return await executeQuery(queries.insertUser, {
name: name,
email: email,
has_profile: has_profile,
});
},
);
```

## Listing users

We will use `routeLoader$` to query all users in the DB, and return the result.

```tsx {7} /Gel/ title="src/routes/users/index.tsx"

import { component$ } from "@builder.io/qwik";
import { routeLoader$ } from "@builder.io/qwik-city";
import { getAllUsers } from "../../actions/user";

export const useGetAllUsers = routeLoader$(async () => {
const users = await getAllUsers();
return users;
});

export default component$(() => {
const users = useGetAllUsers().value;

return (
<section>
<h1>Users Directory</h1>
<ul>
{Array.isArray(users) && users.length > 0 ? (
users.map((user: any) => (
<li key={user.id ?? user.name}>
<b>Name:</b> {user.name}
{user.email && (
<div style={{ marginLeft: "1rem" }}>
<span>
<b>Email:</b> {user.email}
</span>
</div>
)}
</li>
))
) : (
<li>No users found.</li>
)}
</ul>
</section>
);
});


```

## Adding users

We will use `routeAction$` and `zod$` form to create user.

```tsx {7} /Gel/ title="src/routes/users/index.tsx"

import { component$ } from "@builder.io/qwik";
import { routeAction$, zod$, z, Form } from "@builder.io/qwik-city";
import { insertUser } from "../../actions/user";

export const useCreateUser = routeAction$(
async ({ name, email }) => {
const user = await insertUser(name, email, true);
if (!user)
return { error: "A user already exists with that email.", user: null };
return { error: null, user };
},
zod$({
name: z.string().min(1, { message: "Name is required" }),
email: z.string().email({ message: "Invalid email address" }),
}),
);

export default component$(() => {
const action = useCreateUser();
const errors = action.value?.fieldErrors;
const customError = action.value?.error;

return (
<section>
<h1>Create User</h1>
<Form action={action}>
<label>
Name
<input name="name" value={action.formData?.get("name") ?? ""} />
</label>
<label>
Email
<input name="email" value={action.formData?.get("email") ?? ""} />
</label>
<button type="submit">Create</button>
</Form>
{action.value?.user && <h2>User created successfully!</h2>}
{(errors || customError) && (
<div style={{ color: "red" }}>
{errors?.name && (
<div>
<h2>{errors.name}</h2>
</div>
)}
{errors?.email && (
<div>
<h2>{errors.email}</h2>
</div>
)}
{customError && (
<div>
<h2>{customError}</h2>
</div>
)}
</div>
)}
</section>
);
});

```





1 change: 1 addition & 0 deletions packages/docs/src/routes/docs/menu.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
- [Builder.io](integrations/builderio/index.mdx)
- [Cypress](integrations/cypress/index.mdx)
- [Drizzle](integrations/drizzle/index.mdx)
- [Gel](integrations/gel/index.mdx)
- [i18n](integrations/i18n/index.mdx)
- [Icons](integrations/icons/index.mdx)
- [Image Optimization](integrations/image-optimization/index.mdx)
Expand Down
12 changes: 6 additions & 6 deletions packages/qwik/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@
"import": {
"development": "./dist/core.mjs",
"production": "./dist/core.prod.mjs",
"min": "./dist/core.min.mjs",
"default": "./dist/core.prod.mjs"
"default": "./dist/core.prod.mjs",
"min": "./dist/core.min.mjs"
},
"require": {
"development": "./dist/core.cjs",
Expand All @@ -64,8 +64,8 @@
"import": {
"development": "./dist/core.mjs",
"production": "./dist/core.prod.mjs",
"min": "./dist/core.min.mjs",
"default": "./dist/core.prod.mjs"
"default": "./dist/core.prod.mjs",
"min": "./dist/core.min.mjs"
},
"require": {
"development": "./dist/core.cjs",
Expand All @@ -78,8 +78,8 @@
"import": {
"development": "./dist/core.mjs",
"production": "./dist/core.prod.mjs",
"min": "./dist/core.min.mjs",
"default": "./dist/core.mjs"
"default": "./dist/core.mjs",
"min": "./dist/core.min.mjs"
},
"require": {
"development": "./dist/core.cjs",
Expand Down
Loading