Blog: admin-written coaching articles, server-rendered public /blog with SEO metadata, sitemap, RSS, robots

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-12 18:42:56 -05:00
parent 1a83f4f2ff
commit 49a98e7ee3
24 changed files with 375 additions and 23 deletions
+54 -2
View File
@@ -91,6 +91,7 @@
<button data-pane="members" type="button"><svg viewBox="0 0 24 24"><circle cx="12" cy="7" r="3.2"/><circle cx="5" cy="17" r="2.6"/><circle cx="19" cy="17" r="2.6"/><path d="M12 10v3M12 13l-5 2M12 13l5 2"/></svg>Members</button>
<button data-pane="reports" type="button"><svg viewBox="0 0 24 24"><path d="M12 3l9 16H3z"/><path d="M12 10v4M12 17v.5"/></svg>Reports<span class="pill" id="repBadge" hidden></span></button>
<button data-pane="traffic" type="button"><svg viewBox="0 0 24 24"><path d="M3 17l6-6 4 4 8-8"/><path d="M14 7h7v7"/></svg>Traffic</button>
<button data-pane="blog" type="button"><svg viewBox="0 0 24 24"><path d="M4 4h12l4 4v12H4z"/><path d="M8 12h8M8 16h8M8 8h4"/></svg>Blog</button>
<button data-pane="pnl" type="button"><svg viewBox="0 0 24 24"><path d="M4 19V5M4 19h16"/><path d="M8 15l3-4 3 2 5-6"/></svg>P&amp;L</button>
<button data-pane="settings" type="button"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z"/></svg>Settings</button>
</nav>
@@ -280,6 +281,57 @@
<div class="tablewrap" style="margin-top:12px"><table class="adm-table" id="pcRecent"></table></div>
</div>
</div>
<div class="pane" id="pane-blog" hidden>
<div class="card" id="blogList">
<div class="card-head"><h3>Articles</h3><span class="sub" id="blSub"></span></div>
<p class="muted small" style="margin:0 0 10px">Coaching and teaching stories, published at <a href="/blog" target="_blank" rel="noopener">instantadpay.com/blog</a>. Every published post gets its own page with a title tag, description, canonical link, social preview card, structured data, and a spot in the sitemap and RSS feed. Drafts are visible only to you (open one from its row to preview the real page).</p>
<p><button type="button" class="btn small" id="blNew">New article</button></p>
<div class="tablewrap"><table class="adm-table" id="blTable"></table></div>
</div>
<div class="card" id="blogEditor" hidden>
<div class="card-head"><h3 id="blEdTitle">New article</h3><span class="sub" id="blEdSub"></span></div>
<div style="display:grid;gap:10px">
<label class="small">Title (the headline and the browser title; under 60 characters shows whole in search results) <span id="blTitleCount" class="muted"></span><input id="blTitle" type="text" maxlength="140" placeholder="The thimble and the bucket"></label>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px">
<label class="small">URL slug (letters, numbers, dashes)<input id="blSlug" type="text" maxlength="80" placeholder="auto from the title"></label>
<label class="small">Tags (comma separated; the first one shows as the category)<input id="blTags" type="text" maxlength="200" placeholder="mindset, team building"></label>
</div>
<label class="small">Excerpt (the meta description and the card text; 120 to 160 characters is ideal) <span id="blExcCount" class="muted"></span><textarea id="blExcerpt" maxlength="300" rows="2" style="width:100%"></textarea></label>
<div style="display:grid;grid-template-columns:1fr auto;gap:8px;align-items:end">
<label class="small">Cover image (1200x630 works best; it becomes the social preview card)<input id="blCover" type="text" placeholder="/uploads/... or https://..."></label>
<span><button type="button" class="btn small sec" id="blCoverBtn">Upload</button><input type="file" id="blCoverFile" accept="image/png,image/jpeg,image/webp" hidden></span>
</div>
<p class="small muted" id="blCoverInfo" style="margin:-4px 0 0"></p>
<div>
<div class="ed-bar" aria-label="Formatting">
<button type="button" data-bl="bold" title="Bold"><b>B</b></button>
<button type="button" data-bl="italic" title="Italic"><i>I</i></button>
<button type="button" data-blblock="h2" title="Section heading">H2</button>
<button type="button" data-blblock="h3" title="Sub heading">H3</button>
<button type="button" data-blblock="p" title="Paragraph">P</button>
<button type="button" data-blblock="blockquote" title="Quote">Quote</button>
<button type="button" data-bl="insertUnorderedList" title="Bullet list">&bull; List</button>
<button type="button" data-bl="insertOrderedList" title="Numbered list">1. List</button>
<button type="button" id="blLinkBtn" title="Insert link">&#128279; Link</button>
<button type="button" id="blImgBtn" title="Insert image">&#128444; Image</button><input type="file" id="blImgFile" accept="image/png,image/jpeg,image/webp,image/gif" hidden>
<button type="button" id="blHtmlBtn" title="Edit the HTML directly">&lt;/&gt;</button>
</div>
<div id="blBody" class="ed-body" contenteditable="true" data-ph="Write the article. Headings break it up; short paragraphs read better on phones." style="min-height:360px;line-height:1.6"></div>
<textarea id="blHtml" class="ed-body" hidden style="min-height:360px;font-family:var(--mono);font-size:13px"></textarea>
<p class="small muted" style="margin:6px 0 0"><span id="blWords">0 words</span> &middot; 600 or more gives a page something to rank on; one idea per section.</p>
</div>
<div class="chips" style="gap:8px;flex-wrap:wrap">
<button type="button" class="btn small" id="blSaveDraft">Save draft</button>
<button type="button" class="btn small" id="blPublish">Publish</button>
<button type="button" class="btn small sec" id="blUnpublish" hidden>Back to draft</button>
<a class="btn small sec" id="blPreview" href="#" target="_blank" rel="noopener" hidden>Open page</a>
<button type="button" class="btn small sec" id="blClose">Close</button>
<button type="button" class="btn small sec" id="blDelete" hidden style="margin-left:auto">Delete</button>
</div>
<p class="small" id="blMsg" hidden></p>
</div>
</div>
</div>
<div class="pane" id="pane-pnl" hidden>
<div class="card">
<div class="card-head"><h3>Profit and loss</h3><span class="sub">read from the chain index; periods are by block (about 43,200 Polygon blocks a day)</span></div>
@@ -344,7 +396,7 @@
</div>
</div>
<script src="/assets/common.js?v=20260912d"></script>
<script src="/assets/admin.js?v=20260912b"></script>
<script src="/assets/common.js?v=20260912e"></script>
<script src="/assets/admin.js?v=20260912c"></script>
</body>
</html>