autoInstall() — one-line install
Zero-config on-ramp. Returns a fully-constructed DotDotDuck with sensible defaults so you can see the SDK working before deciding what to configure.
Minimum
import { autoInstall } from '@perhapxin/dddk';
import '@perhapxin/dddk/styles.css';
const dddk = autoInstall();
That's it. You get:
- Command palette wired to
Ctrl+K/⌘K. - Subtitle bar mounted center-bottom.
- Dwell long-press detector.
- FAB mascot in the bottom-right corner on desktop and mobile (v0.2.3+ —
fab.alwaysVisible: trueis the autoInstall default). A MobileTrigger is auto-attached. - HERO greeting on first visit — the FAB morphs into a horizontal capsule with a bilingual title + "Tap me → palette" and "Hold me → talk" action rows + keyboard hint (desktop only). Session-storage-gated so returning visitors aren't nagged.
- All seven default duck sprites loaded — sprite URLs resolved via
import.meta.urlat construction time (v0.2.3+), so Dwell swim / cursor / palette footer icon all show correctly on subdirectory hosts + non-Vite setups too. - Locale auto-detected:
zh/zh-*→'zh-TW', everything else →'en'. - SDK-shipped prompt defaults registered on
dddk.prompts. - A demo LLM that responds to any completion with a "wire your real provider" nudge — so agent / InlineAgent / voice-cleanup don't silently no-op; the user sees why nothing is happening.
Passing overrides
Every field of DotDotDuckConfig is accepted verbatim, plus one factory-specific flag (demoLLM).
const dddk = autoInstall({
llm: myOpenAIProvider, // real LLM replaces the demo stub
siteName: 'Acme',
agentName: 'Rex',
paletteCommands: myCommands,
brand: { voice: 'friendly' },
webAgent: {
contextProvider: () => ({ tenant: currentTenant() }),
},
});
autoInstall(overrides) and new DotDotDuck({ ...factoryDefaults, ...overrides }) are functionally equivalent — the factory just picks the defaults. Anything you don't override keeps the demo default.
Disabling the demo LLM
By default, if you don't pass llm, autoInstall wires a demo stub. To keep the old "silent no-op if no LLM" behaviour (matches raw new DotDotDuck({})), set demoLLM: false:
const dddk = autoInstall({ demoLLM: false });
// Palette + Dwell + FAB still mount; agent-side features silently
// no-op until an `llm` gets wired at runtime.
Useful when your LLM provider is async-loaded (e.g. behind auth) and you want the SDK up before it's ready.
Full option type
interface AutoInstallOptions extends Partial<DotDotDuckConfig> {
/**
* When true and no `llm` is provided, wire a demo LLM. Default: true.
*/
demoLLM?: boolean;
/**
* MobileTrigger config. v0.2.3+ auto-attaches a MobileTrigger with
* `fab.alwaysVisible: true` (desktop shows the FAB too) + the built-in
* bilingual HERO greeting. Pass `false` to skip auto-attach entirely;
* pass a partial config to override any field.
*/
mobile?: MobileTriggerConfig | false;
/**
* Sprite URL overrides. v0.2.3+ resolves default sprite URLs from
* `import.meta.url` at install time. Pass a per-key override to swap
* one for your brand.
*/
sprites?: {
avatar?: string; swim?: string; hero?: string;
chill?: string; swimCycle?: string; brandMark?: string;
cursor?: string;
};
/**
* HERO greeting override. Convenience alias for
* `mobile.heroGreeting`. `mobile.heroGreeting` takes precedence if
* both are set.
*/
heroGreeting?: HeroGreetingConfig | false;
}
Return type: DotDotDuck. Same instance you'd get from new DotDotDuck(...). All methods (startAgent, runSkill, submitSurface, etc.) are available.
Examples
// Disable the FAB entirely (host mounts their own trigger):
autoInstall({ mobile: false });
// Position the FAB bottom-left instead of bottom-right:
autoInstall({ mobile: { fab: { position: 'bottom-left' } } });
// Swap the mascot for your brand character:
autoInstall({
sprites: {
avatar: '/my-brand/mascot.png',
swim: '/my-brand/mascot-side.png',
// brand-mark left as default → keeps the dotdotduck logo on the
// palette footer's "Powered by" strip.
},
});
// Custom greeting title, keep everything else default:
autoInstall({
heroGreeting: {
title: { en: "Hi! I'm Rex", 'zh-TW': '嗨!我是 Rex' },
},
});
// Disable the greeting auto-fire on first visit:
autoInstall({ heroGreeting: false });
When NOT to use autoInstall
- You already wire every config field explicitly. Migrating to
autoInstall({...})would just move code around — no benefit. - You need SSR-safe initialisation.
autoInstallreadsnavigator.languageat construction time, so it can't run on the server. Call it insideonMount(Svelte) /useEffect(React) /mounted(Vue). - You want the demo LLM to be permanent. The demo LLM is intentionally hostile-to-real-use — its response tells the user to wire a real provider. If your product legitimately doesn't need an LLM, pass
demoLLM: falseand skip the pill.
Common integration patterns
Vanilla HTML + <script>
<script type="module">
import { autoInstall } from 'https://esm.sh/@perhapxin/dddk@0.2.2';
import 'https://esm.sh/@perhapxin/dddk@0.2.2/styles.css';
const dddk = autoInstall();
window.dddk = dddk; // for DevTools poking
</script>
SvelteKit
<script lang="ts">
import { onMount } from 'svelte';
import { autoInstall } from '@perhapxin/dddk';
import '@perhapxin/dddk/styles.css';
onMount(() => {
const dddk = autoInstall({
llm: myProvider,
paletteCommands: buildCommands(),
});
return () => dddk.destroy?.();
});
</script>
React / Next.js
'use client';
import { useEffect } from 'react';
import { autoInstall } from '@perhapxin/dddk';
import '@perhapxin/dddk/styles.css';
export function DddkBoot() {
useEffect(() => {
const dddk = autoInstall({ llm: getLLM() });
return () => dddk.destroy?.();
}, []);
return null;
}
Related
- overview.md — what the SDK does at a glance.
- quickstart-frameworks.md — framework-specific setup.
- prompts.md — customise the prompts your demo LLM (or real LLM) will use.
- migrating.md — moving from
new DotDotDuck({...})toautoInstall(...).