{
    "version": "https://jsonfeed.org/version/1",
    "title": "Dev",
    "description": "",
    "home_page_url": "https://getpublii.com/dev",
    "feed_url": "https://getpublii.com/dev/feed.json",
    "user_comment": "",
    "author": {
        "name": "Tomasz Dziuda"
    },
    "items": [
        {
            "id": "https://getpublii.com/dev/is-not-helper/",
            "url": "https://getpublii.com/dev/is-not-helper/",
            "title": "{{#isNot}} helper",
            "summary": "The {{#isNot}} helper is a block helper designed to check if a specific context is not loaded. Think of it as the opposite of {{#is}}&hellip;",
            "content_html": "<p>The {{#isNot}} helper is a block helper designed to check if a specific context is <strong>not</strong> loaded. Think of it as the opposite of {{#is}} — it returns true when the page type doesn't match what you're checking for.</p>\n<p>The argument can be a comma-separated list of context names:</p>\n<ul>\n<li><strong>index</strong> - homepage,</li>\n<li><strong>homepage</strong> - new context for the homepage, applied when:\n<ul>\n<li>the <strong>posts</strong> are displayed on the homepage (the existing <strong>index</strong> context).</li>\n<li>the <strong>page</strong> is configured as a homepage (this is the key difference from <strong>index</strong>; normally, if a page is set as the homepage, it uses the page context, but with this new <strong>homepage</strong> context, the homepage can now have a dedicated context).</li>\n<li>The posts appear despite a post prefix (e.g., <code>/blog/</code>) being set, but no <strong>page as the homepage</strong> is explicitly assigned.</li>\n</ul>\n</li>\n<li><strong>blogindex</strong> - custom post listing page when a post prefix (e.g., <code>/blog/</code>) is set in Publii; used to display posts within a specific directory,</li>\n<li><strong>tag</strong> - tag listing page,</li>\n<li><strong>tags</strong> - tags listing,</li>\n<li><strong>post</strong> - single post page,</li>\n<li><strong>page</strong> - single page,</li>\n<li><strong>author</strong> - author listing page,</li>\n<li><strong>404</strong> - 404 error page,</li>\n<li><strong>search</strong> - search results page,</li>\n<li><strong>pagination</strong> - pagination page (tag or homepage) beginning from the second page,</li>\n<li><strong>index-pagination</strong> - pagination homepage page beginning from second page,</li>\n<li><strong>tag-pagination</strong> - pagination tag page beginning from the second page.</li>\n<li><strong>author-pagination</strong> - pagination author page beginning from the second page.</li>\n</ul>\n<p>Syntax:</p>\n<pre class=\"language-handlebars\"><code>{{#isNot ARGUMENT}}\nThis is NOT a page of the type specified in the argument\n{{else}}\nThis IS a page of the type specified in the argument\n{{/isNot}}\n</code></pre>\n<p>Examples:</p>\n<pre class=\"language-handlebars\"><code>{{#isNot \"index\"}}\n</code></pre>\n<p>Above code checks if the current page is <strong>not</strong> a homepage</p>\n<pre class=\"language-handlebars\"><code>{{#isNot \"index,tag\"}}\n</code></pre>\n<p>In the above code condition is true when current page is neither a homepage nor a tag page.</p>\n<pre class=\"language-handlebars\"><code>{{#isNot \"post\"}}\n  &lt;p&gt;This content appears everywhere except single post pages.&lt;/p&gt;\n{{/isNot}}\n</code></pre>\n<p>This is useful when you want to show something site-wide but hide it on individual posts.</p>\n<pre class=\"language-handlebars\"><code>{{#isNot \"404,search\"}}\n  {{&gt; sidebar}}\n{{/isNot}}\n</code></pre>",
            "author": {
                "name": "Tomasz Dziuda"
            },
            "tags": [
            ],
            "date_published": "2025-11-04T05:56:47+01:00",
            "date_modified": "2025-11-04T05:58:01+01:00"
        },
        {
            "id": "https://getpublii.com/dev/image/",
            "url": "https://getpublii.com/dev/image/",
            "title": "Image",
            "summary": "If you want to allow users to upload images in postConfig, pageConfig, authorConfig or tagConfig options, you can use the Image field. This simple field type&hellip;",
            "content_html": "<p>If you want to allow users to upload images in  <code>postConfig</code>, <code>pageConfig</code>, <code>authorConfig</code> or <code>tagConfig</code> options, you can use the <strong>Image</strong> field. This simple field type allows easy image uploads for your configuration needs.</p>\n<p>Here is an example of how to use it: </p>\n<pre class=\"language-json\"><code>{\n    \"name\": \"additionalImage\",\n    \"label\": \"Additional image\",\n    \"value\": \"\",\n    \"type\": \"image\"\n}</code></pre>\n<figure class=\"post__image\"><img loading=\"lazy\"  src=\"https://getpublii.com/dev/media/posts/163/image-control.svg\" alt=\"Image Control for post and page config\" width=\"748\" height=\"352\"></figure>\n<p>To upload images directly to the theme, it is recommended to use the <a href=\"https://getpublii.com/dev/image-upload/\">Image Upload</a> and <a href=\"https://getpublii.com/dev/small-image-upload/\">Small Image Upload</a> controls.</p>",
            "author": {
                "name": "Tomasz Dziuda"
            },
            "tags": [
                   "Theme Settings API"
            ],
            "date_published": "2025-01-14T12:44:34+01:00",
            "date_modified": "2025-04-02T09:48:33+02:00"
        },
        {
            "id": "https://getpublii.com/dev/getpagesbycustomfields-helper/",
            "url": "https://getpublii.com/dev/getpagesbycustomfields-helper/",
            "title": "{{#getPagesByCustomFields}} helper",
            "summary": "The {{getPagesByCustomFields}} helper is designed to retrieve page data based on the criteria defined by custom fields. This powerful feature allows for more precise control&hellip;",
            "content_html": "<p>The <code>{{getPagesByCustomFields}}</code> helper is designed to retrieve page data based on the criteria defined by custom fields. This powerful feature allows for more precise control over which pages are displayed.</p>\n<h2>Syntax</h2>\n<p>The basic syntax for <code>{{getPagesByCustomFields}}</code> involves specifying a query string that includes several parameters to define the search criteria:</p>\n<pre class=\"language-handlebars\"><code>{{#getPagesByCustomFields \"PARAMETERS\"}}\n    &lt;h2&gt;{{ title }}&lt;/h2&gt;\n    &lt;div&gt;{{{ excerpt }}}&lt;/div&gt;\n{{/getPagesByCustomFields}}\n</code></pre>\n<p>Example: </p>\n<pre class=\"language-handlebars\"><code>{{#getPagesByCustomFields \"count=5&amp;customField=indexTest1&amp;customFieldValue=XYZ&amp;customFieldCompare=not-equals\"}}\n    &lt;h2&gt;{{ title }}&lt;/h2&gt;\n    &lt;div&gt;{{{ excerpt }}}&lt;/div&gt;\n{{/getPagesByCustomFields}}\n</code></pre>\n<p>This example will display up to 5 posts where the custom field <code>indexTest1</code> does not equal <code>XYZ</code>.</p>\n<h3>QueryString Options</h3>\n<ul>\n<li><strong>count</strong>: Specifies the number of pages to include in the result. Use <code>-1</code> to return all pages matching the criteria.</li>\n<li><strong>customField</strong>: Indicates the custom field to filter pages by.</li>\n<li><strong>customFieldValue</strong>: Specifies the expected value of the custom field for a page to be included in the results.</li>\n<li><strong>customFieldCompare</strong>: Defines how to compare the custom field's value with <code>customFieldValue</code>. Options include:\n<ul>\n<li><code>equals</code> (default): Selects pages where the custom field value matches <em>customFieldValue</em>.</li>\n<li><code>not-equals</code>: Selects pages where the custom field value does not match <em>customFieldValue</em>.</li>\n<li><code>greater</code>, <code>greater-equals</code>, <code>lesser</code>, <code>lesser-equals</code>: For numeric comparisons.</li>\n<li><code>starts-with</code>, <code>ends-with</code>, <code>contains</code>, <code>not-contains</code>: For string comparisons.</li>\n</ul>\n</li>\n<li><strong>excluded</strong>: Lists IDs of pages to exclude from the results.</li>\n<li><strong>offset</strong>: Sets the number of pages to skip from the beginning of the result set.</li>\n<li><strong>orderby</strong>: Determines the field by which to order the results. Can be a standard field or a <code>customField</code>.</li>\n<li><strong>ordering</strong>: Specifies the direction of sorting (e.g., <code>asc</code>, <code>desc</code>, <code>random</code>).</li>\n<li><strong>orderbyCompareLanguage</strong>: If <code>orderby=customField</code>, allows specifying the locale for sorting, useful for language-specific sorting rules.</li>\n</ul>\n<h2>Detailed customFieldCompare Options</h2>\n<p>The <code>customFieldCompare</code> parameter in the <code>{{getPagesByCustomFields}}</code> helper allows for flexible comparisons between the specified <code>customFieldValue</code> and the values within the custom fields of pages. Understanding the available options for this parameter can significantly broaden your content display's customization and filtering capabilities.</p>\n<h3>Available  Values</h3>\n<ul>\n<li><strong>equals</strong> (default value): Selects pages where the custom field's value exactly matches the <i>customFieldValue</i>.</li>\n<li><strong>not-equals</strong>: Selects pages where the custom field's value does not match the <i>customFieldValue</i>.</li>\n<li><strong>greater</strong>: Targets pages where the custom field's value is greater than the <i>customFieldValue</i>. This is primarily used for numerical comparisons.</li>\n<li><strong>greater-equals</strong>: Selects pages where the custom field's value is greater than or equal to the <i>customFieldValue</i>, again mainly for numerical values.</li>\n<li><strong>lesser</strong>: Filters for pages where the custom field's value is less than the <i>customFieldValue</i>, suitable for numeric comparisons.</li>\n<li><strong>lesser-equals</strong>: Chooses pages where the custom field's value is less than or equal to the <i>customFieldValue</i>, used for numbers.</li>\n<li><strong>starts-with</strong>: Finds pages where the custom field's value begins with the sequence specified in <i>customFieldValue</i>.</li>\n<li><strong>ends-with</strong>: Filters pages where the custom field's value ends with the sequence specified in <i>customFieldValue</i>.</li>\n<li><strong>contains</strong>: Selects pages where the custom field's value contains the sequence specified in <i>customFieldValue</i>.</li>\n<li><strong>not-contains</strong>: The opposite of <code>contains</code>; it selects pages where the custom field's value does not contain the specified sequence.</li>\n</ul>\n<p>Understanding these options allows for precise control over which pages are retrieved based on custom field values, offering a powerful tool for customizing the display of content on your site.</p>\n<p class=\"msg msg--warning\"><strong>IMPORTANT:</strong> It requires availability of the <code>@website.contentStructure</code> global variable</p>",
            "author": {
                "name": "Tomasz Dziuda"
            },
            "tags": [
            ],
            "date_published": "2024-08-15T23:06:24+02:00",
            "date_modified": "2024-08-15T23:06:24+02:00"
        },
        {
            "id": "https://getpublii.com/dev/getpages-helper/",
            "url": "https://getpublii.com/dev/getpages-helper/",
            "title": "{{#getPages}} helper",
            "summary": "{{getPages}} is a helper used to retrieve page data regardless of the current context. Syntax: {{#getPages \"pageID1,pageID2,pageID3\" \"before\" \"after\"}} ... {{/getPages}} Example: {{#getPages \"PAGE_ID_1,PAGE_ID_2,PAGE_ID_N\" \"&lt;ul&gt;\"&hellip;",
            "content_html": "<p><strong>{{getPages}}</strong> is a helper used to retrieve page data regardless of the current context.</p>\n<p>Syntax:</p>\n<pre class=\"language-handlebars\"><code>{{#getPages \"pageID1,pageID2,pageID3\" \"before\" \"after\"}}\n...\n{{/getPages}}</code></pre>\n<p>Example:</p>\n<pre class=\"language-handlebars\"><code>{{#getPages \"PAGE_ID_1,PAGE_ID_2,PAGE_ID_N\" \"&lt;ul&gt;\" \"&lt;/ul&gt;\"}}\n&lt;li&gt;\n    &lt;h2&gt;{{ title }}&lt;/h2&gt;\n    &lt;div&gt;{{{ excerpt }}}&lt;/div&gt;\n&lt;/li&gt;\n{{/getPages}}</code></pre>\n<p>Pages are ordered by the ID order in the string.</p>\n<p>You can also use the <strong>@index</strong> variable to detect the post number in the specified collection:</p>\n<pre class=\"language-handlebars\"><code>{{#getPages \"1,2,3\" \"&lt;ul&gt;\" \"&lt;/ul&gt;\"}}\n&lt;li&gt;\n    &lt;h2&gt;{{ title }}&lt;/h2&gt;\n    &lt;div&gt;{{{ excerpt }}}&lt;/div&gt;\n    {{#checkIf @index '==' 0}}\n    &lt;p&gt;IT'S THE FIRST ELEMENT!&lt;/p&gt;\n    {{/checkIf}}\n&lt;/li&gt;\n{{/getPages}}</code></pre>\n<p>The second parameter creates an HTML prefix, and the third parameter creates an HTML suffix for the generated output.</p>\n<p>Additionally, it is possible to enhance the dynamic fetching and display of pages by utilizing the <a href=\"https://getpublii.com/dev/pages-dropdown/\">pages dropdown</a> control from the Theme Settings API, in conjunction with the <code>concatenate</code> helper to combine query string options with theme option values. This control allows users to select specific pages to be displayed. Integrating this functionality within your theme involves directly referencing the selected pages through the theme configuration. For instance, if you have a pages dropdown control named <code>pagesDropdown</code> in your Theme Settings, its value can be dynamically used with the <code>getPages</code> helper, as shown below:</p>\n<pre class=\"language-handlebars\"><code>{{#getPages (concatenate  @config.custom.pagesDropdown) \"&lt;ul&gt;\" \"&lt;/ul&gt;\"}}\n    &lt;li&gt;\n        &lt;h2&gt;{{ title }}&lt;/h2&gt;\n        &lt;div&gt;{{{ excerpt }}}&lt;/div&gt;\n    &lt;/li&gt;\n{{/getPages}}\n</code></pre>\n<p>In this setup, @config.custom.featuredPagesDropdown directly refers to the comma-separated page IDs the user selects through the dropdown control. This approach ensures that the displayed pages can be dynamically controlled via theme settings, offering a high level of customization for theme users.</p>\n<p class=\"msg msg--warning\"><strong>IMPORTANT:</strong> It requires availability of the <code>@website.contentStructure</code> global variable</p>",
            "author": {
                "name": "Tomasz Dziuda"
            },
            "tags": [
            ],
            "date_published": "2024-08-15T23:02:18+02:00",
            "date_modified": "2024-08-15T23:06:35+02:00"
        },
        {
            "id": "https://getpublii.com/dev/getpage-helper/",
            "url": "https://getpublii.com/dev/getpage-helper/",
            "title": "{{#getPage}} helper",
            "summary": "{{getPage}} is a helper used to retrieve page data regardless of the current context. Syntax: {{#getPage pageID}} ... {{/getPage}} Example: {{#getPage 10}} &lt;h2&gt;{{title}}&lt;/h2&gt; {{{excerpt}}} {{/getPage}}&hellip;",
            "content_html": "<p><strong>{{getPage}}</strong> is a helper used to retrieve page data regardless of the current context.</p>\n<p>Syntax:</p>\n<pre class=\"language-handlebars\"><code>{{#getPage pageID}}\n...\n{{/getPage}}</code></pre>\n<p>Example:</p>\n<pre class=\"language-handlebars\"><code>{{#getPage 10}}\n   &lt;h2&gt;{{title}}&lt;/h2&gt;\n   {{{excerpt}}}\n{{/getPage}}</code></pre>\n<p class=\"msg msg--warning\"><strong>IMPORTANT:</strong> It requires availability of the <code>@website.contentStructure</code> global variable</p>",
            "author": {
                "name": "Tomasz Dziuda"
            },
            "tags": [
            ],
            "date_published": "2024-08-15T22:59:21+02:00",
            "date_modified": "2024-08-15T23:06:38+02:00"
        },
        {
            "id": "https://getpublii.com/dev/pages-dropdown/",
            "url": "https://getpublii.com/dev/pages-dropdown/",
            "title": "Pages dropdown",
            "summary": "The pages dropdown can be used for situations where you want to allow users of your theme to use a specific relation to the given&hellip;",
            "content_html": "<p>The pages dropdown can be used for situations where you want to allow users of your theme to use a specific relation to the given page.</p>\n<p>It can be used e.g., to specify the privacy policy page:</p>\n<pre class=\"language-json\"><code>{\n    \"name\": \"homepageAboutUsPage\",\n    \"label\": \"About Us Page\",\n    \"group\": \"Homepage\",\n    \"value\": \"\",\n    \"type\": \"pages-dropdown\",\n    \"multiple\": false\n}</code></pre>\n<div class=\"post__entry\">\n<p>The pages dropdown returns the ID/s of the selected page/s as a value, so it should be connected with the use of the <a href=\"https://getpublii.com/dev/getpage-helper/\">getPage</a> or <a href=\"https://getpublii.com/dev/getpages-helper/\">getPages</a> helper. If the <strong>multiple</strong> option is set to true, then a string with IDs separated by commas is returned.</p>\n</div>",
            "author": {
                "name": "Tomasz Dziuda"
            },
            "tags": [
                   "Theme Settings API"
            ],
            "date_published": "2024-08-15T22:54:24+02:00",
            "date_modified": "2025-01-18T22:24:18+01:00"
        },
        {
            "id": "https://getpublii.com/dev/page-template-tags/",
            "url": "https://getpublii.com/dev/page-template-tags/",
            "title": "Page template tags",
            "summary": "Below you shall find a list of all the handlebars tags available in the page.hbs and page-TEMPLATE_NAME.hbs files. Template-specific tags {{#page}} - displayed page item Common&hellip;",
            "content_html": "<p>Below you shall find a list of all the handlebars tags available in the <strong>page.hbs</strong> and <strong>page-TEMPLATE_NAME.hbs</strong> files.</p>\n<h3>Template-specific tags</h3>\n<ul>\n<li><strong>{{#page}}</strong> - displayed <a href=\"https://getpublii.com/dev/page-tags/\">page item</a></li>\n</ul>\n<h3>Common tags</h3>\n<ul>\n<li><strong>{{title}}</strong> - page title</li>\n<li><strong>{{metaTitleRaw}}</strong> - meta title in raw form</li>\n<li><strong>{{metaDescriptionRaw}}</strong> - meta description in raw form</li>\n<li><strong>{{metaRobotsRaw}}</strong> - meta robots value in raw form</li>\n<li><strong>{{canonicalUrl}}</strong> - canonical URL for the post page</li>\n<li><strong>{{#featuredPosts}}</strong> - array of the featured <a href=\"https://getpublii.com/dev/post-tags/\">post items</a></li>\n<li><strong>{{hiddenPosts}}</strong> - array of the hidden <a href=\"https://getpublii.com/dev/post-tags/\">post items</a></li>\n<li><strong>{{#tags}}</strong> - array of all <a href=\"https://getpublii.com/dev/tag-tags/\">tag items</a> available on the website</li>\n<li><strong>{{#siteOwner}}</strong> - informations about main author as <a href=\"https://getpublii.com/dev/author-tags/\">author item</a></li>\n<li><strong>{{#authors}}</strong> - array of all <a href=\"https://getpublii.com/dev/author-tags/\">author items</a> on the website (if display of authors w/o posts is enabled it will contain also authors without posts)</li>\n<li><strong>{{menus}}</strong> - array of assigned menus (key is a menu position name)</li>\n<li><strong>{{unassignedMenus}}</strong> - array of unassigned menus (key is a slug of menu name)</li>\n</ul>",
            "author": {
                "name": "Tomasz Dziuda"
            },
            "tags": [
            ],
            "date_published": "2024-08-15T22:41:49+02:00",
            "date_modified": "2024-08-15T22:41:49+02:00"
        },
        {
            "id": "https://getpublii.com/dev/page-tags/",
            "url": "https://getpublii.com/dev/page-tags/",
            "title": "Page tags",
            "summary": "Page item represent pages created in Publii: {{id}} - page ID {{title}} - page title {{featuredImage}} - featured image item {{author}} - page author item&hellip;",
            "content_html": "<p>Page item represent pages created in Publii:</p>\n<ul>\n<li><strong>{{id}}</strong> - page ID</li>\n<li><strong>{{title}}</strong> - page title</li>\n<li><strong>{{featuredImage}}</strong> - <a href=\"https://getpublii.com/dev/featured-image-tags/\">featured image item</a></li>\n<li><strong>{{author}}</strong> - page <a href=\"https://getpublii.com/dev/author-tags/\">author item</a></li>\n<li><strong>{{slug}}</strong> - page slug used in URL</li>\n<li><strong>{{url}}</strong> - page URL</li>\n<li><strong>{{text}}</strong> - page full text</li>\n<li><strong>{{excerpt}}</strong> - page excerpt text</li>\n<li><strong>{{createdAt}}</strong> - page creation date</li>\n<li><strong>{{modifiedAt}}</strong> - page modification date</li>\n<li><strong>{{status}}</strong> - page status (draft)</li>\n<li><strong>{{template}}</strong> - template name used in the page</li>\n<li><strong>{{hasGallery}}</strong> - true if page contains a gallery</li>\n<li><strong>{{hasCustomExcerpt}}</strong> - true if page contains a custom excerpt content</li>\n<li><strong>{{pageViewConfig}}</strong> - object with additional page view-related configuration (if available in the theme</li>\n</ul>",
            "author": {
                "name": "Tomasz Dziuda"
            },
            "tags": [
            ],
            "date_published": "2024-08-15T22:39:16+02:00",
            "date_modified": "2024-08-15T22:39:16+02:00"
        },
        {
            "id": "https://getpublii.com/dev/how-to-add-pages-support-to-your-theme/",
            "url": "https://getpublii.com/dev/how-to-add-pages-support-to-your-theme/",
            "title": "How to add pages support in Publii themes",
            "summary": "Publii's 0.46 release introduced a powerful new feature: Pages. This allows you to create static content separate from your blog posts, perfect for content like&hellip;",
            "content_html": "<p>Publii's <a href=\"https://getpublii.com/blog/release-046.html\">0.46 release</a> introduced a powerful new feature: Pages. This allows you to create static content separate from your blog posts, perfect for content like \"About Us,\" \"Contact,\" or \"Services\" pages. While the official Publii themes released alongside version 0.46  seamlessly integrate Pages, custom or modified themes might require adjustments.</p>\n<p>This guide will walk you through adding Pages support to your Publii theme, ensuring you can take full advantage of this new feature without sacrificing your theme's unique design and functionality.</p>\n<h2>When do you need this guide?</h2>\n<p>You'll find this guide particularly useful if:</p>\n<ol>\n<li>You're using a custom or modified version of an official theme.</li>\n<li>You see a message indicating a lack of Pages support when accessing the Pages tab in Publii.</li>\n<li>You want to understand the technical aspects of implementing Pages support in Publii themes.</li>\n</ol>\n<p>Following these steps, you can extend your theme's capabilities and create rich, static pages within your Publii-powered website.</p>\n<h2>Step 1: Activating pages support</h2>\n<p>The first step is to inform Publii that your theme supports Pages by adding a flag to the theme's configuration file.</p>\n<ol>\n<li>Locate your theme's <code>config.json</code> file. It should be in the following directory:<br>\n<pre class=\"language-markdown\"><code>/Documents/Publii/sites/YOUR_SITE/input/themes/YOUR_THEME/config.json</code></pre>\n</li>\n<li>Open the <code>config.json</code> file in a text editor.</li>\n<li>Find the <code>supportedFeatures</code> section. If it doesn't exist, create it.</li>\n<li>Add the Pages support flag as follows:<br>\n<pre class=\"language-json\"><code>\"supportedFeatures\": {\n    \"pages\": true\n},</code></pre>\n<p> If other supported features exist, simply add the \"pages\" line to the existing object.</p>\n</li>\n</ol>\n<h2>Step 2: Creating the page.hbs file</h2>\n<p>Next, we need to create a template file for Pages. The easiest way is to duplicate the existing <code>post.hbs</code> file and modify it.</p>\n<ol>\n<li>In your theme directory, find the <code>post.hbs</code> file.</li>\n<li>Create a copy of this file and name it <code>page.hbs</code>.</li>\n<li>Open <code>page.hbs</code> in a text editor.</li>\n</ol>\n<p>Now, let's go through the main changes you must make on the <code>page.hbs</code> file:</p>\n<ol>\n<li>Change the main wrapper:\n<ul>\n<li>Replace <code>{{#post}}</code> with <code>{{#page}}</code> at the beginning of the file.</li>\n<li>Replace <code>{{/post}}</code> with <code>{{/page}}</code> at the end of the file.</li>\n</ul>\n</li>\n<li>Remove unsupported sections because they are specific to blog posts and don't apply to static pages:<br>\n<ul>\n<li>Delete the section for displaying tags.</li>\n<li>Remove the post navigation section (previous and next post links).</li>\n<li>Remove the related posts section.</li>\n</ul>\n</li>\n<li>Update configuration references:\n<ul>\n<li>Replace all occurrences of <code>@config.post</code> with <code>@config.page</code> e.g. <code>@config.post.displayFeaturedImage</code> to <code>@config.page.displayFeaturedImage</code></li>\n<li>Additionally, you need to update the <code>config.json</code> file to support page-specific configurations. This involves copying the <code>postConfig</code> section and modifying it to <code>pageConfig</code>. Remove any elements that don't apply to Pages, such as <code>displayRelatedPosts</code> and <code>displayPostNavigation</code>. Here's an example:<br>\n<pre class=\"language-json\"><code>\"pageConfig\": [\n    {\n        \"name\": \"displayDate\",\n        \"label\": \"Display date\",\n        \"value\": 0,\n        \"type\": \"select\",\n        \"pageTemplates\": \"!empty\",\n        \"options\": [\n            {\n                \"label\": \"Enabled\",\n                \"value\": 1\n            },\n            {\n                \"label\": \"Disabled\",\n                \"value\": 0\n            }\n        ]\n    },\n    {\n        \"name\": \"displayShareButtons\",\n        \"label\": \"Display share buttons\",\n        \"value\": 0,\n        \"type\": \"select\",\n        \"pageTemplates\": \"!empty\",\n        \"options\": [\n            {\n                \"label\": \"Enabled\",\n                \"value\": 1\n            },\n            {\n                \"label\": \"Disabled\",\n                \"value\": 0\n            }\n        ]\n    },\n    {\n        \"name\": \"displayChildPages\",\n        \"label\": \"Display child pages\",\n        \"value\": 0,\n        \"type\": \"select\",\n        \"options\": [\n            {\n                \"label\": \"Enabled\",\n                \"value\": 1\n            },\n            {\n                \"label\": \"Disabled\",\n                \"value\": 0\n            }\n        ]\n    }\n]\n</code></pre>\n</li>\n</ul>\n</li>\n<li>Add support for child pages (if needed):<br>\n<pre class=\"language-handlebars\"><code>{{#if @config.page.displayChildPages}}\n   {{#if subpages}}\n      &lt;div class=\"subpages\"&gt;\n         &lt;h2 class=\"subpages__title\"&gt;{{ translate 'page.childPages' }}&lt;/h2&gt;\n         &lt;ul class=\"subpages__list\"&gt;\n            {{#each subpages}}\n               {{#getPage @this}}\n                  &lt;li&gt;\n                     &lt;a href=\"{{url}}\"&gt;{{title}}&lt;/a&gt;\n                     {{#if subpages}}\n                     &lt;ul&gt;\n                        {{&gt; subpages-list}}\n                     &lt;/ul&gt;\n                     {{/if}}\n                  &lt;/li&gt;\n               {{/getPage}}\n            {{/each}}\n         &lt;/ul&gt;\n      &lt;/div&gt;\n   {{/if}}\n{{/if}}</code></pre>\n</li>\n<li>Update other references:\n<ul>\n<li>Change <code>@customHTML.beforePost</code> to <code>@customHTML.beforePage</code>. Additionally, you need to add the corresponding option in the <code>config.json</code> file. In the <code>renderer</code> section, add a new entry for <code>beforePage</code>:<br>\n<pre class=\"language-json\"><code>\"renderer\": {\n    \"customHTML\": {\n        \"beforePost\": \"Before every post\",\n        \"beforePage\": \"Before every page\"\n    }\n}</code></pre>\n</li>\n<li>Make similar changes for other post-specific references</li>\n</ul>\n</li>\n</ol>\n<p>Here's an example of how a section of your <code>page.hbs</code> might look after these changes:</p>\n<pre class=\"language-handlebars\"><code>{{&gt; head}}\n{{&gt; top}}\n&lt;main&gt;\n   {{#page}}\n      {{#if @customHTML.beforePage}}\n         &lt;div&gt;{{{@customHTML.beforePage}}}&lt;/div&gt;\n      {{/if}} \n      &lt;article&gt;\n         &lt;header&gt;\n            &lt;h1&gt;{{title}}&lt;/h1&gt;\n         &lt;/header&gt;\n         {{#if @config.page.displayFeaturedImage}}\n            {{#featuredImage}}\n               &lt;!-- Featured image code here --&gt;\n            {{/featuredImage}}\n         {{/if}}\n         &lt;div&gt;{{{text}}}&lt;/div&gt;\n         &lt;!-- More code here like author name, share buttons, comments ...--&gt;\n      &lt;/article&gt;\n   {{/page}}\n   {{&gt; sidebar}}\n&lt;/main&gt;\n{{&gt; footer}}</code></pre>\n<h2>Step 3: Restarting Publii</h2>\n<p>After making these changes:</p>\n<ol>\n<li>Save all modified files.</li>\n<li>Close Publii if it's currently running.</li>\n<li>Restart Publii to ensure all new settings are loaded.</li>\n</ol>\n<h2>Conclusion</h2>\n<p>You should now be able to create and edit Pages in your Publii project. Remember that the exact implementation may vary depending on your theme's specifics. Always test your changes thoroughly to ensure pages display correctly and don't introduce any errors.</p>\n<p>Following this guide, you've successfully extended your Publii theme to support the new Pages feature. This enhancement allows for more versatile content creation and site structure, opening up new possibilities for your static website.</p>",
            "author": {
                "name": "Tomasz Dziuda"
            },
            "tags": [
                   "Tutorials"
            ],
            "date_published": "2024-07-28T18:41:21+02:00",
            "date_modified": "2025-04-02T09:56:02+02:00"
        },
        {
            "id": "https://getpublii.com/dev/repeater/",
            "url": "https://getpublii.com/dev/repeater/",
            "title": "Repeater",
            "summary": "The Repeater field allows for the dynamic addition of a list of items, each comprising multiple fields. It's particularly useful for cases where a variable&hellip;",
            "content_html": "<p>The Repeater field allows for the dynamic addition of a list of items, each comprising multiple fields. It's particularly useful for cases where a variable number of entries, each with the same structure, is needed. Below is a detailed guide on its configuration and capabilities.</p>\n<h2>Configuration</h2>\n<p>The Repeater field is defined as follows:</p>\n<pre class=\"language-json\"><code>{\n  \"name\": \"test\",\n  \"label\": \"Repeater Test\",\n  \"group\": \"Global Changes\",\n  \"type\": \"repeater\",\n  \"value\": [],\n  \"maxCount\": 10,\n  \"translations\": {\n    \"addItem\": \"Add Item\",\n    \"duplicateItem\": \"Duplicate Item\",\n    \"emptyState\": \"Click the button to add the first item\",\n    \"removeItem\": \"Remove Item\"\n  },\n  \"hasEmptyState\": true,\n  \"hideLabels\": false,\n  \"structure\": [\n    {\n      \"name\": \"field1\",\n      \"label\": \"Field 1\",\n      \"type\": \"text\",\n      \"placeholder\": \"Fill it\",\n      \"spellcheck\": true,\n      \"value\": \"\",\n      \"width\": 25,\n      \"dependencies\": [\n        {\n          \"field\": \"use_global_setting\",\n          \"type\": \"pluginOption\",\n          \"value\": \"yes\"\n        }\n      ]\n    },\n    {\n      \"name\": \"field2\",\n      \"label\": \"Field 2\",\n      \"type\": \"number\",\n      \"placeholder\": \"Fill it\",\n      \"spellcheck\": true,\n      \"value\": 0,\n      \"width\": 25\n    },\n    {\n      \"name\": \"field3\",\n      \"label\": \"Field 3\",\n      \"type\": \"textarea\",\n      \"placeholder\": \"Fill it\",\n      \"spellcheck\": true,\n      \"value\": \"\",\n      \"width\": 50,\n      \"dependencies\": [\n        {\n          \"field\": \"field1\",\n          \"type\": \"option\",\n          \"value\": \"specific value\"\n        }\n      ]\n    }\n  ]\n}\n</code></pre>\n<h3>Field Properties</h3>\n<p>Below is a comprehensive breakdown of the field properties available within the repeater configuration. These properties are critical for defining the structure and behavior of each field in the repeater. They cover everything from the basic setup, such as naming and labeling fields, to more advanced configurations, like input placeholders, default values, and conditional dependencies. </p>\n<ul>\n<li><strong>structure</strong>: Defines the structure of the fields within each repeater item. Supports the following properties:\n<ul>\n<li><strong>name</strong>: Field name.</li>\n<li><strong>label</strong>: Field label for display.</li>\n<li><strong>type</strong>: Field type. Supported types include <code>text</code>, <code>number</code>, <code>textarea</code>, <code>dropdown</code>, <code>checkbox</code>, <code>radio</code>, <code>posts-dropdown</code>, <code>tags-dropdown</code>, <code>authors-dropdown</code>, <code>colorpicker</code>, <code>smallupload</code></li>\n<li><strong>options</strong>: Array of objects <code>{ label: X, value: Y }</code> for <code>dropdown</code> or <code>radio</code> types.</li>\n<li><strong>placeholder</strong>: Text placeholder for <code>text</code>, <code>number</code>, <code>email</code>, <code>url</code>, and <code>textarea</code>.</li>\n<li><strong>spellcheck</strong>: Enables spell check.</li>\n<li><strong>multiple</strong>: Enables multiple selections for dropdowns related to posts, tags, authors.</li>\n<li><strong>rows</strong>: Number of rows for <code>textarea</code>.</li>\n<li><strong>min</strong>, <strong>max</strong>, <strong>step</strong>: Attributes for <code>number</code> and <code>range</code> types.</li>\n<li><strong>allowed-post-status</strong>: Filters posts by status for <code>posts-dropdown</code>.</li>\n<li><strong>width</strong>: Field width as a percentage.</li>\n<li><strong>outputFormat</strong>: Format for the <code>colorpicker</code>.</li>\n<li><strong>value</strong>: Default value.</li>\n</ul>\n</li>\n<li><strong>maxCount</strong>: Maximum number of items allowed. Default is <code>-1</code> for unlimited.</li>\n<li><strong>translations</strong>: Custom translations for UI elements like add, duplicate, remove buttons.</li>\n<li><strong>hasEmptyState</strong>: Displays an empty state message when no items are present.</li>\n<li><strong>hideLabels</strong>: Option to hide field labels for all but the first item row.</li>\n</ul>\n<h3>Dependencies in Repeater Field</h3>\n<p>The Repeater field supports dependencies, enabling the dynamic display or hiding of fields based on the values of other fields within the same repeater item or global theme options. This functionality enhances the interactivity and adaptability of the form elements, providing a tailored user experience based on input. There are two types of dependencies:</p>\n<ol>\n<li>\n<p><strong>External Option Dependency</strong> (<code>externalOption</code>): This dependency type allows a field within a repeater to depend on a external option value. If the condition set by the <code>pluginOption</code> dependency is met, the field becomes visible or hidden according to the specified logic.</p>\n</li>\n<li>\n<p><strong>Option Dependency</strong>: This refers to dependencies between fields within the same repeater item. Unlike the <code>externalOption</code> type, this does not specify a dependency type, implying it's an intra-repeater dependency. It allows for the showing or hiding of fields based on the values of other fields within the same item.</p>\n</li>\n</ol>\n<h4>Example Configuration</h4>\n<p>To illustrate, consider the following JSON configuration snippet that demonstrates both types of dependencies:</p>\n<pre class=\"language-json\"><code>{\n  \"name\": \"use_in_text\",\n  \"label\": \"Use in post text\",\n  \"type\": \"checkbox\",\n  \"value\": true,\n  \"width\": 33,\n  \"dependencies\": [\n    {\n      \"field\": \"wrapper\",\n      \"type\": \"externalOption\",\n      \"value\": \"custom\"\n    }\n  ]\n},\n{\n  \"name\": \"use_in_title\",\n  \"label\": \"Use in post title\",\n  \"type\": \"checkbox\",\n  \"value\": false,\n  \"width\": 33,\n  \"dependencies\": [\n    {\n      \"field\": \"use_in_text\",\n      \"type\": \"option\",\n      \"value\": \"true\"\n    }\n  ]\n}\n</code></pre>\n<h4>Dependency Logic Explained</h4>\n<ul>\n<li>\n<p><strong>External Option Dependency</strong>: The field <code>use_in_text</code> is visible only if the external option <code>wrapper</code> is set to <code>custom</code>. This demonstrates how a field within a repeater can depend on an external setting.</p>\n</li>\n<li>\n<p><strong>Intra-Repeater Dependency</strong>: The visibility of <code>use_in_title</code> is contingent upon the <code>use_in_text</code> checkbox being checked (<code>true</code>). This showcases the dependency of one field on another within the same repeater item.</p>\n</li>\n</ul>\n<h2>Implementing in Theme</h2>\n<p>After configuring the repeater field within your theme settings, the next step is to render the added items on your website. This section explains how to display the content of a repeater field named \"test\" within a Publii theme using Handlebars templating.</p>\n<h3>Rendering Repeater Field Content</h3>\n<p>To display each item from the repeater in your theme, you will utilize the Handlebars <code>each</code> loop. This method iterates over the items in the repeater field, allowing you to access and render the individual fields' values.</p>\n<p>Below is a sample code snippet that demonstrates how to loop through the items in the \"test\" repeater field and display the content of <code>field1</code>, <code>field2</code>, and <code>field3</code> within your theme, e.g. in <code>index.hbs</code> file:</p>\n<pre class=\"language-handlebars\"><code>{{#each @config.custom.test}}\n  &lt;div class=\"custom-repeater-item\"&gt;\n    &lt;div class=\"field\"&gt;\n      &lt;span class=\"label\"&gt;Field 1:&lt;/span&gt;\n      &lt;span class=\"value\"&gt;{{field1}}&lt;/span&gt;\n    &lt;/div&gt;\n    &lt;div class=\"field\"&gt;\n      &lt;span class=\"label\"&gt;Field 2:&lt;/span&gt;\n      &lt;span class=\"value\"&gt;{{field2}}&lt;/span&gt;\n    &lt;/div&gt;\n    &lt;div class=\"field\"&gt;\n      &lt;span class=\"label\"&gt;Field 3:&lt;/span&gt;\n      &lt;p class=\"value\"&gt;{{field3}}&lt;/p&gt;\n    &lt;/div&gt;\n  &lt;/div&gt;\n{{/each}}\n</code></pre>\n<h4>Key Points:</h4>\n<ul>\n<li><strong>Iteration</strong>: <code>{{#each @config.custom.test}}</code> iterates over the repeater items, allowing access to each item's fields.</li>\n<li><strong>Field Access</strong>: Inside the loop, <code>{{field1}}</code>, <code>{{field2}}</code>, <code>{{field3}}</code> are used to insert the values of the corresponding fields.</li>\n<li><strong>HTML Structure</strong>: The sample uses <code>div</code> and <code>span</code> tags to structure the output, which can be customized based on your theme's design requirements.</li>\n</ul>",
            "author": {
                "name": "Tomasz Dziuda"
            },
            "tags": [
                   "Theme Settings API"
            ],
            "date_published": "2024-03-23T08:46:55+01:00",
            "date_modified": "2025-09-27T13:31:48+02:00"
        }
    ]
}
