<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>isHistory — Mapping the Digital Past</title><description>Mapping the digital past — articles, profiles, and events from the curated archive of technology history. No code, just the human stories behind the machines.</description><link>https://dcbf5610.ishistory.pages.dev/</link><language>en-us</language><lastBuildDate>Fri, 19 Jun 2026 02:22:06 GMT</lastBuildDate><atom:link href="https://dcbf5610.ishistory.pages.dev/rss.xml" rel="self" type="application/rss+xml"/><item><title>The Complete Markdown Showcase: Every Element, Every Variant</title><link>https://dcbf5610.ishistory.pages.dev/blog/markdown-showcase/</link><guid isPermaLink="true">https://dcbf5610.ishistory.pages.dev/blog/markdown-showcase/</guid><description>A comprehensive reference post exercising every Markdown element supported by isHistory — CommonMark, GFM, Obsidian Flavored Markdown, KaTeX math, callouts, code blocks, tables, blockquotes, and every extended HTML element. Use this as a living style guide.</description><pubDate>Thu, 18 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;This post is a &lt;strong&gt;living style guide&lt;/strong&gt; for the isHistory markdown pipeline. Every element that the pipeline can render is exercised below, with multiple variants where applicable. If you&amp;#39;re authoring a new post and want to see how a particular syntax will look, find it here.&lt;/p&gt;
&lt;p&gt;The pipeline supports:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CommonMark&lt;/strong&gt; — the baseline spec (headings, paragraphs, lists, code, links, images, blockquotes, horizontal rules)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GFM (GitHub Flavored Markdown)&lt;/strong&gt; — tables, task lists, strikethrough, autolinks, deletion/insertion&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Obsidian Flavored Markdown&lt;/strong&gt; — callouts (&lt;code&gt;&amp;gt; [!note]&lt;/code&gt;, &lt;code&gt;&amp;gt; [!tip]&lt;/code&gt;, &lt;code&gt;&amp;gt; [!important]&lt;/code&gt;, &lt;code&gt;&amp;gt; [!warning]&lt;/code&gt;, &lt;code&gt;&amp;gt; [!caution]&lt;/code&gt;), wiki-links (&lt;code&gt;[[target]]&lt;/code&gt;, &lt;code&gt;[[target|alias]]&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;KaTeX math&lt;/strong&gt; — inline (&lt;code&gt;$...$&lt;/code&gt;) and display (&lt;code&gt;$$...$$&lt;/code&gt;) math&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;rehype-pretty-code&lt;/strong&gt; — Shiki-powered syntax highlighting with dual themes (light/dark), line highlighting, line numbers, diff syntax, code block titles&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extended HTML elements&lt;/strong&gt; — &lt;code&gt;&amp;lt;kbd&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;mark&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;abbr&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;summary&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;dl&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;sub&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;sup&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;del&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;ins&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;cite&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;q&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;address&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Headings (h2 through h6)&lt;/h2&gt;
&lt;p&gt;The page title is the only &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;. Inside the article body, headings start at h2. The TOC in the sidebar auto-generates from h2 and h3.&lt;/p&gt;
&lt;h3&gt;This is an h3&lt;/h3&gt;
&lt;h4&gt;This is an h4&lt;/h4&gt;
&lt;h5&gt;This is an h5&lt;/h5&gt;
&lt;h6&gt;This is an h6&lt;/h6&gt;
&lt;p&gt;Heading anchor links (the chain icon) appear on hover to the left of every h2–h6. Clicking one updates the URL hash for deep-linking.&lt;/p&gt;
&lt;h2&gt;Paragraphs and Inline Formatting&lt;/h2&gt;
&lt;p&gt;A standard paragraph. Markdown wraps consecutive lines into a single paragraph. To start a new paragraph, leave a blank line between blocks.&lt;/p&gt;
&lt;p&gt;A second paragraph immediately after. The vertical rhythm comes from the Tailwind Typography plugin&amp;#39;s default &lt;code&gt;prose-lg&lt;/code&gt; spacing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bold text&lt;/strong&gt; uses double asterisks. &lt;strong&gt;Alternatively, double underscores.&lt;/strong&gt; &lt;em&gt;Italic text&lt;/em&gt; uses single asterisks. &lt;em&gt;Alternatively, single underscores.&lt;/em&gt; &lt;em&gt;&lt;strong&gt;Bold italic&lt;/strong&gt;&lt;/em&gt; uses triple asterisks. &lt;del&gt;Strikethrough&lt;/del&gt; uses double tildes (GFM). &lt;code&gt;Inline code&lt;/code&gt; uses single backticks.&lt;/p&gt;
&lt;p&gt;You can also use the legacy HTML tags: &lt;b&gt;bold&lt;/b&gt;, &lt;i&gt;italic&lt;/i&gt;, &lt;s&gt;strikethrough&lt;/s&gt;, &lt;u&gt;underline&lt;/u&gt;, &lt;tt&gt;teletype&lt;/tt&gt;, &lt;small&gt;small text&lt;/small&gt;, &lt;big&gt;big text&lt;/big&gt;.&lt;/p&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;p&gt;Inline link: &lt;a href=&quot;https://ishistory.pp.ua&quot;&gt;isHistory homepage&lt;/a&gt;. Link with title attribute (hover): &lt;a href=&quot;https://docs.astro.build&quot; title=&quot;Astro documentation&quot;&gt;Astro docs&lt;/a&gt;. Reference-style link: &lt;a href=&quot;https://docs.astro.build&quot;&gt;Astro&lt;/a&gt;. Auto-link (bare URL): &lt;a href=&quot;https://astro.build&quot;&gt;https://astro.build&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Internal links use relative paths: &lt;a href=&quot;/blog/&quot;&gt;blog index&lt;/a&gt;, &lt;a href=&quot;/series/&quot;&gt;series index&lt;/a&gt;. Wiki-links (Obsidian-style) also work: [[astro-website-cms-obsidian-plugin]] resolves to the file&amp;#39;s permalink. Wiki-links with aliases: [[astro-website-cms-obsidian-plugin|the CMS post]].&lt;/p&gt;
&lt;p&gt;External links automatically get &lt;code&gt;target=&amp;quot;_blank&amp;quot;&lt;/code&gt; and &lt;code&gt;rel=&amp;quot;noopener noreferrer&amp;quot;&lt;/code&gt; via rehype-external-links. Example: &lt;a href=&quot;https://github.com&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Emphasis and Semantic Inline Elements&lt;/h2&gt;
&lt;p&gt;&lt;abbr title=&quot;HyperText Markup Language&quot;&gt;HTML&lt;/abbr&gt; abbreviations get a dotted underline and a tooltip on hover. &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;K&lt;/kbd&gt; opens search. &lt;kbd&gt;Esc&lt;/kbd&gt; closes modals.&lt;/p&gt;
&lt;p&gt;Use &lt;mark&gt;mark&lt;/mark&gt; to highlight text. Use &lt;cite&gt;cite&lt;/cite&gt; for citation titles. Use &lt;q&gt;inline quotes&lt;/q&gt; for short quotations (auto-wrapped in curly quotes). Use &lt;samp&gt;sample output&lt;/samp&gt; for computer output.&lt;/p&gt;
&lt;p&gt;Subscript: H&lt;sub&gt;2&lt;/sub&gt;O. Superscript: E = mc&lt;sup&gt;2&lt;/sup&gt;. Combination: a&lt;sub&gt;n&lt;/sub&gt;&lt;sup&gt;2&lt;/sup&gt; + b&lt;sub&gt;n&lt;/sub&gt;&lt;sup&gt;2&lt;/sup&gt; = c&lt;sub&gt;n&lt;/sub&gt;&lt;sup&gt;2&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;&lt;del&gt;Deleted text&lt;/del&gt; shows removals. &lt;ins&gt;Inserted text&lt;/ins&gt; shows additions. These are useful for editorial revisions.&lt;/p&gt;
&lt;h2&gt;Lists&lt;/h2&gt;
&lt;h3&gt;Unordered List&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;First item&lt;/li&gt;
&lt;li&gt;Second item&lt;ul&gt;
&lt;li&gt;Nested item (level 2)&lt;ul&gt;
&lt;li&gt;Nested item (level 3)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Back to level 2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Third item&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Ordered List&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;First item&lt;/li&gt;
&lt;li&gt;Second item&lt;/li&gt;
&lt;li&gt;Third item&lt;ol&gt;
&lt;li&gt;Nested ordered (level 2)&lt;/li&gt;
&lt;li&gt;Another nested&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Fourth item&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Mixed List&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Ordered item one&lt;ul&gt;
&lt;li&gt;Unordered nested under it&lt;/li&gt;
&lt;li&gt;Another unordered&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Ordered item two&lt;ul&gt;
&lt;li&gt;More nesting&lt;ol&gt;
&lt;li&gt;Deeply nested ordered&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Task List (GFM)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input checked=&quot;&quot; disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; Completed task&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; Incomplete task&lt;/li&gt;
&lt;li&gt;&lt;input checked=&quot;&quot; disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; Another completed task with &lt;strong&gt;bold&lt;/strong&gt; and &lt;em&gt;italic&lt;/em&gt; text inside&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; A task with a &lt;a href=&quot;https://astro.build&quot;&gt;link&lt;/a&gt; inside&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Task list items get custom checkboxes — checked items have a strikethrough on their text.&lt;/p&gt;
&lt;h3&gt;Definition List&lt;/h3&gt;
&lt;dl&gt;
  &lt;dt&gt;Astro&lt;/dt&gt;
  &lt;dd&gt;A modern static site generator that ships zero JavaScript by default.&lt;/dd&gt;
  &lt;dt&gt;Tailwind CSS&lt;/dt&gt;
  &lt;dd&gt;A utility-first CSS framework for rapid UI development.&lt;/dd&gt;
  &lt;dt&gt;KaTeX&lt;/dt&gt;
  &lt;dd&gt;A fast, easy-to-use JavaScript library for TeX math rendering on the web.&lt;/dd&gt;
&lt;/dl&gt;&lt;h2&gt;Blockquotes — Every Variant&lt;/h2&gt;
&lt;h3&gt;Simple Blockquote&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;This is a simple blockquote. It has one paragraph and no nesting.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Multi-Paragraph Blockquote&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;First paragraph of the blockquote.&lt;/p&gt;
&lt;p&gt;Second paragraph, separated by a blank line inside the blockquote.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Nested Blockquote&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Outer blockquote, level 1.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Inner blockquote, level 2.&lt;/p&gt;
&lt;p&gt;Still inside the inner blockquote.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Blockquote with Attribution&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;The best way to predict the future is to invent it.&lt;/p&gt;
&lt;p&gt;— Alan Kay&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Blockquote with Rich Content&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Bold&lt;/strong&gt;, &lt;em&gt;italic&lt;/em&gt;, &lt;del&gt;strikethrough&lt;/del&gt;, &lt;code&gt;inline code&lt;/code&gt;, and a &lt;a href=&quot;https://astro.build&quot;&gt;link&lt;/a&gt; — all work inside blockquotes.&lt;/p&gt;
&lt;p&gt;Even a nested list:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Item one&lt;/li&gt;
&lt;li&gt;Item two&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And a code block:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;const x = 42;
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Pull Quote (auto-styled)&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Design is not just what it looks like and feels like. Design is how it works.&lt;/p&gt;
&lt;p&gt;— Steve Jobs&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;All blockquotes get the editorial pull-quote treatment: large italic text, decorative opening quotation mark, gradient background, indigo left border, and subtle shadow.&lt;/p&gt;
&lt;h2&gt;Tables — Every Variant&lt;/h2&gt;
&lt;h3&gt;Simple Table&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Astro&lt;/td&gt;
&lt;td&gt;Framework&lt;/td&gt;
&lt;td&gt;Static site generator&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tailwind&lt;/td&gt;
&lt;td&gt;CSS&lt;/td&gt;
&lt;td&gt;Utility-first framework&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KaTeX&lt;/td&gt;
&lt;td&gt;Library&lt;/td&gt;
&lt;td&gt;Math rendering&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Table with Alignment&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;left&quot;&gt;Left aligned&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;Center aligned&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Right aligned&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;left&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;center&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;right&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;longer text&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;longer text&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;longer text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;short&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;short&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;short&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Table with Inline Formatting&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Syntax&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Bold&lt;/td&gt;
&lt;td&gt;&lt;code&gt;**text**&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;text&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Italic&lt;/td&gt;
&lt;td&gt;&lt;code&gt;*text*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;text&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Strikethrough&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~~text~~&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;del&gt;text&lt;/del&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inline code&lt;/td&gt;
&lt;td&gt;&lt;code&gt;`code`&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;code&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Link&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[text](url)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://astro.build&quot;&gt;text&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Table with Many Rows (Zebra Striping)&lt;/h3&gt;
&lt;p&gt;Tables with 4+ rows get automatic zebra striping on alternating rows. Hover highlights the row with a subtle indigo tint.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Era&lt;/th&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Notable Event&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Pre-history&lt;/td&gt;
&lt;td&gt;1843&lt;/td&gt;
&lt;td&gt;Ada Lovelace&amp;#39;s first algorithm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Pre-history&lt;/td&gt;
&lt;td&gt;1936&lt;/td&gt;
&lt;td&gt;Turing machine paper&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Birth of AI&lt;/td&gt;
&lt;td&gt;1956&lt;/td&gt;
&lt;td&gt;Dartmouth Conference&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;First winter&lt;/td&gt;
&lt;td&gt;1974&lt;/td&gt;
&lt;td&gt;Lighthill Report&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Expert systems&lt;/td&gt;
&lt;td&gt;1980&lt;/td&gt;
&lt;td&gt;Rise of MYCIN, XCON&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Second winter&lt;/td&gt;
&lt;td&gt;1987&lt;/td&gt;
&lt;td&gt;LISP machine market collapse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Deep learning&lt;/td&gt;
&lt;td&gt;2012&lt;/td&gt;
&lt;td&gt;AlexNet wins ImageNet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Transformer&lt;/td&gt;
&lt;td&gt;2017&lt;/td&gt;
&lt;td&gt;&amp;quot;Attention Is All You Need&amp;quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;Generative AI&lt;/td&gt;
&lt;td&gt;2022&lt;/td&gt;
&lt;td&gt;ChatGPT launches&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Wide Table (Horizontal Scroll)&lt;/h3&gt;
&lt;p&gt;Wide tables overflow horizontally on small screens. On desktop, they fit within the prose column.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Column A&lt;/th&gt;
&lt;th&gt;Column B&lt;/th&gt;
&lt;th&gt;Column C&lt;/th&gt;
&lt;th&gt;Column D&lt;/th&gt;
&lt;th&gt;Column E&lt;/th&gt;
&lt;th&gt;Column F&lt;/th&gt;
&lt;th&gt;Column G&lt;/th&gt;
&lt;th&gt;Column H&lt;/th&gt;
&lt;th&gt;Column I&lt;/th&gt;
&lt;th&gt;Column J&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;alpha&lt;/td&gt;
&lt;td&gt;beta&lt;/td&gt;
&lt;td&gt;gamma&lt;/td&gt;
&lt;td&gt;delta&lt;/td&gt;
&lt;td&gt;epsilon&lt;/td&gt;
&lt;td&gt;zeta&lt;/td&gt;
&lt;td&gt;eta&lt;/td&gt;
&lt;td&gt;theta&lt;/td&gt;
&lt;td&gt;iota&lt;/td&gt;
&lt;td&gt;kappa&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;Callouts — Every Type&lt;/h2&gt;
&lt;p&gt;The rehype-callouts plugin (GitHub theme) supports five callout types. Each renders as a colored block with an SVG indicator and a title.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[!note]
This is a &lt;strong&gt;note&lt;/strong&gt; callout. Use it for neutral, informational asides that don&amp;#39;t warrant stronger emphasis.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!tip]
This is a &lt;strong&gt;tip&lt;/strong&gt; callout. Use it for helpful suggestions, best practices, or shortcuts that improve the reader&amp;#39;s experience.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!important]
This is an &lt;strong&gt;important&lt;/strong&gt; callout. Use it for information that the reader must not skip — critical context, prerequisites, or warnings about data loss.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!warning]
This is a &lt;strong&gt;warning&lt;/strong&gt; callout. Use it for cautionary advice about things that could go wrong, common pitfalls, or edge cases.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!caution]
This is a &lt;strong&gt;caution&lt;/strong&gt; callout. Use it for the strongest warnings — actions that are irreversible, dangerous, or violate security.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Callouts with Custom Titles&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;[!note] Custom Title Here
When you add text after &lt;code&gt;[!note]&lt;/code&gt; on the same line, it replaces the default &amp;quot;Note&amp;quot; title. The body of the callout goes on the next line.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!tip] Pro Tip
Custom titles make callouts more specific. Use them when the default title is too generic.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Callouts with Rich Content&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;[!important] Read This First
Callouts support &lt;strong&gt;all&lt;/strong&gt; markdown inside them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lists&lt;/li&gt;
&lt;li&gt;&lt;code&gt;inline code&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://astro.build&quot;&gt;Links&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Even code blocks:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;function important() {
  return &amp;#39;this works inside callouts too&amp;#39;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Collapsible Callouts&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;[!note]- Collapsed by default (click to expand)
The &lt;code&gt;-&lt;/code&gt; after &lt;code&gt;[!note]&lt;/code&gt; makes the callout collapsed by default. Users click the title to expand it. Useful for long asides that aren&amp;#39;t essential to the main flow.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!note]+ Expanded by default (click to collapse)
The &lt;code&gt;+&lt;/code&gt; after &lt;code&gt;[!note]&lt;/code&gt; makes the callout expanded by default but collapsible. Useful for content that should be visible initially but can be hidden.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Code Blocks — Every Variant&lt;/h2&gt;
&lt;h3&gt;Plain Code Block (no language)&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;This is a plain code block with no language specified.
No syntax highlighting is applied.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;JavaScript&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;// A JavaScript code block with syntax highlighting
const greet = (name) =&amp;gt; {
  console.log(`Hello, ${name}!`);
  return `Greetings, ${name}`;
};

greet(&amp;#39;world&amp;#39;);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;TypeScript&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;// TypeScript with type annotations
interface User {
  id: number;
  name: string;
  email?: string;
}

function getUser(id: number): Promise&amp;lt;User&amp;gt; {
  return fetch(`/api/users/${id}`).then((res) =&amp;gt; res.json());
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Python&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# Python with type hints
from typing import List, Optional

def fibonacci(n: int) -&amp;gt; List[int]:
    &amp;quot;&amp;quot;&amp;quot;Generate the first n Fibonacci numbers.&amp;quot;&amp;quot;&amp;quot;
    if n &amp;lt;= 0:
        return []
    if n == 1:
        return [0]
    fibs = [0, 1]
    for _ in range(2, n):
        fibs.append(fibs[-1] + fibs[-2])
    return fibs

print(fibonacci(10))
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Bash / Shell&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;#!/usr/bin/env bash
# A bash script example
set -euo pipefail

PROJECT_DIR=&amp;quot;$(cd &amp;quot;$(dirname &amp;quot;${BASH_SOURCE[0]}&amp;quot;)&amp;quot; &amp;amp;&amp;amp; pwd)&amp;quot;
cd &amp;quot;$PROJECT_DIR&amp;quot;

echo &amp;quot;Building project...&amp;quot;
npm run build
echo &amp;quot;Deploying...&amp;quot;
npx wrangler pages deploy dist
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;JSON&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &amp;quot;name&amp;quot;: &amp;quot;isHistory&amp;quot;,
  &amp;quot;version&amp;quot;: &amp;quot;1.0.0&amp;quot;,
  &amp;quot;type&amp;quot;: &amp;quot;module&amp;quot;,
  &amp;quot;scripts&amp;quot;: {
    &amp;quot;dev&amp;quot;: &amp;quot;astro dev&amp;quot;,
    &amp;quot;build&amp;quot;: &amp;quot;astro build&amp;quot;,
    &amp;quot;preview&amp;quot;: &amp;quot;astro preview&amp;quot;
  },
  &amp;quot;dependencies&amp;quot;: {
    &amp;quot;astro&amp;quot;: &amp;quot;^6.0.0&amp;quot;,
    &amp;quot;tailwindcss&amp;quot;: &amp;quot;^4.0.0&amp;quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;CSS&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-css&quot;&gt;/* CSS with nested selectors */
.button {
  display: inline-flex;
  align-items: center;
  padding: 0.5rem 1rem;
  border-radius: 0.375rem;
  background: #4f46e5;
  color: #ffffff;
  transition: background-color 0.2s ease;
}

.button:hover {
  background: #4338ca;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;HTML&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;!doctype html&amp;gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;meta charset=&amp;quot;UTF-8&amp;quot; /&amp;gt;
    &amp;lt;title&amp;gt;Example&amp;lt;/title&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;main&amp;gt;
      &amp;lt;h1&amp;gt;Hello, world!&amp;lt;/h1&amp;gt;
      &amp;lt;p&amp;gt;This is an HTML code block.&amp;lt;/p&amp;gt;
    &amp;lt;/main&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;YAML&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;# YAML frontmatter example
title: &amp;quot;Sample Post&amp;quot;
description: &amp;quot;A sample post for demonstration.&amp;quot;
pubDate: 2026-06-18
tags:
  - Markdown
  - Reference
draft: false
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;SQL&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- SQL query example
SELECT
  u.id,
  u.name,
  COUNT(p.id) AS post_count,
  MAX(p.created_at) AS last_post
FROM users u
LEFT JOIN posts p ON p.author_id = u.id
WHERE u.created_at &amp;gt;= &amp;#39;2026-01-01&amp;#39;
GROUP BY u.id, u.name
HAVING COUNT(p.id) &amp;gt; 0
ORDER BY post_count DESC
LIMIT 10;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Code Block with Title (filename)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;import { defineConfig } from &amp;#39;astro/config&amp;#39;;

export default defineConfig({
  site: &amp;#39;https://ishistory.pp.ua&amp;#39;,
  integrations: [],
});
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Code Block with Line Highlighting&lt;/h3&gt;
&lt;p&gt;Use &lt;code&gt;{1,3-5}&lt;/code&gt; syntax to highlight specific lines:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;const config = {
  site: &amp;#39;https://ishistory.pp.ua&amp;#39;,
  integrations: [],
  markdown: {
    shikiConfig: { theme: &amp;#39;github-dark&amp;#39; },
    syntaxHighlight: &amp;#39;shiki&amp;#39;,
  },
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Code Block with Line Numbers&lt;/h3&gt;
&lt;p&gt;Use &lt;code&gt;showLineNumbers&lt;/code&gt; to add line numbers:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;function quicksort(arr) {
  if (arr.length &amp;lt;= 1) return arr;
  const pivot = arr[0];
  const left = arr.slice(1).filter((x) =&amp;gt; x &amp;lt; pivot);
  const right = arr.slice(1).filter((x) =&amp;gt; x &amp;gt;= pivot);
  return [...quicksort(left), pivot, ...quicksort(right)];
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Diff Code Block&lt;/h3&gt;
&lt;p&gt;Use &lt;code&gt;diff&lt;/code&gt; language to show additions/removals:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-diff&quot;&gt;function greet(name) {
-  console.log(&amp;quot;Hello, &amp;quot; + name);
+  console.log(`Hello, ${name}!`);
+  return `Greetings, ${name}`;
}

greet(&amp;quot;world&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Multiple Features Combined&lt;/h3&gt;
&lt;p&gt;Title + line numbers + line highlighting:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;export function factorial(n: number): number {
  if (n &amp;lt; 0) throw new Error(&amp;#39;Negative input&amp;#39;);
  let result = 1;
  for (let i = 2; i &amp;lt;= n; i++) {
    result *= i;
  }
  return result;
}

export function binomial(n: number, k: number): number {
  return factorial(n) / (factorial(k) * factorial(n - k));
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Inline Code&lt;/h3&gt;
&lt;p&gt;Inline code uses single backticks: &lt;code&gt;const x = 42&lt;/code&gt;. Code inside a sentence: &lt;code&gt;Array.prototype.map()&lt;/code&gt;. With special characters: &lt;code&gt;&amp;lt;div className=&amp;quot;foo&amp;quot; /&amp;gt;&lt;/code&gt;. With backticks inside: &lt;code&gt;`single backtick`&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Math — KaTeX&lt;/h2&gt;
&lt;p&gt;The pipeline supports inline math with &lt;code&gt;$...$&lt;/code&gt; and display math with &lt;code&gt;$$...$$&lt;/code&gt;. Math is rendered by KaTeX.&lt;/p&gt;
&lt;h3&gt;Inline Math&lt;/h3&gt;
&lt;p&gt;The Pythagorean theorem: $a^2 + b^2 = c^2$. The area of a circle: $A = \pi r^2$. Euler&amp;#39;s identity: $e^{i\pi} + 1 = 0$. A quadratic equation: $x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$.&lt;/p&gt;
&lt;p&gt;Inline math inherits the surrounding text color and respects line-height.&lt;/p&gt;
&lt;h3&gt;Display Math&lt;/h3&gt;
&lt;p&gt;$$
\int_{-\infty}^{\infty} e^{-x^2} , dx = \sqrt{\pi}
$$&lt;/p&gt;
&lt;p&gt;$$
\sum_{n=1}^{\infty} \frac{1}{n^2} = \frac{\pi^2}{6}
$$&lt;/p&gt;
&lt;p&gt;$$
\frac{\partial f}{\partial x} = \lim_{h \to 0} \frac{f(x+h) - f(x)}{h}
$$&lt;/p&gt;
&lt;h3&gt;Matrices&lt;/h3&gt;
&lt;h1&gt;$$
\begin{bmatrix}
a &amp;amp; b \
c &amp;amp; d
\end{bmatrix}
\begin{bmatrix}
x \
y
\end{bmatrix}&lt;/h1&gt;
&lt;p&gt;\begin{bmatrix}
ax + by \
cx + dy
\end{bmatrix}
$$&lt;/p&gt;
&lt;h3&gt;Aligned Equations&lt;/h3&gt;
&lt;p&gt;$$
\begin{aligned}
\nabla \times \vec{B} &amp;amp;= \mu_0 \vec{J} + \mu_0 \varepsilon_0 \frac{\partial \vec{E}}{\partial t} \
\nabla \times \vec{E} &amp;amp;= -\frac{\partial \vec{B}}{\partial t} \
\nabla \cdot \vec{B} &amp;amp;= 0 \
\nabla \cdot \vec{E} &amp;amp;= \frac{\rho}{\varepsilon_0}
\end{aligned}
$$&lt;/p&gt;
&lt;h3&gt;Cases (Piecewise Functions)&lt;/h3&gt;
&lt;p&gt;$$
f(x) = \begin{cases}
x^2 &amp;amp; \text{if } x \geq 0 \
-x^2 &amp;amp; \text{if } x &amp;lt; 0
\end{cases}
$$&lt;/p&gt;
&lt;h3&gt;Summation and Products&lt;/h3&gt;
&lt;p&gt;$$
\prod_{i=1}^{n} i = n! \qquad \sum_{k=0}^{n} \binom{n}{k} = 2^n
$$&lt;/p&gt;
&lt;h3&gt;Limits and Calculus&lt;/h3&gt;
&lt;p&gt;$$
\lim_{n \to \infty} \left(1 + \frac{1}{n}\right)^n = e \approx 2.71828\ldots
$$&lt;/p&gt;
&lt;h3&gt;Greek Letters and Symbols&lt;/h3&gt;
&lt;p&gt;$$
\alpha, \beta, \gamma, \delta, \epsilon, \zeta, \eta, \theta, \iota, \kappa, \lambda, \mu, \nu, \xi, \pi, \rho, \sigma, \tau, \upsilon, \phi, \chi, \psi, \omega
$$&lt;/p&gt;
&lt;p&gt;$$
\Gamma, \Delta, \Theta, \Lambda, \Xi, \Pi, \Sigma, \Upsilon, \Phi, \Psi, \Omega
$$&lt;/p&gt;
&lt;h3&gt;Math with Text&lt;/h3&gt;
&lt;p&gt;$$
P(\text{Event}) = \frac{\text{favorable outcomes}}{\text{total outcomes}} \times 100%
$$&lt;/p&gt;
&lt;h2&gt;Horizontal Rules&lt;/h2&gt;
&lt;p&gt;A horizontal rule creates an editorial section break — a gradient line with a centered indigo dot. Three variants of syntax all produce the same result:&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Above is a horizontal rule using three hyphens.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Above is a horizontal rule using three asterisks.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Above is a horizontal rule using three underscores.&lt;/p&gt;
&lt;h2&gt;Images&lt;/h2&gt;
&lt;p&gt;Astro logo (placeholder):&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://astro.build/assets/press/basic-logo.svg&quot; alt=&quot;Astro logo placeholder&quot; title=&quot;Astro logo&quot;&gt;&lt;/p&gt;
&lt;p&gt;Images get a rounded border and subtle box-shadow. Long alt text appears in the figcaption styling if wrapped in a figure (using HTML).&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://placehold.co/600x300/4F46E5/FFFFFF/png?text=Figure+with+caption&quot; alt=&quot;A placeholder figure with a caption&quot; loading=&quot;lazy&quot; /&gt;
  &lt;figcaption&gt;Figures with figcaptions get centered, smaller, muted text below the image. Use this for editorial figures that need attribution or explanation.&lt;/figcaption&gt;
&lt;/figure&gt;&lt;h2&gt;Details and Summary (Disclosure Widget)&lt;/h2&gt;
&lt;details&gt;
  &lt;summary&gt;Click to expand — basic details element&lt;/summary&gt;
  The `&lt;details&gt;` element creates a collapsible disclosure widget. The `&lt;summary&gt;` is the clickable header. Content below the summary is hidden until expanded.&lt;p&gt;  Markdown works inside:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lists&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bold&lt;/strong&gt; and &lt;em&gt;italic&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Inline code&lt;/code&gt;&lt;/details&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;details&gt;
  &lt;summary&gt;Multiple paragraphs inside details&lt;/summary&gt;&lt;p&gt;  First paragraph. Note the blank line above — it ensures proper paragraph spacing.&lt;/p&gt;
&lt;p&gt;  Second paragraph. Without the blank line, paragraphs would be squished together.&lt;/p&gt;
&lt;p&gt;  Even code blocks work:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;console.log(&amp;#39;inside a details element&amp;#39;);
&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;&lt;details open&gt;
  &lt;summary&gt;Expanded by default&lt;/summary&gt;
  Add the `open` attribute to `&lt;details&gt;` to start expanded. Users can collapse it by clicking the summary.
&lt;/details&gt;&lt;h2&gt;Addresses and Citations&lt;/h2&gt;
&lt;address&gt;
  Written by Ishaan&lt;br /&gt;
  isHistory Project&lt;br /&gt;
  Email: &lt;a href=&quot;mailto:ishistory@proton.me&quot;&gt;ishistory@proton.me&lt;/a&gt;&lt;br /&gt;
  Web: &lt;a href=&quot;https://ishistory.pp.ua&quot;&gt;ishistory.pp.ua&lt;/a&gt;
&lt;/address&gt;&lt;p&gt;As Alan Turing &lt;cite&gt;once wrote&lt;/cite&gt;, &amp;quot;We can only see a short distance ahead, but we can see plenty there that needs to be done.&amp;quot;&lt;/p&gt;
&lt;h2&gt;Footnotes&lt;/h2&gt;
&lt;p&gt;GFM supports footnotes via the &lt;code&gt;[^1]&lt;/code&gt; syntax[^1]. Footnotes appear at the bottom of the document with a clickable reference link[^longnote].&lt;/p&gt;
&lt;p&gt;[^1]: This is the first footnote. Click the back arrow to return to the text.&lt;/p&gt;
&lt;p&gt;[^longnote]: Here&amp;#39;s one with multiple paragraphs and code.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Indent paragraphs to include them in the footnote.

```
code blocks work too
```

And back to text.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Footnotes can also be inline[^inline-note] like this.&lt;/p&gt;
&lt;p&gt;[^inline-note]: This footnote is defined inline at the point of reference.&lt;/p&gt;
&lt;h2&gt;Combination Examples&lt;/h2&gt;
&lt;h3&gt;A Callout with Math Inside&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;[!tip] Math in Callouts
The quadratic formula $x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$ works inline inside callouts. So does display math:&lt;/p&gt;
&lt;p&gt;$$\text{discriminant} = b^2 - 4ac$$&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;A Table with Code and Math&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Code&lt;/th&gt;
&lt;th&gt;Math&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Square root&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Math.sqrt(x)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$\sqrt{x}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Power&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Math.pow(x, n)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$x^n$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sum&lt;/td&gt;
&lt;td&gt;&lt;code&gt;arr.reduce((a,b) =&amp;gt; a+b, 0)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$\sum_{i=1}^{n} x_i$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Integral&lt;/td&gt;
&lt;td&gt;n/a (numerical only)&lt;/td&gt;
&lt;td&gt;$\int_a^b f(x) , dx$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;A Blockquote with a Code Block&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Code is like humor. When you have to explain it, it&amp;#39;s bad.&amp;quot; — Cory House&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;// Even bad code can be improved
function bad() {
  return [1, 2, 3].map((x) =&amp;gt; x * 2).filter((x) =&amp;gt; x &amp;gt; 2).reduce((a, b) =&amp;gt; a + b, 0);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Edge Cases&lt;/h2&gt;
&lt;h3&gt;Empty Elements&lt;/h3&gt;
&lt;p&gt;A horizontal rule with no content around it:&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;A paragraph immediately after a horizontal rule.&lt;/p&gt;
&lt;h3&gt;Special Characters&lt;/h3&gt;
&lt;p&gt;The pipe character &lt;code&gt;|&lt;/code&gt; in tables needs escaping: | escaped pipe | in a table cell.&lt;/p&gt;
&lt;p&gt;Less-than &lt;code&gt;&amp;lt;&lt;/code&gt; and greater-than &lt;code&gt;&amp;gt;&lt;/code&gt; should be escaped in code: &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; becomes &lt;code&gt;&amp;amp;lt;div&amp;amp;gt;&lt;/code&gt; in raw HTML, but inside backticks &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; is fine.&lt;/p&gt;
&lt;p&gt;Ampersands: AT&amp;amp;T, Tom &amp;amp; Jerry, P&amp;amp;G. In code: &lt;code&gt;if (a &amp;amp;&amp;amp; b)&lt;/code&gt;. In URLs: &lt;code&gt;?a=1&amp;amp;b=2&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Emojis&lt;/h3&gt;
&lt;p&gt;Standard emojis work in markdown: 🚀 rocket, ✅ check, ❌ cross, ⚠️ warning, 💡 idea, 📌 pin, 🎯 target, 📝 memo. They render with the system emoji font.&lt;/p&gt;
&lt;h3&gt;Very Long Line&lt;/h3&gt;
&lt;p&gt;This is a single paragraph that contains a very long line of text without any line breaks in the source markdown. Markdown will wrap this to fit the available width automatically based on the prose container&amp;#39;s max-width. The 65ch optimal line length means the text wraps at approximately 65 characters per line, which is the recommended maximum for reading comfort per Baymard Institute research. Longer lines cause readers to lose their place when jumping from the end of one line to the start of the next; shorter lines force the eye to return too often, breaking rhythm. The 65ch value strikes the right balance for most body text.&lt;/p&gt;
&lt;h3&gt;Unicode and Internationalization&lt;/h3&gt;
&lt;p&gt;Latin: café, naïve, résumé, façade. Greek: α β γ δ ε ζ η θ ι κ λ μ. Cyrillic: А Б В Г Д Е Ж. Chinese: 你好世界. Japanese: こんにちは世界. Korean: 안녕하세요 세계. Arabic: مرحبا بالعالم. Hebrew: שלום עולם. Hindi: नमस्ते दुनिया. Thai: สวัสดีชาวโลก.&lt;/p&gt;
&lt;p&gt;Right-to-left text: &lt;span dir=&quot;rtl&quot;&gt;مرحبا بالعالم&lt;/span&gt; — wraps in a span with &lt;code&gt;dir=&amp;quot;rtl&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;This post exercised:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;6 heading levels (h1 implicit, h2–h6 in body)&lt;/li&gt;
&lt;li&gt;Paragraphs with inline formatting (bold, italic, strikethrough, code, mark, kbd, abbr, sub, sup, del, ins, cite, q, samp, small, big, tt, u)&lt;/li&gt;
&lt;li&gt;Links (inline, reference, auto, internal, external, wiki-link)&lt;/li&gt;
&lt;li&gt;Lists (unordered, ordered, nested, mixed, task list, definition list)&lt;/li&gt;
&lt;li&gt;Blockquotes (simple, multi-paragraph, nested, with attribution, with rich content)&lt;/li&gt;
&lt;li&gt;5 callout types (note, tip, important, warning, caution) × 4 variants each (default, custom title, rich content, collapsible)&lt;/li&gt;
&lt;li&gt;Tables (simple, aligned, with formatting, many-row, wide overflow)&lt;/li&gt;
&lt;li&gt;Code blocks (10+ languages, with title, line highlighting, line numbers, diff, combined)&lt;/li&gt;
&lt;li&gt;Math (inline, display, matrices, aligned, cases, summation, limits, Greek letters, with text)&lt;/li&gt;
&lt;li&gt;Horizontal rules (3 syntaxes)&lt;/li&gt;
&lt;li&gt;Images (inline, figure with caption)&lt;/li&gt;
&lt;li&gt;Details/summary (collapsed, expanded, with rich content)&lt;/li&gt;
&lt;li&gt;Addresses, citations, footnotes&lt;/li&gt;
&lt;li&gt;Edge cases (special characters, emojis, long lines, Unicode, RTL text)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you spot anything missing or rendering incorrectly, open an issue on the &lt;a href=&quot;https://github.com/IsOrganisation/isHistory-astro-project&quot;&gt;GitHub repo&lt;/a&gt;.&lt;/p&gt;
</content:encoded><category>markdown</category><category>reference</category><category>style-guide</category><author>ishistory@proton.me (Ishaan)</author></item><item><title>Your Astro Website Deserves a Better CMS: Meet isHistory</title><link>https://dcbf5610.ishistory.pages.dev/blog/astro-website-cms-obsidian-plugin/</link><guid isPermaLink="true">https://dcbf5610.ishistory.pages.dev/blog/astro-website-cms-obsidian-plugin/</guid><description>How I built isHistory CMS — an Obsidian plugin that turns your notes into a full content management system for Astro-powered websites with live validation, pre-flight deployment, and mobile support.</description><pubDate>Thu, 28 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Your Astro Website Deserves a Better CMS&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;How I Built isHistory CMS — an Obsidian plugin that turns your notes into a full content management system for Astro-powered websites&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;#39;ve ever built a content-heavy site with &lt;a href=&quot;https://astro.build&quot;&gt;Astro&lt;/a&gt;, you know the framework is fast, the builds are snappy, and the content collections system is genuinely elegant. But day-to-day content management? That&amp;#39;s another story.&lt;/p&gt;
&lt;p&gt;Open VS Code. Navigate through folders. Manually edit YAML frontmatter. Hope you didn&amp;#39;t miss a required field. It works — but it&amp;#39;s not a workflow. It&amp;#39;s a chore.&lt;/p&gt;
&lt;p&gt;I built &lt;strong&gt;isHistory CMS&lt;/strong&gt; to solve this problem. It&amp;#39;s now an official &lt;a href=&quot;https://community.obsidian.md/plugins/ishistory-cms&quot;&gt;Obsidian Community Plugin&lt;/a&gt; that turns Obsidian into a full CMS for Astro websites. Think of it as a spell‑checker for your blog posts — but instead of checking spelling, it checks that every post has all the information your Astro site needs to display it properly.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; – isHistory CMS gives you a visual dashboard, live frontmatter validation, one‑click pre‑flight marking, and a mobile‑friendly editorial interface — all inside Obsidian. No external servers, no API keys, your data stays in your vault.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;The Problem: Managing History Content in a Static World&lt;/h2&gt;
&lt;p&gt;Building an AI history publication in Astro is fast, elegant, and delightfully developer-friendly — until you have to manage it day to day. Each post in my publication has:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;track&lt;/strong&gt; (Articles, Profiles, or Events)&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;series order code&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Validation rules&lt;/strong&gt; for frontmatter fields&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;publishing status&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;#39;s a lot of metadata to juggle across dozens of Markdown files. A single typo in a frontmatter field can silently break your entire build.&lt;/p&gt;
&lt;p&gt;The default workflow — manually editing YAML in VS Code — works, but for a content-heavy site like mine, it becomes an active burden. I built isHistory CMS to turn Obsidian into a writing-first environment where content management feels like writing, not programming.&lt;/p&gt;
&lt;h2&gt;What isHistory CMS Does&lt;/h2&gt;
&lt;p&gt;isHistory CMS is designed for the &lt;strong&gt;isHistory Astro project&lt;/strong&gt; (a deep‑dive into the history of AI) but works with &lt;strong&gt;any Astro site that uses Content Collections&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;A Visual Dashboard for Your Content&lt;/h3&gt;
&lt;p&gt;The plugin opens a full dashboard view inside Obsidian that displays every post in your content collections as interactive cards. Each card shows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Post title&lt;/li&gt;
&lt;li&gt;Track badge&lt;/li&gt;
&lt;li&gt;Validation status (ready / errors)&lt;/li&gt;
&lt;li&gt;Description&lt;/li&gt;
&lt;li&gt;Tags&lt;/li&gt;
&lt;li&gt;Draft status&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Color‑coded left borders instantly tell you whether a post is ready for publication, has errors, or is still a work in progress.&lt;/p&gt;
&lt;p&gt;The dashboard also includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;stats bar&lt;/strong&gt; (archive posts, vault notes, track counts, drafts, errors, ready posts)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Full‑text search&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Filter buttons&lt;/strong&gt; for tracks, drafts, recent edits, errors&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sort options&lt;/strong&gt; (series order, newest first, oldest first, title, errors first, drafts first)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Live Frontmatter Validation&lt;/h3&gt;
&lt;p&gt;Missing a required field like &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, or &lt;code&gt;track&lt;/code&gt; can cause your Astro build to fail silently. isHistory CMS validates every post against your content schema &lt;strong&gt;in real time&lt;/strong&gt;, directly inside Obsidian.&lt;/p&gt;
&lt;p&gt;The validation engine checks for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Missing required fields&lt;/li&gt;
&lt;li&gt;Badly formatted dates&lt;/li&gt;
&lt;li&gt;Tags that aren&amp;#39;t YAML lists&lt;/li&gt;
&lt;li&gt;Series fields with missing partners&lt;/li&gt;
&lt;li&gt;Track mismatches&lt;/li&gt;
&lt;li&gt;Draft/published conflicts&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Errors and warnings appear on dashboard cards and in the sidebar validator as you type. What used to be a build‑time surprise becomes an in‑your‑face fix‑it‑now prompt while you&amp;#39;re still editing.&lt;/p&gt;
&lt;h3&gt;Pre‑flight: Mark Posts Ready for Deployment&lt;/h3&gt;
&lt;p&gt;The &lt;strong&gt;Pre‑flight&lt;/strong&gt; button is the heart of the publishing workflow. When you click Pre‑flight on a post, the plugin:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sets &lt;code&gt;draft: false&lt;/code&gt; in frontmatter&lt;/li&gt;
&lt;li&gt;Adds a published timestamp (and today&amp;#39;s date if none is set)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This signals your Astro site that the post is ready to go live on the next build. You can also Pre‑flight multiple posts at once through the bulk operation modal.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Pre‑flight marks the post as ready, but it &lt;strong&gt;does not&lt;/strong&gt; deploy it. Deployment requires a separate Git sync step (see &lt;a href=&quot;#getting-started-with-ishistory-cms&quot;&gt;Getting Started&lt;/a&gt;).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Mobile‑First Design&lt;/h3&gt;
&lt;p&gt;isHistory CMS is built with mobile support from the ground up. The manifest declares &lt;code&gt;isDesktopOnly: false&lt;/code&gt;, and every UI component is tested on the Obsidian mobile app. The dashboard grid adapts to smaller screens, the sidebar view works in the mobile drawer, and the new post creation flow is fully touch‑friendly.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The Technical Journey: From Idea to Official Plugin&lt;/h2&gt;
&lt;p&gt;Getting a plugin into the Obsidian Community Plugin directory is a rigorous process. Here are the key lessons from my review journey.&lt;/p&gt;
&lt;h3&gt;Eliminating XSS Vectors&lt;/h3&gt;
&lt;p&gt;The review team flagged three instances of &lt;code&gt;innerHTML&lt;/code&gt; in my initial code. I replaced every one with Obsidian&amp;#39;s native &lt;code&gt;createEl&lt;/code&gt; API, which constructs DOM elements programmatically and automatically escapes dangerous content.&lt;/p&gt;
&lt;h3&gt;Taming Asynchronous Chaos&lt;/h3&gt;
&lt;p&gt;Obsidian plugins interact with the vault file system through event listeners. My solution was a centralized debouncing framework that queues file paths and processes them on a schedule, eliminating race conditions and UI freezes.&lt;/p&gt;
&lt;h3&gt;Honest UX: Pre‑flight, Not Publish&lt;/h3&gt;
&lt;p&gt;I originally called the button &amp;quot;Publish.&amp;quot; But the plugin only modifies local frontmatter — actual deployment requires Git. Renaming it to &lt;strong&gt;Pre‑flight&lt;/strong&gt; sets accurate expectations: the plane is ready for takeoff, but the pilot (you) still needs to push the throttles (Git sync).&lt;/p&gt;
&lt;h3&gt;The CSS Specificity Lesson&lt;/h3&gt;
&lt;p&gt;The review&amp;#39;s CSS lint caught five uses of &lt;code&gt;!important&lt;/code&gt;. I replaced them with higher‑specificity selectors (e.g., &lt;code&gt;.cms-card.cms-card-track-A&lt;/code&gt; instead of &lt;code&gt;.cms-card-track-A&lt;/code&gt; with &lt;code&gt;!important&lt;/code&gt;).&lt;/p&gt;
&lt;h3&gt;Artifact Attestations and Build Verification&lt;/h3&gt;
&lt;p&gt;I set up a GitHub Actions workflow that runs on every tag push, executes a build verification script, generates attestations for &lt;code&gt;main.js&lt;/code&gt; and &lt;code&gt;styles.css&lt;/code&gt;, and creates the release automatically. The build script checks for forbidden patterns like &lt;code&gt;innerHTML&lt;/code&gt; and &lt;code&gt;console.log&lt;/code&gt;, and verifies no &lt;code&gt;!important&lt;/code&gt; remains in the CSS.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The Broader Ecosystem&lt;/h2&gt;
&lt;p&gt;The idea of using Obsidian as a CMS for Astro isn&amp;#39;t new. Several tools have explored this space:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Focus&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Vault CMS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Open‑source headless CMS with auto‑detection of routes and preconfigured workspace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Astro Composer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Automates post creation, slug generation, and link conversion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bases CMS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Card‑based views and bulk operations for Obsidian&amp;#39;s core Bases plugin&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Where does isHistory CMS fit?&lt;/strong&gt;
While Vault CMS emphasises automation and a complete publishing platform, &lt;strong&gt;isHistory CMS is built for writers who need rigorous frontmatter validation, track‑based organisation, and a clean editorial interface inside Obsidian.&lt;/strong&gt; It&amp;#39;s designed for the isHistory AI history project but works with any Astro site that uses Content Collections.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Current stats:&lt;/strong&gt; 25 downloads, four releases, recent v1.6.0 update. The plugin has not yet been manually reviewed by Obsidian staff, but it&amp;#39;s available in the community directory.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Getting Started with isHistory CMS&lt;/h2&gt;
&lt;h3&gt;Installation&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Open Obsidian -&amp;gt; &lt;strong&gt;Settings&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Community Plugins&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Browse&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Search for &lt;strong&gt;isHistory CMS&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Install and enable the plugin&lt;/li&gt;
&lt;li&gt;A new ribbon icon will appear — click it to open the dashboard&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Configuration&lt;/h3&gt;
&lt;p&gt;The plugin looks for content inside &lt;code&gt;src/content/blog&lt;/code&gt; (archive path) and &lt;code&gt;src/content/vault&lt;/code&gt; by default. If your Astro project is structured differently, change these paths in &lt;strong&gt;Settings -&amp;gt; isHistory CMS&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;No external server, no API keys, no cloud dependency. Your data stays in your vault, on your machine, under your control.&lt;/p&gt;
&lt;h3&gt;Deployment Pipeline&lt;/h3&gt;
&lt;p&gt;Pre‑flighting a post marks it as ready, but it doesn&amp;#39;t push it live. To deploy:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install &lt;a href=&quot;https://obsidian.md/plugins?id=obsidian-git&quot;&gt;Obsidian Git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Configure it to auto‑commit and push on an interval (e.g., every 5 minutes)&lt;/li&gt;
&lt;li&gt;Your Astro site&amp;#39;s CI/CD (Vercel, Netlify, Cloudflare Pages, etc.) detects the push and rebuilds automatically&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Full pipeline:&lt;/strong&gt; Write -&amp;gt; Pre‑flight -&amp;gt; Git sync -&amp;gt; Auto‑deploy&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you click Pre‑flight and your site doesn&amp;#39;t update, the first place to check is your Git sync — the plugin&amp;#39;s FAQ covers this exact scenario.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Why I Built This and What Comes Next&lt;/h2&gt;
&lt;p&gt;I built isHistory CMS because Obsidian is where I think and write. It should also be where I manage my content. Now it finally is.&lt;/p&gt;
&lt;p&gt;The Obsidian plugin review process pushed the code toward a higher standard of security, usability, and maintainability. The result is a plugin I use every day to run my own site — and one that has already been downloaded 25 times since its recent release.&lt;/p&gt;
&lt;h3&gt;Roadmap&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Git integration&lt;/strong&gt; – embed Git operations directly so Pre‑flight can optionally commit and push without a separate plugin&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Schema auto‑detection&lt;/strong&gt; – read Astro content config files to eliminate manual path configuration&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Media management view&lt;/strong&gt; – bring image and asset management into the same dashboard&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Try isHistory CMS&lt;/h2&gt;
&lt;p&gt;If you&amp;#39;re running an Astro site — especially a content‑heavy one with complex frontmatter validation needs — give isHistory CMS a try.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://community.obsidian.md/plugins/ishistory-cms&quot;&gt;Install isHistory CMS from Obsidian Community Plugins&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Free&lt;/strong&gt; and &lt;strong&gt;open source&lt;/strong&gt; (MIT licensed)&lt;/li&gt;
&lt;li&gt;Available now in the Obsidian Community Plugin directory&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Write in Obsidian. Validate in real time. Pre‑flight with confidence. Deploy with Git. Your notes deserve a better CMS, and now they have one.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;FAQ&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Q: Does isHistory CMS work with any Astro site?&lt;/strong&gt;
A: Yes — it works with any Astro project that uses Content Collections. The default paths are &lt;code&gt;src/content/blog&lt;/code&gt; and &lt;code&gt;src/content/vault&lt;/code&gt;, but you can configure them in settings.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: Does the plugin deploy my site?&lt;/strong&gt;
A: No. Pre‑flight only modifies local frontmatter (sets &lt;code&gt;draft: false&lt;/code&gt; and adds timestamps). Deployment requires a Git sync (e.g., Obsidian Git) and your hosting platform&amp;#39;s auto‑deploy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: Is my data sent to any server?&lt;/strong&gt;
A: No. Everything stays in your local Obsidian vault. No external APIs, no telemetry, no cloud dependencies.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: Is it really mobile‑friendly?&lt;/strong&gt;
A: Yes. The plugin is tested on the Obsidian mobile app and adapts to smaller screens.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: How is this different from Vault CMS?&lt;/strong&gt;
A: Vault CMS focuses on automation and a complete publishing platform. isHistory CMS focuses on &lt;strong&gt;rigorous validation, track‑based organisation, and a clean editorial interface&lt;/strong&gt; — ideal for writers managing complex frontmatter.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Linked References&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/dr-ishaan/astro-cms-obsidian-plugin&quot;&gt;isHistory CMS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><category>obsidian</category><category>astro</category><category>cms</category><author>ishistory@proton.me (Ishaan)</author></item></channel></rss>