# Using other packages

Any package your app ships, in a screen: createImport, versions, and the three places a package goes.

```ts title="server/expo.ts"
import { createImport } from "@backtickjs/core";
import type { impactAsync as ImpactAsync } from "expo-haptics";
import type { LinearGradient as ExpoLinearGradient } from "expo-linear-gradient";

// What the app provides from these packages, typed as the packages type
// them, for any script to splice.
export const impactAsync = createImport<typeof ImpactAsync>({
  name: "impactAsync",
  from: "expo-haptics",
  version: "~57.0.0",
});

export const LinearGradient = createImport<typeof ExpoLinearGradient>({
  name: "LinearGradient",
  from: "expo-linear-gradient",
  version: "~57.0.0",
});
```

A screen can use any package your app ships. `createImport` names an export of
a package, typed as the package types it, and splices like anything else:
`$impactAsync()`, `<$LinearGradient>`.

## Three places, one package

A package a screen uses has to be in all three places:

**1. The screen:** spliced, as any value or component:

```tsx title="server/Home.tsx"
import { cs } from "@backtickjs/core";
import { Pressable, Text } from "@backtickjs/react-native";
import { impactAsync, LinearGradient } from "./expo.js";

export async function Home() {
  return cs`(
    <$LinearGradient
      colors={["#7c3aed", "#0891b2"]}
      style={{ flex: 1, padding: 24 }}
    >
      <$Pressable onPress={() => $impactAsync()}>
        <$Text style={{ color: "#fff", fontSize: 24 }}>Tap to feel it</$Text>
      </$Pressable>
    </$LinearGradient>
  )`;
}
```

**2. Your server:** the versions the app provides, for the bundler to check
against each import's range:

```tsx title="server/index.tsx"
import { createServer } from "node:http";
import { createRequire } from "node:module";
import { bundler } from "@backtickjs/bundler";
import { Home } from "./Home.js";

// The packages the app provides to screens, each at the version it's built
// with.
const require = createRequire(import.meta.url);
const packageVersions = {
  react: require("react/package.json").version,
  "react-native": require("react-native/package.json").version,
  "expo-haptics": require("expo-haptics/package.json").version,
  "expo-linear-gradient": require("expo-linear-gradient/package.json").version,
};

createServer(async (request, response) => {
  const bundle = await bundler.build({ input: <Home />, packageVersions });
  response.setHeader("content-type", "text/javascript");
  response.end(bundle.generate({ format: "cjs" }).code);
}).listen(3000);
```

**3. Your app:** the modules a screen may require, handed to `evaluate`:

```tsx title="App.tsx"
import { evaluate } from "@backtickjs/react-native-client";
import * as ExpoHaptics from "expo-haptics";
import * as ExpoLinearGradient from "expo-linear-gradient";
import * as React from "react";
import * as JSXRuntime from "react/jsx-runtime";
import * as ReactNative from "react-native";

// What a screen may require: the packages this app was built with.
export const modules = {
  react: React,
  "react/jsx-runtime": JSXRuntime,
  "react-native": ReactNative,
  "expo-haptics": ExpoHaptics,
  "expo-linear-gradient": ExpoLinearGradient,
};

export async function fetchScreen(url: string): Promise<React.ReactNode> {
  const response = await fetch(url);
  return evaluate(await response.text(), modules) as React.ReactNode;
}
```

Install the package in your app as usual, `npx expo install expo-haptics`, so
it's built into the app and its native code ships with it.

## Versions are checked

`createImport`'s `version` is the range of the package that the export works
with. When the bundle is built, the bundler checks it against what your server
says the app provides, and refuses a screen the app can't run:

```text
Can't import `impactAsync` from "expo-haptics": the client provides react@19.2.3, react-native@0.86.3.
Can't import `impactAsync` from "expo-haptics": it needs expo-haptics@~57.0.0, and the client provides expo-haptics@58.0.1.
```

The first is a package missing from `packageVersions`; the second, an app built
with a version outside the range. Serving apps of several versions, give each
its own `packageVersions`, and each gets a screen it can run.
