server$()
server$() allows you to create a function that always execute on the server, making it a great place to access the DB or perform server-only actions.
server$ is a form of RPC (Remote Procedure Call) mechanism between the client and server, just like a traditional HTTP endpoint but strongly typed thanks for Typescript, and easier to maintain.
import { component$, useSignal } from '@builder.io/qwik';
import { server$ } from '@builder.io/qwik-city';
 
// By wrapping a function with `server$()` we mark it to always
// execute on the server. This is a form of RPC mechanism.
const serverGreeter = server$((firstName: string, lastName: string) => {
  const greeting = `Hello ${firstName} ${lastName}`;
  console.log('Prints in the server', greeting);
  return greeting;
});
 
export default component$(() => {
  const firstName = useSignal('');
  const lastName = useSignal('');
 
  return (
    <section>
      <label>First name: <input bind:value={firstName} /></label>
      <label>Last name: <input bind:value={lastName} /></label>
 
      <button
        onClick$={async () => {
          const greeting = await serverGreeter(firstName.value, lastName.value);
          alert(greeting);
        }}
      >
        greet
      </button>
    </section>
  );
});server$ can also read the HTTP cookies, headers, or environment variables, using this. In this case you will need to use a function instead of an arrow function.
// Notice that the wrapped function is declared as a `async function`
const addUser = server$(async function(id: number, fullName: string, address: Address) {
  // The `this` is the `RequestEvent` object, which contains
  // the HTTP headers, cookies, and environment variables.
  const db = createClient(this.env.get('DB_KEY'));
  if (this.cookie.get('user-session')) {
    await db.from('users').insert({
      id,
      fullName,
      address
    });
    return {
      success: true,
    }
  }
  return {
    success: false,
  }
})Server$ can accept any number of arguments and return any value that can be serialized by Qwik, that includes primitives, objects, arrays, bigint, JSX nodes and even Promises, just to name a few.
Streaming responses
server$ can return a stream of data by using an async generator. This is useful for streaming data from the server to the client.
import { component$, useSignal } from '@builder.io/qwik';
import { server$ } from '@builder.io/qwik-city';
 
const stream = server$(async function* () {
  for (let i = 0; i < 10; i++) {
    yield i;
    await new Promise((resolve) => setTimeout(resolve, 1000));
  }
});
 
export default component$(() => {
  const message = useSignal('');
  return (
    <div>
      <button
        onClick$={async () => {
          const response = await stream();
          for await (const i of response) {
            message.value += ` ${i}`;
          }
        }}
      >
        start
      </button>
      <div>{message.value}</div>
    </div>
  );
});This API is actually used to implement QwikGPT streaming responses in our docs site.
How does server$() work?
Un server$() wraps a function and returns an async proxy to the function. On the server, the proxy function directly calls the wrapped function, and a HTTP endpoint is automatically created by the server$() function.
On the client, the proxy function invokes the wrapped function via an HTTP request, using fetch().
Note: The
server$()function must ensure that the server and client have the same version of the code executing. If there is a version skew the behavior is undefined and may result in an error. If version skew is a common problem then a more formal RPC mechanism should be used such as a tRPC or other library.



