If you’ve read our guide to adding comments in Markdown, you already know the syntax: wrap text in <!-- --> and it won’t show up in the rendered output. That part is simple and it’s the same everywhere.

What isn’t the same everywhere is what “won’t show up” actually means. On some platforms, an HTML comment is truly deleted before the page is ever generated — it never exists in the shipped output at all. On others, it’s just told not to display, while the literal text sits right there in the page’s HTML source, visible to anyone who right-clicks and chooses “View Page Source.” And on a few platforms, the comment doesn’t get hidden at all — it gets stripped so aggressively that the whole thing, syntax and content, just vanishes on import.

Those are three genuinely different outcomes, and mixing them up is how internal notes end up leaking, or how a “hidden” TODO turns into a paragraph of literal <!-- characters on a live page. This guide walks through what actually happens, platform by platform.

The distinction that matters: removed vs. hidden

Before the platform tour, it’s worth naming the core difference explicitly, because it’s the thing most comment tutorials skip.

Removed at build time means the comment’s content never makes it into the file that gets served to a browser. If you view the page source, it’s simply not there. This is what you want for anything you’d be embarrassed to have a curious visitor stumble across — draft pricing, internal reviewer names, “don’t publish this until legal signs off,” that kind of thing.

Hidden at render time means the comment’s content is in the HTML that gets served — it’s just wrapped in <!-- -->, which browsers know not to display. A regular visitor won’t see it in the rendered page. Anyone who opens dev tools or view-source will see it immediately, in plain text.

Standard HTML comments (<!-- like this -->) are almost always the second kind, not the first. That’s true no matter what Markdown processor you’re using, because Markdown itself doesn’t do anything special with HTML comments — it passes them through untouched, and it’s the browser, not Markdown, that decides not to render them visually. The confusion comes from platforms that layer a build system on top of Markdown, because some of those build systems have their own, separate comment syntax that behaves differently. More on that below.

Platform-by-platform behavior

GitHub — repo files vs. Issues/PRs

In a rendered file (a README, a wiki page, anything under a repo’s Markdown rendering), HTML comments are hidden-not-removed: view the raw file (?raw=true or the “Raw” button) and the comment text is right there. This is expected and fine for a public repo, since anyone can already read your whole file’s raw source anyway — there’s no secret being kept from anyone.

Issues and pull requests behave the same way but get used differently in practice: GitHub’s own issue and PR templates use HTML comments as instructional placeholder text (<!-- Please describe the change and link any related issues -->). Once submitted, that instructional text is hidden in the rendered comment, exactly as designed — but it’s still sitting in the issue body’s raw Markdown, retrievable via the API or an “Edit” click. Don’t put anything in a PR template comment you wouldn’t want a bot or a scraper reading back to you later.

GitLab

Functionally identical to GitHub for both files and merge request descriptions — HTML comments hide in rendered view, remain fully present in the raw Markdown. GitLab also uses the same instructional-placeholder-comment pattern in its default MR templates.

npm and PyPI package pages

Both npmjs.com and pypi.org render your README.md for the package listing page using largely the same rendering assumptions as GitHub. HTML comments are hidden from the rendered listing but present in the page’s HTML source — worth remembering if your README’s HTML comments contain anything like internal build notes or unpublished feature flags.

Jekyll (this site’s own engine) — and why it’s a special case

This is where the removed-vs-hidden distinction stops being theoretical, because Jekyll gives you both options, and they’re not interchangeable.

A plain HTML comment in a Jekyll post behaves like everywhere else — hidden from the rendered page, present in the shipped HTML:

<!-- This survives the build and sits in the final HTML, just invisible -->

But Jekyll’s Liquid templating layer also has its own comment tag, and it works completely differently:

{% comment %}
This text is deleted during the build. It never appears
anywhere in the generated _site output, not even in the source.
{% endcomment %}

{% comment %}...{% endcomment %} content is stripped by Jekyll itself, before the HTML is ever written to disk. That’s the actual “removed at build time” behavior — genuinely useful for author-only notes you don’t want in your Git-hosted output at all, as opposed to notes you’re fine with a curious reader finding in view-source.

The catch: {% comment %} only works in files Jekyll actually processes through Liquid (posts and pages with front matter). It does nothing useful inside a fenced code block meant to display Liquid syntax as an example — in fact, unescaped {% %} or {{ }} inside a code sample is exactly the class of bug we’ve written about in our own troubleshooting guide, where Jekyll tries to execute what you meant as illustrative text.

Hugo

Hugo has the same two-tier structure as Jekyll, just with different names. Plain HTML comments behave like everywhere else: hidden, not removed. Hugo templates additionally support Go template comments ({{/* like this */}}) for .html layout files, which are stripped at build time — but that syntax is a layout-file feature, not something you write inside your Markdown content itself. If you’re commenting inside a Markdown post body on a Hugo site, you’re almost always using the plain HTML form, which means: hidden, not removed.

MkDocs, Docusaurus, and other static-site generators

These follow the same general rule as Jekyll and Hugo’s content layer: they pass HTML comments through to the rendered HTML untouched. The comment is hidden visually but present in source. Docusaurus (React/MDX-based) is worth a specific flag: because MDX treats { as the start of a JavaScript expression, curly-brace syntax in prose can trigger build errors in ways plain Jekyll/Hugo content doesn’t — a separate gotcha from the comment-visibility question, but one that trips up the same audience.

Confluence

Confluence doesn’t render Markdown to HTML the way the platforms above do — it converts to its own storage format, and as our Confluence guide documents, raw HTML gets stripped or escaped on import rather than preserved. In practice, that means an HTML comment pasted into Confluence’s /markdown panel usually doesn’t survive as a hidden comment at all — it’s either dropped entirely or shows up as literal, visible <!-- text, depending on the import path. If you need a genuinely hidden internal note in Confluence, use a real Confluence feature built for it (an inline comment, or the {noformat}/expand macros) rather than relying on Markdown syntax that the platform was never built to honor.

Notion

Notion strips raw HTML entirely on import, and that includes comment syntax — it’s not a “hidden but present” situation, it’s a “gone” situation, per our Notion compatibility guide. If you need a genuinely invisible internal note inside a Notion page, Notion’s own commenting feature (select text, add a comment) is the tool for that job, not an HTML comment carried over from a Markdown file.

Obsidian

Obsidian is the one platform on this list where “hidden vs. removed” barely applies, because there’s no build/publish step by default — you’re just looking at your own local file. In Reading view, an HTML comment is hidden the same way it would be in a browser. In Source/Live Preview mode, you see it as plain text, since you’re literally looking at the file. Nothing is ever removed; it’s your file, sitting on your disk, exactly as you typed it, until you delete it yourself.

VS Code Markdown Preview

The simplest case on this list: the built-in preview pane hides HTML comments, the editor pane shows them, because you’re editing a plain local file and the preview is just a live render of it — no build step, no publish step, nothing gets removed.

Quick reference

Platform / context HTML comment behavior
GitHub (files, Issues, PRs) Hidden in render, present in raw source
GitLab (files, MRs) Hidden in render, present in raw source
npm / PyPI README Hidden in render, present in page source
Jekyll — <!-- --> Hidden in render, present in shipped HTML
Jekyll — {% comment %} Removed entirely at build time
Hugo — <!-- --> in content Hidden in render, present in shipped HTML
Hugo — {{/* */}} in layouts Removed entirely at build time
MkDocs / Docusaurus Hidden in render, present in shipped HTML
Confluence Usually dropped or shown literally — not reliably hidden
Notion Stripped entirely on import
Obsidian Nothing removed — visible in Source mode, hidden in Reading view
VS Code preview Hidden in preview pane, visible in editor pane

What this means in practice

Two practical takeaways follow directly from the table above.

Never treat an HTML comment as a privacy or security boundary. On the majority of platforms here, “hidden” means “not displayed,” not “not present.” Anything sensitive — API keys, internal pricing, a note about a security issue you haven’t disclosed yet — needs to actually not be in the file at all, or needs to live somewhere with real access control. If you’re publishing through Jekyll or Hugo specifically and want a note that genuinely never reaches the output, use the templating engine’s own comment tag ({% comment %} or {{/* */}}), not a plain HTML comment.

Don’t assume a comment will survive a platform migration. If you’re moving content from a Git-based Markdown workflow into Confluence or Notion, any HTML comments you were relying on for editorial notes, TODOs, or draft flags will very likely not make the trip — either they’ll vanish silently or, worse, show up as visible clutter. Strip them out (or convert them to that platform’s native commenting feature) before you migrate, rather than after someone notices.

You can test any of this yourself before committing to a workflow: paste Markdown containing comments into the Markdown Live Preview Editor and check both the rendered pane and the raw output. It won’t simulate a Confluence or Notion import, but it will immediately confirm the base case — hidden in render, present in source — that every platform above starts from before adding its own quirks on top.