<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="/feed.xsl" type="text/xsl"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/">
<channel>
<title>publican.dev</title>
<link>https://publican.dev/</link>
<atom:link href="https://publican.dev/feed.xml" rel="self" type="application/rss+xml" />
<language>en-US</language>
<description>Publican: a simpler HTML-first Static Site Generator for Node.js.</description>
<lastBuildDate>Wed, 15 Apr 2026 15:43:50 GMT</lastBuildDate>
<sy:updatePeriod>daily</sy:updatePeriod>
<sy:updateFrequency>1</sy:updateFrequency>
<item>
<title>StaticSearch v0.7.0 update</title>
<link>https://publican.dev/news/staticsearch-0.7.0/</link>
<guid isPermaLink="true">https://publican.dev/news/staticsearch-0.7.0/</guid>
<pubDate>Wed, 15 Apr 2026 00:00:00 GMT</pubDate>
<dc:creator>Craig Buckler</dc:creator>
<description>StaticSearch v0.7.0 improves search functionality and provides useful accessibility improvements.</description>
<content:encoded><![CDATA[
<p><a href="https://www.npmjs.com/package/staticsearch">StaticSearch v0.7.0</a> was released on <time datetime="2026-04-14">April 14, 2026</time>. There should be no breaking changes but there are a few new features included <em>fuzzier</em> results generation.</p>
<h2 id="fuzzy-search-results">Fuzzy search results</h2>
<p>StaticSearch now finds partial segments of words so there’s less need to type them in full.</p>
<ul>
<li>
<p>When you type the characters <code class="language-bash"><span class="token string">"exp"</span></code>, the results show pages containing words such as “expert”, “explain”, “explicit”, “explore”, “export”, and “express”.</p>
</li>
<li>
<p>Changing the search term to <code class="language-bash"><span class="token string">"expl"</span></code> returns pages with the words “explain”, “explicit”, and “explore”.</p>
</li>
<li>
<p>Changing it to <code class="language-bash"><span class="token string">"expla"</span></code> then returns pages with “explain”.</p>
</li>
</ul>
<p>A <code class="language-bash">fuzzy</code> setting determines the maximum number of words to fetch. Set it on the <a href="https://publican.dev/tools/staticsearch/search-web-component/">web component</a>:</p>
<p class="filename language-html"><dfn>HTML excerpt</dfn></p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>static-search</span> <span class="token attr-name">fuzzy</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>5<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>search<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>static-search</span><span class="token punctuation">></span></span>
</code></pre>
<p>the <a href="https://publican.dev/tools/staticsearch/search-bind-module/#input-field-attributes">bind module <code class="language-bash"><span class="token operator">&lt;</span>input<span class="token operator">></span></code> field</a>:</p>
<p class="filename language-html"><dfn>HTML excerpt</dfn></p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>search<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>staticsearch_search<span class="token punctuation">"</span></span> <span class="token attr-name">fuzzy</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>5<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
</code></pre>
<p>or as the second argument of the <a href="https://publican.dev/tools/staticsearch/search-api/#staticsearchfind-method">API .find() method</a>:</p>
<p class="filename language-js"><dfn>JavaScript excerpt</dfn></p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> result <span class="token operator">=</span> <span class="token keyword">await</span> staticsearch<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token string">'my search query'</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<ul>
<li>The default <code class="language-bash">fuzzy</code> value is <code class="language-bash"><span class="token number">6</span></code>. Searching for <code class="language-bash"><span class="token string">"exp"</span></code> returns results for all six words above.</li>
<li>Setting <code class="language-bash"><span class="token assign-left variable">fuzzy</span><span class="token operator">=</span><span class="token string">"3"</span></code> returns results for the first three words (“expert”, “explain”, and “explicit”).</li>
<li>Setting <code class="language-bash"><span class="token assign-left variable">fuzzy</span><span class="token operator">=</span><span class="token string">"1"</span></code> or lower reverts to the original search behaviour and the user must type most of the word before results appear.</li>
</ul>
<h2 id="keyboardfocusable-activation">Keyboard-focusable activation</h2>
<p>The <a href="https://publican.dev/tools/staticsearch/search-web-component/#search-activation-element"><code class="language-bash"><span class="token operator">&lt;</span>static-search<span class="token operator">></span></code> activation element</a> which triggers the search dialog is now keyboard-focusable so you can open it by hitting Enter or space.</p>
<h2 id="activate-search-from-any-element">Activate search from any element</h2>
<p>When using the <a href="https://publican.dev/tools/staticsearch/search-web-component/"><code class="language-bash"><span class="token operator">&lt;</span>static-search<span class="token operator">></span></code> web component</a>, any HTML element can trigger the search dialog by adding a <code class="language-bash">data-static-search</code> attribute, e.g.</p>
<p class="filename language-html"><dfn>HTML excerpt</dfn></p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#<span class="token punctuation">"</span></span> <span class="token attr-name">data-static-search</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>search<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>click here to search<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span>
</code></pre>
<h2 id="activation-element-part-name">Activation element <code class="language-bash">::part</code> name</h2>
<p>The <a href="https://publican.dev/tools/staticsearch/search-web-component/#search-activation-element">activation element</a> sets a <code class="language-bash">part</code> attribute name of <code class="language-bash">activate</code> unless you define your own, e.g.</p>
<p class="filename language-html"><dfn>HTML excerpt</dfn></p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>static-search</span> <span class="token attr-name">fuzzy</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>5<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token attr-name">part</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>trigger<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>search<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>static-search</span><span class="token punctuation">></span></span>
</code></pre>
<p>Style it using the <code class="language-bash">part</code> name, e.g.</p>
<p class="filename language-css"><dfn>CSS excerpt</dfn></p>
<pre class="language-css"><code class="language-css"><span class="token selector">static-search::part(trigger)</span> <span class="token punctuation">{</span>
<span class="token property">color</span><span class="token punctuation">:</span> #00f<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre>
<h2 id="build-directory-location">Build directory location</h2>
<p>The StaticSearch <a href="https://publican.dev/tools/staticsearch/search-indexer/">indexer</a> now looks for static sites built to the subdirectories:</p>
<ol>
<li><code class="language-bash">./build/</code></li>
<li><code class="language-bash">./dist/</code></li>
<li><code class="language-bash">./dest/</code></li>
<li><code class="language-bash">./out/</code>, or</li>
<li><code class="language-bash">./target/</code></li>
</ol>
<p>When none exist, it uses the current working directory.</p>
<h2 id="omit-default-stop-words">Omit default stop words</h2>
<p>StaticSearch automatically removes common stop words considered insignificant to the meaning of text – such as “and”, “the”, and “but” in English. It supports stop words in Afrikaans (<code class="language-bash">af</code>), Croatian (<code class="language-bash">hr</code>), Czech (<code class="language-bash">cs</code>), Danish (<code class="language-bash">da</code>), Dutch (<code class="language-bash"><span class="token function">nl</span></code>), English (<code class="language-bash">en</code>), Estonian (<code class="language-bash">et</code>), Finnish (<code class="language-bash"><span class="token keyword">fi</span></code>), French (<code class="language-bash">fr</code>), German (<code class="language-bash">de</code>), Hungarian (<code class="language-bash">hu</code>), Irish (<code class="language-bash">ga</code>), Italian (<code class="language-bash">it</code>), Latvian (<code class="language-bash">lv</code>), Lithuanian (<code class="language-bash">lt</code>), Malay (<code class="language-bash">ms</code>), Norwegian (<code class="language-bash">no</code>), Polish (<code class="language-bash">pl</code>), Portuguese (<code class="language-bash">pt</code>), Romanian (<code class="language-bash">ro</code>), Slovak (<code class="language-bash">sk</code>), Somali (<code class="language-bash">so</code>), Spanish (<code class="language-bash">es</code>), Swahili (<code class="language-bash">sw</code>), Swedish (<code class="language-bash">sv</code>), Turkish (<code class="language-bash"><span class="token function">tr</span></code>), and Zulu (<code class="language-bash">zu</code>).</p>
<p>In some cases, such as smaller sites, you may wish to omit these defaults or use your own set. You can do this on the command line:</p>
<p class="filename language-bash"><dfn>terminal</dfn></p>
<pre class="language-bash"><code class="language-bash">staticsearch <span class="token parameter variable">-W</span>
<span class="token comment"># or</span>
staticsearch <span class="token parameter variable">--ignorestopdefault</span>
</code></pre>
<p>in an <a href="https://publican.dev/tools/staticsearch/search-indexer/#load-environment-files">environment variable</a>:</p>
<p class="filename language-ini"><dfn>example <code class="language-bash">.env</code></dfn></p>
<pre class="language-ini"><code class="language-ini"><span class="token comment"># StaticSearch environment variables</span>
<span class="token key attr-name">STOPWORDS_DEFAULT</span><span class="token punctuation">=</span><span class="token value attr-value">false</span>
</code></pre>
<p>or using the <a href="https://publican.dev/tools/staticsearch/search-indexer/#using-the-staticsearch-nodejs-api">Node.js API</a>:</p>
<p class="filename language-js"><dfn><code class="language-bash">index.js</code> example</dfn></p>
<pre class="language-js"><code class="language-js"><span class="token comment">// run indexer</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> staticsearch <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'staticsearch'</span><span class="token punctuation">;</span>
staticsearch<span class="token punctuation">.</span>stopWordsDefault <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token keyword">await</span> staticsearch<span class="token punctuation">.</span><span class="token function">index</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<h2 id="miscellaneous-updates">Miscellaneous updates</h2>
<p>Minor changes include:</p>
<ul>
<li>Index files are generated to a <code class="language-bash">search</code> subdirectory of the build directory unless overridden.</li>
<li>The search result scrollbar thumbs now use the <code class="language-bash">--staticsearch-color-fore2</code> color.</li>
<li>Words with valid technical meanings have been removed from the English stop word list.</li>
<li>Slug paths generated on Windows devices now use <code class="language-bash">/</code> rather than <code class="language-bash"><span class="token punctuation">&#92;</span></code>.</li>
</ul>
<h2 id="get-started">Get started</h2>
<p>The <a href="https://publican.dev/tools/staticsearch/">StaticSearch documentation</a> provides a <a href="https://publican.dev/tools/staticsearch/quickstart/">quick start guide</a>, and details about the <a href="https://publican.dev/tools/staticsearch/search-indexer/">indexer</a>, <a href="https://publican.dev/tools/staticsearch/search-web-component/">web component</a>, <a href="https://publican.dev/tools/staticsearch/search-bind-module/">bind module</a>, and <a href="https://publican.dev/tools/staticsearch/search-api/">JavaScript API</a>.</p>
<p>StaticSearch works well with Publican sites. The <a href="https://publican.dev/docs/">Publican documentation</a> provides a <a href="https://publican.dev/docs/quickstart/concepts/">quick start guide</a>, a <a href="https://publican.dev/docs/setup/content/">detailed set-up guide</a>, <a href="https://publican.dev/docs/reference/publican-options/">API references</a>, and <a href="https://publican.dev/docs/recipe/">common recipes</a> you can use and adapt for your own projects.</p>
<ul class="flexcenter">
<li><a href="https://publican.dev/docs/quickstart/concepts" class="button">Get started</a></li>
<li><a href="https://publican.dev/about/donate/" class="button">Donate</a></li>
</ul>
]]></content:encoded>
</item>
<item>
<title>Publican v0.12.1 update and documentation theme</title>
<link>https://publican.dev/news/publican_0.12.1-doc-theme/</link>
<guid isPermaLink="true">https://publican.dev/news/publican_0.12.1-doc-theme/</guid>
<pubDate>Mon, 09 Mar 2026 00:00:00 GMT</pubDate>
<dc:creator>Craig Buckler</dc:creator>
<description>A new Publican theme for documentation websites has been released.</description>
<content:encoded><![CDATA[
<p><a href="https://www.npmjs.com/package/publican">Publican v0.12.1</a> was released on <time datetime="2026-03-03">March 3, 2026</time>.</p>
<p>This was a third-party module update so there are no breaking changes.</p>
<h2 id="documentation-theme">Documentation theme</h2>
<p>A new Publican theme is available that’s designed for documentation websites.</p>
<img src="https://publican.dev/images/publican-theme-doc.avif" alt="Publican documentation theme" width="1590" height="1425"  loading="lazy">
<ul>
<li>
<p><strong>demonstration site:</strong></p>
<p><a href="https://publican-theme-doc.pages.dev/">https://publican-theme-doc.pages.dev/</a></p>
</li>
<li>
<p><strong>code repository:</strong></p>
<p><a href="https://github.com/craigbuckler/publican.theme.doc">github.com/craigbuckler/publican.theme.doc</a></p>
</li>
</ul>
<p>The theme is fast, standards based, and uses best practise techniques. It features main menus, page menus, <a href="https://publican.dev/tools/staticsearch/">StaticSearch</a>, a responsive layout, a light/dark switcher, sitemaps, security, and a 100% Lighthouse performance score.</p>
<p>The theme uses new CSS techniques to provide complimentary light and dark mode color schemes from a single hue value (<code class="language-bash"><span class="token number">0</span></code> to <code class="language-bash"><span class="token number">360</span></code>) set in the <code class="language-bash">.env.dev</code> file:</p>
<p class="filename language-bash"><dfn><code class="language-bash">.env.dev</code></dfn></p>
<pre class="language-bash"><code class="language-bash"><span class="token comment"># default blue</span>
<span class="token assign-left variable">SITE_THEMEHUE</span><span class="token operator">=</span><span class="token number">270</span>
</code></pre>
<p>If necessary, you can override this and specify your own CSS colors. The theme uses <a href="https://esbuild.github.io/">esbuild</a> to bundle and minify client-side CSS and JavaScript files.</p>
<p>Please <a href="https://github.com/craigbuckler/publican.theme.doc">download and adapt the theme</a> for your own purposes. Alternatives are available on the <a href="https://publican.dev/themes/">themes page</a>.</p>
<h2 id="get-started">Get started</h2>
<p>The <a href="https://publican.dev/docs/">Publican documentation</a> provides a <a href="https://publican.dev/docs/quickstart/concepts/">quick start guide</a>, a <a href="https://publican.dev/docs/setup/content/">detailed set-up guide</a>, <a href="https://publican.dev/docs/reference/publican-options/">API references</a>, and <a href="https://publican.dev/docs/recipe/">common recipes</a> you can use and adapt for your own projects.</p>
<ul class="flexcenter">
<li><a href="https://publican.dev/docs/quickstart/concepts" class="button">Get started</a></li>
<li><a href="https://publican.dev/about/donate/" class="button">Donate</a></li>
</ul>
]]></content:encoded>
</item>
<item>
<title>StaticSearch v0.6.0 update</title>
<link>https://publican.dev/news/staticsearch-0.6.0/</link>
<guid isPermaLink="true">https://publican.dev/news/staticsearch-0.6.0/</guid>
<pubDate>Tue, 06 Jan 2026 00:00:00 GMT</pubDate>
<dc:creator>Craig Buckler</dc:creator>
<description>StaticSearch v0.6.0 improves results ordering, can highlight search terms in a page, and supports more languages.</description>
<content:encoded><![CDATA[
<p><a href="https://www.npmjs.com/package/staticsearch">StaticSearch v0.6.0</a> was released on <time datetime="2026-01-06">January 6, 2026</time>. There should be no breaking changes but there are a few new features and results ordering may change.</p>
<h2 id="improved-results-ordering">Improved results ordering</h2>
<p>The latest update:</p>
<ol>
<li>
<p>orders results from highest to lowest relevancy as before.</p>
</li>
<li>
<p>If those values match, it orders results from highest to lowest <code class="language-bash">found</code> value (a number between <code class="language-bash"><span class="token number">0</span></code> and <code class="language-bash"><span class="token number">1</span></code> that indicates the proportion of search words found in a page).</p>
</li>
<li>
<p>If those values match, it orders results from newest to oldest date.</p>
</li>
</ol>
<h2 id="highlight-search-words">Highlight search words</h2>
<p>Setting a <code class="language-bash">highlight</code> attribute on the <a href="https://publican.dev/tools/staticsearch/search-web-component/#web-component-attributes">web component</a> or <a href="https://publican.dev/tools/staticsearch/search-bind-module/#search-result-attributes">bind module</a> scrolls to and highlights the first matching search terms on a results page.</p>
<p>This uses <a href="https://developer.mozilla.org/docs/Web/URI/Reference/Fragment/Text_fragments">text fragment links</a> which can have issues:</p>
<ol>
<li>
<p>searching for “highlight” will return pages containing “highlighted” and “highlighter”, but they are not highlighted.</p>
</li>
<li>
<p>A highlighted word could appear outside your main content, such as in a menu.</p>
</li>
</ol>
<h2 id="selected-search-text">Selected search text</h2>
<p>When using the <a href="https://publican.dev/tools/staticsearch/search-web-component/"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>static-search</span><span class="token punctuation">></span></span></code> web component</a>, activating search now selects the current search term as well as focusing the field. This allows quicker searches for a new term.</p>
<h2 id="additional-language-support">Additional language support</h2>
<p>StaticSearch removes commonly-used <em>stop words</em> considered insignificant to the meaning of text – such as <em>“and”</em>, <em>“the”</em>, and <em>“but”</em> in English. This can produce better results and v0.6.0 now supports stop words in:</p>
<ul>
<li>Afrikaans (<code class="language-bash">af</code>)</li>
<li>Croatian (<code class="language-bash">hr</code>)</li>
<li>Czech (<code class="language-bash">cs</code>)</li>
<li>Danish (<code class="language-bash">da</code>)</li>
<li>Dutch (<code class="language-bash"><span class="token function">nl</span></code>)</li>
<li>English (<code class="language-bash">en</code>)</li>
<li>Estonian (<code class="language-bash">et</code>)</li>
<li>Finnish (<code class="language-bash"><span class="token keyword">fi</span></code>)</li>
<li>French (<code class="language-bash">fr</code>)</li>
<li>German (<code class="language-bash">de</code>)</li>
<li>Hungarian (<code class="language-bash">hu</code>)</li>
<li>Irish (<code class="language-bash">ga</code>)</li>
<li>Italian (<code class="language-bash">it</code>)</li>
<li>Latvian (<code class="language-bash">lv</code>)</li>
<li>Lithuanian (<code class="language-bash">lt</code>)</li>
<li>Malay (<code class="language-bash">ms</code>)</li>
<li>Norwegian (<code class="language-bash">no</code>)</li>
<li>Polish (<code class="language-bash">pl</code>)</li>
<li>Portuguese (<code class="language-bash">pt</code>)</li>
<li>Romanian (<code class="language-bash">ro</code>)</li>
<li>Slovak (<code class="language-bash">sk</code>)</li>
<li>Somali (<code class="language-bash">so</code>)</li>
<li>Spanish (<code class="language-bash">es</code>)</li>
<li>Swahili (<code class="language-bash">sw</code>)</li>
<li>Swedish (<code class="language-bash">sv</code>)</li>
<li>Turkish (<code class="language-bash"><span class="token function">tr</span></code>)</li>
<li>Zulu (<code class="language-bash">zu</code>)</li>
</ul>
<h2 id="smaller-payload">Smaller payload</h2>
<p>Thanks to an <a href="https://esbuild.github.io/">esbuild</a> update, the minified JavaScript has reduced by a couple of kilobytes to less than 11Kb – <em>despite having more code!</em></p>
<h2 id="get-started">Get started</h2>
<p>The <a href="https://publican.dev/tools/staticsearch/">StaticSearch documentation</a> provides a <a href="https://publican.dev/tools/staticsearch/quickstart/">quick start guide</a>, and details about the <a href="https://publican.dev/tools/staticsearch/search-indexer/">indexer</a>, <a href="https://publican.dev/tools/staticsearch/search-web-component/">web component</a>, <a href="https://publican.dev/tools/staticsearch/search-bind-module/">bind module</a>, and <a href="https://publican.dev/tools/staticsearch/search-api/">JavaScript API</a>.</p>
<p>StaticSearch works well with Publican sites. The <a href="https://publican.dev/docs/">Publican documentation</a> provides a <a href="https://publican.dev/docs/quickstart/concepts/">quick start guide</a>, a <a href="https://publican.dev/docs/setup/content/">detailed set-up guide</a>, <a href="https://publican.dev/docs/reference/publican-options/">API references</a>, and <a href="https://publican.dev/docs/recipe/">common recipes</a> you can use and adapt for your own projects.</p>
<ul class="flexcenter">
<li><a href="https://publican.dev/docs/quickstart/concepts" class="button">Get started</a></li>
<li><a href="https://publican.dev/about/donate/" class="button">Donate</a></li>
</ul>
]]></content:encoded>
</item>
<item>
<title>Publican v0.12.0 update</title>
<link>https://publican.dev/news/publican-0.12.0/</link>
<guid isPermaLink="true">https://publican.dev/news/publican-0.12.0/</guid>
<pubDate>Tue, 09 Dec 2025 00:00:00 GMT</pubDate>
<dc:creator>Craig Buckler</dc:creator>
<description>Publican v0.12.0 improves virtual content and supports markdown templates.</description>
<content:encoded><![CDATA[
<p><a href="https://www.npmjs.com/package/publican">Publican v0.12.0</a> was released on <time datetime="2025-12-09">December 9, 2025</time>.</p>
<p>There should be no breaking changes but it may change how you approach organizing content and templates.</p>
<h2 id="virtual-content-data-objects">Virtual content data objects</h2>
<p>Previous versions of Publican permitted <a href="https://publican.dev/docs/setup/content/#virtual-content-files">virtual content files</a> that could be programmatically added, e.g.</p>
<p class="filename language-js"><dfn><code class="language-bash">publican.config.js</code></dfn></p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> content <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">&#96;</span><span class="token string">
---
title: Virtual post
description: My first virtual post
author: Craig Buckler
date: 2026-01-02
---
This is a virtual post!
</span><span class="token template-punctuation string">&#96;</span></span><span class="token punctuation">;</span>
publican<span class="token punctuation">.</span><span class="token function">addContent</span><span class="token punctuation">(</span>
<span class="token string">'article/virtual-post.md'</span><span class="token punctuation">,</span>
  content
&#96;<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p>The main drawback was you had to convert values to a string and place them into the front matter … <em>only for Publican to convert them back again!</em> This was cumbersome when reading JSON data from a Content Management System.</p>
<p>The <a href="https://publican.dev/docs/reference/publican-methods/#addcontent"><code class="language-bash">.addContent<span class="token punctuation">(</span><span class="token punctuation">)</span></code> method</a> in Publican v0.12.0 supports an optional property/value <code class="language-bash">dataObject</code> as the third parameter:</p>
<pre class="language-js"><code class="language-js">publican<span class="token punctuation">.</span><span class="token function">addContent</span><span class="token punctuation">(</span> <span class="token operator">&lt;</span>filename<span class="token operator">></span><span class="token punctuation">,</span> <span class="token operator">&lt;</span>content<span class="token operator">></span> <span class="token punctuation">[</span><span class="token punctuation">,</span> <span class="token operator">&lt;</span>dataObject<span class="token operator">></span> <span class="token punctuation">]</span> <span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p>For example:</p>
<p class="filename language-js"><dfn><code class="language-bash">publican.config.js</code></dfn></p>
<pre class="language-js"><code class="language-js">publican<span class="token punctuation">.</span><span class="token function">addContent</span><span class="token punctuation">(</span>
<span class="token string">'article/virtual-post.md'</span><span class="token punctuation">,</span>
<span class="token keyword">null</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span>
<span class="token literal-property property">title</span><span class="token operator">:</span> <span class="token string">'My title'</span><span class="token punctuation">,</span>
<span class="token literal-property property">description</span><span class="token operator">:</span> <span class="token string">'My description'</span><span class="token punctuation">,</span>
<span class="token literal-property property">content</span><span class="token operator">:</span> <span class="token string">'This is the page content.'</span>
<span class="token literal-property property">date</span><span class="token operator">:</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token comment">// now</span>
<span class="token literal-property property">tags</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'automatic'</span><span class="token punctuation">,</span> <span class="token string">'content'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token literal-property property">groups</span><span class="token operator">:</span> <span class="token string">'virtual, content'</span>
<span class="token punctuation">}</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p>Note:</p>
<ol>
<li>
<p>Unless it’s falsy, the <code class="language-bash"><span class="token operator">&lt;</span>content<span class="token operator">></span></code> parameter takes precedence over the data object’s <code class="language-bash">content</code> property.</p>
</li>
<li>
<p>Front matter values defined in the <code class="language-bash"><span class="token operator">&lt;</span>content<span class="token operator">></span></code> parameter take precedence over the data object’s properties.</p>
</li>
</ol>
<p>Refer to the <a href="https://publican.dev/docs/reference/publican-methods/#addcontent"><code class="language-bash">.addContent<span class="token punctuation">(</span><span class="token punctuation">)</span></code> method documentation</a>.</p>
<h2 id="markdown-templates">Markdown templates</h2>
<p>Publican reads and outputs text files so you can create templates for HTML, XML, TXT, SVG, JSON, or any other text type. To build static web pages, you typically define HTML templates that pull in content.</p>
<p>Publican v0.12.0 supports templates in markdown format (with an <code class="language-bash">.md</code> extension) which Publican converts to HTML.</p>
<p>Refer to the <a href="https://publican.dev/docs/setup/templates/">templates documentation</a>. Markdown format is also supported when adding <a href="https://publican.dev/docs/reference/publican-methods/#addtemplate">virtual templates</a>.</p>
<h2 id="get-started">Get started</h2>
<p>The <a href="https://publican.dev/docs/">Publican documentation</a> provides a <a href="https://publican.dev/docs/quickstart/concepts/">quick start guide</a>, a <a href="https://publican.dev/docs/setup/content/">detailed set-up guide</a>, <a href="https://publican.dev/docs/reference/publican-options/">API references</a>, and <a href="https://publican.dev/docs/recipe/">common recipes</a> you can use and adapt for your own projects.</p>
<ul class="flexcenter">
<li><a href="https://publican.dev/docs/quickstart/concepts" class="button">Get started</a></li>
<li><a href="https://publican.dev/about/donate/" class="button">Donate</a></li>
</ul>
]]></content:encoded>
</item>
<item>
<title>Publican v0.11.0 update</title>
<link>https://publican.dev/news/publican-0.11.0/</link>
<guid isPermaLink="true">https://publican.dev/news/publican-0.11.0/</guid>
<pubDate>Wed, 22 Oct 2025 00:00:00 GMT</pubDate>
<dc:creator>Craig Buckler</dc:creator>
<description>Publican v0.11.0 provides arbitrary post groups and fixes some minor issues.</description>
<content:encoded><![CDATA[
<p><a href="https://www.npmjs.com/package/publican">Publican v0.11.0</a> was released on <time datetime="2025-10-22">October 22, 2025</time>.</p>
<p>There should be no breaking changes unless you’ve used a custom <code class="language-bash">groups:</code> value in front matter. This is now a <a href="https://publican.dev/docs/reference/front-matter/#groups">Publican value</a> that controls <a href="#post-groups">post groups</a>.</p>
<h2 id="post-groups">Post groups</h2>
<p>You can organise pages into arbitrary <em>groups</em> based on any factor, e.g. featured posts, years, authors, etc. You can add any post to a group by:</p>
<ol>
<li>
<p>setting a <a href="https://publican.dev/docs/reference/front-matter/#groups"><code class="language-bash">groups:</code> front matter</a> value, e.g. <code class="language-bash">groups: featured</code>, or</p>
</li>
<li>
<p>defining a <code class="language-bash">filter</code> function in your <a href="https://publican.dev/docs/reference/publican-options/#group-index-pages">Publican configuration file</a>.</p>
</li>
</ol>
<p>The following example creates a <code class="language-bash">latest</code> group with all posts dated within the past 28 days in reverse chronological order:</p>
<p class="filename language-js"><dfn><code class="language-bash">publican.config.js</code> excerpt</dfn></p>
<pre class="language-js"><code class="language-js">publican<span class="token punctuation">.</span>config<span class="token punctuation">.</span>groupPages <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token literal-property property">sortBy</span><span class="token operator">:</span> <span class="token string">'date'</span><span class="token punctuation">,</span>
<span class="token literal-property property">sortOrder</span><span class="token operator">:</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span>
<span class="token literal-property property">list</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token string-property property">'latest'</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token parameter">data</span> <span class="token operator">=></span> data<span class="token punctuation">.</span>date <span class="token operator">>=</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span>Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">28</span> <span class="token operator">*</span> <span class="token number">24</span> <span class="token operator">*</span> <span class="token number">60</span> <span class="token operator">*</span> <span class="token number">60</span> <span class="token operator">*</span> <span class="token number">1000</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre>
<p>You can <a href="https://publican.dev/docs/setup/group-indexes/#tacsgroup">list grouped posts in any template</a>:</p>
<pre class="language-js"><code class="language-js">&#36;{ tacs<span class="token punctuation">.</span>group<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'latest'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>
<span class="token parameter">p</span> <span class="token operator">=></span> <span class="token template-string"><span class="token template-punctuation string">&#96;</span><span class="token string">&lt;p>&lt;a href="</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">&#36;{</span> p<span class="token punctuation">.</span>link <span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">"></span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">&#36;{</span> p<span class="token punctuation">.</span>title <span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&lt;/a>&lt;/p></span><span class="token template-punctuation string">&#96;</span></span>
<span class="token punctuation">)</span> }
</code></pre>
<p>You can also <a href="https://publican.dev/docs/setup/group-indexes/#generating-index-pages">generate paged index pages</a> by adding a <code class="language-bash">root</code> path and optional <code class="language-bash">size</code>, <code class="language-bash">template</code>, and <code class="language-bash">index</code> values:</p>
<p class="filename language-js"><dfn><code class="language-bash">publican.config.js</code> excerpt</dfn></p>
<pre class="language-js"><code class="language-js">publican<span class="token punctuation">.</span>config<span class="token punctuation">.</span>groupPages <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token literal-property property">sortBy</span><span class="token operator">:</span> <span class="token string">'date'</span><span class="token punctuation">,</span>
<span class="token literal-property property">sortOrder</span><span class="token operator">:</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span>
<span class="token literal-property property">size</span><span class="token operator">:</span> <span class="token number">12</span><span class="token punctuation">,</span>
<span class="token literal-property property">template</span><span class="token operator">:</span> <span class="token string">'list.html'</span><span class="token punctuation">,</span>
<span class="token literal-property property">index</span><span class="token operator">:</span> <span class="token string">'monthly'</span><span class="token punctuation">,</span>
<span class="token literal-property property">list</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token string-property property">'latest'</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token function-variable function">filter</span><span class="token operator">:</span> <span class="token parameter">data</span> <span class="token operator">=></span> data<span class="token punctuation">.</span>date <span class="token operator">>=</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span>Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">28</span> <span class="token operator">*</span> <span class="token number">24</span> <span class="token operator">*</span> <span class="token number">60</span> <span class="token operator">*</span> <span class="token number">60</span> <span class="token operator">*</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token literal-property property">root</span><span class="token operator">:</span> <span class="token string">'latest'</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre>
<p>If there were 30 <code class="language-bash">latest</code> posts, an index <code class="language-bash">size</code> of 12 creates:</p>
<ul>
<li><code class="language-bash">latest/index.html</code> shows posts 1 to 12</li>
<li><code class="language-bash">latest/1/index.html</code> shows posts 13 to 24</li>
<li><code class="language-bash">latest/2/index.html</code> shows posts 25 to 30</li>
</ul>
<p>For more information, refer to <a href="https://publican.dev/docs/setup/group-indexes/">Publican group indexes</a>.</p>
<h2 id="minor-fixes">Minor fixes</h2>
<p>Version 0.11.0 fixes the following issues:</p>
<ol>
<li>
<p><a href="https://publican.dev/docs/setup/watch-mode/">Watch mode</a> works on Windows</p>
<p>Previous versions would not re-render in native Windows installations (not in WSL).</p>
</li>
<li>
<p><a href="https://publican.dev/docs/reference/publican-options/#navigation-menus">Disable navigation menus</a></p>
<p>Set <code class="language-bash">publican.config.nav <span class="token operator">=</span> <span class="token boolean">false</span></code> if you’re not using the <a href="https://publican.dev/docs/reference/global-properties/#tacsnav"><code class="language-bash">tacs.nav</code> object</a>. This should make rendering a little faster.</p>
</li>
<li>
<p>No need for empty <a href="https://publican.dev/docs/setup/content/">content</a> or <a href="https://publican.dev/docs/setup/templates/">template</a> directories</p>
<p>Previous versions required empty directories even when using <a href="https://publican.dev/docs/setup/content/#virtual-content-files">virtual files</a> alone.</p>
</li>
<li>
<p>Improved error reporting.</p>
</li>
</ol>
<h2 id="get-started">Get started</h2>
<p>The <a href="https://publican.dev/docs/">Publican documentation</a> provides a <a href="https://publican.dev/docs/quickstart/concepts/">quick start guide</a>, a <a href="https://publican.dev/docs/setup/content/">detailed set-up guide</a>, <a href="https://publican.dev/docs/reference/publican-options/">API references</a>, and <a href="https://publican.dev/docs/recipe/">common recipes</a> you can use and adapt for your own projects.</p>
<ul class="flexcenter">
<li><a href="https://publican.dev/docs/quickstart/concepts" class="button">Get started</a></li>
<li><a href="https://publican.dev/about/donate/" class="button">Donate</a></li>
</ul>
]]></content:encoded>
</item>
<item>
<title>StaticSearch v0.5.0 update</title>
<link>https://publican.dev/news/staticsearch-0.5.0/</link>
<guid isPermaLink="true">https://publican.dev/news/staticsearch-0.5.0/</guid>
<pubDate>Tue, 05 Aug 2025 00:00:00 GMT</pubDate>
<dc:creator>Craig Buckler</dc:creator>
<description>StaticSearch now supports more languages and can limit results to pages containing some or every search word.</description>
<content:encoded><![CDATA[
<p><a href="https://www.npmjs.com/package/staticsearch">StaticSearch v0.5.0</a> was released on <time datetime="2025-08-05">August 5, 2025</time>. There should be no breaking changes but – <em>more importantly</em> – it has a new logo!..</p>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 506.7 257.3" width="88" height="45" class="logolarge"><path d="M88.3 130.4a63 63 0 0 1-49-19.2l21.6-21.6c23.3 25 65.4 9.1 33.1-5.8-11.4-4.4-25-7.9-34.6-16.3C40.2 51.8 46.3 16.4 69.9 7.6c21.4-9 53.3-4.9 69.7 12.4l-21.8 21.6c-7.2-6.9-14.1-10.9-23.9-10.9-8.5-1.1-16.4 6.5-8.6 12.9 8.9 6 21.7 8 31.7 13.1 25.3 9.1 30.5 47.8 9.1 63.3-8.9 6.9-21.5 10.3-37.8 10.3Z"/><path d="M132.2 70.9V43.2h70.2v27.7h-70.2Zm18.1 57.5V8.3h33.9v120.1h-33.9Z"/><path d="M236.1 130.1c-62.8-1.6-48.4-106.7 13.8-86.1a24.6 24.6 0 0 1 16 17.4v48.8c-2.8 13.2-16.9 20-29.8 19.9Zm7.6-29.8c18.6.9 18.7-29.8.2-29.1-18.6-.6-18.9 29.6-.2 29.1Zm13.1 28.1v-22.8l4.7-20.8-4.7-20.6V43.3h33v85.1h-33Z"/><path d="M287.9 70.9V43.2h70.2v27.7h-70.2Zm18.2 57.5V8.3H340v120.1h-33.9Z"/><path d="M372.6 35.3c-22.8.3-22.8-35.6 0-35.3 22.8-.4 22.8 35.7 0 35.3Zm-16.9 93.1V43.3h33.9v85.1h-33.9Z"/><path d="M437.5 130.4c-35.9 1.7-61.8-36.4-42.3-67.6 15.3-24.5 54.9-29.5 75.9-9.1L449.8 75c-9-8.7-27.5-3.2-26.8 10.6-.7 14.4 19.1 20 27.7 9.9l21.3 21.3a46.8 46.8 0 0 1-34.4 13.7ZM49 230.4a63 63 0 0 1-49-19.2l21.6-21.6c23.3 25 65.4 9.1 33.1-5.8-11.4-4.4-25-7.9-34.6-16.3C.9 151.8 7 116.4 30.6 107.6c21.4-9 53.3-4.9 69.7 12.4l-21.8 21.6c-7.2-6.9-14.1-10.9-23.9-10.9-8.5-1.1-16.4 6.5-8.6 12.9 8.9 6 21.7 8 31.7 13.1 25.3 9.1 30.5 47.8 9.1 63.3-8.9 6.9-21.5 10.3-37.8 10.3Z"/><path d="M146.2 230.4c-49.3 2.5-69.7-58.7-27-83.5 34.9-18.4 78.8 7.7 68.2 49l-76.8.5v-20.8l64.2-.5-15.7 9.2c2.3-20.6-20.8-28.6-29.7-10.2-3.5 9.4-3.2 25.3 6.5 30.8a24.9 24.9 0 0 0 29.4-5.9l17 16.8a45.6 45.6 0 0 1-36 14.5Z"/><path d="M224 230.1c-62.8-1.6-48.4-106.7 13.8-86.1a24.6 24.6 0 0 1 16 17.4v48.8c-2.8 13.2-16.9 20-29.8 19.9Zm7.6-29.8c18.6.9 18.7-29.8.2-29.1-18.6-.6-18.9 29.6-.2 29.1Zm13.1 28.1v-22.8l4.7-20.8-4.7-20.6v-20.9h33v85.1h-33Zm37.7 0v-85.1h33.9v85.1h-33.9Zm33.9-46-15.7-14c8.4-17.2 18.2-26.7 37.2-26.8 6.6 0 12.6 1.2 17 5.4l-19 27c-7.1-6.8-20.7-3-19.4 8.5Zm71.5 48c-35.9 1.7-61.8-36.4-42.3-67.6 15.3-24.5 54.9-29.5 75.9-9.1L400.1 175c-9-8.7-27.5-3.2-26.8 10.6-.7 14.4 19.1 20 27.7 9.9l21.3 21.3a46.8 46.8 0 0 1-34.4 13.7Z"/><path d="M418.6 228.4V101.8h33.9v126.6h-33.9Zm54.1 0c-1.1-5.8 2.9-52.1-2.9-55.4-6.2-5.9-18.2-1.6-17.4 7.7l-13.1-5.9c-1.7-27.8 29.5-40.7 51.6-29.1a29.1 29.1 0 0 1 15.7 27.2v55.5h-33.9Z"/><path d="m398.8 222.7 14.3-14.2 34.6 34.6-14.2 14.2z"/></svg>
<h2 id="logical-orand-searches">Logical OR/AND searches</h2>
<p>Search results now contain a new <a href="https://publican.dev/tools/staticsearch/search-api/#staticsearchfind-method"><code class="language-bash">found</code> value</a> that gives the proportion of search words found on a page. For example, a page featuring two of the four search words entered has a <code class="language-bash">found</code> value of <code class="language-bash"><span class="token number">0.5</span></code>. You can set a new <code class="language-bash">minfound</code> attribute on the <a href="https://publican.dev/tools/staticsearch/search-web-component/#web-component-attributes">web component</a> or <a href="https://publican.dev/tools/staticsearch/search-bind-module/#search-result-attributes">bind module</a> to limit results to pages with an equal or higher <code class="language-bash">found</code> value.</p>
<p>Consider a cooking website <em>(thanks for the suggestion, Jos!)</em> where users can search for recipes according to ingredients they have in the cupboard:</p>
<ul>
<li>
<p>setting <code class="language-html">minfound="0"</code> (the default) is a <em>logical OR</em>.</p>
<p>A recipe page appears in results when it contains ANY of the ingredients. Recipes containing all ingredients <em>should</em> be at the top, but there will be less useful recipes featuring a single ingredient.</p>
</li>
<li>
<p>setting <code class="language-html">minfound="1"</code> is a <em>logical AND</em>.</p>
<p>A recipe page appears in results when it contains ALL the ingredients. That may be a little too restrictive.</p>
</li>
<li>
<p>setting <code class="language-html">minfound="0.8"</code> means a recipe page appears in results when it contains at least 80% of the ingredients.</p>
<p>Again, recipes containing all ingredients should be at the top, but there could be useful results featuring four of five ingredients entered.</p>
</li>
</ul>
<p>StaticSearch allows you build a custom recipe search where the user could click ingredients and use a slider to change the <em>precision / fuzziness</em> of results.</p>
<h2 id="additional-language-support">Additional language support</h2>
<p>StaticSearch removes commonly-used <em>stop words</em> considered insignificant to the meaning of text – such as <em>“and”</em>, <em>“the”</em>, and <em>“but”</em> in English. This can produce better results and v0.5.0 now supports stop words in:</p>
<ul>
<li>Danish (<code class="language-html">da</code>)</li>
<li>Dutch (<code class="language-html">nl</code>)</li>
<li>English (<code class="language-html">en</code>)</li>
<li>Finnish (<code class="language-html">fi</code>)</li>
<li>French (<code class="language-html">fr</code>)</li>
<li>German (<code class="language-html">de</code>)</li>
<li>Italian (<code class="language-html">it</code>)</li>
<li>Norwegian (<code class="language-html">no</code>)</li>
<li>Portuguese (<code class="language-html">pt</code>)</li>
<li>Spanish (<code class="language-html">es</code>)</li>
<li>Swedish (<code class="language-html">sv</code>)</li>
<li>Turkish (<code class="language-html">tr</code>)</li>
</ul>
<p>The lists are courtesy of <a href="https://github.com/stopwords-iso">Stopwords ISO</a>.</p>
<h2 id="staticsearch-on-frontend-focus">StaticSearch on Frontend Focus</h2>
<p>The <a href="https://frontendfoc.us/issues/703">Frontend Focus newsletter, issue 703</a> featured StaticSearch, so many thanks to their editors.</p>
<h2 id="get-started">Get started</h2>
<p>The <a href="https://publican.dev/tools/staticsearch/">StaticSearch documentation</a> provides a <a href="https://publican.dev/tools/staticsearch/quickstart/">quick start guide</a>, and details about the <a href="https://publican.dev/tools/staticsearch/search-indexer/">indexer</a>, <a href="https://publican.dev/tools/staticsearch/search-web-component/">web component</a>, <a href="https://publican.dev/tools/staticsearch/search-bind-module/">bind module</a>, and <a href="https://publican.dev/tools/staticsearch/search-api/">JavaScript API</a>.</p>
<p>StaticSearch works well with Publican sites. The <a href="https://publican.dev/docs/">Publican documentation</a> provides a <a href="https://publican.dev/docs/quickstart/concepts/">quick start guide</a>, a <a href="https://publican.dev/docs/setup/content/">detailed set-up guide</a>, <a href="https://publican.dev/docs/reference/publican-options/">API references</a>, and <a href="https://publican.dev/docs/recipe/">common recipes</a> you can use and adapt for your own projects.</p>
<ul class="flexcenter">
<li><a href="https://publican.dev/docs/quickstart/concepts" class="button">Get started</a></li>
<li><a href="https://publican.dev/about/donate/" class="button">Donate</a></li>
</ul>
]]></content:encoded>
</item>
<item>
<title>Publican v0.10.2 and StaticSearch v0.4.0 updates</title>
<link>https://publican.dev/news/publican-0.10.2-staticsearch-0.4.0/</link>
<guid isPermaLink="true">https://publican.dev/news/publican-0.10.2-staticsearch-0.4.0/</guid>
<pubDate>Wed, 25 Jun 2025 00:00:00 GMT</pubDate>
<dc:creator>Craig Buckler</dc:creator>
<description>Publican v0.10.2 fixes a problem with double string replacements. StaticSearch v0.4.0 has improved content indexing.</description>
<content:encoded><![CDATA[
<p><a href="https://www.npmjs.com/package/publican">Publican v0.10.2</a> and <a href="https://www.npmjs.com/package/staticsearch">StaticSearch v0.4.0</a> were released on <time datetime="2025-06-25">June 25, 2025</time>.</p>
<p>There should be no breaking changes.</p>
<h2 id="publican-string-replacement-issue">Publican string replacement issue</h2>
<p>Publican allows you to define content <a href="https://publican.dev/docs/reference/publican-options/#string-replacement">string replacements</a>. Previous releases would run the replacement twice when content was rendered inside a template. This didn’t normally cause a problem:</p>
<p class="filename language-js"><dfn><code class="language-bash">publican.config.js</code> excerpt</dfn></p>
<pre class="language-js"><code class="language-js">publican<span class="token punctuation">.</span>config<span class="token punctuation">.</span>replace<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'Hi'</span><span class="token punctuation">,</span> <span class="token string">'Hello'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p>However, it would matter when the replacement <em>included</em> the search string:</p>
<p class="filename language-js"><dfn><code class="language-bash">publican.config.js</code> excerpt</dfn></p>
<pre class="language-js"><code class="language-js">publican<span class="token punctuation">.</span>config<span class="token punctuation">.</span>replace<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'Hi'</span><span class="token punctuation">,</span> <span class="token string">'Hi there'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p><code class="language-bash">Hi</code> becomes <code class="language-bash">Hi there</code> which then becomes <code class="language-bash">Hi there there</code>!</p>
<p>Version <code class="language-bash">v0.10.2</code> fixes this so string replacement occurs once.</p>
<h2 id="staticsearch-v040-updates">StaticSearch v0.4.0 updates</h2>
<p>The following features have been added or improved:</p>
<ol>
<li>
<p><a href="https://publican.dev/tools/staticsearch/search-indexer/#document-indexing-options">Document indexing</a> has been improved so content can be identified even when a page does not have a <code class="language-bash"><span class="token operator">&lt;</span>main<span class="token operator">></span></code> element.</p>
</li>
<li>
<p>You can set a <a href="https://publican.dev/tools/staticsearch/search-indexer/#logging-options">log verbosity level</a>.</p>
</li>
<li>
<p>When no search directory is set (<code class="language-bash"><span class="token parameter variable">--searchdir</span></code>), it defaults to a <code class="language-bash">search</code> sub-directory in the build directory (<code class="language-bash"><span class="token parameter variable">--builddir</span></code>).</p>
</li>
<li>
<p>An issue was fixed where pages were not indexed because a <code class="language-bash">noindex</code> reference was found inside minified HTML even though it was outside a <code class="language-bash"><span class="token operator">&lt;</span>meta <span class="token assign-left variable">name</span><span class="token operator">=</span><span class="token string">"robots"</span><span class="token operator">></span></code> tag.</p>
</li>
<li>
<p>The README now points to the comprehensive <a href="https://publican.dev/tools/staticsearch/">Publican.dev StaticSearch documentation</a>.</p>
</li>
</ol>
<h2 id="get-started">Get started</h2>
<p>The <a href="https://publican.dev/docs/">Publican documentation</a> provides a <a href="https://publican.dev/docs/quickstart/concepts/">quick start guide</a>, a <a href="https://publican.dev/docs/setup/content/">detailed set-up guide</a>, <a href="https://publican.dev/docs/reference/publican-options/">API references</a>, and <a href="https://publican.dev/docs/recipe/">common recipes</a> you can use and adapt for your own projects.</p>
<ul class="flexcenter">
<li><a href="https://publican.dev/docs/quickstart/concepts" class="button">Get started</a></li>
<li><a href="https://publican.dev/about/donate/" class="button">Donate</a></li>
</ul>
]]></content:encoded>
</item>
<item>
<title>Publican v0.10.1 update</title>
<link>https://publican.dev/news/publican-0.10.1/</link>
<guid isPermaLink="true">https://publican.dev/news/publican-0.10.1/</guid>
<pubDate>Tue, 17 Jun 2025 00:00:00 GMT</pubDate>
<dc:creator>Craig Buckler</dc:creator>
<description>Publican v0.10.1 fixes a problem with slug string replacement on HTML index files.</description>
<content:encoded><![CDATA[
<p><a href="https://www.npmjs.com/package/publican">Publican v0.10.1</a> was released on <time datetime="2025-06-17">June 17, 2025</time>.</p>
<p>There should be no breaking changes, but the following features have been improved. <em>We’re getting closer to a version 1.0.0 release!</em></p>
<h2 id="fixed-slug-string-replacement-issue">Fixed slug string replacement issue</h2>
<p>In previous Publican releases, <a href="https://publican.dev/docs/reference/publican-options/#slug-string-replacement">slug string replacement</a> occurred <em>after</em> the file path had been converted to a slug. Consider the following example which removes two or more digits followed by an underscore:</p>
<p class="filename language-js"><dfn><code class="language-bash">publican.config.js</code> excerpt</dfn></p>
<pre class="language-js"><code class="language-js"><span class="token comment">// slug replacement - removes NN_</span>
publican<span class="token punctuation">.</span>config<span class="token punctuation">.</span>slugReplace<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">&#92;d{2,}_</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p>The file path <code class="language-bash">path/01_index.md</code> is converted to <code class="language-bash">/path/01_index/index.html</code> first. The <code class="language-bash">slugReplace</code> would then convert that to <code class="language-bash">/path/index/index.html</code> and we get an unnecessary <code class="language-bash">index</code> path.</p>
<p>In v0.10.1, slug string replacement occurs first. The file <code class="language-bash">path/01_index.md</code> is converted to <code class="language-bash">/path/index.md</code> which then becomes <code class="language-bash">/path/index.html</code>.</p>
<p>The update is unlikely to break your site, but you may need to check paths are what you expect them to be.</p>
<h2 id="word-count-accuracy-improvement">Word count accuracy improvement</h2>
<p>Word counts on documents with embedded <code class="language-bash"><span class="token operator">&lt;</span>code<span class="token operator">></span></code> sections should be more accurate.</p>
<h2 id="new-publicandev-tools-documentation">New Publican.dev tools documentation</h2>
<p>There’s a new <a href="https://publican.dev/tools/">Tools</a> menu on this site that provides documentation for my other utilities that can help Publican site development.</p>
<ol>
<li>
<p><a href="https://publican.dev/tools/staticsearch/">StaticSearch</a> – my client-side search engine for static sites</p>
</li>
<li>
<p><a href="https://publican.dev/tools/livelocalhost/">LiveLocalhost</a> – my tiny local development web server with automatic hot reloading</p>
</li>
</ol>
<h2 id="get-started">Get started</h2>
<p>The <a href="https://publican.dev/docs/">Publican documentation</a> provides a <a href="https://publican.dev/docs/quickstart/concepts/">quick start guide</a>, a <a href="https://publican.dev/docs/setup/content/">detailed set-up guide</a>, <a href="https://publican.dev/docs/reference/publican-options/">API references</a>, and <a href="https://publican.dev/docs/recipe/">common recipes</a> you can use and adapt for your own projects.</p>
<ul class="flexcenter">
<li><a href="https://publican.dev/docs/quickstart/concepts" class="button">Get started</a></li>
<li><a href="https://publican.dev/about/donate/" class="button">Donate</a></li>
</ul>
]]></content:encoded>
</item>
<item>
<title>Publican v0.10.0 update and StaticSearch</title>
<link>https://publican.dev/news/publican-0.10.0-staticsearch/</link>
<guid isPermaLink="true">https://publican.dev/news/publican-0.10.0-staticsearch/</guid>
<pubDate>Tue, 10 Jun 2025 00:00:00 GMT</pubDate>
<dc:creator>Craig Buckler</dc:creator>
<description>Publican v0.10.0 provides improved performance logging and introduces StaticSearch - a search engine for static sites.</description>
<content:encoded><![CDATA[
<p><a href="https://www.npmjs.com/package/publican">Publican v0.10.0</a> was released on <time datetime="2025-06-08">June 8, 2025</time>.</p>
<p>There are no breaking changes, but the following features have been improved and a new <a href="#introducing-staticsearch">static site search engine</a> is available.</p>
<h2 id="better-performance-logging">Better performance logging</h2>
<p>Previous releases of Publican could conflict with other applications recording <a href="https://nodejs.org/docs/latest/api/perf_hooks.html">Node.js <code class="language-bash">performance</code> metrics</a>. This has been fixed using <a href="https://www.npmjs.com/package/perfpro">PerfPro</a> – a new profiler that namespaces applications so records cannot clash.</p>
<p>Publican and related tools such as <a href="https://www.npmjs.com/package/livelocalhost">LiveLocalhost</a> and <a href="https://www.npmjs.com/package/staticsearch">StaticSearch</a> have also adopted <a href="https://www.npmjs.com/package/concol">ConCol</a> for prettier and less cluttered console logging:</p>
<img src="https://publican.dev/images/concol.png" alt="ConCol color logging" width="941" height="951"  loading="lazy">
<h2 id="introducing-staticsearch">Introducing StaticSearch</h2>
<p>This site is fairly large. While it offers reasonable navigation and <a href="https://publican.dev/tag/">tags</a>, finding the page you want can be tricky.</p>
<p>Static sites cannot easily provide search facilities because there’s no back-end database. You can integrate a third-party search service such as <a href="https://www.algolia.com/">Alogia</a>, <a href="https://www.addsearch.com/">AddSearch</a>, or <a href="https://programmablesearchengine.google.com/">Google’s Programmable Search Engine</a>. These index your site and provide a search API, but have an ongoing cost.</p>
<p>JavaScript-only search facilities such as <a href="https://lunrjs.com/">Lunr</a> require you to pass all content in a specific format. Every page then has a full index of your site, so the payload can become large as your site grows.</p>
<p>My preferred option is <a href="https://pagefind.app/">pagefind</a>. This analyses your built site and creates WASM binary indexes. Unfortunately, it can require some configuration, produces quite large files, and has problems with <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP">Content Security Policies</a> and Safari compatibility.</p>
<p><em>So I’ve rolled my own…</em></p>
<p><a href="https://www.npmjs.com/package/staticsearch">StaticSearch</a> is my new search engine for static sites. It’s enabled on Publican.dev: click the search icon in the header or press <kbd>Ctrl</kbd> | <kbd>Cmd</kbd> + <kbd>K</kbd>.</p>
<p>StaticSearch is easy to use and fully compatible with Publican, but you can use any static site generator. It:</p>
<ol>
<li>quickly indexes built HTML (like pagefind)</li>
<li>is pure JavaScript without any CSP issues, and</li>
<li>has a tiny payload and no AI nonsense.</li>
</ol>
<p>At most, the search facility requires 13Kb of JavaScript and 4Kb of CSS. You can reduce that to just 6Kb if you’re building your own UI. Word index data typically totals:</p>
<ul>
<li>100Kb for a 100 page site</li>
<li>800Kb for a 1,000 page site.</li>
</ul>
<p>Index data is incrementally loaded on demand as you search for different words. Indexes are cached in <a href="https://www.npmjs.com/package/pixdb">IndexedDB</a> so results appear faster the more searches you do.</p>
<h3 id="staticsearch-quickstart">StaticSearch quickstart</h3>
<p>Assuming your static site has been generated in a sub-directory named <code class="language-bash">./build/</code>, run StaticSearch using:</p>
<pre class="language-bash"><code class="language-bash">npx staticsearch
</code></pre>
<p>It creates a new directory named <code class="language-bash">./build/search/</code> containing JavaScript code and index data.</p>
<p>If your site is in a different directory, such as <code class="language-bash">./dist/</code>, use:</p>
<pre class="language-bash"><code class="language-bash">npx staticsearch <span class="token parameter variable">--builddir</span> ./dist/ <span class="token parameter variable">--searchdir</span> ./dist/search/
</code></pre>
<p>You can now add a search facility to the site using HTML code on any/all pages:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>module<span class="token punctuation">"</span></span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/search/staticsearch-component.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>static-search</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>search<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>static-search</span><span class="token punctuation">></span></span>
</code></pre>
<p>Any HTML element can be placed inside <code class="language-bash"><span class="token operator">&lt;</span>static-search<span class="token operator">></span></code> to activate the search when it’s clicked. You may then need to rebuild your site and re-run <code class="language-bash">staticsearch</code> to ensure everything’s up to date.</p>
<p>StaticSearch is new – full documentation will appear on <a href="https://publican.dev/">Publican.dev</a> shortly.</p>
<h2 id="minor-redesign-of-publicandev">Minor redesign of Publican.dev</h2>
<p>This site’s been updated to provide search and reduce the clutter in the header.</p>
<h2 id="get-started">Get started</h2>
<p>The <a href="https://publican.dev/docs/">Publican documentation</a> provides a <a href="https://publican.dev/docs/quickstart/concepts/">quick start guide</a>, a <a href="https://publican.dev/docs/setup/content/">detailed set-up guide</a>, <a href="https://publican.dev/docs/reference/publican-options/">API references</a>, and <a href="https://publican.dev/docs/recipe/">common recipes</a> you can use and adapt for your own projects.</p>
<ul class="flexcenter">
<li><a href="https://publican.dev/docs/quickstart/concepts/" class="button">Get started</a></li>
<li><a href="https://publican.dev/about/donate/" class="button">Donate</a></li>
</ul>
]]></content:encoded>
</item>
<item>
<title>Publican v0.9.0 update</title>
<link>https://publican.dev/news/publican-0.9.0-update/</link>
<guid isPermaLink="true">https://publican.dev/news/publican-0.9.0-update/</guid>
<pubDate>Thu, 08 May 2025 00:00:00 GMT</pubDate>
<dc:creator>Craig Buckler</dc:creator>
<description>Publican v0.9.0 provides more control over directory and tag index pages.</description>
<content:encoded><![CDATA[
<p><a href="https://www.npmjs.com/package/publican">Publican v0.9.0</a> was released on <time datetime="2025-05-08">May 8, 2025</time>.</p>
<p>There are no breaking changes, but the following features have been added.</p>
<h2 id="directory-index-pages">Directory index pages</h2>
<p>In previous releases, directory index pages (the pages listing posts in a directory) had the <code class="language-bash">data.index</code> content property set <code class="language-bash"><span class="token boolean">false</span></code>. Sitemaps would therefore omit pages such as: <code class="language-bash">/docs/1/</code>, <code class="language-bash">/docs/2/</code>, <code class="language-bash">/docs/3/</code>, etc.</p>
<p>A new <a href="https://publican.dev/docs/reference/publican-options/#directory-index-pages"><code class="language-bash">publican.config.dirPages.index</code> configuration property</a> is now available which is set to <code class="language-bash">monthly</code> by default. Index pages will appear in sitemaps unless you explicitly set it to <code class="language-bash"><span class="token boolean">false</span></code>.</p>
<h2 id="index-page-content-properties">Index page content properties</h2>
<p>Two new content properties are available:</p>
<ol>
<li>
<p><a href="https://publican.dev/docs/reference/content-properties/#dataisdirindex"><code class="language-js">data<span class="token punctuation">.</span>isDirIndex</code></a></p>
<p>When a page is a directory index (listing pages in a directory), <code class="language-js">data<span class="token punctuation">.</span>isDirIndex</code> is set to the directory’s root page title. The directory name is used when that is not set.</p>
</li>
<li>
<p><a href="https://publican.dev/docs/reference/content-properties/#dataistagindex"><code class="language-js">data<span class="token punctuation">.</span>isTagIndex</code></a></p>
<p>When a page is a tag index (listing pages with a specific tag), <code class="language-js">data<span class="token punctuation">.</span>isDirIndex</code> is set to the tag name.</p>
</li>
</ol>
<p>The following example code uses <code class="language-js">data<span class="token punctuation">.</span>isTagIndex</code> to assign more descriptive titles and descriptions to tag index pages:</p>
<p class="filename language-js"><dfn><code class="language-bash">publican.config.js</code> excerpt</dfn></p>
<pre class="language-js"><code class="language-js"><span class="token comment">// set tag index titles and descriptions</span>
publican<span class="token punctuation">.</span>config<span class="token punctuation">.</span>processRenderStart<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token parameter">tacs</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  tacs<span class="token punctuation">.</span>all<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">p</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>p<span class="token punctuation">.</span>isTagIndex<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> posts <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">&#96;</span><span class="token string">post&#36;{ p<span class="token punctuation">.</span>childPageTotal <span class="token operator">===</span> <span class="token number">1</span> <span class="token operator">?</span> <span class="token string">''</span> <span class="token operator">:</span> <span class="token string">'s'</span> }</span><span class="token template-punctuation string">&#96;</span></span><span class="token punctuation">;</span>
      p<span class="token punctuation">.</span>title <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">&#96;</span><span class="token string">'&#36;{ p<span class="token punctuation">.</span>isTagIndex }' &#36;{ posts }</span><span class="token template-punctuation string">&#96;</span></span><span class="token punctuation">;</span>
      p<span class="token punctuation">.</span>description <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">&#96;</span><span class="token string">List of &#36;{ p<span class="token punctuation">.</span>childPageTotal } &#36;{ posts } using the tag '&#36;{ p<span class="token punctuation">.</span>isTagIndex }'.</span><span class="token template-punctuation string">&#96;</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<h2 id="new-basic-theme">New basic theme</h2>
<p>If you missed the <a href="https://publican.dev/news/publican-0.8.0-update/">v0.8.0 announcement</a>, a new basic Publican theme is available at:</p>
<ul>
<li>
<p><strong>demonstration site:</strong></p>
<p><a href="https://publican-theme-basic.pages.dev/">https://publican-theme-basic.pages.dev/</a></p>
</li>
<li>
<p><strong>code repository:</strong></p>
<p><a href="https://github.com/craigbuckler/publican.theme.basic">github.com/craigbuckler/publican.theme.basic</a></p>
</li>
</ul>
<p>The theme is fast, standards based, and uses best practise techniques. It features pages, blog posts, tag indexes, a light/dark switcher, RSS feed, sitemaps, security, and a 100% Lighthouse score.</p>
<p>The theme uses Publican alone for rendering – <em>there are no other dependencies</em>. In development mode, it provides a <a href="https://www.npmjs.com/package/livelocalhost"><code class="language-bash">livelocalhost</code></a> server to automatically reload HTML and CSS when files change.</p>
<p>Please <a href="https://github.com/craigbuckler/publican.theme.basic">download and adapt the theme</a> for your own purposes.</p>
<h2 id="get-started">Get started</h2>
<p>The <a href="https://publican.dev/docs/">Publican documentation</a> provides a <a href="https://publican.dev/docs/quickstart/concepts/">quick start guide</a>, a <a href="https://publican.dev/docs/setup/content/">detailed set-up guide</a>, <a href="https://publican.dev/docs/reference/publican-options/">API references</a>, and <a href="https://publican.dev/docs/recipe/">common recipes</a> you can use and adapt for your own projects.</p>
<ul class="flexcenter">
<li><a href="https://publican.dev/docs/quickstart/concepts/" class="button">Get started</a></li>
<li><a href="https://publican.dev/about/donate/" class="button">Donate</a></li>
</ul>
]]></content:encoded>
</item>
</channel>
</rss>