{"id":285217,"date":"2026-03-19T18:48:00","date_gmt":"2026-03-19T18:48:00","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/wireservice\/"},"modified":"2026-03-19T21:23:51","modified_gmt":"2026-03-19T21:23:51","slug":"wireservice","status":"publish","type":"plugin","link":"https:\/\/twd.wordpress.org\/plugins\/wireservice\/","author":23457969,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_crdt_document":"","version":"1.2.0","stable_tag":"1.2.0","tested":"6.9.4","requires":"6.4","requires_php":"8.3","requires_plugins":null,"header_name":"Wireservice","header_author":"Tyler Fisher","header_description":"A WordPress plugin for publishing posts to the AT Protocol based on the standard.site lexicon.","assets_banners_color":"","last_updated":"2026-03-19 21:23:51","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/wordpress.wireservice.net","header_author_uri":"https:\/\/tylerjfisher.com","rating":0,"author_block_rating":0,"active_installs":0,"downloads":117,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description"],"tags":{"1.2.0":{"tag":"1.2.0","author":"tylrfishr","date":"2026-03-19 21:23:51"}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3486768,"resolution":"128x128","location":"assets","locale":""},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3486768,"resolution":"256x256","location":"assets","locale":""}},"assets_banners":[],"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.2.0"],"block_files":[],"assets_screenshots":[],"screenshots":[],"jetpack_post_was_ever_published":false},"plugin_section":[],"plugin_tags":[223780,223781,5699],"plugin_category":[],"plugin_contributors":[258143],"plugin_business_model":[],"class_list":["post-285217","plugin","type-plugin","status-publish","hentry","plugin_tags-atproto","plugin_tags-bluesky","plugin_tags-syndication","plugin_contributors-tylrfishr","plugin_committers-tylrfishr"],"banners":[],"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/wireservice\/assets\/icon-128x128.png?rev=3486768","icon_2x":"https:\/\/ps.w.org\/wireservice\/assets\/icon-256x256.png?rev=3486768","generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p>Publish your posts and pages to the AT Protocol using the standard.site lexicons.<\/p>\n\n<h3>Requirements<\/h3>\n\n<ul>\n<li>PHP 8.3+<\/li>\n<li>WordPress 6.4+<\/li>\n<\/ul>\n\n<h3>Setup<\/h3>\n\n<ol>\n<li>Go to <strong>Settings &gt; Wireservice<\/strong>.<\/li>\n<li>Connect your AT Protocol account via the OAuth flow.<\/li>\n<li>Configure your <strong>Publication<\/strong> settings (name, description, icon, theme colors) and sync to AT Protocol.<\/li>\n<li>Enable <strong>Document<\/strong> syncing and configure how post titles, descriptions, and cover images are sourced.<\/li>\n<\/ol>\n\n<h3>How It Works<\/h3>\n\n<h3>Publication<\/h3>\n\n<p>Your WordPress site is represented as a <code>site.standard.publication<\/code> record on AT Protocol. The plugin syncs site-level metadata including:<\/p>\n\n<ul>\n<li><strong>Name<\/strong> &mdash; from WordPress site title, Yoast SEO, or a custom value<\/li>\n<li><strong>Description<\/strong> &mdash; from WordPress tagline, Yoast SEO, or a custom value<\/li>\n<li><strong>Icon<\/strong> &mdash; from WordPress site icon or a custom upload<\/li>\n<li><strong>Theme colors<\/strong> &mdash; background, foreground, accent, and accent foreground. NOTE: these are used by other ATProto platforms to style your content, not on your WordPress site.<\/li>\n<li><strong>Discoverability<\/strong> &mdash; opt in or out of discovery feeds. NOTE: these are used by other ATProto platforms to show your publication in algorithmic feeds, not on your WordPress site.<\/li>\n<\/ul>\n\n<p>The plugin also serves a <code>.well-known\/site.standard.publication<\/code> endpoint that returns the AT-URI of your publication record.<\/p>\n\n<h3>Documents<\/h3>\n\n<p>When document syncing is enabled, published posts and pages are automatically synced as <code>site.standard.document<\/code> records. Each document includes:<\/p>\n\n<ul>\n<li>Title and description (configurable source)<\/li>\n<li>Cover image (featured image, Yoast SEO image, or custom)<\/li>\n<li>Publication date and last-updated date<\/li>\n<li>Relative path (permalink)<\/li>\n<li>Tags and categories<\/li>\n<li>Optionally, full plain-text content<\/li>\n<\/ul>\n\n<p>Documents are created on publish, updated on edit, and deleted when a post is trashed, deleted, or unpublished.<\/p>\n\n<p>A <code>&lt;link rel=\"site.standard.document\"&gt;<\/code> tag is added to the <code>&lt;head&gt;<\/code> of each synced post for verification.<\/p>\n\n<p>Note that Wireservice does not have a content lexicon yet. This is in development.<\/p>\n\n<h3>Per-Post Overrides<\/h3>\n\n<p>A <strong>Wireservice<\/strong> meta box appears on the post editor, allowing per-post overrides for:<\/p>\n\n<ul>\n<li>Title source<\/li>\n<li>Description source<\/li>\n<li>Cover image source<\/li>\n<li>Whether to include full content<\/li>\n<\/ul>\n\n<h3>Yoast SEO Integration<\/h3>\n\n<p>When Yoast SEO is active, additional source options become available for both publication and document settings:<\/p>\n\n<ul>\n<li><strong>Publication<\/strong>: Yoast organization name, website name, homepage meta description<\/li>\n<li><strong>Documents<\/strong>: Yoast SEO title, social title, X title, meta description, social description, X description, social image, X image<\/li>\n<\/ul>\n\n<h3>Self-Hosting the OAuth Service<\/h3>\n\n<p>Wireservice authenticates with AT Protocol through an external OAuth service. By default it uses <code>https:\/\/aip.wireservice.net<\/code>, but you can run your own instance using <a href=\"https:\/\/github.com\/graze-social\/aip\">AIP<\/a>, a high-performance OAuth 2.1 authorization server with native AT Protocol integration.<\/p>\n\n<h3>Running AIP<\/h3>\n\n<p>AIP requires Rust 1.87+. To run locally:<\/p>\n\n<ol>\n<li><p>Generate an OAuth signing key with <code>goat<\/code>: <code>goat key generate -t p256<\/code>. Save the public and private keys somewhere safe.<\/p><\/li>\n<li><p>Clone AIP: <code>git clone https:\/\/github.com\/graze-social\/aip.git<\/code><\/p><\/li>\n<li><p>Setup environment variables:<\/p>\n\n<p><code>EXTERNAL_BASE=https:\/\/your-domain.com\nDPOP_NONCE_SEED=$(openssl rand -hex 32)\nSTORAGE_BACKEND=sqlite\nATPROTO_OAUTH_SIGNING_KEYS=<\/code>did:key:${YOUR_PRIVATE_KEY}<code>OAUTH_SIGNING_KEYS=<\/code>did:key:${YOUR_PRIVATE_KEY}<code>ENABLE_CLIENT_API=true\nOAUTH_SUPPORTED_SCOPES=\"atproto:atproto atproto:repo:site.standard.publication atproto:repo:site.standard.document\natproto:blob:*\/*\"<\/code><\/p><\/li>\n<li><p>Run AIP: <code>cargo run --bin aip<\/code><\/p><\/li>\n<\/ol>\n\n<p>Or with Docker:<\/p>\n\n<pre><code>`\n<\/code><\/pre>\n\n<p>docker build -t aip .\ndocker run -p 8080:8080 \\\n  \/\/ all of the above env vars here\n  aip\n    `<\/p>\n\n<p>For production, use the <code>postgres<\/code> storage backend instead of <code>sqlite<\/code>. Depending on your hosting environment, you may need to manually set the <code>DNS_NAMESERVERS<\/code> env var so that your AIP service can resolve handles properly. (Wireservice uses <code>8.8.8.8,1.1.1.1<\/code>).<\/p>\n\n<h3>Configuring Wireservice<\/h3>\n\n<p>Once your AIP instance is running, update the OAuth Service URL in WordPress:<\/p>\n\n<ol>\n<li>Go to <strong>Settings &gt; Wireservice<\/strong>.<\/li>\n<li>Set the <strong>OAuth Service URL<\/strong> to your AIP instance (e.g., <code>https:\/\/your-domain.com<\/code>).<\/li>\n<\/ol>\n\n<p>This is stored as the <code>wireservice_oauth_url<\/code> option and can also be set programmatically:<\/p>\n\n<pre><code>`\n<\/code><\/pre>\n\n<p>update_option('wireservice_oauth_url', 'https:\/\/your-domain.com');\n    <code>&lt;h3&gt;Filters&lt;\/h3&gt;<\/code>\n\/\/ Customize which post types are synced (default: post, page)\nadd_filter('wireservice_syncable_post_types', function ($types) {\n    $types[] = 'custom_post_type';\n    return $types;\n});<\/p>\n\n<p>\/\/ Control whether a specific post should sync\nadd_filter('wireservice_should_sync_post', function ($should_sync, $post) {\n    return $should_sync;\n}, 10, 2);\n    `<\/p>\n\n<h3>License<\/h3>\n\n<p><a href=\"LICENSE.md\">AGPL 3.0<\/a><\/p>","raw_excerpt":"Publish your posts and pages to the AT Protocol using the standard.site lexicons.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/285217","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=285217"}],"author":[{"embeddable":true,"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/tylrfishr"}],"wp:attachment":[{"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=285217"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=285217"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=285217"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=285217"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=285217"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=285217"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}