diff --git a/DESCRIPTION b/DESCRIPTION
index 7c76f72ebb0b5e579ae33aba9c45bbd79a45ec1d..f5eba098c0913c69a9b69d02a4521d934eeb54a8 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -10,6 +10,9 @@ Roxygen: list(markdown = TRUE)
 RoxygenNote: 7.2.3
 Imports: 
     bookdown,
+    usethis,
     yaml
 Suggests: 
+    testthat (>= 3.0.0),
     tinytex
+Config/testthat/edition: 3
diff --git a/NAMESPACE b/NAMESPACE
index 8a7fc2a591368c5e97442a9f093972fd5935e979..614161c18463edfbf72dd2150179377fa1dd0230 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -2,6 +2,7 @@
 
 export("%>%")
 export(add_gitignore)
+export(create_fairify)
 export(getDataPath)
 export(iconv_filename)
 export(loadConfig)
diff --git a/R/add_gitignore.R b/R/add_gitignore.R
index 6ef5ba8f164f6185a0aab4590f68adb38bdace97..58e1881fbb541990e7e63e3c442fc9893b6b2ef9 100644
--- a/R/add_gitignore.R
+++ b/R/add_gitignore.R
@@ -1,16 +1,18 @@
 #' Add .gitignore file suitable for R project
 #'
+#' @inheritParams create_fairify
 #' @inheritParams utils::download.file
 #'
 #' @return `NULL`, this function is used for side effect.
 #' @export
 #'
 #' @examples
-#' tmpfile <- tempfile()
-#' add_gitignore(destfile = tmpfile)
-#' readLines(tmpfile)
-add_gitignore <- function(url = "https://raw.githubusercontent.com/github/gitignore/main/R.gitignore",
-                          destfile = ".gitignore") {
+#' path <- tempdir()
+#' add_gitignore(path = path)
+#' readLines(file.path(path, ".gitignore"))
+add_gitignore <- function(path = ".",
+                          url = "https://raw.githubusercontent.com/github/gitignore/main/R.gitignore") {
+  destfile = file.path(path, ".gitignore")
   stopifnot(download.file(url, destfile) == 0)
   header <- add_comment_block("R template from:",
                               url,
diff --git a/R/create_fairify.R b/R/create_fairify.R
new file mode 100644
index 0000000000000000000000000000000000000000..d0570a097cca8df00e24a2031c15f04dd43b018d
--- /dev/null
+++ b/R/create_fairify.R
@@ -0,0 +1,29 @@
+#' Create a "fairified" project
+#'
+#' Create a package ready for fairify your project.
+#'
+#' @inheritParams usethis::create_package
+#' @param tidy if `TRUE`, run [usethis::use_testthat()], [usethis::use_tidy_description()], and [usethis::use_tidy_dependencies()]
+#' @param with_reports If `TRUE`, run `create_reports`, preparing package structure for report publications
+#' @param ... Further parameters passed to [usethis::create_package]
+#'
+#' @return
+#' @export
+#'
+#' @examples
+#' path <- tempdir()
+#' create_fairify(path, open = FALSE)
+#' list.files(path)
+create_fairify <- function(path, tidy = TRUE, open = rlang::is_interactive(), with_reports = TRUE, ...) {
+  usethis::create_package(path, rstudio = TRUE, open = FALSE, ...)
+  if (tidy) {
+    usethis::local_project(path)
+    usethis::use_testthat()
+    usethis::use_tidy_description()
+  }
+  add_gitignore(path)
+  if (with_reports) create_reports(path = path)
+  if (open) {
+    proj_activate(path)
+  }
+}
diff --git a/man/add_gitignore.Rd b/man/add_gitignore.Rd
index 2da1f10b41ef06afb5822499d0693017fecf6600..2cee7879ad8e6b67f3423d4bf07dbfdc94a61836 100644
--- a/man/add_gitignore.Rd
+++ b/man/add_gitignore.Rd
@@ -5,18 +5,17 @@
 \title{Add .gitignore file suitable for R project}
 \usage{
 add_gitignore(
-  url = "https://raw.githubusercontent.com/github/gitignore/main/R.gitignore",
-  destfile = ".gitignore"
+  path = ".",
+  url = "https://raw.githubusercontent.com/github/gitignore/main/R.gitignore"
 )
 }
 \arguments{
+\item{path}{A path. If it exists, it is used. If it does not exist, it is
+created, provided that the parent path exists.}
+
 \item{url}{a \code{\link{character}} string (or longer vector
     for the \code{"libcurl"} method) naming the URL of a resource to be
     downloaded.}
-
-\item{destfile}{a character string (or vector, see the \code{url}
-    argument) with the file path where the downloaded file is to be
-    saved.  Tilde-expansion is performed.}
 }
 \value{
 \code{NULL}, this function is used for side effect.
@@ -25,7 +24,7 @@ add_gitignore(
 Add .gitignore file suitable for R project
 }
 \examples{
-tmpfile <- tempfile()
-add_gitignore(destfile = tmpfile)
-readLines(tmpfile)
+path <- tempdir()
+add_gitignore(path = path)
+readLines(file.path(path, ".gitignore"))
 }
diff --git a/man/create_fairify.Rd b/man/create_fairify.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..82e3283021695f14a95149d940b54e09c92b9902
--- /dev/null
+++ b/man/create_fairify.Rd
@@ -0,0 +1,39 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/create_fairify.R
+\name{create_fairify}
+\alias{create_fairify}
+\title{Create a "fairified" project}
+\usage{
+create_fairify(
+  path,
+  tidy = TRUE,
+  open = rlang::is_interactive(),
+  with_reports = TRUE,
+  ...
+)
+}
+\arguments{
+\item{path}{A path. If it exists, it is used. If it does not exist, it is
+created, provided that the parent path exists.}
+
+\item{tidy}{if \code{TRUE}, run \code{\link[usethis:use_testthat]{usethis::use_testthat()}}, \code{\link[usethis:tidyverse]{usethis::use_tidy_description()}}, and \code{\link[usethis:tidyverse]{usethis::use_tidy_dependencies()}}}
+
+\item{open}{If \code{TRUE}, \link[usethis:proj_activate]{activates} the new project:
+\itemize{
+\item If using RStudio desktop, the package is opened in a new session.
+\item If on RStudio server, the current RStudio project is activated.
+\item Otherwise, the working directory and active project is changed.
+}}
+
+\item{with_reports}{If \code{TRUE}, run \code{create_reports}, preparing package structure for report publications}
+
+\item{...}{Further parameters passed to \link[usethis:create_package]{usethis::create_package}}
+}
+\description{
+Create a package ready for fairify your project.
+}
+\examples{
+path <- tempdir()
+create_fairify(path, open = FALSE)
+list.files(path)
+}
diff --git a/tests/testthat.R b/tests/testthat.R
new file mode 100644
index 0000000000000000000000000000000000000000..3d8820ae2d4844d23c6361ec47f6a946259d2919
--- /dev/null
+++ b/tests/testthat.R
@@ -0,0 +1,12 @@
+# This file is part of the standard setup for testthat.
+# It is recommended that you do not modify it.
+#
+# Where should you do additional test configuration?
+# Learn more about the roles of various files in:
+# * https://r-pkgs.org/testing-design.html#sec-tests-files-overview
+# * https://testthat.r-lib.org/articles/special-files.html
+
+library(testthat)
+library(fairify)
+
+test_check("fairify")
diff --git a/tests/testthat/test-create_fairify.R b/tests/testthat/test-create_fairify.R
new file mode 100644
index 0000000000000000000000000000000000000000..a60ab6b885ed9f16c93ca6185965b4a99afd9ec3
--- /dev/null
+++ b/tests/testthat/test-create_fairify.R
@@ -0,0 +1,6 @@
+test_that("create_fairify works", {
+  path <- tempfile()
+  create_fairify(path, open = FALSE)
+  project <- basename(path)
+  expect_true(file.exists(file.path(path, paste0(project, ".Rproj"))))
+})