diff --git a/src/base/config.c b/src/base/config.c
index de0cdb2da51473c2e17b373d91a896f5d29bfae7..7db7087865c948a48b0e2774e7d29ccad5d86ead 100644
--- a/src/base/config.c
+++ b/src/base/config.c
@@ -3,6 +3,7 @@
 #include <lektor/database.h>
 #include <lektor/net.h>
 #include <lektor/reg.h>
+#include <lektor/lib/strv.h>
 
 #include <dlfcn.h>
 #include <pwd.h>
@@ -20,62 +21,57 @@ PRIVATE_FUNCTION int config_new(lkt_db *db, const char *conf);
 /* Get the default user config file, the ~/.config/lektor/lektor.ini file. */
 PRIVATE_FUNCTION void config_default_file(char *dest, size_t len);
 
-static inline char *
-strip(char *s)
-{
-    char *p = s + strlen(s);
-    while (p > s && isspace(*(--p)))
-        *p = 0;
-    return s;
-}
-
-static inline char *
-skip(char *s)
-{
-    while (*s && isspace(*s))
-        s++;
-    return s;
-}
-
 PRIVATE_FUNCTION int
-handler(lkt_db *user, const char *section, const char *name, const char *value)
+handler(lkt_db *user, const char *section, const struct strv name, const struct strv value)
 {
-    RETURN_UNLESS(section && name && value, "Skip incomplete line", 1);
-    RETURN_UNLESS(database_config_set(user, section, name, value), "Failed to update config", 1);
+    RETURN_UNLESS(section && strv_len(name) && strv_len(value), "Skip incomplete line", 1);
+    RETURN_UNLESS(database_config_set_strv_1_2(user, section, name, value),
+                  "Failed to update config", 1);
     return 0;
 }
 
 PRIVATE_FUNCTION void
-___set_log_level_internal(const char *level)
+___set_log_level_internal(const struct strv level)
 {
-    if (!level[0]) {
+    static UNUSED struct strv error_strv   = STRV_STATIC("error");
+    static UNUSED struct strv warning_strv = STRV_STATIC("warning");
+    static UNUSED struct strv warn_strv    = STRV_STATIC("warn");
+    static UNUSED struct strv debug_strv   = STRV_STATIC("debug");
+    static UNUSED struct strv info_strv    = STRV_STATIC("info");
+
+    if (strv_len(level) == 0) {
         LOG_WARN("CONFIG", "Invalid empty 'log' option");
         return;
     }
 
-    if (STR_MATCH(level, "error"))
+    if (strv_equal_nocase(level, error_strv))
         lkt_set_log_level(LOG_LEVEL_ERROR);
-    else if (STR_MATCH(level, "warn") || STR_MATCH(level, "warning"))
+    else if (strv_equal_nocase(level, warn_strv))
         lkt_set_log_level(LOG_LEVEL_WARN);
-    else if (STR_MATCH(level, "info"))
+    else if (strv_equal_nocase(level, warning_strv))
+        lkt_set_log_level(LOG_LEVEL_WARN);
+    else if (strv_equal_nocase(level, info_strv))
         lkt_set_log_level(LOG_LEVEL_INFO);
-    else if (STR_MATCH(level, "debug"))
+    else if (strv_equal_nocase(level, debug_strv))
         lkt_set_log_level(LOG_LEVEL_DEBUG);
     else
-        lkt_set_log_level((LOG_LEVEL)(int)strtol(level, NULL, 0));
+        lkt_set_log_level((LOG_LEVEL)(int)strv_to_int(level));
 
     LOG_INFO("CONFIG", "Log level set to %d", lkt_get_log_level());
 }
 
 PRIVATE_FUNCTION void
-___set_log_level(const char *name, const char *level)
+___set_log_level(const struct strv name, const struct strv level)
 {
+    static const struct strv log_strv = STRV_STATIC("log");
+
     /* Just check the key name here */
-    if (!STR_MATCH(name, "log")) {
-        LOG_WARN("CONFIG", "Invalid option '%s[:=]%s' with no section", name, level);
-        return;
+    if (strv_equal_nocase(name, log_strv)) {
+        ___set_log_level_internal(level);
+    } else {
+        LOG_WARN("CONFIG", "Invalid option '" STRV_FMT "=" STRV_FMT "' with no section",
+                 STRV_ARG(name), STRV_ARG(level));
     }
-    ___set_log_level_internal(level);
 }
 
 PRIVATE_FUNCTION void
@@ -89,16 +85,21 @@ ___apply_log_level(lkt_db *db)
         database_config_set(db, "log", "level", loglevel);
     } else {
         /* 'log/level' is present, use that one */
-        ___set_log_level_internal(loglevel);
+        ___set_log_level_internal(strv_from_str(loglevel));
     }
 }
 
+PRIVATE_FUNCTION bool
+___char_is_not_comment_delim(char x)
+{
+    return !(x == ';' || x == '#');
+}
+
 PRIVATE_FUNCTION int
 ini_parse(const char *path, lkt_db *db)
 {
-    char *start, *end, *name, *value;
-    char section[LKT_LINE_MAX], line[LKT_LINE_MAX];
-    int error = 0, linenum = 0, len;
+    char section[LKT_LINE_MAX], file_line[LKT_LINE_MAX];
+    int error = 0, linenum = 0;
     FILE *file = fopen(path, "r");
     if (!file) {
         LOG_ERROR("PARSER", "Failed to open config file '%s'", path);
@@ -106,71 +107,76 @@ ini_parse(const char *path, lkt_db *db)
     }
 
     memset(section, 0, LKT_LINE_MAX);
-    memset(line, 0, LKT_LINE_MAX);
+    memset(file_line, 0, LKT_LINE_MAX);
+
+    static struct strv comment_prefix_1   = STRV_STATIC(";");
+    static struct strv comment_prefix_2   = STRV_STATIC("#");
+    static struct strv bracket_left_strv  = STRV_STATIC("[");
+    static struct strv bracket_right_strv = STRV_STATIC("]");
 
     LOG_INFO("CONFIG", "Save config to database from file");
 
     /* Parse the file */
-    while (NULL != fgets(line, LKT_LINE_MAX, file)) {
+    while (NULL != fgets(file_line, LKT_LINE_MAX, file)) {
         ++linenum;
-        start = skip(strip(line));
+        struct strv line = strv_trim(strv_from_str(file_line));
 
         /* Skip comments */
-        if (strspn(start, ";#"))
+        if (strv_starts_with(line, comment_prefix_1) || strv_starts_with(line, comment_prefix_2))
             continue;
 
         /* Handle sections */
-        else if (start[0] == '[') {
-            end = &start[1 + strcspn(start + 1, "]")];
-            if (end[0] == ']') {
-                end[0] = '\0';
-                len    = (int)strlen(&start[1]);
-                len    = MIN(len + 1, LKT_LINE_MAX);
-                memcpy(section, &start[1], (size_t)len);
-                section[LKT_LINE_MAX - 1] = '\0';
-            }
-
-            else {
+        else if (strv_starts_with(line, bracket_left_strv)) {
+            if (strv_ends_with(line, bracket_right_strv)) {
+                strv_chop_left(&line, 1);
+                strv_chop_right(&line, 1);
+                if (!strv_as_str(line, section, LKT_LINE_MAX)) {
+                    error = 1;
+                    LOG_ERROR("PARSER", "Failed to copy the section name at line '%d'", linenum);
+                }
+            } else {
                 error = 1;
                 LOG_ERROR("PARSER", "Invalid section name at line '%d'", linenum);
             }
         }
 
-        /* Handle name[:=]name pair */
-        else if (start[0]) {
-            end = &start[1 + strcspn(start + 1, ":=")];
-            if (end[0] == '=' || end[0] == ':') {
-                end[0] = '\0';
-                name   = strip(start);
-                value  = &end[1];
-
-                /* Find a comment */
-                end = &value[strcspn(value, ";#")];
-                if (end[0])
-                    end[0] = '\0';
-
-                /* Skip all spaces */
-                value = skip(value);
-                strip(value);
-
-                /* Handle the SECTION, NAME[:=]VALUE
-                   The only option that has no SECTION is the log level:
-                   log[:=]ERROR|WARN|INFO|DEBUG|\d+ */
-                if (section[0]) {
-                    if (handler(db, section, name, value)) {
-                        error = 1;
-                        LOG_ERROR("PARSER", "Failed to '[handle] %s, %s{:,=}%s' at line '%d'",
-                                  section, name, value, linenum);
-                    }
-                } else {
-                    /* Keep for legacy reasons */
-                    ___set_log_level(name, value);
+        /* Handle empty lines */
+        else if (strv_len(line) == 0) {
+            continue;
+        }
+
+        /* Handle name=name pair */
+        else {
+            int separator_index = -1;
+            if (!strv_index_of(line, '=', &separator_index)) {
+                LOG_ERROR("PARSER", "Invalid line '%d', no (key, value) pair found", linenum);
+                continue;
+            }
+
+            const struct strv key = strv_trim(strv_chop_left(&line, separator_index));
+            strv_chop_left(&line, 1); /* Skip the "=" character */
+            const struct strv value = strv_trim(strv_take_left_while(line, ___char_is_not_comment_delim));
+
+            /* Handle the (key, value) pair */
+            if (strv_len(value) == 0 || strv_len(key) == 0) {
+                LOG_ERROR("PARSER", "Invalid key pair at line '%d'", linenum);
+                LOG_ERROR_IF(strv_len(key), "PARSER", "The key was: '"STRV_FMT"'", STRV_ARG(key));
+                LOG_ERROR_IF(strv_len(value), "PARSER", "The value was: '"STRV_FMT"'", STRV_ARG(value));
+            }
+
+            else if (section[0]) {
+                LOG_DEBUG("PARSER", "Found line: [%s] '"STRV_FMT"' = '"STRV_FMT"'", section, STRV_ARG(key), STRV_ARG(value));
+                if (handler(db, section, key, value)) {
+                    error = 1;
+                    LOG_ERROR("PARSER",
+                              "Failed to '[handle] %s, " STRV_FMT "=" STRV_FMT "' at line '%d'",
+                              section, STRV_ARG(key), STRV_ARG(value), linenum);
                 }
             }
 
             else {
-                error = 1;
-                LOG_ERROR("PARSER", "Invalid name[:=]value pair at line '%d'", linenum);
+                /* Keep for legacy reasons */
+                ___set_log_level(key, value);
             }
         }
     }
@@ -305,7 +311,7 @@ config_default(FILE *output)
 
 /* Recursive mkdir, where the last word of the string is a file, not a folder. */
 PRIVATE_FUNCTION void
-__mkdir(const char *dir)
+___mkdir(const char *dir)
 {
     char tmp[PATH_MAX];
     char *p = NULL;
@@ -336,7 +342,7 @@ retry_config:
 
         LOG_INFO("INIT", "Creating default config file");
         config_default_file(conf_file, conf_len);
-        __mkdir(conf_file); /* Create the folder for the file. */
+        ___mkdir(conf_file); /* Create the folder for the file. */
 
         FILE *file_desc = fopen(conf_file, "w+");
         RETURN_UNLESS(file_desc, "Failed to open default config file to initialize it", 1);