diff --git a/DESCRIPTION b/DESCRIPTION
index 57676cd35cd674aa70876a60dbdb8c5fa8c88beb..f4d231d948582695e2d232ba6ecff81ec9210475 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -46,6 +46,7 @@ Roxygen: list(markdown = TRUE)
 Collate:
     'base.R'
     'resources.R'
+    'errors.R'
     'mix.R'
     'state.R'
     'plotting.R'
diff --git a/R/api.R b/R/api.R
index 1b2db95a21a47e1f7f6ea99725f5176fa8de8c18..e1586a471c992e06beafb2d7bded99faa1656295 100644
--- a/R/api.R
+++ b/R/api.R
@@ -684,16 +684,12 @@ prepare_app <- function(dir_before,
     init$projects <- norm_path(projects)
     init$metfrag_db_dir <- if (nchar(norm_path(metfrag_db_dir))>0L) norm_path(metfrag_db_dir) else ""
     init$metfrag_runtime <- if (nchar(norm_path(metfrag_runtime))>0L) norm_path(metfrag_runtime) else ""
-    if (!dir.exists(init$top_data_dir)) stop(errorCondition(paste0("Data directory (top_data_dir), currently `",
-                                                              init$top_data_dir,
-                                                              "` does not exist. Abort."),
-                                                       class = "top-data-dir-absent"))
-    if (!dir.exists(init$projects)) stop(errorCondition(paste0("User root directory (projects), currently `",
-                                                          init$projects,"` does not exist.. Abort."),
-                                                   class= "projects-absent"))
-
-    if (nchar(init$metfrag_db_dir)>0L && !dir.exists(init$metfrag_db_dir)) stop(errorCondition("MetFrag DB directory specified, but cannot be found.", class = "mf-db-dir-absent"))
-    if (nchar(init$metfrag_runtime)>0L && !file.exists(init$metfrag_runtime)) stop(errorCondition("MetFrag jar file specified, but cannot be found.", class = "mf-jar-absent"))
+    
+    if (!dir.exists(init$top_data_dir)) stop(errc_top_data_dir_absent)
+    if (!dir.exists(init$projects)) stop(errc_projects_absent)
+
+    if (nchar(init$metfrag_db_dir)>0L && !dir.exists(init$metfrag_db_dir)) stop(errc_mf_db_dir_absent)
+    if (nchar(init$metfrag_runtime)>0L && !file.exists(init$metfrag_runtime)) stop(errc_mf_jar_absent)
     
     dir_start <- tempfile("shinyscreen")
     dir.create(dir_start, recursive = T)
diff --git a/R/errors.R b/R/errors.R
new file mode 100644
index 0000000000000000000000000000000000000000..d3fe162dca8d7c6418c771b2baad5ef48748cbad
--- /dev/null
+++ b/R/errors.R
@@ -0,0 +1,23 @@
+## Copyright (C) 2020,2021,2023 by University of Luxembourg
+
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+
+##     http://www.apache.org/licenses/LICENSE-2.0
+
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+
+errc_mf_jar_absent = errorCondition("MetFrag jar file specified, but cannot be found.", class = "mf-jar-absent")
+errc_mf_db_dir_absent = errorCondition("MetFrag DB directory specified, but cannot be found.", class = "mf-db-dir-absent")
+errc_mf_db_file_absent = errorCondition("MetFrag DB file specified, but cannot be found.", class = "mf-db-dir-absent")
+
+errc_projects_absent = errorCondition("User root directory (projects), currently does not exist.. Abort.", class= "projects-absent")
+errc_top_data_dir_absent = errorCondition("Data directory (top_data_dir) does not exist. Abort.",
+                                         class = "top-data-dir-absent")
+
+errc_conf_file_absent <- errorCondition("There is no config file in the project directory.",class="conf-file-absent")
diff --git a/R/state.R b/R/state.R
index 7bdb5b05ef5b1c47394cd9d24a4bfdda565d0446..38875f1b94770562d167170bec53bd97e9e13dfd 100644
--- a/R/state.R
+++ b/R/state.R
@@ -1,4 +1,4 @@
-## Copyright (C) 2020,2021 by University of Luxembourg
+## Copyright (C) 2020,2021,2023 by University of Luxembourg
 
 ## Licensed under the Apache License, Version 2.0 (the "License");
 ## you may not use this file except in compliance with the License.
@@ -12,8 +12,22 @@
 ## See the License for the specific language governing permissions and
 ## limitations under the License.
 
+init_state <- function(m) {
+    m$out$tab = list()
+    m$input$datafiles = NULL
+    m$input$tab$mzml = EMPTY_MZML
+    lab = gen_uniq_lab(list(),pref="L")
+    m$input$tab$lists = list()
+    m$input$tab[[lab[[1]]]] = EMPTY_CMPD_LIST
+    m$out$tab$comp = EMPTY_COMP_TAB
+    m
+}
 
-##' @export
+#' @title Create Initial State
+#' @details Creates an initial, bare state.
+#' @return A state object.
+#' @export
+#' @author Todor Kondić
 new_state <- function() {
     m <- new_conf()
     init_state(m)
@@ -55,25 +69,57 @@ reinit_run_data <- function(projects,top_data_dir,project,run=NULL) {
     run
 }
 
+is_metfrag_available <- function(conf) {
+    rtime = conf$metfrag$runtime
+    dbpath = conf$metfrag$db_path
 
-## This helps decouple "cross-platform" configuration from the
-## (file-)system dependent facts.
-##' @export
+    if (nchar(rtime)==0L && nchar(dbpath)==0L) return(F)
+    if (!file.exists(rtime)) stop(errc_mf_jar_absent)
+    if (!file.exists(dbpath)) stop(errc_mf_db_file_absent)
+    T
+}
+
+#' @title Create Runtime Configuration
+#' @details This is a part of the configuration that can only be
+#'     diagnosed at runtime.
+#' @param project `character(1)`, project title (and the directory name under `projects`)
+#' @param conf `conf`, configuration object, optional 
+#' @return `run` substate
+#' @author Todor Kondić
+#' @export
 new_runtime_state <- function(project,conf=NULL) {
     
     if (!is.character(project)) stop("Argument `project' must be a character string.")
     if (!dir.exists(project)) stop('Project directory either does not exist, or is unreadable.')
-    project_path <- norm_path(project)
-    project <- basename(project)
-    run <- list()
-    run$project <- project
-    run$paths$project <- project_path
+    project_path = norm_path(project)
+    project = basename(project)
+    run = list()
+    run$project = project
+    run$paths$project = project_path
+
+    if (is.null(conf)) {
+        run$metfrag$available = F
+    } else {
+        run$metfrag$available = is_metfrag_available(conf)
+    }
 
-    run$paths$data <- if (is.null(conf$paths$data)) {
-                          project_path
-                      } else {
-                          run$paths$data <- norm_path(conf$paths$data)
-                      }
+    if (run$metfrag$available) {
+        mfdir = file.path(run$paths$project,"metfrag")
+        dir.create(mfdir)
+        dir.create(file.path(mfdir,"results"))
+        dir.create(file.path(mfdir,"config"))
+        dir.create(file.path(mfdir,"spec"))
+        dir.create(file.path(mfdir,"log"))
+        run$metfrag$path=mfdir
+    }
+
+    
+    run$paths$data = if (is.null(conf$paths$data)) {
+        project_path
+    } else {
+        norm_path(conf$paths$data)
+    }
+    
     
     if (!dir.exists(run$paths$data)) stop("Path to data directory either does not exist, or is inaccesible.")
 
@@ -89,16 +135,23 @@ new_empty_project <- function(project) {
 }
 
 ##' @export
+##' @title Create a New Project
+##' @param project `character(1)`, path to a directory containing all the projects
+##' @param datatab `datatab`, a `data.table` describing data files, optional
+##' @param conf `conf`, a configuration object, optional
+##' @author Todor Kondić
 new_project <- function(project,datatab=NULL,conf=NULL) {
-    m <- new_state()
-    m$run <- new_runtime_state(project)
-    fn_conf <- file.path(m$run$paths$project,FN_CONF)
-    m$conf <- if (is.null(conf)) {yaml::yaml.load_file(fn_conf)} else conf 
-    m$conf$compounds$lists <- label_cmpd_lists(m$conf$compounds$lists)
-    m$run <- new_runtime_state(project,conf=m$conf)
-
+    m = new_state()
+    m$run = new_runtime_state(project)
+    fn_conf = file.path(m$run$paths$project,FN_CONF)
+    m$conf = if (is.null(conf)) {
+                 if (!file.exists(fn_conf)) stop(errc_conf_file_absent)
+                 yaml::yaml.load_file(fn_conf)
+             } else conf 
+    m$conf$compounds$lists = label_cmpd_lists(m$conf$compounds$lists)
+    m$run = new_runtime_state(project,conf=m$conf)
     if (!is.null(datatab)) {
-        m$input$tab$mzml <- datatab
+        m$input$tab$mzml = datatab
     }
     
     m
@@ -188,18 +241,8 @@ get_fn_ftab <- function(m) {
     file.path(m$run$paths$project, FN_DATA_TAB)
 }
 
-init_state <- function(m) {
-    m$out$tab <- list()
-    m$input$datafiles <- NULL
-    m$input$tab$mzml <- EMPTY_MZML
-    lab <- gen_uniq_lab(list(),pref="L")
-    m$input$tab$lists <- list()
-    m$input$tab[[lab[[1]]]] <- EMPTY_CMPD_LIST
-    m$out$tab$comp <- EMPTY_COMP_TAB
-    m
-}
-
 base_conf <- function () {
+    ## Base state.
     m <- list()
     m$conf <- list(project=NA_character_,
                    compounds=list(lists=list(),
@@ -209,6 +252,7 @@ base_conf <- function () {
 }
 
 extr_conf <- function(m) {
+    ## Extraction defaults.
     m$conf$tolerance <- list("ms1 coarse"=MS1_ERR_COARSE,
                              "ms1 fine"=MS1_ERR_FINE,
                              "eic"=EIC_ERR,
@@ -219,6 +263,7 @@ extr_conf <- function(m) {
 }
 
 presc_conf <- function(m) {
+    ## Prescreening defaults.
     m$conf$prescreen <- list("ms1_int_thresh"=MS1_INT_THOLD,
                              "ms2_int_thresh"=MS2_INT_THOLD,
                              "s2n"=MS1_SN_FAC,
@@ -227,16 +272,25 @@ presc_conf <- function(m) {
 }
 
 fig_conf <- function(m) {
+    ## Plotting defaults.
     m$conf$figures$rt_min <- "NA_real_ min"
     m$conf$figures$rt_max <- "NA_real_ min"
     m$conf$figures$ext <- "pdf"
     m
 }
 
-new_conf <- function() fig_conf(
-                           presc_conf(
-                               extr_conf(
-                                   base_conf())))
+metfrag_conf <- function(m) {
+    ## MetFrag configuration defaults.
+    m$conf$metfrag$runtime = ""
+    m$conf$metfrag$db_path = ""
+    m
+}
+
+new_conf <- function() metfrag_conf(
+                           fig_conf(
+                               presc_conf(
+                                   extr_conf(
+                                       base_conf()))))
 
 encode_ms2_to_line <- function(ms2) {
     ## ms2 is a data.frame whose first column is mz and the second intensity.
diff --git a/man/new_project.Rd b/man/new_project.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..f0e35d4460ac338e94052e9b126fd2dff16b3494
--- /dev/null
+++ b/man/new_project.Rd
@@ -0,0 +1,21 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/state.R
+\name{new_project}
+\alias{new_project}
+\title{Create a New Project}
+\usage{
+new_project(project, datatab = NULL, conf = NULL)
+}
+\arguments{
+\item{project}{\code{character(1)}, path to a directory containing all the projects}
+
+\item{datatab}{\code{datatab}, a \code{data.table} describing data files, optional}
+
+\item{conf}{\code{conf}, a configuration object, optional}
+}
+\description{
+Create a New Project
+}
+\author{
+Todor Kondić
+}
diff --git a/man/new_runtime_state.Rd b/man/new_runtime_state.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..80612a373bfd8fd081a34ad8d07e66462c04fd7d
--- /dev/null
+++ b/man/new_runtime_state.Rd
@@ -0,0 +1,26 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/state.R
+\name{new_runtime_state}
+\alias{new_runtime_state}
+\title{Create Runtime Configuration}
+\usage{
+new_runtime_state(project, conf = NULL)
+}
+\arguments{
+\item{project}{\code{character(1)}, project title (and the directory name under \code{projects})}
+
+\item{conf}{\code{conf}, configuration object, optional}
+}
+\value{
+\code{run} substate
+}
+\description{
+Create Runtime Configuration
+}
+\details{
+This is a part of the configuration that can only be
+diagnosed at runtime.
+}
+\author{
+Todor Kondić
+}
diff --git a/man/new_state.Rd b/man/new_state.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..40208002c585f6146b9e5ea9103fd79cc0110ec3
--- /dev/null
+++ b/man/new_state.Rd
@@ -0,0 +1,20 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/state.R
+\name{new_state}
+\alias{new_state}
+\title{Create Initial State}
+\usage{
+new_state()
+}
+\value{
+A state object.
+}
+\description{
+Create Initial State
+}
+\details{
+Creates an initial, bare state.
+}
+\author{
+Todor Kondić
+}
diff --git a/tests/testthat/test-state.R b/tests/testthat/test-state.R
index 636fbe59c6bb30ad1daa21ce740be816a8bf9c8f..2c5ae485cc02871853761ad06babfe5e7de59859 100644
--- a/tests/testthat/test-state.R
+++ b/tests/testthat/test-state.R
@@ -1,3 +1,34 @@
+test_that("Test state creation",{
+
+    withr::with_tempdir({
+        ## new_empty_project
+        ppath = file.path('test','project')
+        dir.create(ppath,recursive=T)
+        res = shinyscreen::new_empty_project(ppath)
+        testthat::expect_true(dir.exists(res$run$paths$project))
+        testthat::expect_false(res$run$metfrag$available)
+        
+        ## new_project
+        testthat::expect_error(shinyscreen::new_project(ppath),class="conf-file-absent")
+        
+        ## Switch metfrag on when conditions met.
+        conf = res$conf
+        mf_jar = "bingo.jar"
+        saveRDS(" ",mf_jar)
+        mf_db = "bingo.csv"
+        saveRDS(" ",mf_db)
+        conf$metfrag$runtime = norm_path(mf_jar)
+        conf$metfrag$db_path = norm_path(mf_db)
+        testthat::expect_true(is_metfrag_available(conf))
+        
+        yaml::write_yaml(conf,file.path(ppath,FN_CONF))
+        x = shinyscreen::new_project(ppath)
+        testthat::expect_true(x$run$metfrag$available)
+    })
+})
+
+
+
 test_that("pack_ms2_w_summ",{
     summ = STATE_DATA$out$tab$summ
     ms2 = STATE_DATA$extr$ms2
@@ -17,3 +48,4 @@ test_that("pack_ms2_w_summ",{
     
     
 })
+