Reproducible projects in R require three things to be explicit and stable:
General-purpose tools such as renv,
usethis, or here address parts of this
problem. Project-template packages like tinyProject,
prodigenr, or workflowr provide predefined
directory layouts and conventions.
link2GI addresses a more specific use case: projects
that combine R with external command-line geospatial
software (e.g. GDAL, OTB, GRASS, SAGA) and therefore depend on
a strict and reproducible directory and configuration
structure across operating systems.
Using RStudio, a new project can be created by simply selecting the Create Project Structure (link2GI) template from the File -> New Project -> New Directory -> New Project Wizard dialogue.
This section provides a minimal, canonical workflow
for spatial R projects using link2GI. It is intended as a
quick entry point before the more detailed explanations
below. However it will cover most standard demands
Once: create the project
Always: inside the project
Run outside the project directory. This creates:
renv environmentAfter opening the project, define your root_folder and run the created setup script. This defines:
dirs)Important restrictions
- Do not call
initProj()again — this duplicates folder-creation logic.- Do not use
setwd().- Do not hard-code absolute paths.
- Do not mix setup code with analysis logic.
initProj() creates a project
once.setupProj() reconstructs its environment every
time.All advanced features described below build on this principle.
initProj() in link2GIinitProj() is a project creation
function, not a general runtime setup tool.
It is designed to be executed once per project, at creation time. Its responsibilities are limited to:
git and renv,base,
baseSpatial, advancedSpatial, or
YAML-based).After this step, the project exists as a static on-disk structure.
initProj() vs
setupProj()A core design decision in link2GI is the strict
separation between project creation and project
runtime setup.
| Function | Purpose |
|---|---|
initProj() |
Create a new project on disk |
setupProj() |
Re-create the runtime environment of an existing project |
initProj()Calling initProj() from inside a project directory will
create nested duplicate folder trees. This behaviour is
intentional given its role as a project generator.
setupProj()dirs object.All runtime scripts (e.g. main-control.R, processing
scripts, Quarto documents) should rely on
setupProj()—never on
initProj().
link2GI ships with predefined structural setups stored
in a YAML configuration file. These setups define:
dataFolder),docsFolder),tmpFolder),code_subfolder),git and renv initialisation.Defaults can be inspected programmatically:
The defaults are declarative: they describe structure, not behaviour.
A minimal example using a predefined setup:
root_folder <- tempdir()
dirs <- initProj(
root_folder = root_folder,
standard_setup = "baseSpatial"
)This creates the full directory structure, initial scripts, and configuration files.
Defaults can be extended during project creation:
dirs <- initProj(
root_folder = "~/projects/my_project",
standard_setup = "baseSpatial",
folders = c("data/raw/provider1", "docs/quarto"),
init_git = TRUE,
init_renv = TRUE
)This creates a project whose structure is the union of the selected default and the explicitly provided additions.
src/functions/000_setup.REvery link2GI project contains a single environment
bootstrap script:
src/functions/000_setup.R
This script is a contract, not an example.
Its responsibilities are:
setupProj() once,dirs object.Important restrictions
- call
initProj()again — this duplicates folder-creation logic.- use
setwd().- hard-code absolute paths.
- mix setup code with analysis logic.
A minimal, correct structure is:
root_folder <- normalizePath(getwd(), winslash = "/", mustWork = TRUE)
dirs <- setupProj(
root_folder = root_folder,
folders = c("data/source", "data/results", "docs/figures", "tmp"),
code_subfolder = c("src", "src/functions", "src/configs"),
libs = c("terra", "sf", "dplyr", "link2GI"),
fcts_folder = file.path(root_folder, "src", "functions")
)
dirsinitProj() generates project files by applying
brew::brew() to templates shipped with the package.
Templates are responsible only for writing files, not for managing runtime state.
Each project uses exactly one setup template (selected via
standard_setup) to generate 000_setup.R.
Maintaining multiple near-identical setup templates is discouraged. A recommended pattern is:
Nested project directories
If a structure like this appears:
project/
data/
src/
project/
data/
src/
then initProj() was executed inside an existing project
or with an incorrect root_folder.
This is expected behaviour for a project generator.
dirs pointing to unexpected
locations
If dirs contains absolute paths outside the project
directory, verify that:
root_folder is set to getwd() in
000_setup.R,initProj()
in link2GIinitProj() vs
setupProj()loc_name)src/functions/000_setup.R