Search by

drupal / pixienote

Drupal-Infrastructure

A private personal information hub for contacts, bookmarks, notes, schedules, and service links.

Package info

git.drupalcode.org/project/pixienote.git

Type:drupal-recipe

pkg:composer/drupal/pixienote

Statistics

Installs: 6

Dependents: 0

Suggesters: 0

1.0.0-alpha2 2026-10-09 22:49 UTC

This package is auto-updated.

Last update: 2026-10-13 00:08:11 UTC


README

PixieNote is a Drupal Recipe for a private personal information hub. It adds contacts, bookmarks, notes, schedules, service links, RSS news, a note-photo grid, tags, list views, search, browser printing, and the Bootstrap Cloud Pixie Dark presentation.

Start with the Documentation for service walkthroughs, installation, and operations in English and Japanese. The same guides are available in this repository.

See release notes for the changes and limitations of 1.0.0-alpha2.

The Recipe contains configuration, a manifest of public RSS feed definitions, and the footer layout settings. The guarded installer creates those feed entities with site-generated IDs and initializes image effects after the Recipe is applied. It does not include imported feed items, sample content, user accounts, email addresses, credentials, private keys, uploaded files, or identifiers copied from the production site. The Recipe navigation omits Bootstrap Cloud's default logo. Add your own branding after installation if desired. The front page is the i News Top view at /top; the included public feeds appear after their first refresh. English, Japanese, Simplified Chinese, and Thai are available as interface languages with URL prefixes (/en, /ja, /zh-hans, /th). The Recipe ships translations for selected configuration labels, including the Tags navigation item, but does not ship translated personal content or guarantee complete contributed-module interface translations.

The selected configuration-label translations use the contributed recipe_config_translation module. This project is not covered by Drupal's Security Advisory Policy; review its upstream releases and security status before using it in a production site. The host site's Composer lock controls the resolved module version; keep that lockfile under version control for repeatable deployments. Reapply the Recipe after installing a previously missing language or updating this module to refresh the shipped label translations.

Requirements

  • Drupal 11 (individual dependencies may require a later minor release)
  • PHP supported by the installed Drupal release
  • Composer
  • Drush 13 for the required node-access rebuild
  • A fresh site installed with the Minimal profile
  • A private-file directory configured outside the public web root before uploading contact or note images

Dependency updates

The Recipe allows compatible releases within each dependency's major series. Routine minor and patch releases do not require a Recipe change or a separate PixieNote merge request. The installing site's composer.lock records the resolved versions for repeatable deployments; review and test dependency updates together in that site's normal update workflow before deployment. The validation record identifies the versions actually tested, rather than claiming that every older version allowed by a constraint has been tested.

Only raise a minimum version or add an upper bound for a demonstrated API, security, or compatibility requirement. The temporary Twig restriction below is one such documented compatibility exception. Menu Link Config retains its explicit alpha stability allowance without lowering the site's overall minimum stability.

Install

1.0.0-alpha1 is the initial release and lacks the guarded installer. For 1.0.0-alpha2 and later releases that include scripts/install-safe.sh, select the reviewed release explicitly in Composer: the default stable-only constraint cannot install an alpha release. Keep the project's minimum-stability at stable. Menu Link Config currently has only an alpha release, so require it directly in the root project as shown below. Use the alpha2 command only after that release is available on Drupal.org.

Run these commands from the root of an installed Drupal project. Drupal's recommended project template from 11.2 onward already places Recipe packages in recipes/. If your Composer project does not have that installer path, configure it before requiring PixieNote:

composer config allow-plugins.drupal/core-recipe-unpack true
composer require drupal/core-recipe-unpack composer/installers:^2.3
composer config --merge --json extra.installer-paths '{"recipes/{$name}":["type:drupal-recipe"]}'

The Recipe application below assumes recipes/pixienote/recipe.yml exists after Composer finishes. If it does not, check the installer path instead of applying a different copy of the Recipe.

For the reviewed 1.0.0-alpha2 release, install the Recipe, its alpha-only dependency, and Drush from the Drupal Composer repository:

composer require 'drupal/pixienote:1.0.0-alpha2' 'drupal/menu_link_config:^1.0@alpha' 'drush/drush:^13' --with-all-dependencies

For development of an unreleased 1.x checkout, register its absolute path as a Composer path repository instead:

composer config repositories.pixienote path /absolute/path/to/pixienote
composer require 'drupal/pixienote:1.x-dev' 'drupal/menu_link_config:^1.0@alpha' 'drush/drush:^13' --with-all-dependencies

The checkout must be on 1.x. Composer does not apply the alpha stability allowance from a transitive dependency to the root project. The direct requirement keeps the root minimum-stability at stable. Do not use this development-branch command for a published release; select its reviewed version and keep the direct Menu Link Config requirement while it remains alpha. The separate 1.0.0-alpha1 command below predates this dependency.

Before applying the Recipe, create a private-file directory in the Composer project root, outside web/, and make it writable by the PHP web-server user. In web/sites/default/settings.php, set the following path (adjust it if your project uses a different web root):

$settings['file_private_path'] = dirname($app_root) . '/private';

On the standard recommended-project layout, create that directory with mkdir -p private from the Composer project root. Do not put private files in web/sites/default/files or commit them to version control.

Before running the commands below, replace any placeholder site email address in Drupal's Basic site settings with a deliverable address that you control. The setup-contact script uses that address as the recipient of the public Contact form; it does not ship or print an email address. It refuses to create the form if the address is invalid. If a feedback form already exists, the script validates but does not replace its recipient. Changing the site's email later does not update the form; edit its recipient separately in Drupal's Contact forms administration screen.

The 1.0.0-alpha1 release predates the guarded installer below. For 1.0.0-alpha2 or a newer release containing scripts/install-safe.sh, use this command after installing the Recipe package and Drush with Composer. It is for an empty Minimal site in a standard recommended-project layout only. It enables maintenance mode before applying configuration, checks the private-file path and existing content, creates or verifies the public feed sources and image effects, sets up Contact, rebuilds and verifies node access, and reopens the site only if every step succeeds. Before reopening, it checks that essential rendering plugins are discoverable and internally renders the front page. A failed rendering check triggers one additional cache rebuild; a second failure leaves maintenance mode enabled. This check does not replace testing the public site through its actual web server after installation. The first empty-site preflight runs before maintenance mode is enabled. If it rejects the site, the original mode is unchanged; keep it private and use the update procedure instead. After the preflight, a failed step leaves maintenance mode enabled; correct the reported problem and rerun the same command. It does not import personal content or change the site email. The inventory checks every installed content entity type, not just nodes and files. Only Drupal's initial accounts and unchanged packaged public RSS samples are allowed, including when retrying an incomplete installation. Their stored public fields and defaults must match: title, URL, language, refresh interval and empty cached metadata. Drupal-generated runtime identity is not an expected content value. The 13 default sources are listed by stable descriptive keys in assets/aggregator/feed/sources.yml. This is the only packaged feed list; prior lists are preserved in Git history, not shipped as runtime profiles. The manifest contains no entity IDs. Additional feed sources, dynamic menu links, and other content are rejected. Unsupported non-SQL content storage is rejected rather than silently skipped; Drupal core's non-persistent Contact message storage is not a stored-content inventory.

Private storage must not contain the public web root either; filesystem roots and ancestor directories are not suitable private-file locations. The installer follows directory symlinks reachable from the web root and rejects links into the private-file directory. It also rejects dangling links, which could expose private data when their targets are created later. Remove or repair these links before retrying. It cannot inspect custom web-server or reverse-proxy aliases; ensure those do not expose the private directory before making the site public. The installer checks whether the Drush PHP process can read and write the private directory; separately verify that the PHP web-server user can read and write it before accepting image uploads.

bash recipes/pixienote/scripts/install-safe.sh

Run vendor/bin/drush cron after the successful command if you want to fetch the public RSS feeds immediately. Feed availability is not a prerequisite for reopening the site. To update an existing, populated PixieNote site, follow the separate update procedure below rather than running the fresh installer. Fetched feed descriptions, links, images and cache state are also existing content for this fresh-install guard, even if no items were imported. After refreshing feeds or customizing them, use the populated-site update procedure; do not clear that data merely to make the fresh-install guard accept the site.

The published 1.0.0-alpha1 release has no guarded installer. Its manual sequence below is for an isolated test site only, not a publicly reachable site. Keep that site closed until the node-access rebuild has finished and the privacy checks in Verification have passed. Do not treat these manual commands as a safe production installation procedure.

For that published release, the manual sequence remains:

composer require 'drupal/pixienote:1.0.0-alpha1' 'drush/drush:^13' --with-all-dependencies
cd web
../vendor/bin/drush recipe ../recipes/pixienote
../vendor/bin/drush php:script setup-contact --script-path=../recipes/pixienote/scripts
../vendor/bin/drush php:eval '\Drupal\node_view_permissions\NodeAccessRebuildHelper::rebuild();'
../vendor/bin/drush cr
../vendor/bin/drush cron

Do not create private records or open the site to other users before the node-access rebuild finishes successfully. The Node View Permissions module marks access grants for rebuilding during installation, but Drupal's original public default grant may still be present until that rebuild. A cache rebuild alone is not sufficient. Then create an authenticated user. PixieNote intentionally ships no accounts or personal content. Ordinary authenticated users can create contacts, bookmarks, notes, and schedules. The commands above install the legacy 1.0.0-alpha1 package. The Tags behavior below applies to the 1.x source and 1.0.0-alpha2, not alpha1. The current source allows Bootstrap Cloud 7.x; 7.1.8 includes the theme's Accessible Menu integration fixes. The published alpha1 package retains its original dependencies and navigation configuration. The main navigation ends with i Pics, Tags, and +. Accessible Menu's Bootstrap 5 Disclosure Menu makes the entire Tags label a single toggle that opens the service-specific /a/tags, /b/tags, and /n/tags links. Tab focuses the toggle; Enter or Space opens the menu, and Escape closes it. The existing /tags View remains available at its URL, but the parent is not a separate navigation action. Bootstrap Cloud 7.1.8 renders the parent as a native button without depending on the site's hostname. This release includes Bootstrap Cloud MR!92 for navigation contrast, native disclosure controls, and avoiding duplicate Bootstrap loading. The previous 7.1.7 release rendered the parent as a link with button semantics. The main navigation + link opens /node/add. The i Services link list remains available at /m and follows the source site's administrator-managed permissions; use an administrator account to add service links. The standard administration-menu Add content link remains available separately. Anonymous visitors see the six service labels in the same order as signed-in users. Five private-service labels lead to the localized login form; i News continues to link to its public feed. After login, Drupal's route access checks hide those login-only links and expose the private service links in their place. Direct requests to private service paths remain access-denied until authentication. Do not grant anonymous access content to make private menu links visible.

The five login links, the + link, and the Calendar links are Menu Link Config configuration entities. They are distributed in config/ with machine names such as anonymous_address_login and calendar_navigation_month; none has a packaged UUID. Reapplying the Recipe does not duplicate them or overwrite administrator changes to existing configuration entities. No custom module or extra setup command is needed for these links.

The drupal/menu_link_config dependency currently uses an alpha release and is not covered by Drupal's security advisory policy. Evaluate that dependency before deploying this candidate. Sites that tested an earlier revision with content-based login links must remove those five obsolete links through menu administration before applying this revision. Sites that installed the earlier seven content-based links must also remove the old +, Calendar, and five Calendar navigation links through menu administration. Confirm each old link's menu, title, and destination before deleting it, especially if the site has customized its menus. The Recipe does not delete existing site content automatically, so leaving an old link in place can display a duplicate.

The seven old links to replace are:

MenuTitleDestination
Main navigation+/node/add
CalendarCalendar/calendar/month
Calendar navigationMonth/calendar
Calendar navigationWeek/calendar/week
Calendar navigationDay/calendar/day
Calendar navigationYear/calendar/year
Calendar navigationList/calendar/list

Record any customized titles, weights, and destinations before removing these old links, then restore those settings on the generated configuration links after applying the revised Recipe. Reapplying the Recipe subsequently preserves those configuration changes.

The Recipe includes a small set of public RSS feed definitions for English, Japanese, Simplified Chinese, and Thai. Feed items are not included and are fetched only when Drupal's Aggregator refreshes the feeds. Anonymous visitors can read the i News lists; the other personal-service views remain protected. The feed sources are created by scripts/install-safe.sh, not by a content fixture in the Recipe. Applying drush recipe alone will not create them. After the guarded alpha2 installer succeeds, run vendor/bin/drush cron from the project root to request the first feed refresh. It requires outbound access to the included public feed URLs; items are not guaranteed to appear until the sources respond and Aggregator processes them. The legacy alpha1 manual sequence runs cron as its last step.

Re-applying the Recipe to an existing PixieNote installation is supported, but existing configuration entities are not automatically overwritten. Configuration actions do run again: they restore the Pixie Dark theme, accessible-menu and print settings, clear anonymous permissions, and grant the Recipe's authenticated permissions. Configuration actions also move only the tag View's menu settings to the main menu, expose its child links, restore Accessible Menu settings for the main menu, and hide the lower Tools block. Tag filters, ownership arguments, fields, and records are preserved. The Recipe's language overrides update the Tags menu title and description to their shipped translations; other language-specific configuration overrides are retained. They also keep the i Services View at /m, remove its legacy main-menu entry, restore the standard administration Add content link, and keep the separate main-menu + entry pointed at /node/add. Review those actions before re-applying to a customized site. Apply later configuration changes through Drupal's normal configuration management workflow. Re-application is not a content migration or a replacement for a site backup.

Postal codes on existing installations

The home and office postal code fields are strings in fresh installations so leading zeroes, hyphens, spaces, and letters are preserved. Re-applying the Recipe does not change existing field storage definitions. On an existing installation, plan and test a separate migration on a staging copy after taking a database and files backup. Prefer creating replacement string fields, copying and verifying the existing values, updating form and display settings, and only then removing the old fields. Integer storage may already have lost leading zeroes, which cannot be inferred reliably during migration. Do not attempt an in-place field type change or run a data migration without a reviewed site-specific plan.

Updating

Back up the database, private files, and active configuration first. On a standard Drupal 11 project, core-recipe-unpack moves the Recipe's package dependencies into the site's composer.json and removes drupal/pixienote as a direct requirement. Therefore composer update drupal/pixienote is not an update path. Review the desired release and the site's root dependency constraints, then fetch that Recipe release again. For the 1.x series, update any older restrictive Bootstrap Cloud and Twig root constraints at the same time. This is a one-time constraint migration, not a step for each dependency release. The installer may have unpacked the old exact theme constraint into the site's root composer.json; updating PixieNote alone could select an older Recipe release. Confirm that the existing feedback Contact form still has the intended recipient; rerunning setup-contact preserves it rather than syncing it to the current site email address.

Use the exact release being tested while only alpha releases are available. The example below upgrades from the initial alpha to 1.0.0-alpha2 after it is published. Change the Recipe version to the reviewed target release when updating; ^1.0 alone excludes alpha releases. The broad root theme constraint can remain unchanged for subsequent 7.x updates. The initial alpha still imposes its own exact theme dependency; using the newer Recipe is necessary to remove that package-level restriction. Keep Menu Link Config as an explicit root requirement while it has only an alpha release.

composer require 'drupal/pixienote:1.0.0-alpha2' 'drupal/menu_link_config:^1.0@alpha' 'drupal/bootstrap_cloud:^7' 'twig/twig:>=3.29 <3.30' 'drush/drush:^13' --with-all-dependencies

Recipe releases have no automatic update path. Existing configuration entities, including Views and blocks, retain local edits when a Recipe is re-applied, while configuration actions run again and can replace theme or permission customizations. Compare local configuration with the updated Recipe and import reviewed changes through your site's configuration management. Do not blindly replace the active configuration on a site with private data.

For 1.0.0-alpha2 or a newer release containing scripts/upgrade-safe.sh, use that guarded command after Composer resolves the reviewed release. First test a complete database and private-files restore on a staging copy, review site-specific configuration, and take a fresh verified backup. Then run from the project root:

PIXIENOTE_BACKUP_VERIFIED=1 bash recipes/pixienote/scripts/upgrade-safe.sh

This guard closes the site and validates the private-file path. Before running it, confirm that the existing installation still has at least one Aggregator feed source. The upgrade refuses a site with zero feeds rather than treating it as a fresh installation; inspect and restore its configuration and content from a verified backup before retrying. Feed setup adds current public sources whose URLs are not already present. It preserves every existing feed and its imported items, including administrator edits and older alpha1 sources; it neither rewrites nor deletes feeds. Therefore an alpha1 installation can temporarily retain the six older CCTV sources while adding six VOA sources (13 to 19 feeds). Reapplying is idempotent and does not add another copy of a current URL. Review and remove any retired feed only after deciding how its imported items should be retained. Image effects are likewise created with Drupal-generated IDs on fresh sites and left unchanged when their settings match. A failure keeps maintenance mode enabled for inspection. A successful run restores its original value.

From the published 1.0.0-alpha1 release

A disposable Drupal 11 installation confirmed that applying the current 1.x Recipe after the published 1.0.0-alpha1 archive preserves a synthetic private i Note. Its owner could still read it; another authenticated user and an anonymous visitor could not. This is a focused test, not a migration of a customized production site.

Reapplication does not remove content entities that were shipped by alpha1. Its six CCTV sample feeds remain when the six VOA replacements are added, so the sample feed count rises from 13 to 19. The alpha1 + link in Main navigation and Calendar link in the Calendar menu also remain alongside their new configuration-based counterparts. A site that used an intermediate development revision may have five additional legacy Calendar navigation links. Do not assume that a successful Recipe command produces the same menu and feed set as a fresh installation.

Before updating, back up the database, files, and active configuration, then record any edits to the old feeds and menu links. After reapplication, inspect the old + link targeting /node/add in Main navigation and the old Calendar link targeting /calendar/month in the Calendar menu. Remove only the confirmed legacy content-based links through menu administration; keep the new configuration-based links and any locally created links. Review the six CCTV feed URLs and their imported items before deciding whether to remove those feeds. Do not delete by a packaged UUID or blindly remove a feed with a matching title. Finally, check the menus in all four languages and verify that the owner, another authenticated user, and an anonymous visitor retain the expected access to private content. The full old-link inventory appears in the installation notes above.

Calendar navigation on existing installations

Fresh installations use a dedicated Calendar navigation menu and block for Month, Week, Day, Year, and List. Drupal generates these internal menu URLs with the active language prefix and installation base path. The block appears only on authenticated calendar pages, including empty calendars and the schedule list; the existing Calendar shortcut remains separate.

On an installation created before this change, re-application adds the new menu and block without replacing existing Views or schedule records. After backing up and reviewing local changes, edit the ischeduler_calendar View and remove only its legacy Schedule list link custom-text header (display.default.display_options.header.list_link) containing the five literal /calendar links. Retain any other locally added headers and the View's filters, arguments, displays, and schedule data. Export and review the resulting configuration, then rebuild caches. Do not replace the entire View to update navigation. Check all five menu links in each of the four languages.

What is installed

Content typePurposeList path
i AddressContacts/a
i BookmarkBookmarks/b
i NoteNotes/n
i SchedulerMonth and week calendars/calendar
i ServicesAdministrator-managed service links/m

The i News feed list is at /f, with its Top page at /top and a recent-news block on /m. The i Pics grid at /n/p shows images attached to the current user's i Note records. These are Views, not extra content types. RSS feeds and imported items are shared site content; they are not user-isolated. A new contact's birthday is empty until entered; the source site's "today" default is intentionally not carried over to avoid a misleading age.

Included RSS sample sources

LanguageSources
EnglishBBC News
Japaneseasahi.com, Yahoo! ニュース, 毎日新聞, 日本経済新聞
Simplified Chinese法广中文新闻; 美国之音中文网: 新闻, 编辑推荐, 国会报道, 台湾, 港澳, 军事
ThaiSanook!

The feed URLs are public examples and can be edited or removed after installation. The Recipe does not copy or publish any fetched feed items. The reference site's six CCTV feed URLs returned HTTP 403 and imported no items in a fresh-install check on 2026-10-04. The six public VOA Chinese replacement URLs are listed by the publisher at https://www.voachinese.com/rssfeeds and each imported items through Drupal Aggregator on that date. The existing RFI feed also imported items. Public feed availability can change; verify the sources again after installation. The guarded upgrade does not distinguish historical feed lists: it preserves whatever sources and imported items already exist. To use a different default list, review and make that change explicitly in Drupal after taking a backup. The reference site's CNN Top Stories URL returned only April 2023 items in the same check, so the Recipe uses BBC News for the English list instead. The legacy CNN URL is http://rss.cnn.com/rss/cnn_topstories.rss; add it manually only if its published items become current again.

The calendar opens at /calendar; /calendar/month is the reference site's monthly alias, linked from a Calendar menu in the header only on calendar pages. The weekly calendar is available at /calendar/week. Day and year views at /calendar/day and /calendar/year are chronological lists rather than calendar grids; both default to the current date or year and accept a date argument in the URL. The schedule list remains at /calendar/list. The configuration also installs an empty Tags vocabulary, tag lists, search, a responsive Pixie Dark theme, an accessible menu, and a printable browser view. Tags are optional at first because no example terms are installed. The accessible menu loads its pinned JavaScript build from jsDelivr; an offline installation needs a separately hosted copy. Bootstrap Cloud accepts compatible 7.x updates; the site's lockfile controls the version deployed. The selected HiraMaruPro-W4 font is not bundled with Bootstrap Cloud or this Recipe. Browsers without that font use the theme's fallback stack, so exact typography depends on fonts installed on each visitor's device. Twig is temporarily constrained to 3.29.x: 3.30.0 produces a template TypeError and HTTP 500 responses in the fresh Drupal 11.4.7 Recipe test environment. The constraint is unpacked into the site's root Composer requirements. Remove it only after an upstream fix is verified against the full Recipe suite. The footer uses the stable 3.x series of the Copyright Footer module. Its organization name, organization URL, origin year, version, and version URL start empty. After applying the Recipe, set your own values in the Copyright Footer block configuration; no publisher identity is installed as a site default. Bootstrap Cloud 7.1.8 centers the copyright/Contact row, restores the mobile navigation icon contrast, and fixes dark editor/form text colors. The public Contact link appears beside the copyright text in a centered row. The documented setup step creates the required Contact form from the installing site's own mail setting.

Privacy defaults

PixieNote grants authenticated users permissions for their own personal records and uses Node View Permissions for bundle-level view access. Review role permissions before allowing multiple unrelated users onto one site. Images use Drupal's private file scheme; configure file_private_path in settings.php before enabling uploads. Keep self-registration disabled, as in a fresh Minimal install. Taxonomy terms are a shared vocabulary, so this Recipe is intended for a personal site or a trusted group, not as a fully isolated multi-tenant service. Aggregator feed sources and their items are public, including to anonymous visitors. Add only sources suitable for that public audience. The news views filter by language, not by owner or by membership in the packaged sample list; newly added sources are not private. Do not add private feeds or feed URLs containing credentials or access tokens.

Verification

On a fresh test site, run the guarded installer both with a valid private-file path and with a path inside the web root. The invalid path must fail while leaving maintenance mode enabled. An error after Recipe application must also leave the site closed; a retry must clear the default grant before reopening. Assert that the node-access rebuild flag is clear, there is no nid = 0 default grant in node_access, and anonymous and other authenticated users cannot read another owner's private record or download its private image or thumbnail. The included functional and privacy-audit tests exercise those conditions.

The license audit compares the complete GPL text after normalizing whitespace. Drupal.org reformats LICENSE.txt in release downloads, so a byte-for-byte source checksum is not suitable for the distributed package. Changes to the license text still fail the audit; only whitespace formatting is ignored.

ReapplicationTest applies the Recipe to a populated, customized test site. It verifies preservation of a note, its tag and private image (including the file bytes), an edited RSS source, a Views title, a block weight, and the site name. It checks that existing entity IDs are unchanged, documented theme and permission actions run again, and the retained note and image remain readable only by their owner. This tests reapplication of the same Recipe, not an upgrade between different releases or a substitute for a backup/restore test. To run this focused check in the Drupal test checkout, with its test server running and the usual SIMPLETEST_* and browser-output variables configured:

vendor/bin/phpunit -c web/core/phpunit.xml.dist recipes/pixienote/tests/src/Functional/ReapplicationTest.php

If you use a PHP-enabled Drupal test checkout, run phpcs with the Drupal and DrupalPractice standards and run the tests in tests/. Current versions of several dependencies, including Calendar View and Printable, emit Drupal 11 deprecation notices. PHP 8.4 additionally reports nullable parameter deprecations in Calendar View. These are upstream compatibility warnings, not passing evidence for future Drupal versions; do not suppress test failures while reviewing them.

Scope

The Recipe reproduces the reusable structure and principal behavior of the source service. Production-only branding, analytics, advertising, mail settings, API credentials, content, and the site-specific print-link layout overlay are intentionally excluded. The production calendar uses a beta Calendar module with month, week, day, and year views. This Recipe recreates its month and week grids with the supported stable Calendar View module. Day and year views use Drupal core Views as chronological lists instead of grids, so the layout and navigation are not pixel-identical. PDF export relies on the browser's Print dialog; Printable's save-PDF feature is disabled.