The making of...

The various formats of the CV and technical experience listing were produced using the Nightshade DOC package, using this and this source, respectively.

The layout of the CV is defined as a list, like

(defvar cv-layout
  `((table ((row ((string . "CURRICULUM VITAE")
		  (data . (db:db-record-full-name (get-db-record))))))
	   :heading)
    (table ((row ((data . (db:address-line-1
			   (db:db-record-address (get-db-record))))
		  (string . "Email:")
		  (data . (car (db:db-record-emails (get-db-record))))))
	    (row ((data . (db:address-town
			   (db:db-record-address (get-db-record))))
		  (string . "Homepage:")
		  (data . (db:db-record-url (get-db-record)))))
	    (row ((data . (db:address-code
			   (db:db-record-address (get-db-record))))))
	    (row ((data . (db:address-country
			   (db:db-record-address (get-db-record))))
		  (string . "Date:")
		  (data . (format-today)))))
	   :table)
    (data . (progn (setq *qual* 0 *exp* 0) ()))
    (section ((many ((data . (if (next-qualification-p)
				 ""
				 (doc:return-from-many)))
		     (paragraph ((data . (describe-current-qualification)))))))
	     "QUALIFICATIONS"
	     ,cv-indent)
	;; etc
which is then converted to text, HTML and LaTeX with functions like doc-to-latex, as in

  (with-open-file (out ":doc/cv/cv.tex"
		       :direction :output :if-exists :supersede)
    (doc:doc-to-latex cv-layout
		      out
		      (let* ((*stream* (open ":doc/cv/style.css"
					     :direction :input))
			     (*streams* `((,*stream* 0))))
			(or *stream* (error "Open failed."))
			(parse-css))))

The HTML stylesheet is used to control some of the formatting produced by doc-to-latex, hence the call to parse-css.

Some of the document is dynamically generated during the conversion, for example via the expression (db:db-record-full-name (get-db-record)) in the CV layout.