Skip to content

Getting started

The extension APIs in @fkn/lib let your web app operate on embedded pages through the FKN browser extension. Nothing here requires an FKN account or any server-side setup: the library talks to the extension running in the user’s browser, and the user approves each capability your app asks for.

Terminal window
npm install @fkn/lib

The library ships ESM and CJS builds with full TypeScript types. Hover any symbol in the code blocks on this site to see them.

The extension announces itself to every page. Check for it before using any extension-backed API:

import {
const isExtensionExposed: () => boolean
isExtensionExposed
,
const waitForExtensionExposure: (timeout?: number) => Promise<void>
waitForExtensionExposure
} from '@fkn/lib'
// Synchronous check, true once the content script has announced itself
if (
function isExtensionExposed(): boolean
isExtensionExposed
()) {
var console: Console
console
.
Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
('FKN extension is here')
}
// Or wait for it (resolves when exposed, rejects when it is not installed)
await
function waitForExtensionExposure(timeout?: number): Promise<void>
waitForExtensionExposure
()

When the extension is missing you can route the user to an install flow:

import {
const promptInstall: (reason?: string) => Promise<boolean>
promptInstall
} from '@fkn/lib'
await
function promptInstall(reason?: string): Promise<boolean>
promptInstall
()

Attach an iframe your page embeds, then drive it with locators. The first sensitive action triggers the FKN consent prompt; the user decides once, for the session, or always.

import {
const attachFrame: ({ iframe, domains }: AttachFrameOptions) => Promise<Frame>
attachFrame
,
const waitForExtensionExposure: (timeout?: number) => Promise<void>
waitForExtensionExposure
} from '@fkn/lib'
await
function waitForExtensionExposure(timeout?: number): Promise<void>
waitForExtensionExposure
()
const
const iframe: HTMLIFrameElement
iframe
=
var document: Document

window.document returns a reference to the document contained in the window.

MDN Reference

document
.
ParentNode.querySelector<"iframe">(selectors: "iframe"): HTMLIFrameElement | null (+4 overloads)

Returns the first element that is a descendant of node that matches selectors.

MDN Reference

querySelector
('iframe')!
const
const frame: Frame
frame
= await
function attachFrame({ iframe, domains }: AttachFrameOptions): Promise<Frame>
attachFrame
({
iframe: HTMLIFrameElement
iframe
})
// The user sees a consent prompt for "act on the page" the first time
await
const frame: Frame
frame
.
locator: (selector: string) => Locator
locator
('.controls').
locator: (selector: string) => Locator
locator
('#play').
click: (options?: (OperationTimeoutOptions & {
position?: {
x?: number | undefined;
y?: number | undefined;
} | undefined;
}) | undefined) => Promise<void>
click
()
// Reading is a separate capability with its own prompt
const
const title: string
title
= await
const frame: Frame
frame
.
locator: (selector: string) => Locator
locator
('h1').
textContent: (_options?: OperationTimeoutOptions | undefined) => Promise<string>
textContent
()

Continue with attachFrame() for the full reference, or try everything live in the playground.