Help us measure site usage?

With your permission, we use self-hosted analytics to understand page usage. It is optional and does not affect the Service. Learn more.

GobeginnercliAI generated

Markdown Link Scanner

Build a Go command-line tool that checks the links in Markdown files, like a project's README and documentation, and reports the broken ones: links to local files that don't exist, links to headings that don't exist, and web links that return errors. It checks web links several at a time with a timeout, remembers links it already checked, and prints each broken link with the file and line number, so it's easy to fix. It can run in a CI pipeline, failing when something is broken. It's a good first Go project: you'll learn walking folders, reading files line by line, regular expressions, net/http, goroutines with a simple limit on concurrency, and table-driven tests.

Estimate
~8.5h
Steps
6
Completed by
0
Proposed by
codeseed.app

net/http · regexp · path/filepath

Project roadmap

  1. 01

    Define the tool

    ~1h

    Write README.md: the usage (linkcheck [paths] with folders searched for .md files), options (--no-external to skip web links, --timeout, --concurrency and --ignore patterns), what each kind of problem looks like in the output (file:line: link: reason), and the exit codes (0 when all links work, 1 when some are broken). Done when: README.md shows example output for each kind of broken link.

  2. 02

    Find the links

    ~1.5h

    Walk the given folders with filepath.WalkDir, collecting .md files. Read each file line by line with bufio.Scanner and extract links with a regular expression for [text](target) and <https://...> links, recording the file and line number. Skip links inside code blocks (lines between ``` fences). Done when: running on a test folder lists every link with its file and line.

  3. 03

    Check local links

    ~1.5h

    For relative links, resolve the path against the Markdown file's folder and check the file exists with os.Stat. For links with a #heading part, read the target file's headings and turn them into anchors the way GitHub does (lowercase, spaces to dashes, and most punctuation removed), then check the anchor exists. Done when: missing files and wrong heading anchors are reported with the right reasons.

  4. 04

    Check web links

    ~2h

    Check http and https links with an http.Client that has a timeout, trying HEAD first and falling back to GET when the server doesn't allow HEAD. Report 4xx and 5xx status codes and network errors. Check each unique URL only once, and run at most --concurrency checks at the same time using goroutines, a buffered channel as a semaphore and a sync.WaitGroup. Done when: broken web links are reported, and each unique URL is requested once.

  5. 05

    Report the results

    ~1h

    Print the problems sorted by file and line, then a summary: files checked, links checked, and broken links by kind. Apply --ignore patterns (for example URLs of sites that block automated checks). Exit with code 1 when any link is broken. Done when: the output is sorted and clear, and the exit code is correct.

  6. 06

    Test it

    ~1.5h

    Write table-driven tests: link extraction (including code blocks and several links on one line), heading anchor generation, local file and anchor checks using a temporary folder, and web checks against an httptest.Server returning 200, 404 and slow responses. Done when: go test ./... passes.

Ready to build this?

Get a GitHub repo and start building. Your AI reviewer checks each step as you go.

~8.5h · 6 steps

Tech stack

net/httpregexppath/filepath