diff --git a/.gitignore b/.gitignore
index ff2f188380adfc0dad66743f4c1156df05045c28..51dd93171d7b3f7320857cce32d82ba49f6c4c8c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 *.pdf
-img/*.svg
+img/graph/*.svg
+img/plot/*.svg
diff --git a/.spelling b/.spelling
index 514f348f0eb4b3429f6e116d3374591898062ea2..ed0aad018e399a42392a84a977af8b51eedb3d7e 100644
--- a/.spelling
+++ b/.spelling
@@ -1,2 +1,6 @@
+csvautobooktabular
+Graphviz
+img
 pandoc
+results.csv
 WatsonCrick1953
diff --git a/README.md b/README.md
index 8761becbfb086b0d4aa8405d849ebed32d149e95..bf6ad05b78cf5bd28563d94893aaec1f51d23d82 100644
--- a/README.md
+++ b/README.md
@@ -4,22 +4,37 @@ Change to Document Title Here
 Building
 --------
 
-Build the PDF:
+To build the PDF, just type `make`. Make already does incremental compilation,
+i.e. it re-compiles only those targets whose sources changed. If you want to
+watch for changes and automatically run `make` when something changes, use
+[watchexec][]:
 
 ```
-make title.pdf
+watchexec make
 ```
 
+The `watchexec` tool honors `.gitignore`.
+
 ### Requirements
 
-Required:
+These requirements are all more or less optional or replaceable. If you want to
+build the template PDF, you need these dependencies:
+
+- [git][]
+- [pandoc and pandoc-citeproc][pandoc]
+- LaTeX, either through **texlive** or **MiKTeX**
+- GNU **make**
+- [graphviz][]
+- R including the packages **data.table**, **tidyverse** and **svglite**
+- [watchexec][]
+- [markdown-spellcheck][]
 
-- [git](https://git-scm.com/downloads)
-- [pandoc, pandoc-citeproc](https://pandoc.org/installing.html)
-- LaTeX, either texlive or MiKTeX
-- make
+**Note:** On MS Windows, it might be helpful using [chocolatey][].
 
-Optional:
 
-- [graphviz](https://graphviz.gitlab.io/download/)
-- [watchexec](https://github.com/watchexec/watchexec/releases)
+[chocolatey]: https://chocolatey.org/
+[git]: https://git-scm.com/downloads
+[graphviz]: https://graphviz.gitlab.io/download/
+[markdown-spellcheck]: https://www.npmjs.com/package/markdown-spellcheck
+[pandoc]: https://pandoc.org/installing.html
+[watchexec]: https://github.com/watchexec/watchexec/releases
diff --git a/chapter-3-results.md b/chapter-3-results.md
index b1efb97246a31589d62464cb8a9d4fd54a9f7f11..734a639137eab23f9a08ef3610e50ed23e7839f8 100644
--- a/chapter-3-results.md
+++ b/chapter-3-results.md
@@ -14,6 +14,6 @@ You can automatically insert tables from your results if you store them in CSV.
 
 \begin{table}
   \centering
-  \csvautobooktabular{results.csv}
+  \csvautobooktabular{img/plot/results.csv}
   \caption{These are my super significant results.}
 \end{table}
diff --git a/chapter-4-discussion.md b/chapter-4-discussion.md
index 2e06c7168ff3a96c1958bb183961392da6744e1a..ae3a79e3e2aef245f2fd6e8877eb95d463dba086 100644
--- a/chapter-4-discussion.md
+++ b/chapter-4-discussion.md
@@ -1,5 +1,12 @@
 Discussion
 ==========
 
+You can add flow charts produced with Graphviz as in figure \ref{flowchart}.
+Note how you inline the \LaTeX\ references.
+
 ![This is the image caption. This image shows how git remotes
-work.](img/git-remote-commands.svg)
+work.\label{flowchart}](img/graph/git-remote-commands.svg)
+
+See these awesome, auto-generated plot in figure \ref{plot}.
+
+![The plot from the results data.\label{plot}](img/plot/results.svg)
diff --git a/img/Makefile b/img/Makefile
index dc8bfbf8ac65675393195d7f10ff34cd7bc5e185..27fce70863c740f5ca0603d1ab896311b6facece 100644
--- a/img/Makefile
+++ b/img/Makefile
@@ -1,20 +1,24 @@
-SOURCES_DOT = $(wildcard *.dot)
+default: all
 
-OBJECTS_DOT_SVG = $(SOURCES_DOT:.dot=.svg)
+all: subdirs
 
-OBJECTS = \
-	$(OBJECTS_DOT_SVG) \
+SUBDIRS = \
+	graph \
+	plot \
 
-all: $(OBJECTS)
+$(SUBDIRS):
+	$(MAKE) -C $@
 
-$(OBJECTS):
-
-%.svg: %.dot
-	dot -Tsvg -o $@ $<
+subdirs: $(SUBDIRS)
 
 clean:
-	rm -f $(OBJECTS)
+	@for dir in $(SUBDIRS); do \
+	  $(MAKE) -C $$dir $@; \
+	done
 
 .PHONY: \
 	all \
 	clean \
+	default \
+	subdirs \
+	$(SUBDIRS) \
diff --git a/img/graph/Makefile b/img/graph/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..dc8bfbf8ac65675393195d7f10ff34cd7bc5e185
--- /dev/null
+++ b/img/graph/Makefile
@@ -0,0 +1,20 @@
+SOURCES_DOT = $(wildcard *.dot)
+
+OBJECTS_DOT_SVG = $(SOURCES_DOT:.dot=.svg)
+
+OBJECTS = \
+	$(OBJECTS_DOT_SVG) \
+
+all: $(OBJECTS)
+
+$(OBJECTS):
+
+%.svg: %.dot
+	dot -Tsvg -o $@ $<
+
+clean:
+	rm -f $(OBJECTS)
+
+.PHONY: \
+	all \
+	clean \
diff --git a/img/git-remote-commands.dot b/img/graph/git-remote-commands.dot
similarity index 100%
rename from img/git-remote-commands.dot
rename to img/graph/git-remote-commands.dot
diff --git a/img/plot/Makefile b/img/plot/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..12005f2ab4effbd4d886a03ba846523104823ed9
--- /dev/null
+++ b/img/plot/Makefile
@@ -0,0 +1,20 @@
+SOURCES_CSV = $(wildcard *.csv)
+
+OBJECTS_CSV_SVG = $(SOURCES_CSV:.csv=.svg)
+
+OBJECTS = \
+	$(OBJECTS_CSV_SVG) \
+
+all: $(OBJECTS)
+
+$(OBJECTS):
+
+%.svg: %.csv
+	Rscript --vanilla $*.R
+
+clean:
+	rm -f $(OBJECTS)
+
+.PHONY: \
+	all \
+	clean \
diff --git a/img/plot/results.R b/img/plot/results.R
new file mode 100644
index 0000000000000000000000000000000000000000..14acca495cc4cad117c0bc7aa0f346741c8b3f4e
--- /dev/null
+++ b/img/plot/results.R
@@ -0,0 +1,9 @@
+library(data.table)
+library(ggplot2)
+
+data <- fread("results.csv")
+
+plot <- ggplot(data, aes(x, y)) +
+    geom_point(aes(col = cat))
+
+ggsave("results.svg", plot)
diff --git a/img/plot/results.csv b/img/plot/results.csv
new file mode 100644
index 0000000000000000000000000000000000000000..6a9061cebc6bd55182f4ab39873ffef8acd59b75
--- /dev/null
+++ b/img/plot/results.csv
@@ -0,0 +1,6 @@
+cat,x,y,foo
+a,1,2,8
+b,6,3,7
+c,7,4,5
+d,2,5,1
+e,1,8,7
diff --git a/results.csv b/results.csv
deleted file mode 100644
index 88700c7147b68d4273d85ef5c7dc491c73d56851..0000000000000000000000000000000000000000
--- a/results.csv
+++ /dev/null
@@ -1,3 +0,0 @@
-a,b,c
-1,2,3
-4,5,6