Widgets Ecosystem
Relevant source files
The following files were used as context for generating this wiki page:
The Widgets Ecosystem provides members with modular HTML snippets and scripts to enhance their static homepages. These components include functional elements like hit counters and guestbooks, as well as cosmetic enhancements like custom backgrounds and cursor effects.
The system emphasizes a "hands-off" philosophy where the platform never injects code into member pages automatically. Instead, members choose to paste snippets or use the dashboard's "Add to a page" feature, which inserts the selected widget at the cursor position within the in-browser editor.
Sources: src/widgets.js:1-4, PLAN.md:204-209
Component Architecture
The widget system is structured into several categories: dynamic SVG badges, interactive iframes, static assets, and client-side scripts.
Core Widget Types
| Category | Description | Examples |
|---|---|---|
| Dynamic Badges | SVG images generated on-the-fly based on user data. | Hit counter, Last updated, Status line |
| Interactions | Embedded features via iframes or standard links. | Guestbook, Webring bar |
| Decorative | Static SVG assets and stamps for page flair. | 88x31 buttons, Stamps, Tiling backgrounds |
| Effects | External JavaScript files that provide visual animations. | Sparkle cursor, Falling snow |
Sources: src/widgets.js:52-71, src/style.js:13-17
Data Flow for Dynamic Widgets
Dynamic widgets like the hit counter and status line are served through specific /_hw/ routes on member subdomains. These routes fetch data from the database and return a generated SVG.
The server sets short cache headers for dynamic SVG widgets (e.g., 60 seconds for status, 300 seconds for hit counters) to ensure content stays relatively fresh while reducing database load.
Sources: src/widgets.js:75-78, src/server.js:125-131
Dynamic SVG Generation
The system uses specific helper functions in src/widgets.js to create SVG images from text or numbers. These functions calculate the required width based on the string length to ensure the image fits the content.
SVG Generator Functions
counterSvg(n): Generates a 6-digit padded counter with a retro blue and yellow theme.lineSvg(text): Creates a single line of monospace text inside a bordered box.updatedSvg(t): Wraps an ISO date string inlineSvgto show the last modification date.statusSvg(status): Wraps the user's custom status string.
Sources: src/widgets.js:34-50
// Example of monospace width calculation in src/widgets.js
const lineSvg = (text) => {
const w = [...text].length * 7 + 14;
return `<svg xmlns="http://www.w3.org/2000/svg" width="${w}" height="20" ...`;
};
Sources: src/widgets.js:45-48
The Guestbook System
The Guestbook is the primary interactive widget. It operates within an <iframe> to maintain isolation from the member's main page.
Themes and Customization
The guestbook supports multiple CSS themes that members can select via a query parameter (?theme=). Available themes include:
- Classic: Default PuppyPad look.
- Night: Dark mode with blue accents.
- Notebook: Ruled line background with Courier New font.
- Pastel: Purple and pink theme with Verdana font.
- Arcade: High-contrast black and neon green theme.
Sources: src/widgets.js:20-30, src/server.js:154-159
Moderation and Security
To prevent abuse, the guestbook includes several layers of protection:
- Honeypot: A hidden "website" field that drops submissions if filled by bots.
- Word Filter: Members can define a list of blocked words in their dashboard.
- Link Holding: Entries containing URLs are automatically set to
approved = 0and require manual approval. - IP Blocking: Members can block specific visitor IPs for up to 90 days.
- Rate Limiting: Limits submissions to 3 entries per 10 minutes per IP.
Sources: src/server.js:161-182, PLAN.md:144-149
Style Editor and Backgrounds
The Style Editor acts as a meta-widget that generates puppypad.css. It allows members to select tiling backgrounds provided by the platform.
Background Management
Backgrounds are defined as a list of IDs and descriptive names. The platform provides several "see-through" patterns that adopt the member's chosen page color.
Members can also use their own uploaded images as backgrounds by selecting the "own" option and picking a file from their site directory.
Sources: src/widgets.js:10-14, src/style.js:19-33, src/views.js:338-348
Integration and Deployment
Members integrate widgets using the groups function which provides snippets for the dashboard.
Dashboard Insertion Logic
When a member clicks "Add to a page", the application opens the code editor with an insert parameter. The editor UI then uses a small client-side script to place the snippet at the current cursor position.
// Insertion logic from src/views.js
var ins = document.getElementById('insert'), snip = ...;
if(ins) ins.addEventListener('click', function(){
if(cm){ cm.replaceRange(snip, cm.getCursor()); cm.focus(); }
else { ta.setRangeText(snip, ta.selectionStart, ta.selectionEnd, 'end'); ta.focus(); }
draw();
});
Sources: src/views.js:324-329
Asset Routing
All static widget assets (backgrounds, buttons, effects) are served via a centralized asset router. These files are served with a long cache duration of 30 days (max-age=2592000) because they are shared across all member sites.
Sources: src/widgets.js:84-93
Conclusion
The Widgets Ecosystem in PuppyPad provides a balance between user ease-of-use and technical transparency. By serving dynamic content through sub-resources like SVGs and iframes, the system maintains the static nature of member sites while offering modern interactive features. The architecture ensures that widgets remain lightweight, cacheable, and secure against common web vulnerabilities.