{"id":"697ab4e14bcd26c09b04d611","title":"2026 01 29 Publishing Technical Articles","path":"how-to/technical-articles/2026-01-29-publishing-technical-articles","contentMarkdown":"# 29-Jan-2026 — Publishing Technical Articles\n\n_____\n\nThis article explains how to create and publish technical articles to the NGX-Ramblers CMS.\n\n## Overview\n\nTechnical articles are written in markdown and stored in `non-vcs/technical-articles/`. A publishing script handles uploading to the CMS and updating the index page automatically.\n\n## File Naming Convention\n\nFiles must start with a date in `YYYY-MM-DD` format. The full filename (minus extension) becomes the URL slug:\n\n| Example Filename | Published Path |\n|------------------|----------------|\n| `2026-01-29-input-source.md` | `how-to/technical-articles/2026-01-29-input-source` |\n| `2026-01-29-publishing.md` | `how-to/technical-articles/2026-01-29-publishing` |\n\n## Heading Format\n\nThe first heading determines the title shown in the index. Use this format:\n\n```markdown\n# DD-Mon-YYYY — Article Title [#123](https://github.com/nbarrett/ngx-ramblers/issues/123)\n```\n\nThe script extracts the title by removing the date prefix, so the index entry becomes:\n\n```\n- [29-Jan-2026 — Article Title](https://ngx-ramblers.org.uk/how-to/technical-articles/2026-01-29-article-name)\n```\n\n## Creating a New Article\n\n1. Copy the template:\n\n```bash\ncp non-vcs/technical-articles/TEMPLATE.md \\\n   non-vcs/technical-articles/YYYY-MM-DD-article-name.md\n```\n\n2. Edit the content using standard markdown:\n   - Use `## Heading` for sections\n   - Use `### Subheading` for subsections\n   - Use markdown tables (no HTML)\n   - Use fenced code blocks with language hints\n\n## Publishing\n\nFrom the `server` directory:\n\n```bash\nCMS_USERNAME=<user> CMS_PASSWORD=<pass> npx tsx lib/release-notes/publish-technical-article.ts \\\n  ../non-vcs/technical-articles/YYYY-MM-DD-article-name.md\n```\n\nThe script will:\n1. Extract the date from the filename for the index entry\n2. Use the full filename slug for the URL path\n3. Extract the title from the first heading\n4. Publish to `how-to/technical-articles/<filename-slug>`\n5. Add an entry to the index page (if not already present)\n\n## Environment Variables\n\n| Variable | Required | Default |\n|----------|----------|---------|\n| `CMS_USERNAME` | Yes | — |\n| `CMS_PASSWORD` | Yes | — |\n| `CMS_URL` | No | `https://www.ngx-ramblers.org.uk` |\n\n## Republishing\n\nRunning the publish command again will update an existing article. The index entry is only added once (duplicates are detected by path).\n\n## Related Files\n\n| File | Purpose |\n|------|---------|\n| `non-vcs/technical-articles/TEMPLATE.md` | Starting template for new articles |\n| `non-vcs/technical-articles/README.md` | Quick reference documentation |\n| `server/lib/release-notes/publish-technical-article.ts` | Publishing script |\n| `server/lib/release-notes/cms-client.ts` | CMS API client |\n","contentHtml":"<h1>29-Jan-2026 — Publishing Technical Articles</h1>\n<hr>\n<p>This article explains how to create and publish technical articles to the NGX-Ramblers CMS.</p>\n<h2>Overview</h2>\n<p>Technical articles are written in markdown and stored in <code>non-vcs/technical-articles/</code>. A publishing script handles uploading to the CMS and updating the index page automatically.</p>\n<h2>File Naming Convention</h2>\n<p>Files must start with a date in <code>YYYY-MM-DD</code> format. The full filename (minus extension) becomes the URL slug:</p>\n<table>\n<thead>\n<tr>\n<th>Example Filename</th>\n<th>Published Path</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>2026-01-29-input-source.md</code></td>\n<td><code>how-to/technical-articles/2026-01-29-input-source</code></td>\n</tr>\n<tr>\n<td><code>2026-01-29-publishing.md</code></td>\n<td><code>how-to/technical-articles/2026-01-29-publishing</code></td>\n</tr>\n</tbody></table>\n<h2>Heading Format</h2>\n<p>The first heading determines the title shown in the index. Use this format:</p>\n<pre><code class=\"language-markdown\"># DD-Mon-YYYY — Article Title [#123](https://github.com/nbarrett/ngx-ramblers/issues/123)\n</code></pre>\n<p>The script extracts the title by removing the date prefix, so the index entry becomes:</p>\n<pre><code>- [29-Jan-2026 — Article Title](https://ngx-ramblers.org.uk/how-to/technical-articles/2026-01-29-article-name)\n</code></pre>\n<h2>Creating a New Article</h2>\n<ol>\n<li>Copy the template:</li>\n</ol>\n<pre><code class=\"language-bash\">cp non-vcs/technical-articles/TEMPLATE.md \\\n   non-vcs/technical-articles/YYYY-MM-DD-article-name.md\n</code></pre>\n<ol start=\"2\">\n<li>Edit the content using standard markdown:<ul>\n<li>Use <code>## Heading</code> for sections</li>\n<li>Use <code>### Subheading</code> for subsections</li>\n<li>Use markdown tables (no HTML)</li>\n<li>Use fenced code blocks with language hints</li>\n</ul>\n</li>\n</ol>\n<h2>Publishing</h2>\n<p>From the <code>server</code> directory:</p>\n<pre><code class=\"language-bash\">CMS_USERNAME=&lt;user&gt; CMS_PASSWORD=&lt;pass&gt; npx tsx lib/release-notes/publish-technical-article.ts \\\n  ../non-vcs/technical-articles/YYYY-MM-DD-article-name.md\n</code></pre>\n<p>The script will:</p>\n<ol>\n<li>Extract the date from the filename for the index entry</li>\n<li>Use the full filename slug for the URL path</li>\n<li>Extract the title from the first heading</li>\n<li>Publish to <code>how-to/technical-articles/&lt;filename-slug&gt;</code></li>\n<li>Add an entry to the index page (if not already present)</li>\n</ol>\n<h2>Environment Variables</h2>\n<table>\n<thead>\n<tr>\n<th>Variable</th>\n<th>Required</th>\n<th>Default</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>CMS_USERNAME</code></td>\n<td>Yes</td>\n<td>—</td>\n</tr>\n<tr>\n<td><code>CMS_PASSWORD</code></td>\n<td>Yes</td>\n<td>—</td>\n</tr>\n<tr>\n<td><code>CMS_URL</code></td>\n<td>No</td>\n<td><code>https://www.ngx-ramblers.org.uk</code></td>\n</tr>\n</tbody></table>\n<h2>Republishing</h2>\n<p>Running the publish command again will update an existing article. The index entry is only added once (duplicates are detected by path).</p>\n<h2>Related Files</h2>\n<table>\n<thead>\n<tr>\n<th>File</th>\n<th>Purpose</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>non-vcs/technical-articles/TEMPLATE.md</code></td>\n<td>Starting template for new articles</td>\n</tr>\n<tr>\n<td><code>non-vcs/technical-articles/README.md</code></td>\n<td>Quick reference documentation</td>\n</tr>\n<tr>\n<td><code>server/lib/release-notes/publish-technical-article.ts</code></td>\n<td>Publishing script</td>\n</tr>\n<tr>\n<td><code>server/lib/release-notes/cms-client.ts</code></td>\n<td>CMS API client</td>\n</tr>\n</tbody></table>\n"}