Skip to content

Script setup and first mount ​

Runnable exampleOpen this chapter in the browser

This page runs the same Vanilla JS source as the local fixture. Model requests go through a server-side gateway; provider keys stay out of the browser.

Run locallypnpm tutorial:dev j-02 --locale enSourceexamples/tutorials/j-02-script-setup/

This chapter adds Pling to a page that already has HTML and JavaScript. The page keeps its own markup and event handlers. The integration creates one runtime and mounts the assistant; it deliberately declares no page actions.

The empty action list matters. Before a page owner exposes a control, the agent should not be able to guess one from the DOM.

Install the adapter ​

Install the Vanilla package:

Package managerCommand
pnpmpnpm add @plingjs/vanilla
npmnpm install @plingjs/vanilla
Yarnyarn add @plingjs/vanilla

The package brings in the framework-neutral runtime, DOM execution layer, agent loop, and dock UI. The dock injects its own styles. If the application already ships a large global stylesheet, check for fixed-position overlap rather than trying to merge all component styles.

Create the runtime once ​

Create the runtime near the application's boot code:

ts
import { createPling } from "@plingjs/vanilla";

const root = document.querySelector<HTMLElement>("#app");
if (!root) throw new Error("Missing #app mount point");

const pling = createPling();

pling.dock({ title: "Page assistant" });

The runtime owns the registry for this page. pling.dock() mounts the launcher and conversation panel. Calling either repeatedly creates extra registries or extra assistant entries, so keep this at a single page-level entry point.

If a page is a multi-page application and the script is re-executed per navigation, destroy the previous runtime before creating another. That is a later continuity topic; for this chapter, use one document and one runtime.

Keep the page as it was ​

The fixture starts with ordinary HTML:

html
<main class="page">
  <section class="setup">
    <h1>Connected. Nothing exposed yet.</h1>
    <ol class="checks">...</ol>
  </section>
</main>

The JavaScript fills the existing mount point and attaches any existing event listeners. Pling does not need to create the page tree or own the state. That remains true when the page is server-rendered or built by another tool.

Configure the model ​

In a Vite project, use the shared development variables:

bash
VITE_AGENT_BASE_URL=https://api.example.com/v1
VITE_AGENT_MODEL=chat-model
VITE_AGENT_API_KEY=replace-with-a-development-key

Restart the development server after changing .env.local. For a page built without Vite, pass the same values explicitly:

ts
const pling = createPling({
  agent: {
    config: {
      baseUrl: "https://api.example.com/v1",
      model: "chat-model",
      apiKey: "replace-with-a-development-key",
    },
  },
});

These values are visible in the browser. Development direct access is not a production secret model. For production, use a same-origin gateway and keep credentials on the server.

If the model provider blocks browser access, configure a Vite proxy and point the browser at the local path:

bash
VITE_AGENT_BASE_URL=/llm/v1
VITE_AGENT_MODEL=chat-model
VITE_AGENT_API_KEY=replace-with-a-development-key
VITE_AGENT_PROXY_TARGET=https://api.example.com

Run the example ​

The source is in examples/tutorials/j-02-script-setup/. From a repository checkout:

bash
git clone https://github.com/plingjs/pling.git
cd pling
pnpm install
pnpm tutorial:dev j-02

Open http://127.0.0.1:5240/. For Chinese, run pnpm tutorial:dev j-02 --locale zh and open http://127.0.0.1:5240/?lang=zh.

Check:

  1. The original page and its four checks render.
  2. The assistant launcher appears.
  3. A configured model can answer a question.
  4. The registry still has zero actions and zero records.
  5. There is no DOM mutation caused merely by mounting Pling, other than the assistant host.

Common failures ​

SymptomLikely causeCheck
createPling is not definedThe module was not imported or the script failed earlierInspect the module import and browser console
The launcher is absentpling.dock() was not called or the script threw before itCheck the mount order and the console
Two launchers appearThe boot script ran twiceKeep one runtime per document; destroy it on teardown
The model cannot answerNo base URL/model/keyUse .env.local or explicit agent.config
The assistant sees no actionsNothing has been declaredExpected in this chapter
Styles conflict with the host pageThe page has broad global CSS or fixed controlsScope host styles and check the lower-right viewport

Next step ​

The next chapter adds the first business declarations. It will attach a scope to the task module, records to rows, a fill action to the input, a submit action to the form button, and a completion action to each row. The existing DOM and event handlers stay intact.

Continue with Quick start: add Pling to a vanilla page.