Skip to main content
Every group that writes more than a handful of documents eventually reinvents the same preamble: the margins, the header, the section style, the fonts. The question is not whether to standardize it — it’s at which of three levels: a shared preamble, a .sty package, or a full .cls document class. Most people jump to the class too early; this guide walks the escalation path in order.

Level 1: Customize the Preamble (Start Here)

Before writing any class file, know that article, report, and book are far more customizable than they look. Packages like titlesec (section styling), fancyhdr (headers/footers), and geometry (margins) cover most “we want our own look” requirements: If only one or two documents need this look, stop here. A preamble is the easiest thing to understand, debug, and hand to a co-author.

Level 2: Move It into a .sty Package

The moment the same preamble appears in a second document, extract it. A package is just your preamble in a file: Each document then starts with \documentclass{article} and \usepackage{groupstyle} — one file to maintain, and updating the style updates every document. Note the two conventions: \RequirePackage instead of \usepackage inside package files, and \ProvidesPackage with a date so LaTeX can report version mismatches. This level is the right stopping point for most teams. A package rides on top of a standard class, so everything written for article keeps working.

Level 3: A Real .cls Document Class

Write a class when you need to change what the document fundamentally is — its title layout, its sectioning model, its default structure — not just its styling. A minimal class that builds on article: The pattern to copy: declare, forward options, load a base class, then override. Building on article via \LoadClass means you inherit thirty years of robustness and only maintain your differences. Writing a class from absolute scratch is almost never the right call. Documents using it become trivially short — which is the whole point:

Practical Rules from the Trenches

  • \makeatletter / \makeatother are only needed in documents. Inside .sty/.cls files, @ is already a letter — commands like \@title just work.
  • Version-date your \ProvidesClass line and update it on every change; it’s the difference between “which version made this PDF?” being answerable or not.
  • Keep content commands out of the class. A class defines how documents look, not what they say — boilerplate text belongs in a template document, not in .cls.
  • Ship the class next to the documents. Put groupreport.cls in the project (or its own repository shared via Git) rather than a local texmf tree, so every collaborator — and every CI compile — sees the same class without installation.
That last rule is what makes custom classes work in a cloud editor too: a .cls in the project folder is found before anything else, so a shared project with the class checked in compiles for everyone identically. Try it in a shared project →