You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
wp-plugin: rebrand to Unbounded, fix fresh-install warning, add a demo that cannot rot (#419)
* wp-plugin: rebrand to Unbounded, fix fresh-install warning
The product is just "Unbounded" now, so update the nine user-facing
strings: plugin name, admin menu, settings page, meta box, and field
descriptions.
The <browsers-unbounded> element name deliberately stays. It is the
widget's public API -- ui/src/index.tsx only matches "lantern-network"
(legacy) or "browsers-unbounded", so renaming the tag would silently
render nothing. The option key and admin slug stay for the same reason.
Also stop interpolating $options['layout'] and ['theme'] unguarded. On a
fresh install nobody has saved settings yet, get_option() returns false,
and PHP 8 prints "Trying to access array offset on false" into the page
while emitting empty data attributes. Fall back to banner/dark and pass
both through esc_attr(), since the registered sanitizer is still a
no-op @todo and these land in HTML attributes.
Verified against WordPress 6.x + PHP 8.2 with WP_DEBUG on: the old
version warns and emits data-layout='', the new one is clean and
defaults correctly.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lh3TcyWL8MMtTYPo7H2buS
* wp-plugin: add a Playground-based demo site
Every previous demo of this plugin has rotted. The Heroku instance 404s, the
wordpress.com trial expired, and the S3 zip that try.wpdemo.net installs has
served the February 2024 build ever since -- a version whose front-end hook
predates the homepage and posts settings, so a demo created from it today
installs a plugin that silently ignores half the options its own settings
screen offers.
WordPress Playground removes the server from the equation: WordPress compiled
to WebAssembly, booted in the visitor's browser, plugin installed and activated
from a blueprint. Nothing to host, nothing to expire, nothing to keep patched.
Verified end to end -- the widget renders inside it, globe canvas and connect
switch included.
build.sh generates wp-plugin.zip from the plugin source rather than committing
an archive, so the demo cannot drift from the tree the way the S3 object did.
index.html derives the zip URL from location.origin, so the same files work on
a preview deployment, production, or a custom domain with no edits.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lh3TcyWL8MMtTYPo7H2buS
* wp-plugin: build the demo zip with python, not zip(1)
Cloudflare's Pages build image has no zip binary, so the first preview
deployment failed at the preflight check. python3 is present in both that
image and locally, so zipfile keeps CI and local builds on one code path
rather than adding a dependency to the build environment.
Archive layout is unchanged -- same top-level wp-plugin/ directory entry and
the same two files -- and the result still installs and activates cleanly in
WordPress with the widget rendering.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lh3TcyWL8MMtTYPo7H2buS
* wp-plugin: address PR review feedback
Build the zip link with DOM APIs instead of innerHTML. The reported XSS path
does not actually open -- location.pathname normalises " < > to %22 %3C %3E, so
it cannot carry raw HTML metacharacters -- but concatenating a URL into
innerHTML is a fragile pattern with no upside here, and createElement plus
textContent renders identically.
Fix three stale docs while here:
- the meta box is its own box in the editor sidebar, not a field inside Page
Attributes, so the setup steps pointed readers somewhere that does not exist
- the plugin header still described the widget as applying "to selected
pages", predating the homepage and posts settings it now also supports
- a sentence missing its verb, and a fence missing its language (MD040)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lh3TcyWL8MMtTYPo7H2buS
* wp-plugin: put the demo widget above the fold
The blueprint set location=footer, which hooks wp_footer and renders the widget
below the whole theme -- header, title, content, footer -- so a visitor landed
on the demo and saw stock WordPress with the thing they came to look at off
screen.
location=header hooks wp_head instead. The element is not valid head content,
so the browser closes head and hoists it, landing it as the first child of
body: measured at 32px from the top, 630px tall, in an 818px viewport.
This is also the plugin's own default. The blueprint was overriding it for no
reason.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lh3TcyWL8MMtTYPo7H2buS
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
"code": "<?php require_once '/wordpress/wp-load.php'; $id = wp_insert_post(array('post_type'=>'page','post_title'=>'Unbounded Demo','post_status'=>'publish','post_content'=>'<p>This page is running the Unbounded WordPress plugin. The widget below turns this browser into a volunteer proxy that helps people reach the open internet.</p>')); update_post_meta($id,'_browsers_unbounded_enable','1'); update_option('browsers_unbounded_options', array('layout'=>'banner','theme'=>'dark','location'=>'header','homepage'=>'on')); update_option('show_on_front','page'); update_option('page_on_front',$id); update_option('blogname','Unbounded Demo');"
0 commit comments