diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index eb0d7c9d5d21348c91012ffe1370f543e6156c63..9f7c4440e3af1c3eb23f818aae7a5aee6c7a2ce6 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -58,52 +58,43 @@ android {
 }
 
 dependencies {
-  implementation(kotlin("stdlib", "1.6.10"))
-
   // App Compat
-  implementation("com.google.android.material", "material", "1.1.0-alpha10")
-
-  implementation("androidx.appcompat", "appcompat", "1.1.0")
-  implementation("androidx.browser", "browser", "1.2.0")
-  implementation("androidx.cardview", "cardview", "1.0.0")
-  implementation("androidx.recyclerview", "recyclerview", "1.1.0")
-  implementation("androidx.swiperefreshlayout", "swiperefreshlayout", "1.1.0-beta01")
-  implementation("androidx.preference", "preference", "1.1.0")
+  implementation(libs.androidx.material)
+
+  implementation(libs.androidx.appcompat)
+  implementation(libs.androidx.browser)
+  implementation(libs.androidx.cardview)
+  implementation(libs.androidx.recyclerview)
+  implementation(libs.androidx.swiperefreshlayout)
+  implementation(libs.androidx.preference)
   // Only needed for ringtone preference
-  implementation("androidx.legacy", "legacy-preference-v14", "1.0.0")
-  implementation("androidx.constraintlayout", "constraintlayout", "2.0.0-beta4")
-
-  withVersion("2.2.5") {
-    implementation("androidx.room", "room-runtime", version)
-    kapt("androidx.room", "room-compiler", version)
-    implementation("androidx.room", "room-rxjava2", version)
-    testImplementation("androidx.room", "room-testing", version)
-  }
-  withVersion("2.2.0") {
-    implementation("androidx.lifecycle", "lifecycle-extensions", version)
-    implementation("androidx.lifecycle", "lifecycle-reactivestreams", version)
-  }
-  testImplementation("androidx.arch.core", "core-testing", "2.1.0")
+  implementation(libs.androidx.legacy)
+  implementation(libs.androidx.constraintlayout)
+
+  implementation(libs.androidx.room.runtime)
+  kapt(libs.androidx.room.compiler)
+  implementation(libs.androidx.room.rxjava)
+  testImplementation(libs.androidx.room.testing)
+  implementation(libs.androidx.lifecycle.extensions)
+  implementation(libs.androidx.lifecycle.reactivestreams)
   implementation(project(":lifecycle-ktx"))
-
-  implementation("androidx.paging", "paging-runtime", "2.1.2")
-
-  implementation("androidx.multidex", "multidex", "2.0.1")
+  implementation(libs.androidx.paging.runtime)
+  implementation(libs.androidx.multidex)
 
   // Utility
-  implementation("io.reactivex.rxjava2", "rxandroid", "2.1.1")
-  implementation("io.reactivex.rxjava2", "rxjava", "2.2.12")
-  implementation("org.threeten", "threetenbp", "1.4.0", classifier = "no-tzdb")
-  implementation("org.jetbrains", "annotations", "17.0.0")
-  implementation("com.google.code.gson", "gson", "2.8.5")
-  implementation("commons-codec", "commons-codec", "1.13")
-  implementation("com.squareup.retrofit2", "retrofit", "2.6.1")
-  implementation("com.squareup.retrofit2", "converter-gson", "2.6.1")
-  implementation("com.github.pwittchen", "reactivenetwork-rx2", "3.0.6")
-  withVersion("10.1.0") {
-    implementation("com.jakewharton", "butterknife", version)
-    kapt("com.jakewharton", "butterknife-compiler", version)
+  implementation(libs.rxjava.android)
+  implementation(libs.rxjava.java)
+  implementation(libs.threetenbp) {
+    artifact { classifier = "no-tzdb" }
   }
+  implementation(libs.annotations.jetbrains)
+  implementation(libs.gson)
+  implementation(libs.commons.codec)
+  implementation(libs.reactivenetwork)
+  implementation(libs.retrofit.core)
+  implementation(libs.retrofit.converter.gson)
+  implementation(libs.butterknife.core)
+  kapt(libs.butterknife.compiler)
 
   // Quassel
   implementation(project(":viewmodel"))
@@ -113,53 +104,38 @@ dependencies {
   }
 
   // UI
-  implementation("com.leinardi.android", "speed-dial", "3.2.0")
-  implementation("me.zhanghai.android.materialprogressbar", "library", "1.6.1")
-  implementation("com.google.android.flexbox", "flexbox", "3.0.0")
+  implementation(libs.speeddial)
+  implementation(libs.materialprogressbar)
+  implementation(libs.flexbox)
   implementation(project(":ui_spinner"))
-  withVersion("0.9.6.0") {
-    implementation("com.afollestad.material-dialogs", "core", version)
-    implementation("com.afollestad.material-dialogs", "commons", version)
-  }
-  withVersion("4.9.0") {
-    implementation("com.github.bumptech.glide", "glide", version)
-    implementation("com.github.bumptech.glide", "recyclerview-integration", version)
-    kapt("com.github.bumptech.glide", "compiler", version)
-  }
+  implementation(libs.materialdialogs.core)
+  implementation(libs.materialdialogs.commons)
+  implementation(libs.glide.core)
+  implementation(libs.glide.recyclerview)
+  kapt(libs.glide.compiler)
 
   // Quality Assurance
   implementation(project(":malheur"))
-  withVersion("2.2") {
-    debugImplementation("com.squareup.leakcanary", "leakcanary-android", version)
-  }
+  debugImplementation(libs.leakcanary.android)
 
   // Dependency Injection
-  withVersion("2.24") {
-    implementation("com.google.dagger", "dagger", version)
-    kapt("com.google.dagger", "dagger-compiler", version)
-    kapt("com.google.dagger", "dagger-android-processor", version)
-    implementation("com.google.dagger", "dagger-android", version)
-    implementation("com.google.dagger", "dagger-android-support", version)
-  }
-
-  testImplementation("junit", "junit", "4.12")
-  testImplementation("org.robolectric", "robolectric", "4.3.1") {
+  implementation(libs.dagger.core)
+  kapt(libs.dagger.compiler)
+  kapt(libs.dagger.processor)
+  implementation(libs.dagger.android.core)
+  implementation(libs.dagger.android.support)
+
+  testImplementation(libs.junit)
+  testImplementation(libs.androidx.test.core)
+  testImplementation(libs.robolectric) {
     exclude(group = "org.threeten", module = "threetenbp")
     exclude(group = "com.google.auto.service", module = "auto-service")
   }
 
-  androidTestImplementation("junit", "junit", "4.12")
-  androidTestImplementation("androidx.test.espresso", "espresso-core", "3.3.0-alpha02")
-  androidTestImplementation("androidx.test.espresso", "espresso-contrib", "3.3.0-alpha02")
-  androidTestImplementation("androidx.test.ext", "junit", "1.1.2-alpha02")
-  androidTestImplementation("androidx.test", "runner", "1.3.0-alpha02")
-  androidTestImplementation("androidx.test", "rules", "1.3.0-alpha02")
-}
-
-data class VersionContext<T>(val version: T)
-
-inline fun <T> withVersion(version: T?, f: VersionContext<T>.() -> Unit) {
-  version?.let {
-    f.invoke(VersionContext(version))
-  }
+  androidTestImplementation(libs.junit)
+  androidTestImplementation(libs.androidx.test.espresso.core)
+  androidTestImplementation(libs.androidx.test.espresso.contrib)
+  androidTestImplementation(libs.androidx.test.junit)
+  androidTestImplementation(libs.androidx.test.runner)
+  androidTestImplementation(libs.androidx.test.rules)
 }
diff --git a/gradle/convention/src/main/kotlin/justjanne.kotlin.android.gradle.kts b/gradle/convention/src/main/kotlin/justjanne.kotlin.android.gradle.kts
index 980d556278f7543a8523239102ae256b5c0ff7f4..ca3b3d88019815d3b9eeedef08c57f59937acabb 100644
--- a/gradle/convention/src/main/kotlin/justjanne.kotlin.android.gradle.kts
+++ b/gradle/convention/src/main/kotlin/justjanne.kotlin.android.gradle.kts
@@ -1,3 +1,4 @@
+import gradle.kotlin.dsl.accessors._5ee02a09f3b6dcc9700f8e51e448c252.implementation
 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
 
 plugins {
@@ -7,6 +8,10 @@ plugins {
   kotlin("kapt")
 }
 
+dependencies {
+  implementation("org.jetbrains.kotlin:kotlin-stdlib:1.6.10")
+}
+
 tasks.withType<KotlinCompile> {
   kotlinOptions {
     freeCompilerArgs = listOf(
diff --git a/gradle/convention/src/main/kotlin/justjanne.kotlin.gradle.kts b/gradle/convention/src/main/kotlin/justjanne.kotlin.gradle.kts
index 48ab1e4c37e04fb66bc40cd9261b18b9c8afd16c..2b18204e004076f5aa2d29c2bb5bee2f6071dba1 100644
--- a/gradle/convention/src/main/kotlin/justjanne.kotlin.gradle.kts
+++ b/gradle/convention/src/main/kotlin/justjanne.kotlin.gradle.kts
@@ -8,6 +8,10 @@ plugins {
   kotlin("kapt")
 }
 
+dependencies {
+  implementation("org.jetbrains.kotlin:kotlin-stdlib:1.6.10")
+}
+
 tasks.withType<KotlinCompile> {
   kotlinOptions {
     freeCompilerArgs = listOf(
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
new file mode 100644
index 0000000000000000000000000000000000000000..ea948c28a43cfcfaad803a20123219f1417aef5e
--- /dev/null
+++ b/gradle/libs.versions.toml
@@ -0,0 +1,82 @@
+[versions]
+androidx-appcompat = "1.1.0"
+androidx-espresso = "3.3.0-alpha02"
+androidx-lifecycle = "2.2.0"
+androidx-room = "2.2.5"
+androidx-test = "1.3.0-alpha02"
+butterknife = "10.1.0"
+dagger = "2.24"
+glide = "4.9.0"
+kotlin = "1.6.10"
+materialdialogs = "0.9.6.0"
+retrofit = "2.6.1"
+
+[libraries]
+androidx-annotation = { module = "androidx.annotation:annotation", version.ref = "androidx-appcompat" }
+androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx-appcompat" }
+androidx-browser = { module = "androidx.browser:browser", version = "1.2.0" }
+androidx-cardview = { module = "androidx.cardview:cardview", version = "1.0.0" }
+androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version = "2.0.0-beta4" }
+androidx-legacy = { module = "androidx.legacy:legacy-preference-v14", version = "1.0.0" }
+androidx-lifecycle-common = { module = "androidx.lifecycle:lifecycle-common", version.ref = "androidx-lifecycle" }
+androidx-lifecycle-extensions = { module = "androidx.lifecycle:lifecycle-extensions", version.ref = "androidx-lifecycle" }
+androidx-lifecycle-reactivestreams = { module = "androidx.lifecycle:lifecycle-reactivestreams", version.ref = "androidx-lifecycle" }
+androidx-material = { module = "com.google.android.material:material", version = "1.1.0-alpha10" }
+androidx-multidex = { module = "androidx.multidex:multidex", version = "2.0.1" }
+androidx-paging-runtime = { module = "androidx.paging:paging-runtime", version = "2.1.2" }
+androidx-preference = { module = "androidx.preference:preference", version = "1.1.0" }
+androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version = "1.1.0" }
+androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "androidx-room" }
+androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "androidx-room" }
+androidx-room-rxjava = { module = "androidx.room:room-rxjava2", version.ref = "androidx-room" }
+androidx-room-testing = { module = "androidx.room:room-testing", version.ref = "androidx-room" }
+androidx-swiperefreshlayout = { module = "androidx.swiperefreshlayout:swiperefreshlayout", version = "1.1.0-beta01" }
+androidx-test-core = { module = "androidx.arch.core:core-testing", version = "2.1.0" }
+androidx-test-espresso-contrib = { module = "androidx.test.espresso:espresso-contrib", version.ref = "androidx-espresso" }
+androidx-test-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "androidx-espresso" }
+androidx-test-junit = { module = "androidx.test.ext:junit", version = "1.1.2-alpha02" }
+androidx-test-rules = { module = "androidx.test:rules", version.ref = "androidx-test" }
+androidx-test-runner = { module = "androidx.test:runner", version.ref = "androidx-test" }
+
+annotations-inject = { module = "javax.inject:javax.inject", version = "1" }
+annotations-jetbrains = { module = "org.jetbrains:annotations", version = "17.0.0" }
+
+butterknife-compiler = { module = "com.jakewharton:butterknife-compiler", version.ref = "butterknife" }
+butterknife-core = { module = "com.jakewharton:butterknife", version.ref = "butterknife" }
+
+commons-codec = { module = "commons-codec:commons-codec", version = "1.13" }
+
+dagger-android-core = { module = "com.google.dagger:dagger-android", version.ref = "dagger" }
+dagger-android-support = { module = "com.google.dagger:dagger-android-support", version.ref = "dagger" }
+dagger-compiler = { module = "com.google.dagger:dagger-compiler", version.ref = "dagger" }
+dagger-core = { module = "com.google.dagger:dagger", version.ref = "dagger" }
+dagger-processor = { module = "com.google.dagger:dagger-android-processor", version.ref = "dagger" }
+
+flexbox = { module = "com.google.android.flexbox:flexbox", version = "3.0.0" }
+
+glide-compiler = { module = "com.github.bumptech.glide:compiler", version.ref = "glide" }
+glide-core = { module = "com.github.bumptech.glide:glide", version.ref = "glide" }
+glide-recyclerview = { module = "com.github.bumptech.glide:recyclerview-integration", version.ref = "glide" }
+
+gson = { module = "com.google.code.gson:gson", version = "2.8.5" }
+junit = { module = "junit:junit", version = "4.12" }
+kotlinpoet = { module = "com.squareup:kotlinpoet", version = "1.8.0" }
+ksp = { module = "com.google.devtools.ksp:symbol-processing-api", version = "1.6.10-1.0.4" }
+leakcanary-android = { module = "com.squareup.leakcanary:leakcanary-android", version = "2.2" }
+
+materialdialogs-commons = { module = "com.afollestad.material-dialogs:commons", version.ref = "materialdialogs" }
+materialdialogs-core = { module = "com.afollestad.material-dialogs:core", version.ref = "materialdialogs" }
+
+materialprogressbar = { module = "me.zhanghai.android.materialprogressbar:library", version = "1.6.1" }
+reactivenetwork = { module = "com.github.pwittchen:reactivenetwork-rx2", version = "3.0.6" }
+
+retrofit-converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit" }
+retrofit-core = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
+
+robolectric = { module = "org.robolectric:robolectric", version = "4.3.1" }
+
+rxjava-android = { module = "io.reactivex.rxjava2:rxandroid", version = "2.1.1" }
+rxjava-java = { module = "io.reactivex.rxjava2:rxjava", version = "2.2.12" }
+
+speeddial = { module = "com.leinardi.android:speed-dial", version = "3.2.0" }
+threetenbp = { module = "org.threeten:threetenbp", version = "1.4.0" }
diff --git a/invokergenerator/build.gradle.kts b/invokergenerator/build.gradle.kts
index 391c1ff15963c57472de7a2d07acc56c82809555..3339302ecd5a10861bd2b97f3d82491aaa019641 100644
--- a/invokergenerator/build.gradle.kts
+++ b/invokergenerator/build.gradle.kts
@@ -7,7 +7,7 @@ repositories {
 }
 
 dependencies {
-  implementation("com.google.devtools.ksp:symbol-processing-api:1.6.10-1.0.4")
+  implementation(libs.ksp)
+  implementation(libs.kotlinpoet)
   implementation(project(":invokerannotations"))
-  implementation("com.squareup", "kotlinpoet", "1.8.0")
 }
diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts
index bc12db12c26973487f9c8508c30bc456aa979572..7607e029e3f1281f35f9d3b2a85c701a68aee882 100644
--- a/lib/build.gradle.kts
+++ b/lib/build.gradle.kts
@@ -22,15 +22,13 @@ plugins {
 }
 
 dependencies {
-  implementation(kotlin("stdlib", "1.6.10"))
+  implementation(libs.androidx.annotation)
 
-  implementation("androidx.annotation", "annotation", "1.1.0")
-
-  implementation("org.threeten", "threetenbp", "1.4.0")
-  implementation("io.reactivex.rxjava2", "rxjava", "2.2.12")
+  implementation(libs.threetenbp)
+  implementation(libs.rxjava.java)
 
   implementation(project(":invokerannotations"))
   ksp(project(":invokergenerator"))
 
-  testImplementation("junit", "junit", "4.12")
+  testImplementation(libs.junit)
 }
diff --git a/lifecycle-ktx/build.gradle.kts b/lifecycle-ktx/build.gradle.kts
index 262225912f9bbfb9198524d35c5de561761e6784..5f83f50e5a2918a4a00c64a0c5b2abe1decd7bcd 100644
--- a/lifecycle-ktx/build.gradle.kts
+++ b/lifecycle-ktx/build.gradle.kts
@@ -21,9 +21,6 @@ plugins {id("justjanne.kotlin")
 }
 
 dependencies {
-  implementation(kotlin("stdlib", "1.6.10"))
-
-  implementation("androidx.annotation", "annotation", "1.1.0")
-
-  implementation("androidx.lifecycle", "lifecycle-common", "2.1.0")
+  implementation(libs.androidx.annotation)
+  implementation(libs.androidx.lifecycle.common)
 }
diff --git a/malheur/build.gradle.kts b/malheur/build.gradle.kts
index 3493429b18808e7adcde142256acaaf193d03188..59b6ed965277600fdefa677554fe826ce30324e7 100644
--- a/malheur/build.gradle.kts
+++ b/malheur/build.gradle.kts
@@ -22,8 +22,6 @@ plugins {
 }
 
 dependencies {
-  implementation(kotlin("stdlib", "1.6.10"))
-
-  implementation("com.google.code.gson", "gson", "2.8.5")
-  implementation("androidx.annotation", "annotation", "1.1.0")
+  implementation(libs.gson)
+  implementation(libs.androidx.annotation)
 }
diff --git a/persistence/build.gradle.kts b/persistence/build.gradle.kts
index e327ec355e942e6dbb04783383c0955efb94f8d0..d9a1d41d62019ea097584f4f2cdb99d97d508551 100644
--- a/persistence/build.gradle.kts
+++ b/persistence/build.gradle.kts
@@ -22,33 +22,23 @@ plugins {
 }
 
 dependencies {
-  implementation(kotlin("stdlib", "1.6.10"))
+  implementation(libs.androidx.appcompat)
 
-  implementation("androidx.appcompat", "appcompat", "1.1.0")
+  implementation(libs.androidx.room.runtime)
+  kapt(libs.androidx.room.compiler)
+  implementation(libs.androidx.room.rxjava)
+  testImplementation(libs.androidx.room.testing)
 
-  withVersion("2.2.5") {
-    implementation("androidx.room", "room-runtime", version)
-    kapt("androidx.room", "room-compiler", version)
-    implementation("androidx.room", "room-rxjava2", version)
-    testImplementation("androidx.room", "room-testing", version)
-  }
-
-  implementation("androidx.paging", "paging-runtime", "2.1.2")
+  implementation(libs.androidx.paging.runtime)
 
   // Utility
-  implementation("org.threeten", "threetenbp", "1.4.0", classifier = "no-tzdb")
-  implementation("org.jetbrains", "annotations", "17.0.0")
+  implementation(libs.threetenbp) {
+    artifact { classifier = "no-tzdb"}
+  }
+  implementation(libs.annotations.jetbrains)
 
   // Quassel
   implementation(project(":lib")) {
     exclude(group = "org.threeten", module = "threetenbp")
   }
 }
-
-data class VersionContext<T>(val version: T)
-
-inline fun <T> withVersion(version: T?, f: VersionContext<T>.() -> Unit) {
-  version?.let {
-    f.invoke(VersionContext(version))
-  }
-}
diff --git a/ui_spinner/build.gradle.kts b/ui_spinner/build.gradle.kts
index eb262984c8c12adb005d82ffbf2504e377693073..831058ab514998a507de20375de2d3fda59cc2e1 100644
--- a/ui_spinner/build.gradle.kts
+++ b/ui_spinner/build.gradle.kts
@@ -22,6 +22,5 @@ plugins {
 }
 
 dependencies {
-  implementation(kotlin("stdlib", "1.6.10"))
-  implementation("androidx.appcompat", "appcompat", "1.1.0")
+  implementation(libs.androidx.appcompat)
 }
diff --git a/viewmodel/build.gradle.kts b/viewmodel/build.gradle.kts
index ffe82cd81b63e7e10e6a8eb8fb97eab5800b744a..8e06357ad0b51c3107b9601ec3796206f750155d 100644
--- a/viewmodel/build.gradle.kts
+++ b/viewmodel/build.gradle.kts
@@ -22,21 +22,19 @@ plugins {
 }
 
 dependencies {
-  implementation(kotlin("stdlib", "1.6.10"))
-
-  implementation("androidx.appcompat", "appcompat", "1.1.0")
-  withVersion("2.2.0") {
-    implementation("androidx.lifecycle", "lifecycle-extensions", version)
-    implementation("androidx.lifecycle", "lifecycle-reactivestreams", version)
-  }
+  implementation(libs.androidx.appcompat)
+  implementation(libs.androidx.lifecycle.extensions)
+  implementation(libs.androidx.lifecycle.reactivestreams)
 
   // Utility
-  implementation("io.reactivex.rxjava2", "rxandroid", "2.1.1")
-  implementation("io.reactivex.rxjava2", "rxjava", "2.2.12")
-  implementation("org.threeten", "threetenbp", "1.4.0", classifier = "no-tzdb")
-  implementation("org.jetbrains", "annotations", "17.0.0")
+  implementation(libs.rxjava.android)
+  implementation(libs.rxjava.java)
+  implementation(libs.threetenbp) {
+    artifact { classifier = "no-tzdb" }
+  }
+  implementation(libs.annotations.jetbrains)
 
-  implementation("javax.inject", "javax.inject", "1")
+  implementation(libs.annotations.inject)
 
   // Quassel
   implementation(project(":persistence"))
@@ -44,13 +42,5 @@ dependencies {
     exclude(group = "org.threeten", module = "threetenbp")
   }
 
-  testImplementation("junit", "junit", "4.12")
-}
-
-data class VersionContext<T>(val version: T)
-
-inline fun <T> withVersion(version: T?, f: VersionContext<T>.() -> Unit) {
-  version?.let {
-    f.invoke(VersionContext(version))
-  }
+  testImplementation(libs.junit)
 }