<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
  <title>TownReels Blog</title>
  <link>https://townreels.com/blog</link>
  <atom:link href="https://townreels.com/blog/rss.xml" rel="self" type="application/rss+xml"/>
  <description>Short promotional videos for restaurants, cafés, bars and bakeries in Fremont, CA, made from the photos already on your phone. AI-produced, checked by a person.</description>
  <language>en-us</language>
  <lastBuildDate>Sun, 23 Aug 2026 00:00:00 GMT</lastBuildDate>
  <item>
    <title>Hello, world</title>
    <link>https://townreels.com/blog/hello-world</link>
    <guid>https://townreels.com/blog/hello-world</guid>
    <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
    <category>meta</category><category>getting-started</category>
    <description>A sample post showing the frontmatter contract the blog loader expects.</description>
    <content:encoded><![CDATA[<p>This post exists to demonstrate the frontmatter contract. Delete it once you
have a real post — <code>python tools/new_post.py --title &quot;...&quot;</code> scaffolds one
with the same fields already filled in.</p>
<h2 id="the-frontmatter-contract">The frontmatter contract</h2>
<p>Every field above is read by <code>web/src/lib/blog.ts</code>:</p>
<ul>
<li><strong><code>title</code></strong> — the <code>&lt;h1&gt;</code>, the <code>&lt;title&gt;</code> tag, and the generated social card.</li>
<li><strong><code>slug</code></strong> — the URL segment. Lowercase ASCII and hyphens only; it must
match the filename, and the backend&#39;s view-count endpoint rejects anything
else so junk cannot enter the table.</li>
<li><strong><code>description</code></strong> — the meta description and the card subtitle. One
sentence.</li>
<li><strong><code>date</code></strong> — <code>YYYY-MM-DD</code>. Also the scheduling mechanism; see below.</li>
<li><strong><code>tags</code></strong> — a YAML list. Each tag gets its own indexable page at
<code>/blog/tags/&lt;tag&gt;</code>, and those pages are in the sitemap.</li>
<li><strong><code>author</code></strong> — shown in the byline and used as the JSON-LD author.</li>
<li><strong><code>draft</code></strong> — <code>true</code> hides the post from production builds entirely.</li>
</ul>
<h2 id="scheduling-a-post">Scheduling a post</h2>
<p>A post is published by being <strong>rebuilt on the right day</strong>, not by an
external CMS. The loader excludes any post whose <code>date</code> is in the future
from production builds, while <code>next dev</code> shows everything so you can preview
what is queued.</p>
<p>So the workflow is: commit the post with a future date and <code>draft: false</code>,
and it sits in the repository, absent from the built site. On the morning
its date arrives, a rebuild reveals it. <code>.github/workflows/blog-reveal.yml</code>
is that rebuild — a weekly cron that checks whether any post is due today,
and if so triggers a deploy, purges the CDN cache, and submits the sitemap
to IndexNow.</p>
<p>If no post is due, the workflow exits without deploying. Once the queue
drains, the cron is a no-op.</p>
<h2 id="writing">Writing</h2>
<p>Markdown is rendered by <code>marked</code> at build time. Headings at depth 2 and 3
get anchor ids and feed the table of contents automatically.</p>
<p>Content is repo-committed and therefore trusted, so the rendered HTML is
deliberately not sanitized — which also means you should not paste
untrusted markdown into <code>content/blog/</code>.</p>
]]></content:encoded>
  </item>
</channel>
</rss>