<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: TypeFire</title>
    <description>The latest articles on DEV Community by TypeFire (@typefire).</description>
    <link>https://dev.to/typefire</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4216225%2Fd2ffa2e0-e1c5-45ad-a505-6c24c4dd7e86.png</url>
      <title>DEV Community: TypeFire</title>
      <link>https://dev.to/typefire</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/typefire"/>
    <language>en</language>
    <item>
      <title>Why Your Mac Opens .md Files in Xcode, and How to Fix It From the Terminal</title>
      <dc:creator>TypeFire</dc:creator>
      <pubDate>Fri, 30 Oct 2026 18:31:43 +0000</pubDate>
      <link>https://dev.to/typefire/why-your-mac-opens-md-files-in-xcode-and-how-to-fix-it-from-the-terminal-4858</link>
      <guid>https://dev.to/typefire/why-your-mac-opens-md-files-in-xcode-and-how-to-fix-it-from-the-terminal-4858</guid>
      <description>&lt;p&gt;You clone a repo, double-click &lt;code&gt;README.md&lt;/code&gt;, and Xcode starts up. Or TextEdit opens it as a wall of hashes and asterisks. Every AI tool you use now writes Markdown, and the Mac still treats it like a config file.&lt;/p&gt;

&lt;p&gt;This is fixable in a few minutes, and once you see how macOS decides which app opens a file, the fix stays put. We'll go through it from the terminal, with the Finder version for anyone who'd rather click.&lt;/p&gt;

&lt;h2&gt;
  
  
  How macOS picks the app: one type, a few extensions
&lt;/h2&gt;

&lt;p&gt;macOS doesn't map extensions to apps directly. It maps each file to a &lt;strong&gt;Uniform Type Identifier&lt;/strong&gt; (UTI), and apps register as handlers for UTIs. Ask Spotlight what type a file is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mdls &lt;span class="nt"&gt;-name&lt;/span&gt; kMDItemContentType README.md
&lt;span class="c"&gt;# kMDItemContentType = "net.daringfireball.markdown"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We checked this on macOS 26.3: &lt;code&gt;.md&lt;/code&gt; and &lt;code&gt;.markdown&lt;/code&gt; both resolve to &lt;code&gt;net.daringfireball.markdown&lt;/code&gt;, the type named after John Gruber's site, where Markdown started. Set a handler for that type and both extensions follow.&lt;/p&gt;

&lt;p&gt;On a developer's Mac, several apps usually claim that type: Xcode, a couple of editors, whatever IDE you installed last. Until you pick one, macOS picks for you, and it's rarely the one you'd choose.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.mdown&lt;/code&gt; and &lt;code&gt;.mkd&lt;/code&gt; are different. Unless an installed app declares them, macOS gives them dynamic types (&lt;code&gt;dyn.ah62d4rv...&lt;/code&gt;), so they need their own handler. If your files use those extensions, renaming them to &lt;code&gt;.md&lt;/code&gt; is the simplest fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix it with duti (two commands)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/moretension/duti" rel="noopener noreferrer"&gt;duti&lt;/a&gt; is a small command-line tool that sets default handlers by UTI. Install it with Homebrew:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;duti
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check what currently opens Markdown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;duti &lt;span class="nt"&gt;-x&lt;/span&gt; md
&lt;span class="c"&gt;# Xcode.app&lt;/span&gt;
&lt;span class="c"&gt;# /Applications/Xcode.app&lt;/span&gt;
&lt;span class="c"&gt;# com.apple.dt.Xcode&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then set the handler by bundle ID. &lt;code&gt;all&lt;/code&gt; covers every role (viewer, editor, shell):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;duti &lt;span class="nt"&gt;-s&lt;/span&gt; &amp;lt;bundle-id&amp;gt; net.daringfireball.markdown all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To find any app's bundle ID:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;defaults &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="s2"&gt;"/Applications/Visual Studio Code.app/Contents/Info"&lt;/span&gt; CFBundleIdentifier
&lt;span class="c"&gt;# com.microsoft.VSCode&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, for VS Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;duti &lt;span class="nt"&gt;-s&lt;/span&gt; com.microsoft.VSCode net.daringfireball.markdown all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;duti -x md&lt;/code&gt; again to confirm. Because it's one line, it fits in a dotfiles bootstrap script, so a new Mac gets the right default on day one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ~/dotfiles/macos/defaults.sh&lt;/span&gt;
duti &lt;span class="nt"&gt;-s&lt;/span&gt; com.microsoft.VSCode net.daringfireball.markdown all
duti &lt;span class="nt"&gt;-s&lt;/span&gt; com.microsoft.VSCode public.json all
duti &lt;span class="nt"&gt;-s&lt;/span&gt; com.microsoft.VSCode public.yaml all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffcp4rthb63wtq6jqhqtj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffcp4rthb63wtq6jqhqtj.png" alt="Terminal: mdls shows .md and .markdown as net.daringfireball.markdown and .mdown as a dynamic type, then duti sets and confirms VS Code as the handler" width="800" height="368"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Check the type, set the handler, confirm. The &lt;code&gt;.mdown&lt;/code&gt; file is the one that needs its own default.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Finder way
&lt;/h2&gt;

&lt;p&gt;If you'd rather not install anything:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select any &lt;code&gt;.md&lt;/code&gt; file and press ⌘I (Get Info).&lt;/li&gt;
&lt;li&gt;Expand &lt;strong&gt;Open with&lt;/strong&gt; and pick the app.&lt;/li&gt;
&lt;li&gt;Press &lt;strong&gt;Change All&lt;/strong&gt;, then confirm.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The step people skip is &lt;strong&gt;Change All&lt;/strong&gt;. Picking an app without it only changes that one file, which is why the problem seems to come back.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why it keeps reverting
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;An app re-registered on update.&lt;/strong&gt; Xcode, in particular, can claim the type again after a big update. Re-run your &lt;code&gt;duti&lt;/code&gt; line; this is where having it in a script pays off.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The file has its own override.&lt;/strong&gt; A file you once set with "Open with" (without Change All) keeps that choice. Select it, Get Info, and press Change All from there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A stale Launch Services database.&lt;/strong&gt; If nothing sticks, rebuilding the database usually clears it. It resets every file association on the Mac, so treat it as a last resort:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;LSREGISTER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister
&lt;span class="nv"&gt;$LSREGISTER&lt;/span&gt; &lt;span class="nt"&gt;-kill&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;-domain&lt;/span&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nt"&gt;-domain&lt;/span&gt; system &lt;span class="nt"&gt;-domain&lt;/span&gt; user
killall Finder
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Reading without opening: Quick Look
&lt;/h2&gt;

&lt;p&gt;A default app fixes double-clicking. Most of the time, though, you just want to &lt;em&gt;read&lt;/em&gt; the file: a README in a repo you cloned, notes an AI agent left behind, release notes in a download.&lt;/p&gt;

&lt;p&gt;That's Quick Look: select the file in Finder and press Space. Out of the box, macOS shows Markdown as raw source. A Quick Look extension can render it with headings, lists, tables and code blocks instead. To test whatever's installed from the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;qlmanage &lt;span class="nt"&gt;-p&lt;/span&gt; README.md      &lt;span class="c"&gt;# preview a file the way Finder's Space does&lt;/span&gt;
pluginkit &lt;span class="nt"&gt;-mAv&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; com.apple.quicklook.preview   &lt;span class="c"&gt;# list installed preview extensions&lt;/span&gt;
qlmanage &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; qlmanage &lt;span class="nt"&gt;-r&lt;/span&gt; cache         &lt;span class="c"&gt;# reset Quick Look if a new extension doesn't show up&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnon1p70n1ut0vao09o4z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnon1p70n1ut0vao09o4z.png" alt="A README.md selected in Finder and previewed with Space, showing a rendered heading, a table, a task list and a code block" width="800" height="520"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Space in Finder with a Markdown Quick Look extension: headings, tables, task lists and code instead of raw text.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Where TypeFire fits
&lt;/h2&gt;

&lt;p&gt;This part is ours, so here's exactly what it does. &lt;a href="https://typefire.app" rel="noopener noreferrer"&gt;TypeFire&lt;/a&gt; is a Mac app that includes a &lt;a href="https://typefire.app/markdown-quick-look-mac" rel="noopener noreferrer"&gt;Markdown Quick Look extension&lt;/a&gt;. Install the app and Space in Finder renders &lt;code&gt;.md&lt;/code&gt; and &lt;code&gt;.markdown&lt;/code&gt; files, math included (&lt;code&gt;$x^2$&lt;/code&gt; inline and &lt;code&gt;$$&lt;/code&gt; blocks). It's free, with nothing to switch on. If another Markdown previewer is installed, TypeFire tells you which one it replaced, and you can switch to another previewer in Settings → Markdown.&lt;/p&gt;

&lt;p&gt;It also has a one-click default: &lt;strong&gt;Settings → Markdown → Set as Default&lt;/strong&gt; makes TypeFire the default app for &lt;code&gt;.md&lt;/code&gt; and &lt;code&gt;.markdown&lt;/code&gt; files (under the hood, the same Launch Services call duti makes).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzpcrinkjgj8atjz3hc3b.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzpcrinkjgj8atjz3hc3b.jpg" alt="Finder's Downloads folder where the .md files show the TypeFire icon after it was set as the default Markdown app" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Once a default is set, every &lt;code&gt;.md&lt;/code&gt; file in Finder carries that app's icon.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You don't need TypeFire for anything above; &lt;code&gt;duti&lt;/code&gt; and Finder do the job. It's for anyone who wants rendered previews and an editor in one install. Our &lt;a href="https://typefire.app/blog/set-default-markdown-editor-mac" rel="noopener noreferrer"&gt;guide to the default Markdown editor on Mac&lt;/a&gt; has the Finder steps.&lt;/p&gt;

&lt;p&gt;Here's opening and editing a &lt;code&gt;.md&lt;/code&gt; from Finder in 85 seconds:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/BAlrUP7Ysqo" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  The short version
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.md&lt;/code&gt; and &lt;code&gt;.markdown&lt;/code&gt; share one type, &lt;code&gt;net.daringfireball.markdown&lt;/code&gt;. Set the handler once.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;brew install duti&lt;/code&gt;, then &lt;code&gt;duti -s &amp;lt;bundle-id&amp;gt; net.daringfireball.markdown all&lt;/code&gt;. Put it in your dotfiles.&lt;/li&gt;
&lt;li&gt;In Finder, the step that matters is &lt;strong&gt;Change All&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;For reading, use Quick Look (Space) with a Markdown extension, and test it with &lt;code&gt;qlmanage -p&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What opens your &lt;code&gt;.md&lt;/code&gt; files right now? Run &lt;code&gt;duti -x md&lt;/code&gt; and see.&lt;/p&gt;

</description>
      <category>macos</category>
      <category>markdown</category>
      <category>terminal</category>
      <category>productivity</category>
    </item>
    <item>
      <title>What Obsidian Really Costs a Dev Team in 2026 (and 4 Ways to Sync a Vault)</title>
      <dc:creator>TypeFire</dc:creator>
      <pubDate>Fri, 30 Oct 2026 05:13:16 +0000</pubDate>
      <link>https://dev.to/typefire/what-obsidian-really-costs-a-dev-team-in-2026-and-4-ways-to-sync-a-vault-pd1</link>
      <guid>https://dev.to/typefire/what-obsidian-really-costs-a-dev-team-in-2026-and-4-ways-to-sync-a-vault-pd1</guid>
      <description>&lt;p&gt;Somebody on your team starts keeping docs in Obsidian. Then a few more people do. At some point a manager asks the reasonable question: do we need to pay for this?&lt;/p&gt;

&lt;p&gt;Short answer: probably not for the license, and maybe for sync. Every figure below comes from &lt;a href="https://obsidian.md/pricing" rel="noopener noreferrer"&gt;Obsidian's own pricing page&lt;/a&gt;, which we checked on October 29, 2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  The price list
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;Required?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;The Obsidian app&lt;/td&gt;
&lt;td&gt;Free, for personal and work use&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sync&lt;/td&gt;
&lt;td&gt;$4 per user per month billed yearly, $5 monthly&lt;/td&gt;
&lt;td&gt;Only if you use it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Publish&lt;/td&gt;
&lt;td&gt;$8 per site per month billed yearly, $10 monthly&lt;/td&gt;
&lt;td&gt;Only if you use it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Commercial license&lt;/td&gt;
&lt;td&gt;$50 per user per year&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Catalyst (early access)&lt;/td&gt;
&lt;td&gt;$25 once&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Students, faculty and nonprofit staff get 40% off Sync and Publish.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is the commercial license required?
&lt;/h2&gt;

&lt;p&gt;No. Obsidian's FAQ answers this directly: you are not required to pay for commercial use. It does encourage organizations to buy the license so the app stays independent and user funded, and companies that buy one can be listed as featured organizations.&lt;/p&gt;

&lt;p&gt;So if your team is happy with the app and syncs files some other way, the honest bill is zero. Buying licenses is a way to support a tool you rely on, and plenty of teams do it for exactly that reason. We wrote up the details on our &lt;a href="https://typefire.app/obsidian-commercial-license" rel="noopener noreferrer"&gt;Obsidian commercial license page&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the money actually goes
&lt;/h2&gt;

&lt;p&gt;The recurring cost is Sync, because it's priced per person, every month, for as long as you use it. Here's what that looks like over three years:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqzk7yc1ekq63ngycrf52.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqzk7yc1ekq63ngycrf52.png" alt="Three years of Obsidian by setup: one person app only $0, one person with Sync $144, one person with Sync and Publish $432, team of 10 with Sync $1,440, team of 10 with Sync and licenses $2,940" width="800" height="376"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Annual billing. The last bar includes the optional license, which more than doubles the team figure.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you want the math as code, so you can plug in your own headcount:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SYNC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;      &lt;span class="c1"&gt;// per user per year, billed yearly&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PUBLISH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// per site per year, billed yearly&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LICENSE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;       &lt;span class="c1"&gt;// per user per year, optional&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;obsidianCost&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;people&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;years&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sync&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sites&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;licenses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;perYear&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sync&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;people&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;SYNC&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
    &lt;span class="nx"&gt;sites&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;PUBLISH&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;licenses&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;people&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;LICENSE&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;perYear&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;years&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;obsidianCost&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;people&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;                   &lt;span class="c1"&gt;// 1440&lt;/span&gt;
&lt;span class="nf"&gt;obsidianCost&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;people&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;licenses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;   &lt;span class="c1"&gt;// 2940&lt;/span&gt;
&lt;span class="nf"&gt;obsidianCost&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;people&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;sites&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;          &lt;span class="c1"&gt;// 432&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Four ways to sync a vault
&lt;/h2&gt;

&lt;p&gt;A vault is a folder of Markdown files, so anything that moves files can sync it. Each option below trades money against something else.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Obsidian Sync
&lt;/h3&gt;

&lt;p&gt;The paid service. It's end-to-end encrypted, keeps version history, supports shared vaults, and works on iOS and Android as well as desktop. If your team needs notes on phones, this is the one to pay for, and nothing else here matches it on mobile.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Git
&lt;/h3&gt;

&lt;p&gt;Free, and most dev teams already know it. You get full history, diffs and blame on your notes, and the vault can live next to your code. The community &lt;a href="https://github.com/Vinzent03/obsidian-git" rel="noopener noreferrer"&gt;Git plugin&lt;/a&gt; can commit and pull on a timer, so nobody has to remember.&lt;/p&gt;

&lt;p&gt;A few lines of &lt;code&gt;.gitignore&lt;/code&gt; keep the noise out. Obsidian rewrites its workspace files every time you open a pane, and you don't want those in every commit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Obsidian: per-device UI state, changes constantly
.obsidian/workspace.json
.obsidian/workspace-mobile.json

# Obsidian's local trash
.trash/

# macOS
.DS_Store
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep the rest of &lt;code&gt;.obsidian/&lt;/code&gt; committed if you want the team to share the same plugins and settings. The trade-off is that Git is a pull and push model: two people editing the same note at the same time get a merge to resolve, the same as with code.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. A cloud folder (iCloud Drive, Dropbox, Syncthing)
&lt;/h3&gt;

&lt;p&gt;Put the vault in a folder that already syncs and you're done. It's free and needs no setup beyond moving the folder. It works best for one person across their own devices; for several people writing in the same files, Git's history makes changes easier to follow.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. TypeFire, between Macs
&lt;/h3&gt;

&lt;p&gt;This one is ours, so here's exactly what it does. &lt;a href="https://typefire.app" rel="noopener noreferrer"&gt;TypeFire&lt;/a&gt; opens the vault you already have, in place: the same &lt;code&gt;.md&lt;/code&gt; files, no import and no copy, and Obsidian keeps working alongside it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp1vkp95tjpc7e69nhwj5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp1vkp95tjpc7e69nhwj5.png" alt="TypeFire reading an Obsidian vault in place: the same Markdown files on disk, no import, no copy" width="800" height="585"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Same folder, same files. TypeFire never rewrites a file you only open.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Notes sync is part of TypeFire Pro, a one-time purchase that covers three Macs, with note version history included. It runs through your own iCloud Drive, so nothing passes through a TypeFire server. It's built for Mac to Mac. For phones, Obsidian Sync is the one to pay for. The &lt;a href="https://typefire.app/docs/sync/icloud-sync" rel="noopener noreferrer"&gt;iCloud sync docs&lt;/a&gt; cover what syncs and how.&lt;/p&gt;

&lt;p&gt;Here's the Notes tab in two minutes:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/QEeInozatMQ" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  While you're in the vault all day
&lt;/h2&gt;

&lt;p&gt;Sync is what costs money. What saves time is getting to a note without leaving the app you're in. TypeFire's note search opens over whatever you're working in, and Enter pastes the note into it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6rul40byfrpavlwyohr2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6rul40byfrpavlwyohr2.png" alt="TypeFire note search opened over another app with a global shortcut, with Enter pasting the note into the document underneath" width="799" height="493"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Search the vault from your editor, terminal or browser, and paste the answer where you are.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We wrote more about this in &lt;a href="https://typefire.app/blog/capture-into-obsidian-from-any-app" rel="noopener noreferrer"&gt;capturing into Obsidian from any app&lt;/a&gt;. For the long version of the cost breakdown, including what Sync gets you, see &lt;a href="https://typefire.app/blog/real-cost-of-obsidian" rel="noopener noreferrer"&gt;Obsidian pricing in 2026&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The short version
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The Obsidian app is free for work, and the $50 commercial license is optional.&lt;/li&gt;
&lt;li&gt;Sync is the real recurring cost: $4 per person per month billed yearly, which comes to $1,440 over three years for a team of ten.&lt;/li&gt;
&lt;li&gt;Need mobile? Pay for Obsidian Sync. Desktop only? Git or a cloud folder costs nothing, and TypeFire covers Mac-to-Mac with a one-time purchase.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How does your team sync its vault, and has anyone made Git work smoothly on mobile?&lt;/p&gt;

</description>
      <category>obsidian</category>
      <category>productivity</category>
      <category>git</category>
      <category>markdown</category>
    </item>
    <item>
      <title>15 Text Expander Snippets Every Developer Should Steal (Commits, PRs, Bug Reports)</title>
      <dc:creator>TypeFire</dc:creator>
      <pubDate>Fri, 30 Oct 2026 01:39:56 +0000</pubDate>
      <link>https://dev.to/typefire/15-text-expander-snippets-every-developer-should-steal-commits-prs-bug-reports-1kbd</link>
      <guid>https://dev.to/typefire/15-text-expander-snippets-every-developer-should-steal-commits-prs-bug-reports-1kbd</guid>
      <description>&lt;p&gt;You type the same things all day. The commit prefix. The PR template. "Steps to reproduce." The standup. The &lt;code&gt;console.log&lt;/code&gt; with a label so you can find it again. Each one is ten seconds, and there are dozens of them a day.&lt;/p&gt;

&lt;p&gt;A text expander turns each into a few keystrokes: type &lt;code&gt;;pr&lt;/code&gt; and the whole template lands, wherever your cursor is. Below are 15 snippets worth setting up, written in the token syntax we use at TypeFire. The ideas work in any good expander; the syntax is ours.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6gvfe0xi1wcpe1jcxq86.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6gvfe0xi1wcpe1jcxq86.png" alt="Typing thx expands into a full email reply" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Type &lt;code&gt;thx&lt;/code&gt;, get the whole reply. The tokens below work the same way.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  A quick primer on the syntax
&lt;/h2&gt;

&lt;p&gt;Every example uses four kinds of placeholder that fill in at the moment of expansion:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;{{fill:Label}}&lt;/code&gt; stops and asks you for a value (a ticket number, a scope). &lt;code&gt;{{fill:Label|default}}&lt;/code&gt; prefills it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;{{date}}&lt;/code&gt;, &lt;code&gt;{{time}}&lt;/code&gt; and formats like &lt;code&gt;{{date:dddd}}&lt;/code&gt; insert today's date, the time or the weekday. Date math works too: &lt;code&gt;{{date:+1d}}&lt;/code&gt; is tomorrow.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;{{clipboard}}&lt;/code&gt; pastes whatever you last copied.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;{{cursor}}&lt;/code&gt; leaves your cursor at that spot after expanding (plain-text snippets only).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Save these as Plain Text snippets, even the Markdown-looking ones, so &lt;code&gt;{{cursor}}&lt;/code&gt; works and the Markdown pastes exactly as written.&lt;/p&gt;

&lt;p&gt;The full list is in the &lt;a href="https://typefire.app/docs/tokens-and-ai/dynamic-tokens" rel="noopener noreferrer"&gt;dynamic tokens docs&lt;/a&gt;, and this 90-second walkthrough shows fill-ins and date math in action:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/CrZ3wkpgCbo" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;A tip on naming: start every abbreviation with a character you never type at the start of a word, like &lt;code&gt;;&lt;/code&gt; or &lt;code&gt;z&lt;/code&gt;. Then &lt;code&gt;;pr&lt;/code&gt; never fires by accident in the middle of a sentence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Git and pull requests
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Conventional commit, &lt;code&gt;;cc&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{{fill:type|feat}}({{fill:scope}}): {{fill:summary}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One form, three boxes, and a correctly formatted commit message every time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Branch name, &lt;code&gt;;br&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git checkout -b {{fill:type|fix}}/{{fill:ticket}}-{{fill:short name}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Pull request template, &lt;code&gt;;pr&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## What changed&lt;/span&gt;
{{cursor}}

&lt;span class="gu"&gt;## Why&lt;/span&gt;

&lt;span class="gu"&gt;## How to test&lt;/span&gt;
&lt;span class="p"&gt;1.&lt;/span&gt;

&lt;span class="gu"&gt;## Checklist&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Tests added or updated
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Docs updated
&lt;span class="p"&gt;-&lt;/span&gt; [ ] No new warnings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your PR template is Markdown, preview it before you push. We wrote up &lt;a href="https://dev.to/typefire/markdown-live-preview-4-ways-to-see-what-your-readme-really-looks-like-before-you-push-ngj"&gt;four ways to preview Markdown live&lt;/a&gt;, including the task-list syntax this one uses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Approve with a nit, &lt;code&gt;;lgtm&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LGTM, thanks! One small nit (non-blocking): {{cursor}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Changelog entry, &lt;code&gt;;cl&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## [{{fill:version}}] - {{date}}&lt;/span&gt;
&lt;span class="gu"&gt;### Added&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; {{cursor}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Code review and bugs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;6. Review checklist, &lt;code&gt;;crv&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; [ ] Does it do what the ticket says?
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Edge cases: empty, huge, unicode, offline
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Errors are handled and shown in plain words
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Tests cover the change
&lt;span class="p"&gt;-&lt;/span&gt; [ ] No secrets, no debug logging left in
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;7. Bug report, &lt;code&gt;;bug&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gs"&gt;**Steps to reproduce**&lt;/span&gt;
&lt;span class="p"&gt;1.&lt;/span&gt; {{cursor}}

&lt;span class="gs"&gt;**Expected**&lt;/span&gt;

&lt;span class="gs"&gt;**Actual**&lt;/span&gt;

&lt;span class="gs"&gt;**Environment:**&lt;/span&gt; {{fill:browser or OS}}, reported {{date}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;8. "Can you share more?", &lt;code&gt;;more&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Thanks for the report! Could you share the exact steps, what you expected, and a screenshot or the console output? That'll help us reproduce it.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Code you type a hundred times
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;9. Labeled log, &lt;code&gt;;log&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;console.log("{{fill:label}}:", {{fill:value}});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;10. TODO with an owner and a date, &lt;code&gt;;todo&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// TODO({{fill:owner}}, {{date}}): {{cursor}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A dated TODO is one somebody might actually come back to.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnjt385rhps8f75rqizxu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnjt385rhps8f75rqizxu.png" alt="Two developer snippets: a console.log with the clipboard and a try/catch scaffold with the cursor inside" width="800" height="507"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Two more from our &lt;a href="https://typefire.app/code-snippet-expander" rel="noopener noreferrer"&gt;developer snippets page&lt;/a&gt;: &lt;code&gt;{{clipboard}}&lt;/code&gt; drops in what you just copied, &lt;code&gt;{{cursor}}&lt;/code&gt; parks the caret inside the block.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;11. Markdown table skeleton, &lt;code&gt;;tbl&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;| {{fill:Column 1}} | {{fill:Column 2}} |
| --- | --- |
|  |  |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Team rituals
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;12. Standup, &lt;code&gt;;su&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gs"&gt;**{{date:dddd}}**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Yesterday: {{cursor}}
&lt;span class="p"&gt;-&lt;/span&gt; Today:
&lt;span class="p"&gt;-&lt;/span&gt; Blockers: none
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;13. On-call handoff, &lt;code&gt;;oncall&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Handing off on-call, {{date:MMMM DD}}.
&lt;span class="p"&gt;-&lt;/span&gt; Open incidents:
&lt;span class="p"&gt;-&lt;/span&gt; Watch out for:
&lt;span class="p"&gt;-&lt;/span&gt; Next check-in: {{date:+1d:dddd}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Two that run code (Mac app)
&lt;/h2&gt;

&lt;p&gt;TypeFire snippets can also be shell scripts: the script runs when you expand it, and its output is pasted. These two live on the Mac app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;14. A fresh UUID, &lt;code&gt;;uuid&lt;/code&gt;&lt;/strong&gt; (Shell Script snippet)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uuidgen | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;'[:upper:]'&lt;/span&gt; &lt;span class="s1"&gt;'[:lower:]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;15. Your local IP, &lt;code&gt;;ip&lt;/code&gt;&lt;/strong&gt; (Shell Script snippet)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ipconfig getifaddr en0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Where they work
&lt;/h2&gt;

&lt;p&gt;On the Mac, snippets expand in every app: your editor, the terminal, Slack, the browser. In Chrome, Edge and Brave, the &lt;a href="https://typefire.app/text-expander-chrome-extension" rel="noopener noreferrer"&gt;TypeFire extension&lt;/a&gt; expands them on every site, so &lt;code&gt;;pr&lt;/code&gt; works right inside GitHub's PR form.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwethrte9pxpzdq3ugtgb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwethrte9pxpzdq3ugtgb.jpg" alt="A snippet being given its own keyboard shortcut in the TypeFire Mac app" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;On the Mac, a snippet can also get its own keyboard shortcut, for the ones you never want to type at all.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you're choosing a browser text expander, we compared the options in our guide to the &lt;a href="https://typefire.app/blog/best-chrome-text-expander-2026" rel="noopener noreferrer"&gt;best Chrome text expander&lt;/a&gt;. And there's a page on &lt;a href="https://typefire.app/code-snippet-expander" rel="noopener noreferrer"&gt;TypeFire for developers&lt;/a&gt; with more code-shaped examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  The short version
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prefix abbreviations with &lt;code&gt;;&lt;/code&gt; or &lt;code&gt;z&lt;/code&gt; so they never fire by accident.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;{{fill:...}}&lt;/code&gt; for the parts that change and &lt;code&gt;{{date}}&lt;/code&gt; for anything dated.&lt;/li&gt;
&lt;li&gt;Start with the five you type most: commit, PR, bug report, standup, log line.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What's the one thing you type every single day that should be a snippet?&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>git</category>
      <category>webdev</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Markdown Live Preview: 4 Ways to See What Your README Really Looks Like Before You Push</title>
      <dc:creator>TypeFire</dc:creator>
      <pubDate>Fri, 30 Oct 2026 01:00:51 +0000</pubDate>
      <link>https://dev.to/typefire/markdown-live-preview-4-ways-to-see-what-your-readme-really-looks-like-before-you-push-ngj</link>
      <guid>https://dev.to/typefire/markdown-live-preview-4-ways-to-see-what-your-readme-really-looks-like-before-you-push-ngj</guid>
      <description>&lt;p&gt;You write a README, push it, open the repo page, and the table is a mess of pipes. The list you indented "correctly" is now a code block. The checkbox is a literal &lt;code&gt;[ ]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Markdown is forgiving to write and unforgiving to render. A live preview catches all of that before anyone else sees it. Here are four ways to get one, depending on where you're writing, plus the mistakes worth looking for.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. VS Code: the preview you already have
&lt;/h2&gt;

&lt;p&gt;VS Code ships a Markdown preview, no extension needed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Cmd+Shift+V&lt;/code&gt; (Mac) or &lt;code&gt;Ctrl+Shift+V&lt;/code&gt; (Windows, Linux) opens the preview in a tab.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd+K V&lt;/code&gt; or &lt;code&gt;Ctrl+K V&lt;/code&gt; opens it side by side, and it scrolls along with the editor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Good for: files that already live in a repo you have open.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. GitHub's own Preview tab
&lt;/h2&gt;

&lt;p&gt;Editing a &lt;code&gt;.md&lt;/code&gt; file in the GitHub web editor? The &lt;strong&gt;Preview&lt;/strong&gt; tab next to &lt;strong&gt;Edit&lt;/strong&gt; renders it with GitHub's own flavor of Markdown, the same one your repo page uses.&lt;/p&gt;

&lt;p&gt;Good for: quick fixes to a file that's already on GitHub.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. &lt;code&gt;grip&lt;/code&gt;: GitHub rendering on localhost
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;grip
grip README.md
&lt;span class="c"&gt;# then open http://localhost:6419&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;grip&lt;/code&gt; renders the file through GitHub's Markdown API, so what you see matches the repo page closely. It refreshes when you save.&lt;/p&gt;

&lt;p&gt;Good for: checking a README exactly the way GitHub will show it, from the terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. A browser editor where the preview is the document
&lt;/h2&gt;

&lt;p&gt;Sometimes there's no repo yet. Someone pasted Markdown into Slack, an AI tool answered with a page of &lt;code&gt;##&lt;/code&gt; and &lt;code&gt;**&lt;/code&gt;, or you're on a machine where you can't install anything.&lt;/p&gt;

&lt;p&gt;For that, we built a free &lt;a href="https://typefire.app/markdown-live-preview" rel="noopener noreferrer"&gt;Markdown live preview&lt;/a&gt; at TypeFire. You paste Markdown in and it renders the moment it lands, right where you pasted it. There's no second pane to keep in sync, because the rendered text is the thing you edit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2e8dlk5jvcbsnoog9r57.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2e8dlk5jvcbsnoog9r57.png" alt="A README pasted into the TypeFire Markdown live preview, rendered in place" width="800" height="382"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A README pasted in: the heading, inline code and the table render where you pasted them.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A few details that matter for developer work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Paste a README or drop the &lt;code&gt;.md&lt;/code&gt; file&lt;/strong&gt; onto the page; tables, fenced code, task lists and links render as they land.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pasting from a web page or a doc converts to Markdown&lt;/strong&gt; with the headings, links and lists kept, which is handy when you're turning a Google Doc into a README.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copy it back out either way:&lt;/strong&gt; File &amp;gt; Copy &amp;gt; As Markdown for the source, or As rich text for an email or a chat.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nothing is uploaded.&lt;/strong&gt; Your text stays in the browser tab, and tabs are saved locally so a refresh doesn't lose them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx0mpk6wgvotrr6rewe3k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx0mpk6wgvotrr6rewe3k.png" alt="Rich text from a web page pasted in and converted to Markdown" width="800" height="250"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Pasted from a web page: the heading, bold, link and list arrive as Markdown.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fawnzqn6xxz94b4f8cs5z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fawnzqn6xxz94b4f8cs5z.png" alt="The File menu with Copy as Markdown and Copy as rich text" width="800" height="236"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;File &amp;gt; Copy gives you the source or the formatted version.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The same editor also ships in TypeFire for Chrome, with your notes in tabs, a text expander and clipboard history:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/9Nay6NC9z54" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Good for: Markdown that doesn't live in a repo yet, or anywhere you can't install tools. If you just need to read a &lt;code&gt;.md&lt;/code&gt; file on a Mac rather than edit it, the &lt;a href="https://typefire.app/blog/markdown-viewer-mac" rel="noopener noreferrer"&gt;Markdown viewer for Mac guide&lt;/a&gt; covers that.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to look for in the preview
&lt;/h2&gt;

&lt;p&gt;Whichever tool you use, these are the five mistakes a preview catches that your eyes skip in raw Markdown:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Tables without a separator row.&lt;/strong&gt; The second line has to be dashes and pipes, or there's no table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;| Flag | What it does |
| --- | --- |
| &lt;span class="sb"&gt;`-v`&lt;/span&gt; | Verbose output |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's the same table without that row, and then with it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgw2tvo46e1qumscymihb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgw2tvo46e1qumscymihb.png" alt="A Markdown table missing its separator row, shown as raw pipes" width="800" height="278"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;No separator row: just text with pipes in it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9b6j19ftng37qm81pxya.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9b6j19ftng37qm81pxya.png" alt="The same table with the separator row, rendered as a table" width="800" height="278"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Add | --- | --- | and it becomes a table.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. A numbered list that doesn't start at 1.&lt;/strong&gt; On GitHub a bullet list can follow a paragraph directly, but a numbered list starting at &lt;code&gt;3.&lt;/code&gt; with no blank line above it merges into the paragraph. Add the blank line, or start at &lt;code&gt;1.&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Nested lists indented by the wrong amount.&lt;/strong&gt; Line nested items up under the text of the parent item. Too little indent and the child item flattens into the parent list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Task lists that need the exact syntax.&lt;/strong&gt; It's &lt;code&gt;- [ ]&lt;/code&gt; and &lt;code&gt;- [x]&lt;/code&gt;, with a space inside the empty brackets and a space after them. &lt;code&gt;-[ ]&lt;/code&gt; stays as literal text.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Fenced code without a language.&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;```bash&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 gets syntax highlighting; a bare&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;```&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 doesn't. The preview shows you which blocks you forgot to tag.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which one should you use?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Writing inside a repo in VS Code: the built-in preview.&lt;/li&gt;
&lt;li&gt;Fixing a file on GitHub: the Preview tab.&lt;/li&gt;
&lt;li&gt;Want GitHub's exact rendering locally: &lt;code&gt;grip&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Markdown from anywhere else, or no install allowed: a &lt;a href="https://typefire.app/markdown-live-preview" rel="noopener noreferrer"&gt;browser live preview&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What's the Markdown rendering bug that bit you last?&lt;/p&gt;

</description>
      <category>markdown</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>github</category>
    </item>
  </channel>
</rss>
