# Markdown Formatting Rules for Free Programming Books Contributors

> Master markdown formatting rules for free programming books contributors. Ensure CI validation with strict guidelines on headings, blank lines, ordering, and link syntax.

- Repository: [Free Ebook Foundation/free-programming-books](https://github.com/EbookFoundation/free-programming-books)
- Tags: best-practices
- Published: 2026-02-23

---

**Contributors to the EbookFoundation/free-programming-books repository must follow strict markdown formatting rules—including specific heading levels, precise blank line placement, alphabetical ordering, and standardized link syntax—to ensure all submissions pass automated CI validation.**

Every contribution to this curated list of free learning resources is governed by conventions defined in [`docs/CONTRIBUTING.md`](https://github.com/EbookFoundation/free-programming-books/blob/main/docs/CONTRIBUTING.md) and enforced by GitHub Actions. These markdown formatting rules ensure the repository remains readable, machine-parsable, and maintainable at scale. Understanding these requirements before submitting a pull request prevents CI failures and accelerates the review process.

## Core Markdown Structure and Headings

The repository mandates specific structural elements to maintain consistency across all language-specific files.

### Heading Levels

Section headings must use **level 3** (`###`) and subsections must use **level 4** (`####`). The repository does not use H1 or H2 headings within individual book list files, as these are reserved for the main index structure.

### Blank Line Requirements

Precise whitespace control is critical for the **fpb-lint** parser. You must follow these spacing rules exactly:

- Insert **two empty lines** after the last link in any section
- Insert **one empty line** between a heading and the first link
- Insert **no empty lines** between two consecutive list items
- Insert **one empty line** at the end of the file

## List Syntax and Entry Formatting

All book entries follow a strict single-line format using asterisks as list markers.

### Basic Entry Structure

Every entry must use this exact syntax:

```markdown
* [Title](URL) - Author (Format)

```

Critical syntax requirements include:

- Use a plain asterisk followed by a space: `* `
- **No space between `]` and `(`** in the link syntax
- Insert a space-dash-space (` - `) after the link, before the author name
- Add a single space before the format in parentheses: ` (PDF)`, ` (HTML)`, etc.
- Place the publication year inside the title: `[Title (2020)](URL)`

### Advanced Formatting with Licenses and Notes

When including licensing information or status notes, append them after the format:

```markdown
* [Learn Rust (2021)](https://example.com/learn-rust) - Jane Doe (HTML) (CC BY-SA) *( :card_file_box: archived)*

```

- **Author-format order**: Author name always precedes the format
- **Licensing**: Place license codes (e.g., `(CC BY-SA)`) after the format list
- **Notes**: Wrap status indicators like `*( :construction: in process)*` at the end

## URL and Link Standards

The repository enforces strict URL hygiene to ensure long-term resource availability.

### URL Formatting Rules

- **Remove trailing slashes** from root-domain URLs: use `http://example.com` not `http://example.com/`
- **Prefer HTTPS** whenever the site supports it; fall back to HTTP only when necessary
- **Use the shortest viable URL** that points directly to the resource
- **No URL shorteners**: Services like `bit.ly` or `youtu.be` are prohibited

### Alphabetical Ordering

All entries must be sorted **alphabetically** (case-insensitive) within each section. The **fpb-lint** tool in [`.github/workflows/fpb-lint.yml`](https://github.com/EbookFoundation/free-programming-books/blob/main/.github/workflows/fpb-lint.yml) automatically verifies this ordering during CI checks.

## Automated Enforcement and CI Validation

The repository uses two primary GitHub Actions workflows to enforce these markdown formatting rules automatically.

### FPB-Lint Validation

The workflow defined in [`.github/workflows/fpb-lint.yml`](https://github.com/EbookFoundation/free-programming-books/blob/main/.github/workflows/fpb-lint.yml) performs structural validation:

- Verifies alphabetical ordering of entries
- Checks blank line placement (two after sections, none between items)
- Validates overall Markdown structure and heading levels

### URL Validation

The **awesome_bot** validator (referenced in the URL checking workflows) ensures:

- Every URL is reachable and returns a valid status code
- No shortened URLs are present in the submission
- Links are properly formatted without syntax errors

If a contribution fails any automated check, the pull request receives a failing status, and contributors must adjust their markdown formatting before maintainers can merge.

## Common Formatting Mistakes to Avoid

Review these frequent errors before submitting:

| Issue | Incorrect | Correct |
|-------|-----------|---------|
| Missing space before format | `* [Book](URL) - Author(PDF)` | `* [Book](URL) - Author (PDF)` |
| Missing author delimiter | `* [Book](URL) Author (PDF)` | `* [Book](URL) - Author (PDF)` |
| Extra blank between items | `* [A](URL)`<br><br>`* [B](URL)` | `* [A](URL)`<br>`* [B](URL)` |
| Trailing slash on domain | `* [Site](http://example.com/)` | `* [Site](http://example.com)` |
| Space in link syntax | `* [Title] (URL)` | `* [Title](URL)` |

## Summary

- All contributions must follow the **asterisk-based list format** with strict spacing rules defined in [`docs/CONTRIBUTING.md`](https://github.com/EbookFoundation/free-programming-books/blob/main/docs/CONTRIBUTING.md)
- Entries require the pattern: `* [Title (Year)](URL) - Author (Format)` with no spaces between brackets and parentheses
- **Two blank lines** must follow the last link in each section, with **no blank lines** between consecutive items
- The **fpb-lint** GitHub Action enforces alphabetical ordering and structural validation automatically
- URLs must use HTTPS where possible, avoid trailing slashes on root domains, and never use URL shorteners

## Frequently Asked Questions

### What happens if I don't follow the markdown formatting rules?

Your pull request will fail the automated CI checks triggered by **fpb-lint** and **awesome_bot**, resulting in a red X status on your submission. Maintainers cannot merge contributions until all formatting validations pass, requiring you to amend your commit with corrected syntax.

### How do I format a book entry with multiple authors?

Insert all author names after the spaced dash, maintaining the space-before-parentheses rule for formats. For example: `* [Book Title](URL) - Jane Doe, John Smith (PDF) (CC BY)`. The repository does not mandate specific author delimiters beyond the initial ` - ` separator.

### Can I use HTML in my contributions?

No, the repository requires **pure Markdown** format. All contribution files are plain `.md` files that must pass the **fpb-lint** parser, which expects specific Markdown list structures and will reject HTML tags that disrupt the automated formatting validation.

### Where are the formatting rules officially documented?

The authoritative source is [`docs/CONTRIBUTING.md`](https://github.com/EbookFoundation/free-programming-books/blob/main/docs/CONTRIBUTING.md) in the repository root, which contains the complete formatting specification. Additionally, examining [`books/free-programming-books-en.md`](https://github.com/EbookFoundation/free-programming-books/blob/main/books/free-programming-books-en.md) provides a production reference for properly structured sections and entry formatting.