Google Docs to Markdown converter: draft to pull request
A Google Docs to Markdown converter only gets you halfway. The real work is frontmatter, a slug, and a pull request your team can actually review.
A Google Docs to Markdown converter only gets you halfway. The real work is frontmatter, a slug, and a pull request your team can actually review.

An agency sends you a Google Doc. It has headings, a couple of images, maybe a comparison table, and a comment thread where three people argued about the second paragraph. Your blog runs on Markdown files in a Git repo. Somewhere between those two facts is an afternoon nobody budgeted for.
Running a Google Docs to Markdown converter is not the hard part anymore. Google Docs has shipped native Markdown export since mid-2024, and the Docs to Markdown add-on has converted documents for a wide developer audience for years. The friction is everything after the .md file lands on your disk: giving it frontmatter your build script actually reads, choosing a slug, re-pathing the images, and turning a one-off deliverable into something your team reviews the way it reviews code. That is what this post covers. If you are moving an entire blog's archive rather than a single draft, that is a different job with different failure modes, and our blog migration guide covers the redirect and ranking risks specific to a full platform move.
Google Workspace and Microsoft 365 together account for roughly 96% of the office productivity software market measured by domain, which is the mundane reason "the agency sent a Google Doc" is the default handoff for most teams, not an edge case you can design around. A Google Docs to Markdown converter is not what fixes that handoff, because the problem was never that Docs is the wrong tool for an agency to write in. It is a genuinely good collaborative editor: comments, suggestion mode, version history. The problem is that a doc built for that kind of review was never built to become a web page, and the two most common paths from one to the other both lose something.
The fastest route, and the one most teams try first, is pasting straight from Docs into a CMS editor. It usually looks fine for about ten seconds. Then the post renders with inconsistent line spacing, a font that does not match the rest of the site, or headings that are visually big but semantically just bold paragraph text. That happens because Google Docs' copy output carries inline <span> and <font> tags and other formatting baggage along with the words, and pasting that directly into a WordPress editor is a well-documented way to end up fighting your own theme's CSS post by post, according to WPBeginner's guide to importing Google Docs into WordPress. For a Markdown-based blog the failure mode is different but just as real: paste-from-Docs rarely produces valid Markdown syntax at all, so you are back to manually retyping headings and links into ## and [text](url) by hand.
The deeper issue is what the document was optimized for. An agency writer drafts in Docs because Docs is built for exactly the review cycle a deliverable needs: track changes, inline comments, an editor and a client trading suggestions in the same file. None of that structure was designed with a static site generator in mind. Headings might be bold, oversized text instead of an actual Heading style. Tables exist because a spreadsheet-style comparison was the easiest way to show it in a doc, not because the target CMS renders tables well. Images are embedded at whatever size looked right on screen, with no folder structure to drop them into. A doc that reviewed cleanly for three people over two weeks can still need real editing before it is a post, and that gap is the actual cost of an agency handoff, not the minutes spent running a converter.
Getting from Google Doc to usable Markdown has two real paths now, and picking the wrong one for what the doc contains is where most of the wasted time comes from.
Google added native Markdown import and export to Docs on a gradual rollout starting July 16, 2024 for Rapid Release domains and July 31, 2024 for Scheduled Release domains, according to Google's own announcement. File > Download now offers a Markdown (.md) format, and File > Open accepts a .md file directly into a new doc. Paste-from-Markdown and copy-as-Markdown ship as separate, related features, and both are off by default: you have to turn them on first, under Tools > Preferences > Enable Markdown, per the same announcement.
Here is the part that trips people up: "supports Markdown" does not mean "supports every Markdown feature." Google's own help documentation on Markdown in Docs, Sheets, Slides, and Drawings lists exactly five things the typed-autocorrect and paste behavior handles: bold, italic, strikethrough, links, and headings. Images, tables, blockquotes, and code blocks are not on that list, and in practice none of them make the round trip through native export intact. So the native export is genuinely good for a doc that is just prose with some bold text, links, and heading levels, and it is the wrong tool the moment a doc has a comparison table or an embedded screenshot, because those elements simply do not survive the round trip.
For anything past plain prose, the tool most teams reach for is the Docs to Markdown add-on (also known by its project name, gd2md-html), which has over 1 million installs on the Google Workspace Marketplace. Its own description is a fair summary of what it does well and where it stops: it "marks up the content (headings, paragraphs, lists, code blocks, etc.) but does not preserve colors and styles in text or tables." That trade is usually the right one. Colors and inline styling rarely belong in a blog post's Markdown anyway; your site's own CSS should own that, not a doc author's font-color picker.
Three specific gaps are worth checking for by hand every time, because they are the ones that slip through silently:
## levels. This is documented directly in the gd2md-html project wiki.Smart quotes and en dashes are the fourth thing worth a manual scan: Google Docs autocorrects straight quotes to curly ones and hyphens to en dashes as you type, and neither converter reliably undoes that on the way out. If your site's style guide bans em dashes and curly quotes (this one does), that is a find-and-replace pass, not something to assume the export handled.
Run the add-on against a typical agency doc, three sections, a pricing comparison table, two inline screenshots, and one subheading the client's editor bolded instead of styling as Heading 2, and you can predict the output before you open it: the pricing table survives as a plain Markdown table with its shading and borders gone, the two screenshots land in the export zip as image1.png and image2.png with no guarantee that order matches the doc, and the bolded subheading prints as a normal paragraph with no ### in front of it. None of that is the add-on malfunctioning. It is doing exactly what its own listing says it does; the manual pass is where you catch the gap between "converted" and "correct."
Once the Markdown is clean, you have a file, not a blog post. The next mile is the one a Doc-to-Markdown converter was never built to handle, and it is where a one-off agency deliverable either becomes a normal part of your workflow or stays a special case every single time.
Every static site generator that builds a blog from Markdown expects more than body text. It expects frontmatter: a title, a slug (usually just the filename), a publish date, an excerpt for the meta description, and a path to a hero image, at minimum. A converter has no idea what your schema looks like, so this part is always manual, and skipping it is what breaks the build. Copy the shape from a post already in your repo rather than inventing new fields; a plain .md file with a body and no frontmatter, or frontmatter with the wrong keys, will not render at all on most setups.
The slug deserves a deliberate choice, not a default. An agency's working filename is usually the doc's title verbatim, complete with spaces, capital letters, and sometimes a client's internal shorthand. Rewrite it: lowercase, hyphenated, keyword-first, with no dates baked in. That is also the moment to check the images have a real home in the repo (an images/ or public/ directory next to the post, not a floating temp folder) and that every path in the Markdown body points there instead of image1.png.
This is exactly the file shape a Git-based AI blog writer produces for posts it drafts itself: Markdown with your frontmatter, committed to a branch, matching what is already in the repo. An agency-sourced doc is a different starting point, someone else wrote the words, but it should land in the same place, formatted the same way, once it is converted.
A Google Doc's comment thread is a good review tool for prose. It is not a review tool for what actually ships. A comment thread does not run your link checker, does not confirm the doc's claims still hold up against a current source, and leaves no permanent record of who approved the final version once the doc itself gets archived or deleted three months later.
A pull request does all three, because it is the same review surface your team already uses for code, not a parallel process invented for content. Committing the converted file to a branch and opening a PR means your existing CI runs against it automatically, the same GitHub Actions checks that catch a broken link, a missing canonical tag, or invalid structured data on any other post. It also leaves the paper trail a comment thread never did: a commit history that names who converted the doc and who reviewed the result, which matters more, not less, for a post someone outside your team wrote first. That is the same audit trail argument we make in more detail in AI content governance, and it applies just as much to an agency's Doc as it does to an AI-drafted post.
Treat the pull request as the actual finish line, not the converted .md file. A file sitting in a branch with no review attached is not meaningfully different from a Doc sitting in a shared drive; it is still one person's word that it is ready. The PR is what turns "the agency's draft" into "the post your team decided to publish," and once that step exists for one converted doc, it is the obvious default for the next one too. Agencies that produce content at this kind of volume run into the same handoff problem from the other side, and our post on white-label AI content for agencies covers what that looks like when the agency is the one running the pipeline.
None of this requires giving up on Google Docs as where an agency writes its first draft. It requires not treating the export as the last step. A Doc is good at review before conversion; a pull request is good at review after it. Skipping the second one because the first one already happened is how a converted file quietly becomes the published post with nobody outside the agency having actually checked it.
If your team is tired of running this conversion by hand every time an agency sends a Doc, Lyra skips the Doc step for new posts entirely: she drafts directly in your repo's Markdown and frontmatter, fact-checks every claim, and opens a pull request you review like any other change.
FAQ
Two options, depending on what the doc contains. If it's plain text with headings, bold, italics, and links, turn on Tools > Preferences > Enable Markdown, then use File > Download > Markdown. If it has tables, code blocks, or images, use the Docs to Markdown add-on instead. Either way, check headings converted correctly (the source has to use real Heading styles, not bold text) and re-path any images by hand.
Yes, since July 2024. File > Download offers a Markdown (.md) option, and File > Open accepts a .md file directly. The native export handles bold, italic, strikethrough, links, and headings. It does not touch images, tables, blockquotes, or code blocks, so a doc with any of those needs a dedicated converter or a manual pass after export.
Because a converter turns markup into Markdown, not a Markdown file into a publishable post. It still needs frontmatter your build reads (title, slug, date, image), real paths for every image instead of a temp zip folder, and a check for the smart quotes and en dashes Docs inserts by default. None of that is a conversion bug: it's the gap between a formatted document and a file your static site generator can build.
A converter is a one-way trip: Doc in, Markdown out, and every future revision from the agency means running the whole pass again by hand. An AI writer built for a Git-based blog, like Lyra, skips the Doc step for new posts entirely: it drafts directly in your repo's Markdown and frontmatter and opens a pull request. For agency drafts that already exist as Docs, the two aren't in conflict, the converter still gets the file into your repo; the writer's fact-check and PR workflow is what you'd want gating every post after that, agency-written or not.
Built by the tool you're reading about
Lyra finds the topics worth ranking for, writes them in your repo's voice, fact-checks every claim, and opens a pull request scored and ready to merge. You review and hit merge. Want to see what she'd write for you? Start free with three posts, no card.
Keep reading

A blog migration playbook for 12 platforms. The export is never the hard part. Your redirect tool dies with the platform, and that is what costs you rankings.

Generate SEO pages from data in Next.js (generateStaticParams) or Astro (Content Layer), gated by code so the set doesn't trip Google's spam filter.

GitHub Actions SEO checks for blog PRs: four automated jobs that catch broken links, bad canonicals, invalid JSON-LD, and image-driven Core Web Vitals failures.