Polished starter — nickname, vibe picker, visit progress, sounds, and live theme readout.
window.ggbro. This is the complete plugin.
{
"id": "com.ggbro.sample.hello",
"name": "Hello Sample",
"version": "3.0.0",
"author": "ggbro",
"description": "Polished starter — nickname, vibe picker, visit progress, sounds, and live theme readout.",
"main": "plugin.js",
"styles": "styles.css",
"permissions": ["ui.toast", "theme.read", "app.info", "ui.panel", "ui.sound", "storage"]
}
/**
* Hello Sample v3 — polished starter using the full panel toolkit.
*/
(async function () {
var visits = 0;
var version = '?';
var accent = '';
var displayName = 'friend';
var vibe = 'friendly';
try {
visits = parseInt((await ggbro.storage.get('visits')).value || '0', 10) || 0;
visits += 1;
await ggbro.storage.set('visits', String(visits));
displayName = (await ggbro.storage.get('displayName')).value || 'friend';
vibe = (await ggbro.storage.get('vibe')).value || 'friendly';
if (['friendly', 'hype', 'chill'].indexOf(vibe) < 0) vibe = 'friendly';
} catch (e) {
ggbro.log('storage', e && e.message);
}
try {
var info = await ggbro.getAppInfo();
version = (info && info.version) || '?';
} catch (e) {
ggbro.log('appinfo', e && e.message);
}
try {
var theme = await ggbro.getTheme();
accent = (theme && (theme.accent || theme.accentPreset)) || '';
} catch (e) {
ggbro.log('theme', e && e.message);
}
function greetLine() {
var lines = {
friendly: 'Hello, ' + displayName + ' — glad you’re here.',
hype: 'Let’s go, ' + displayName + ' — main character energy.',
chill: 'Hey ' + displayName + ' — settle in, no rush.',
};
return lines[vibe] || lines.friendly;
}
async function paintPanel() {
await ggbro.ui.registerPanel({
id: 'main',
title: 'Hello Sample',
schema: [
{
type: 'notice',
id: 'tip',
text: 'Starter pack — rename yourself, pick a vibe, then try the buttons. Docs: ggbro.app/developers/plugins',
tone: 'info',
},
{ type: 'section', id: 's0', title: 'Status' },
{ type: 'text', id: 'ver', label: 'Desktop', value: 'v' + version },
{ type: 'text', id: 'accent', label: 'Accent', value: accent || '—' },
{ type: 'progress', id: 'visitsBar', label: 'Visits (capped preview)', value: Math.min(visits, 20), max: 20 },
{ type: 'text', id: 'visits', label: 'Visits on this PC', value: String(visits) },
{ type: 'section', id: 's1', title: 'Personalize' },
{
type: 'input',
id: 'name',
label: 'Call me',
value: displayName,
placeholder: 'Your nickname',
},
{
type: 'select',
id: 'vibe',
label: 'Greeting vibe',
value: vibe,
options: [
{ value: 'friendly', label: 'Friendly' },
{ value: 'hype', label: 'Hype' },
{ value: 'chill', label: 'Chill' },
],
},
{ type: 'section', id: 's2', title: 'Try it' },
{ type: 'button', id: 'greet', label: 'Say hello' },
{ type: 'button', id: 'ding', label: 'Play sound' },
{ type: 'button', id: 'reset', label: 'Reset visit counter' },
{ type: 'link', id: 'docs', label: 'Plugin docs', href: 'https://ggbro.app/developers/plugins' },
],
});
}
await paintPanel();
await ggbro.toast({
message: greetLine() + ' Open Settings → Plugins for controls.',
type: 'success',
});
ggbro.onThemeChange(function (theme) {
accent = (theme && (theme.accent || theme.accentPreset)) || '';
paintPanel().catch(function () {});
});
ggbro.onEvent(function (event, payload) {
if (event !== 'panelAction' || !payload) return;
if (payload.fieldId === 'name') {
displayName = String(payload.value || 'friend').trim().slice(0, 32) || 'friend';
ggbro.storage.set('displayName', displayName).catch(function () {});
paintPanel();
ggbro.toast({ message: 'Got it — hello, ' + displayName + '!', type: 'success' });
return;
}
if (payload.fieldId === 'vibe') {
vibe = String(payload.value || 'friendly');
if (['friendly', 'hype', 'chill'].indexOf(vibe) < 0) vibe = 'friendly';
ggbro.storage.set('vibe', vibe).catch(function () {});
paintPanel();
return;
}
if (payload.fieldId === 'greet') {
ggbro.toast({
message: greetLine() + ' · visit #' + visits + ' · v' + version,
type: 'success',
});
return;
}
if (payload.fieldId === 'ding') {
ggbro.playSound({ id: 'boing' }).catch(function () {});
ggbro.toast({ message: 'Boing!', type: 'info' });
return;
}
if (payload.fieldId === 'reset') {
visits = 0;
ggbro.storage.set('visits', '0').then(function () {
return paintPanel();
}).then(function () {
return ggbro.toast({ message: 'Visit counter reset', type: 'warning' });
});
}
});
})();
/* Custom properties only — host sanitizer keeps :root/html/body --vars. */
:root {
--ggbro-plugin-hello: 1;
}
# Hello Sample (v2)
Official starter for the host-rendered panel API.
- **Settings → Plugins** panel with Say hello / Play sound / Reset counter
- Visit counter via `storage`
- Live accent readout via `theme.read`
Download the `.ggbro-plugin` pack from the docs examples page.