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.
Install
Section titled “Install”npm install @fkn/libThe library ships ESM and CJS builds with full TypeScript types. Hover any symbol in the code blocks on this site to see them.
Detect the extension
Section titled “Detect the extension”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 itselfif (function isExtensionExposed(): boolean
isExtensionExposed()) { var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
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()First gated action
Section titled “First gated action”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.
document.ParentNode.querySelector<"iframe">(selectors: "iframe"): HTMLIFrameElement | null (+4 overloads)
Returns the first element that is a descendant of node that matches selectors.
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 timeawait 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 promptconst 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.