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
library(link2GI)
initProj("~/projects/example", standard_setup = "baseSpatial")
Always: inside the project
source("src/functions/000_setup.R")
Run outside the project directory. This creates:
renv environmentlibrary(link2GI)
initProj(
root_folder = "~/projects/my_spatial_project",
standard_setup = "baseSpatial",
init_git = TRUE,
init_renv = TRUE
)
After opening the project, define your root_folder and run the created setup script. This defines:
dirs)root_folder <- getwd()
source("src/functions/000_setup.R")
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:
setup_default()
setup_default()$baseSpatial
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.
loc_name)The optional loc_name argument introduces a second hierarchy level below data/, docs/, and tmp/.
This is intended for workflows where a single project manages multiple spatial sites or regions.
If this distinction is not required, loc_name should be left NULL.
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")
)
dirs
initProj() 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,