A project with five R files is manageable. A project with fifteen is not, unless they follow a pattern.
froggeR puts three files in every project’s R/
directory:
_load.R – the entry point_libraries.R – package loading_data_dictionary.R – variable labels and metadataThe underscore prefix is intentional. It sorts these files above your analysis scripts in any directory listing, signaling that they are infrastructure, not analysis.
_load.R: one file to source_load.R is the single entry point for your project.
Source it, and everything initializes:
Inside, it sources the other infrastructure files and runs any project-wide setup:
This cascading pattern means your Quarto documents and analysis
scripts never need more than one source() call. As your
project grows, add new files to _load.R:
source(here::here("R", "_libraries.R"))
source(here::here("R", "_data_dictionary.R"))
source(here::here("R", "helpers.R"))
source(here::here("R", "clean_data.R"))Your Quarto documents stay clean. One source() call at
the top, then analysis.
_libraries.R: packages in one placeEvery library() call lives here. Not scattered across
scripts. Not duplicated in Quarto documents. One file, one place to
check.
This matters for three reasons:
suppressPackageStartupMessages() keeps your console and
rendered documents free of startup noise._data_dictionary.R: label your variables# R/_data_dictionary.R
dictionary <- dplyr::tribble(
~Variable, ~Description,
"age", "Age in years",
"sbp", "Systolic blood pressure (mmHg)",
"treatment", "Treatment group assignment",
)A data dictionary maps variable names to human-readable labels. Keeping it in a dedicated file means your labels are defined once and available everywhere, not buried inside whichever analysis script needed them first.
This is designed for use with {sumExtras} with
sumExtras::add_auto_labels(). Your {gtsummary} tables
get human-readable labels without manual labeling in every script.
Define labels once here, apply them anywhere.
_quarto.yml: the config expects the conventionThe directory structure is not just a suggestion. The template’s
_quarto.yml is wired to it:
Quarto only renders .qmd files found in
pages/. Static assets in www/ are copied to
the output as resources. Rendered HTML goes to docs/,
keeping build artifacts out of your source directories.
The styling and sidebar also reference these paths directly:
format:
html:
theme:
- default
- brand
- www/custom.scss
website:
sidebar:
contents:
- text: Home
href: pages/index.qmdcustom.scss is expected in www/. The
sidebar links to documents in pages/. If you move files out
of convention, these references break and Quarto will tell you something
is missing without telling you why.
This is the payoff of a fixed directory layout: the configuration
works because the structure is predictable. You do not need to edit
_quarto.yml to wire up paths. They are already correct.
For the full _quarto.yml specification, see Quarto
Project Basics.
here::here() and why relative paths breakEvery source() call in the template uses
here::here():
Not this:
The difference matters the moment your working directory is not the project root. In a froggeR project, that happens by design.
When you render pages/index.qmd, Quarto sets the working
directory to pages/. A relative path like
"R/_load.R" resolves to pages/R/_load.R, which
does not exist. The render fails, and the error message does not make
the cause obvious.
here::here() resolves paths from the project root, the
directory containing your .Rproj or .here
file, regardless of the current working directory.
here::here("R", "_load.R") always points to the right file,
whether you call it from the console, from a script in R/,
or from a Quarto document in pages/.
This is not just about source(). Use
here::here() for every file path in your project:
# Reading data
df <- readr::read_csv(here::here("data", "raw_data.csv"))
# Saving output
ggsave(here::here("www", "figure1.png"))One habit that prevents an entire class of path-related errors. See the {here} package documentation for more.