The ultimate Leanpub writing guide: Stop writing like it's 2000

The ultimate Leanpub writing guide: Stop writing like it's 2000

You've got ideas. After cranking out a big post, you thought: "Doesn't this deserve a book and not another forgotten blog post?"

I had the same, especially with my first book. It took me roughly 1,5 years to get from the idea to actually just "acting" and starting to write.

But here's the thing. Most people who start writing a book give up. Not because they run out of ideas (otherwise you wouldn't still be blogging). Not because they can't write. They give up because the big bear comes watching around the corner while you've to fight it blindfolded.

I get it. But did you ever wonder if you're using the right tools? Not mental tools. Real tools that let your writing flow. Tools that help you catch typos before you publish. Tools that support your writing in a good manner. And when you are an illustrative person, sync your diagrams into pictures easily.

Throw away the motivation. You just need a better system with tools integrated before you publish.

This how-to guide shows you how to set up a writing environment that actually works. The environment that catches your mistakes. Supports you in creating professional diagrams and lets you focus on what actually matters: writing something worth reading.

Let's build your ultimate Leanpub setup.

Prerequisites

Before you dive in, you're going to need a hard, non-negotiable prerequisites. This is the foundation everything builds upon:

You'll also need NPM installed. This comes with Node.JS. If you're working on a Windows machine, you can install it using WinGet:

winget install OpenJS.NodeJS.LTS --source winget

For alternative options based on your operating system, check out the official website.

Read it and set it up. The hardest part here is that you'll need to buy a standard subscription to enable GitHub integration.

If you're done, come back here. I'll wait.

Why this setup will change your writing

Most writers use good old Microsoft Word or Google Docs. That's fine if you take it to the supermarket as a grocery list. But for a book? You need:

  • Version control - so you can experiment and see your changes automatically.
  • Automated quality checks - because it's embarrassing to see typos in your official book release.
  • Professional diagrams - Throw away Microsoft Paint, create it by code, and let it generate automatically.
  • Consistency - in tone, styling, and formatting.

This setup gives you all of that with free tools, the same ones other professionals use.

The three pillars of a great writing environment

Writing a book is hard enough. That's why introducing tools shouldn't make you fight harder.

The three tools you can introduce to set up your writing environment is going to form the foundation. A foundation for a professional writing environment. Each tool solves a specific problem that trips up most authors. Together, they create a system where quality is automatic, not accidental.

These tools are:

  • Vale
  • D2
  • Code Spell Checker

Think of them like this: Vale is your editor, D2 is your designer, and Code Spell Checker is your proofreader. These tools work 24/7 and never get tired, and never charge you by the hour.

The best part? Once you've set them up correctly, they fade into the background. You only focus on the writing, while they watch your back.

Let's start with the big one.

Vale: Your writing angel

Remember your teacher who always caught your mistakes before you even knew it? Vale is like that, but doesn't give you a punishment.

Vale is a command-line utility linter for prose. A quick translation: it reads your writing and tells you when you're being unclear, wordy, or just dead wrong.

What Vale does for you:

  • Catches inconsistent terminology use.
  • Enforces your style guide.
  • Finds passive voice that makes your writing weak.
  • Spots complex words when simple ones would work better.

To set up Vale, run the following steps:

  1. Open your terminal and run:
# Install Chocolatey
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))

# Install Vale
choco install Vale

# Or download directly from GitHub releases
# https://github.com/errata-ai/vale/releases
  1. In your Leanpub repository root, create a file named .vale.ini:
StylesPath = styles

MinAlertLevel = suggestion

[*]
Vale.Spelling = NO

[*.txt]
BasedOnStyles = Vale, write-good
  1. Prepare style packages:
# Navigate to your book directory
cd c:\source\my-leanpub-demo-book

# Create styles directory
mkdir styles

cd styles
mkdir writing-good
  1. Add custom style rules, for example, create a rule that catches you saying So:
# Create a file named So.yml
New-Item -Path So.yml -ItemType File

# Add rule content
@'
extends: existence
message: "Don't start a sentence with '%s'."
level: error
raw:
  - '(?:[;-]\s)so[\s,]|\bSo[\s,]'
'@ | Set-Content -Path So.yml -Encoding UTF8

Now, Vale will flag you when you start a sentence with "So". You can create similar rules for:

  • Weasel words.
  • Passive voice detection.
  • Forbidden terminology.
  • Oversued words specific to your domain.

To see a full list of pre-built rules, browse the Vale package hub.

  1. Run vale against your manuscript files:
vale chapter1-the-basics.txt
Figure 1: Running Vale against manuscript

As you can see in the image above, you can instantly identify what needs fixing. No more wondering if your writing is any good.

Create D2 diagrams that don't look like garbage

With AI tools flying around, creating diagrams becomes easy. The thing with AI tools is, they don't always get it right on the fly. You can constantly prompt ChatGPT, or any other tool, to spit out a diagram, or...

... you can store it as code and modify it later to suit your needs.

That's where D2 comes around the corner. With D2, you can define a diagram based on scripting that, in turn, outputs images in the format you like. D2 does:

  • Flowcharts, sequence diagrams, entity relationships, and more.
  • Maintaining consistent styling across all diagrams.
  • Lives in your repository as text (meaning it can be version-controlled).
  • Renders to SVG or PNG for Leanpub.
  • Updates instantly when you change the code.

To set up D2, follow the steps below:

  1. Install D2:
# Using chocolatey
choco install d2

# Or download from the official site
# https://d2lang.com/tour/install
  1. Create your first diagram:
# Create a folder to hold your diagrams
mkdir diagrams

# Create a D2 file
cd diagrams
New-Item -Path writing-workflow.d2 -ItemType File

@'
title: LeanPub Writing Workflow {
  shape: text
  near: top-center
}

writer: Writer {
  shape: person
}

github: GitHub Repository {
  shape: cylinder
}

leanpub: LeanPub {
  shape: cloud
}

readers: Readers {
  shape: person
}

writer -> github: Push changes
github -> leanpub: Webhook triggers
leanpub -> leanpub: Generate book
leanpub -> readers: Deliver updates
'@ | Set-Content -Path writing-workflow.d2 -Encoding UTF8
  1. Generate the diagram:
# Generate SVG
d2 writing-workflow.d2 ..\resources\writing-workflow.svg

# Generate PNG
d2 writing-workflow.d2 ..\resources\writing-workflow.png

The images should be placed in the resources directory to be synced for Leanpub. In your manuscript file, you can now add:

<!-- For SVG -->
![Writing Workflow](writing-workflow.svg)

<!-- For PNG -->
![Writing Workflow](writing-workflow.png)
ℹ️
You don't need to specify resources/writing-workflow.svg or resources/writing-workflow.png.

Code Spell Checker: Because typos kill "the game"

You know what ruins a great book? Seeing "recieve" instead of "receive" on page 47.

It happened to me many times.

Your brain autocorrects typos when you read your own work. But can you be consistent? Every typo is a crack in your credibility to deliver a "good quality" book.

Code Spell Checker can be run both from the CLI and is a VS Code extension. It catches spelling errors in real time, or, if you run it through the CLI, it gives you an overview. It understands your text, code, and technical terms if you create a dictionary.

To install Code Spell Checker, follow the steps below:

  1. Install Code Spell Checker both as CLI and in Visual Studio Code (VS Code):
# Install CLI using NPM
npm install -g git+https://github.com/streetsidesoftware/cspell-cli

# Install it in VS Code
code --install-extension streetsidesoftware.code-spell-checker
  1. To configure Code Spell Checker, add the following two files at the root of the directory:
# cspell.config.yaml
dictionaryDefinitions:
  - name: words
    path: cSpell_dict.txt
    addWords: true
dictionaries:
  - words

The word dictionary for false positives or technical terms:

# cSpell_dict.txt
# Add words here
  1. Run the cspell-cli:
cspell-cli *.txt
Figure 2: Run Code Spell Checker CLI

If you think these are all valid (false-positives), you can easily output the words only and copy the unique words in the cSpell_dict.txt by running the following:

$words = cspell-cli *.txt --words-only
$words | Sort-Object -Unique | clip

Now you've the unique words "clipped" on your clipboard. Paste these words in the cSpell_dict.txt file and run the CLI again. Notice that no words are marked now.

Bonus tip: Formatting code fenced blocks

One of the painful lessons most Leanpub authors learn is the fact that long code blocks get cut off when the PDF is produced.

Imagine you are writing a code block example that is 120 characters wide. It looks fantastic in your editor, but when you generate the PDF, you think, "What has happened?"

The line wraps awkwardly, making it difficult for your readers to copy and paste the code. Your credibility takes a hit.

Markdownlint can catch these issues before hand. It enforces consistent formatting and warns you when code blocks are too wide for print.

Just as the code spell checker, you can install Markdownlint in VS Code or as a CLI option. The steps below describe how you can install markdownlint-cli2 in VS Code and CLI:

  1. Install Markdownlint both as CLI and in Visual Studio Code (VS Code):
# Install as a global CLI tool using npm
npm install markdownlint-cli2 --global

# Install in VS Code
code --install-extension DavidAnson.vscode-markdownlint
  1. To configure Markdownlint only for code-fenced blocks longer than, create a .markdownlint.yaml configuration file:
# .markdownlint.yaml
default: false
MD013:
  code_block_line_length: 80
  code_blocks: true
  tables: false
  line_length: 800

When you run markdownlint-cli2 from the command line, notice it picks up the code-fenced block.

Figure 3: Linting issue on code-fenced line-length

Putting it all together: Your daily workflow

You now have four different tools. Running them every time separately before a commit? Annoying.

Let's create an automation script that does the heavy lifting. Create a single PowerShell script named linter.ps1 in the root of the project running all quality checks in one go. In that way, you know before you commit that something might be broken.

# linter.ps1
param(
    [string]$Path = "manuscript",
    [switch]$SkipDiagrams,
    [switch]$Verbose
)

Write-Host "Running LeanPub Quality Checks..." -ForegroundColor Cyan
Write-Host ""
Write-Host "Running Vale (prose linting)..." -ForegroundColor Yellow
if (Get-Command vale -ErrorAction Ignore)
{
    $chapters = Get-ChildItem -Path *.txt | 
    Where-Object -Property Name -NotIn @('Book.txt', 'cSpell_dict.txt') |
    Select-Object -ExpandProperty FullName
    vale $chapters
}

Write-Host "Running Markdownlint (formatting)..." -ForegroundColor Yellow
if (Get-Command markdownlint-cli2 -ErrorAction Ignore)
{
    markdownlint-cli2 "*.txt" --config .markdownlint.yaml
}

Write-Host "Running Code Spell Checker..." -ForegroundColor Yellow
if (Get-Command cspell -ErrorAction Ignore)
{
    $words = cspell-cli *.txt --words-only -c cspell.config.yaml
    $words | Sort-Object -Unique

    Write-Host "Words found in manuscript:" -ForegroundColor Cyan
    $words | ForEach-Object { Write-Host " - $_" -ForegroundColor Gray }
    Write-Host ""
}

Write-Host "Validating D2 diagrams..." -ForegroundColor Yellow
if (Get-Command d2 -ErrorAction Ignore)
{
    $d2Files = Get-ChildItem -Path "diagrams\*.d2"
    $resourcesFolder = Join-Path -Path $PSScriptRoot -ChildPath 'resources'
    foreach ($file in $d2Files)
    {
        $fileName = $file.Name.Replace('.d2', '.png')
        $outputPath = Join-Path -Path $resourcesFolder -ChildPath $fileName
        Write-Host "  Generating diagram for $($file.Name) in $resourcesFolder..." -ForegroundColor Gray
        d2 $file.FullName $outputPath
    }
}

If you open a PowerShell terminal prompt, you can run the script: .\linter.ps1.

Figure 4: Execute quality checks script

Here is the setup of how your writing looks with this setup:

  1. In the morning, you open VS Code and start writing. The Code Spell checker highlights typos for you.
  2. Before you commit, you execute linter.ps1.
  3. You fix up potential issues + all diagrams are updated with .png files.
  4. After fixing, you push it to GitHub, and you start generating the book's content.
  5. Once you know your book's quality has been checked, you can go back to bed.

Conclusion

Tools won't, of course, write your book for you. But the right tools remove that initial friction so you can get started. They catch your mistakes and make the process feel less like a chore.

You've got your ideas now and the setup. Now you just need to write. Open your editor, start writing a new chapter, and put the words on the page.

Your readers are waiting.