Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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
3 changes: 1 addition & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ If you run into a bug, please post an issue in this [repo](https://github.com/sp

### Create Framework Integrations

Since ForesightJS is framework agnostic, we welcome integrations for popular frameworks and routers. We already have Next.js and React Router integrations, but would love to see:
Since ForesightJS is framework agnostic, we welcome integrations for popular frameworks and routers. We already have official React, Vue, and Angular packages plus Next.js and React Router examples, but would love to see:

- Angular integration
- Svelte integration
- Other popular frameworks or routers

Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,16 @@ _In the GIF above, the [ForesightJS DevTools](https://foresightjs.com/docs/debug

## Integrations

Since ForesightJS is framework agnostic, it can be integrated with any JavaScript framework. There are official packages for React and Vue:
Since ForesightJS is framework agnostic, it can be integrated with any JavaScript framework. There are official packages for React, Vue, and Angular:

- **JavaScript** → [`js.foresight`](https://foresightjs.com/docs/getting-started/quick-start): the framework-agnostic core, usable in any project.
- **React** → [`@foresightjs/react`](https://foresightjs.com/docs/react/installation): `useForesight`, the `Foresight` component, `useForesightEvent`, plus [Next.js](https://foresightjs.com/docs/react/nextjs) and [React Router](https://foresightjs.com/docs/react/react-router) examples.
- **Vue** → [`@foresightjs/vue`](https://foresightjs.com/docs/vue/quick-start): the `v-foresight` directive, the `Foresight` component, and the `useForesight` / `useForesightEvent` composables.
- **Angular** → [`@foresightjs/angular`](https://foresightjs.com/docs/angular/installation): the `[fsForesight]` directive, `ForesightService`, `ForesightComponent`, and `injectForesightEvent`.

> **Note:** The `@foresightjs/react` and `@foresightjs/vue` packages are in beta and not yet stable. They work and are fully tested, but the API may still change.
> **Note:** The `@foresightjs/react`, `@foresightjs/vue`, and `@foresightjs/angular` packages are in beta and not yet stable. They work and are fully tested, but the API may still change.

Using another framework (Angular, Svelte, Solid, )? See [Other Frameworks](https://foresightjs.com/docs/other-frameworks) for how to build your own thin binding on top of the core. Sharing integrations for other frameworks/packages is highly appreciated!
Using another framework (Svelte, Solid, etc.)? See [Other Frameworks](https://foresightjs.com/docs/other-frameworks) for how to build your own thin binding on top of the core. Sharing integrations for other frameworks/packages is highly appreciated!

## Configuration

Expand Down
6 changes: 6 additions & 0 deletions packages/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ Official Vue 3 bindings: the `v-foresight` directive, the `useForesight` and `us

**Published as:** `@foresightjs/vue` on npm

### [foresightjs-angular](./foresightjs-angular/)

Official Angular bindings: the `[fsForesight]` directive, `ForesightService`, `injectForesightEvent`, and the `ForesightComponent` wrapper.

**Published as:** `@foresightjs/angular` on npm

## Development Packages

### [devpage-framework](./devpage-framework/) · [devpage-nextjs](./devpage-nextjs/)
Expand Down
17 changes: 17 additions & 0 deletions packages/docs/docs/_partials/_ai-context.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,20 @@ All documentation pages are available as markdown by adding `.md` to any URL:
- `https://foresightjs.com/docs/vue/migrating-to-v4.md`
- `https://foresightjs.com/docs/vue/behind-the-scenes.md`
- `https://foresightjs.com/docs/vue/ai-context.md`
- `https://foresightjs.com/docs/angular/what-is-foresightjs.md`
- `https://foresightjs.com/docs/angular/installation.md`
- `https://foresightjs.com/docs/angular/initialize-the-manager.md`
- `https://foresightjs.com/docs/angular/quick-start.md`
- `https://foresightjs.com/docs/angular/typescript.md`
- `https://foresightjs.com/docs/angular/directive.md`
- `https://foresightjs.com/docs/angular/foresight-service.md`
- `https://foresightjs.com/docs/angular/foresight-component.md`
- `https://foresightjs.com/docs/angular/injectForesightEvent.md`
- `https://foresightjs.com/docs/angular/configuration/global-settings.md`
- `https://foresightjs.com/docs/angular/configuration/registration-options.md`
- `https://foresightjs.com/docs/angular/events.md`
- `https://foresightjs.com/docs/angular/devtools.md`
- `https://foresightjs.com/docs/angular/static-properties.md`
- `https://foresightjs.com/docs/angular/migrating-to-v4.md`
- `https://foresightjs.com/docs/angular/behind-the-scenes.md`
- `https://foresightjs.com/docs/angular/ai-context.md`
2 changes: 1 addition & 1 deletion packages/docs/docs/_partials/_static-properties.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ ForesightManager.instance.reactivate(navLinks)
Removes an element (or all elements in a `NodeList`) from ForesightManager's tracking.

:::tip Frameworks handle this for you
The official React and Vue integrations call `unregister` automatically when a component unmounts, so you rarely call it yourself there.
The official React, Vue, and Angular integrations call `unregister` automatically when a component unmounts, so you rarely call it yourself there.

Detaching an element from the DOM does **not** unregister it. It is parked (kept registered but inactive) and resumes when it reattaches, so it survives detach/reattach and re-parenting. Unregistering only happens when you call this method explicitly.

Expand Down
4 changes: 2 additions & 2 deletions packages/docs/docs/_partials/_typescript.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,9 @@ const myCallback: ForesightCallback = state => {

### ForesightRegisterOptionsWithoutElement

Useful for if you want to create a custom button component in a modern framework (for example React). And you want to have the `ForesightRegisterOptions` used in `ForesightManager.instance.register({})` without the element as the element will be the ref of the component.
Useful for if you want to create a custom button component in a modern framework. And you want to have the `ForesightRegisterOptions` used in `ForesightManager.instance.register({})` without the element as the element will be the ref of the component.

This type is the options object you pass to the [`useForesight`](../react/useForesight.md) hook in React and the [`useForesight`](../vue/useForesight.md) composable in Vue.
This type is the options object you pass to the [`useForesight`](../react/useForesight.md) hook in React, the [`useForesight`](../vue/useForesight.md) composable in Vue, and Angular's [`[fsForesight]`](../angular/directive.md) / [`ForesightService`](../angular/foresight-service.md) APIs.

```typescript
type ForesightButtonProps = {
Expand Down
19 changes: 19 additions & 0 deletions packages/docs/docs/angular/ai-context.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
keywords:
- ForesightJS
- Angular
- AI context
- LLM context
- llms.txt
- documentation
description: How to use ForesightJS's llms.txt file with AI tools and LLMs
last_updated:
date: 2026-06-26
author: Bart Spaans
---

import AiContext from "../_partials/_ai-context.mdx"

# AI Context

<AiContext />
20 changes: 20 additions & 0 deletions packages/docs/docs/angular/behind-the-scenes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
keywords:
- ForesightJS
- JS.Foresight
- Angular
- user intent prediction
- mouse prediction
- tab prediction
- internal architecture
description: A technical deep-dive into the internal workings of ForesightJS, explaining its architecture, how it predicts mouse movements, and how it predicts tab navigation.
last_updated:
date: 2026-06-26
author: Bart Spaans
---

import BehindTheScenes from "../_partials/_behind-the-scenes.mdx"

# Behind the Scenes

<BehindTheScenes />
22 changes: 22 additions & 0 deletions packages/docs/docs/angular/configuration/global-settings.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
keywords:
- ForesightJS
- JS.Foresight
- Angular
- "@foresightjs/angular"
- configuration
- global settings
- ForesightManager
description: Configure global ForesightJS settings in an Angular app
last_updated:
date: 2026-06-26
author: Bart Spaans
---

import GlobalSettings from "../../_partials/_global-settings.mdx"

# Global Settings

Global settings apply to all registered elements and are configured once via `ForesightManager.initialize()` at your app's entry point. Import `ForesightManager` from `@foresightjs/angular`.

<GlobalSettings />
55 changes: 55 additions & 0 deletions packages/docs/docs/angular/configuration/registration-options.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
keywords:
- ForesightJS
- JS.Foresight
- Angular
- "@foresightjs/angular"
- element configuration
- registration options
- hitSlop
- element metadata
description: The options you pass to the fsForesight directive, ForesightService, and ForesightComponent
last_updated:
date: 2026-06-26
author: Bart Spaans
---

import ElementSettings from "../../_partials/_registration-options.mdx"

# Registration Options

In Angular, registration options are what you pass to the [`[fsForesight]`](../directive.md) directive, [`ForesightService.register`](../foresight-service.md), or [`ForesightComponent`](../foresight-component.md). The directive, service, or component takes care of the element, so there is no `element` option. `callback` is the only required field.

```ts
import { Component } from "@angular/core"
import { ForesightDirective } from "@foresightjs/angular"

@Component({
standalone: true,
imports: [ForesightDirective],
template: `
<a
href="/about"
[fsForesight]="{
callback: prefetchAbout,
hitSlop: 50,
name: 'about-link',
meta: { route: '/about' },
reactivateAfter: 5 * 60 * 1000,
enabled: true
}"
>
About
</a>
`,
})
export class AboutLinkComponent {
readonly prefetchAbout = () => {
void fetch("/api/about")
}
}
```

When options change, the Angular integration patches the existing registration in place.

<ElementSettings />
21 changes: 21 additions & 0 deletions packages/docs/docs/angular/devtools.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
keywords:
- ForesightJS
- JS.Foresight
- Angular
- ForesightDevtools
- js.foresight-devtools
- Debugger
description: Use the ForesightJS development tools in an Angular app
last_updated:
date: 2026-06-26
author: Bart Spaans
---

import Devtools from "../_partials/_devtools.mdx"

# Development Tools

The `ForesightJS` development tools are framework agnostic and work the same in Angular as anywhere else; initialize them once next to your `ForesightManager.initialize` call.

<Devtools />
98 changes: 98 additions & 0 deletions packages/docs/docs/angular/directive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
---
sidebar_position: 2
keywords:
- ForesightJS
- JS.Foresight
- Prefetching
- Angular
- Directive
- fsForesight
- "@foresightjs/angular"
description: The fsForesight Angular directive from @foresightjs/angular
last_updated:
date: 2026-06-26
author: Bart Spaans
---

# fsForesight

`[fsForesight]` is the simplest way to add predictive callbacks to an Angular app. Put it on an element, give it a callback or an options object, and it registers, updates, and unregisters the element for you.

## Import the directive

`ForesightDirective` is standalone, so import it directly in the component that uses it:

```ts
import { Component } from "@angular/core"
import { ForesightDirective } from "@foresightjs/angular"

@Component({
standalone: true,
imports: [ForesightDirective],
template: `<button [fsForesight]="prefetch">Prefetch</button>`,
})
export class ExampleComponent {
readonly prefetch = () => {
void fetch("/api/example")
}
}
```

## Callback shorthand

```html
<button [fsForesight]="handlePrefetch">Hover to prefetch</button>
```

The callback receives the element's [`ForesightElementState`](./configuration/registration-options.md#state-fields).

## With options

For more control, pass any [registration options](./configuration/registration-options.md):

```html
<button
[fsForesight]="{
callback: handlePrefetch,
hitSlop: { top: 20, bottom: 20, left: 20, right: 20 },
name: 'button-with-options',
reactivateAfter: 3000,
enabled: isEnabled()
}"
>
Hover to prefetch
</button>
```

If the bound value changes, the directive patches the existing registration in place rather than tearing it down, so flipping `enabled` or changing `hitSlop` keeps the same element tracked.

## Individual inputs

You can also pass common options through inputs:

```html
<a
href="/docs"
[fsForesight]="prefetchDocs"
fsForesightName="docs-link"
[fsForesightHitSlop]="40"
[fsForesightMeta]="{ route: '/docs' }"
[fsForesightEnabled]="isDocsEnabled()"
>
Docs
</a>
```

Object options and individual inputs are resolved into the same registration options. If you need a native `name` attribute, use `fsForesightName` for the Foresight debug name.

## Reading state

The directive exports itself as `foresight`:

```html
<button [fsForesight]="prefetch" #foresight="foresight">
{{ foresight.state().isCallbackRunning ? "Prefetching" : "Checkout" }}
</button>
```

`state` is an Angular signal containing the latest immutable [`ForesightElementState`](./configuration/registration-options.md#state-fields).
47 changes: 47 additions & 0 deletions packages/docs/docs/angular/events.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
keywords:
- ForesightJS
- JS.Foresight
- Angular
- Events
- Foresight Events
- injectForesightEvent
description: Listen to the built-in ForesightJS events from Angular
last_updated:
date: 2026-06-26
author: Bart Spaans
---

import Events from "../_partials/_events.mdx"

# Events

ForesightManager emits events to provide insight into element registration, prediction activity, and callback execution. These events are primarily used by the [ForesightJS DevTools](./devtools.md), but can also power telemetry, analytics, and counters in your Angular app.

## Usage

In Angular the easiest way to listen to events from a component, directive, or injectable context is [`injectForesightEvent`](./injectForesightEvent.md):

```ts
import { Component, signal } from "@angular/core"
import { injectForesightEvent } from "@foresightjs/angular"

@Component({
selector: "app-prefetch-counter",
standalone: true,
template: `<p>{{ hits() }} prefetches triggered</p>`,
})
export class PrefetchCounterComponent {
readonly hits = signal(0)

constructor() {
injectForesightEvent("callbackInvoked", () => {
this.hits.update(count => count + 1)
})
}
}
```

The standard `ForesightManager.instance.addEventListener` / `removeEventListener` pattern is also available if you want to listen outside Angular.

<Events />
Loading