{"id":389427,"date":"2026-10-20T02:39:51","date_gmt":"2026-10-20T02:39:51","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/coyomi\/"},"modified":"2026-10-20T02:39:30","modified_gmt":"2026-10-20T02:39:30","slug":"coyomi","status":"publish","type":"plugin","link":"https:\/\/ja.wordpress.org\/plugins\/coyomi\/","author":23509587,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"0.3.0","stable_tag":"0.3.0","tested":"7.1.3","requires":"5.5","requires_php":"7.4","requires_plugins":null,"header_name":"Coyomi \u2013 Archive Calendar","header_author":"Pifto Works","header_description":"A calendar widget for date archives that runs no database queries on page views. Post dates are aggregated once when content changes and served as a static JSON file.","assets_banners_color":"","last_updated":"2026-10-20 02:39:30","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"https:\/\/piftoworks.com","rating":0,"author_block_rating":0,"active_installs":0,"downloads":43,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","changelog"],"tags":{"0.3.0":{"tag":"0.3.0","author":"piftoworks","date":"2026-10-20 02:39:30","revision":3755818}},"upgrade_notice":[],"ratings":[],"assets_icons":[],"assets_banners":[],"assets_blueprints":{},"all_blocks":[],"tagged_versions":["0.3.0"],"block_files":[],"assets_screenshots":[],"screenshots":[]},"plugin_section":[],"plugin_tags":[3621,416,247,162],"plugin_category":[40,43,54],"plugin_contributors":[266284],"plugin_business_model":[],"class_list":["post-389427","plugin","type-plugin","status-publish","hentry","plugin_tags-archives","plugin_tags-calendar","plugin_tags-performance","plugin_tags-widget","plugin_category-calendar-and-events","plugin_category-customization","plugin_category-security-and-spam-protection","plugin_contributors-piftoworks","plugin_committers-piftoworks"],"banners":[],"icons":{"svg":false,"icon":"https:\/\/s.w.org\/plugins\/geopattern-icon\/coyomi.svg","icon_2x":false,"generated":true},"screenshots":[],"raw_content":"<!--section=description-->\n<p>Many archive calendar widgets query the database for every month on every page view.\nOn a site with years of posts that means around a hundred queries per page.<\/p>\n\n<p>This widget aggregates the days that have posts once, when content changes, and writes them\nto a static JSON file under <code>wp-content\/uploads\/lwac\/<\/code>. Page views only read that file.<\/p>\n\n<p>Coyomi (\u66a6) means \"calendar\" in Japanese.<\/p>\n\n<ul>\n<li>One query per rebuild (<code>SELECT DISTINCT DATE(post_date)<\/code>), none per page view<\/li>\n<li>Rebuilt when a post is published, unpublished, trashed, deleted, re-dated or re-categorized, plus once a day<\/li>\n<li>The first month is rendered in HTML (works without JavaScript); other months are drawn in the browser<\/li>\n<li>Works with full-page caches: the browser always fetches the current data file<\/li>\n<li>Filter by post types and categories<\/li>\n<li>Five layouts: month calendar, week strip, year (12 month tiles), dropdowns only, and a year \/ month \/ day tree<\/li>\n<li>A settings page (Settings \u2192 Coyomi) with a live preview. Widgets follow it unless they choose their own layout and colors<\/li>\n<li>Five color schemes (Calendrier, Pastel, Classic, Dark, Simple). Every color can be changed per widget; only the changed colors are saved<\/li>\n<li>Other plugins can add events (e.g. sales) to days with the <code>coyomi_events<\/code> filter. An event held on several days in a row is listed on one line, marked \"On now\" or \"Ended\"<\/li>\n<li>No external requests: the calendar talks to no service outside your site and collects no data<\/li>\n<\/ul>\n\n<h3>Developers<\/h3>\n\n<p>Add events with the <code>coyomi_events<\/code> filter. It is called only when the data is rebuilt (never on page views),\nso it may do slow work. Add one entry per day:<\/p>\n\n<pre><code>add_filter( 'coyomi_events', function ( $events, $dataset ) {\n    try {\n        foreach ( my_plugin_sale_days() as $day ) {\n            $events[] = array(\n                'date'   =&gt; $day,                    \/\/ 'YYYY-MM-DD' in the site's time zone\n                'label'  =&gt; 'Autumn sale',           \/\/ plain text, up to 60 characters\n                'url'    =&gt; get_permalink( 123 ),    \/\/ a post on this site, or ''\n                'color'  =&gt; '#bf0000',               \/\/ '#rrggbb' or '#rgb', or '' for the scheme's color\n                'source' =&gt; 'my-plugin',             \/\/ a-z, 0-9, _ and -, up to 32 characters\n            );\n        }\n    } catch ( \\Throwable $e ) {\n        \/\/ Rebuilds also run on a reader's first page view and in cron. On failure, add nothing.\n    }\n    return $events;\n}, 10, 2 );\n<\/code><\/pre>\n\n<p>How events are shown:<\/p>\n\n<ul>\n<li>Days in a row with the same <code>label<\/code>, <code>url<\/code> and <code>source<\/code> are listed as one line (e.g. \"12\/4\u201312\/11\").\nKeep these three the same on every day of one event.<\/li>\n<li>Entries with the same <code>date<\/code>, <code>label<\/code> and <code>url<\/code> are shown once, even when two plugins add them.<\/li>\n<li>The list marks events held today as \"On now\" and past events as \"Ended\", using the reader's date in the browser\n(so a cached page still shows the right state).<\/li>\n<li>Events do not change the month the calendar opens on. Readers reach them with the previous \/ next buttons.<\/li>\n<li>Entries with a date that does not exist or an empty label are dropped.<\/li>\n<\/ul>\n\n<p>Rules for plugins that add events:<\/p>\n\n<ul>\n<li>Add only the events your plugin owns. Do not pass on events your plugin received from another plugin;\nthat plugin can add them itself.<\/li>\n<li><code>url<\/code> must be a post or page on this site. Event links have no <code>rel<\/code> attribute, so never use affiliate\nor other paid links there.<\/li>\n<li><code>date<\/code> is a date in the site's time zone (Settings \u2192 General). The data is rebuilt when the time zone,\nthe permalink structure or the site address changes.<\/li>\n<\/ul>\n\n<p>When your events change, ask for a rebuild. It runs once at the end of the request:<\/p>\n\n<pre><code>do_action( 'coyomi_request_rebuild' );\n<\/code><\/pre>\n\n<p>When your plugin is deactivated, remove your filter before asking for the rebuild, so that the rebuild at\nthe end of the same request does not add your events back.<\/p>\n\n<p>The data file URL is built from the site URL (not the uploads URL), so it keeps working when media is\nserved from another domain or a CDN. If your setup still needs a different URL:<\/p>\n\n<pre><code>add_filter( 'coyomi_data_url', function ( $url, $key, $path ) {\n    return $url; \/\/ must be readable from the page (same origin, or CORS allowed)\n}, 10, 3 );&lt;h3&gt;WP-CLI&lt;\/h3&gt;\n<\/code><\/pre>\n\n<p>* <code>wp coyomi status<\/code> - data files and last rebuild\n* <code>wp coyomi rebuild<\/code> - rebuild all data files\n* <code>wp coyomi compare lwac_calendar-2<\/code> - run the legacy per-month queries once and compare the days<\/p>\n\n<!--section=changelog-->\n<h4>0.3.0<\/h4>\n\n<ul>\n<li>Events held on several days in a row are listed on one line (e.g. \"12\/4\u201312\/11\"), including days outside the month shown.<\/li>\n<li>The event list marks events as \"On now\" or \"Ended\". The state follows the reader's date, so cached pages stay correct.<\/li>\n<li>Identical events (same date, label and URL) are shown once, even when two plugins add them.<\/li>\n<li>Events no longer change the month or week the calendar opens on. It opens on the latest month with posts.<\/li>\n<li>In the week layout, choosing a month in the menu opens the week of the latest post in that month.<\/li>\n<li>A year tile shows one mark per event instead of one per day.<\/li>\n<li>The data is rebuilt when the permalink structure, the site address or the time zone changes.<\/li>\n<li>If a plugin that adds events fails while the data is rebuilt, the calendar keeps the days with posts.<\/li>\n<li>Translations are delivered as language packs from translate.wordpress.org.<\/li>\n<\/ul>\n\n<h4>0.2.1<\/h4>\n\n<ul>\n<li>Fixed: with classic widgets, changing a calendar in the Customizer showed \"An error has occurred\" and the Publish button stayed disabled.<\/li>\n<li>Fixed: in the week layout, the month name on the first day overlapped the weekday.<\/li>\n<\/ul>\n\n<h4>0.2.0<\/h4>\n\n<ul>\n<li>Renamed to Coyomi. Settings, widgets and data of earlier versions are kept as they are.<\/li>\n<li>Hooks and WP-CLI use the new name: coyomi_events, coyomi_request_rebuild, coyomi_data_url, wp coyomi.<\/li>\n<\/ul>\n\n<h4>0.1.4<\/h4>\n\n<ul>\n<li>Removed the migration from Archives Calendar Widget (the settings page panel and its WP-CLI command). Calendars created with it keep working as they are.<\/li>\n<\/ul>\n\n<h4>0.1.3<\/h4>\n\n<ul>\n<li>Color fields show the current color instead of a blank swatch, and the color picker opens at that color.<\/li>\n<li>The help text refers to the \"Default\" button, matching the button label.<\/li>\n<\/ul>\n\n<h4>0.1.2<\/h4>\n\n<ul>\n<li>Fixed: the Simple color scheme showed no grid lines or frame.<\/li>\n<li>Fixed: in the year layout, the current month tile could lose its text. Simple now marks today in red even on days with posts.<\/li>\n<li>\"Edit in the Customizer\" opens the area where each calendar is placed.<\/li>\n<li>The colors panel on the settings page is always open.<\/li>\n<\/ul>\n\n<h4>0.1.1<\/h4>\n\n<ul>\n<li>Settings page (Settings \u2192 Coyomi) with a live preview, placement list, legacy migration and data status.<\/li>\n<li>Widgets follow the site-wide layout, colors and nofollow unless set per widget.<\/li>\n<li>The data file URL is built from the site URL, so it works when uploads are served from another domain.<\/li>\n<li>Fixed: layout and color scheme buttons overlapped on the settings page.<\/li>\n<li>CSS and JS URLs change whenever the files change, so CDNs do not keep serving old copies.<\/li>\n<\/ul>\n\n<h4>0.1.0<\/h4>\n\n<ul>\n<li>First version.<\/li>\n<\/ul>","raw_excerpt":"An archive calendar widget that adds no database queries to your pages.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/ja.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/389427","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ja.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/ja.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/ja.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=389427"}],"author":[{"embeddable":true,"href":"https:\/\/ja.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/piftoworks"}],"wp:attachment":[{"href":"https:\/\/ja.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=389427"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/ja.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=389427"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/ja.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=389427"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/ja.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=389427"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/ja.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=389427"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/ja.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=389427"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}