diff --git a/build.gradle b/build.gradle
index 9687674fc55502fca335ea12c00561833b3679b7..bede3b27c06e4d4d92c5da832fdbb2dbae8aac3f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -4,6 +4,7 @@ plugins {
     id 'org.jastadd'
     id 'java'
     id 'idea'
+    id 'maven-publish'
     id 'java-test-fixtures'
 }
 
@@ -14,11 +15,19 @@ ext {
 // set the main class name for `gradle run`
 application.mainClassName = "${mainClassName}"
 
-sourceCompatibility = 1.8
-targetCompatibility = 1.8
+java.toolchain.languageVersion = JavaLanguageVersion.of(11)
 
 repositories {
     mavenCentral()
+    maven {
+        name 'gitlab-maven'
+        url 'https://git-st.inf.tu-dresden.de/api/v4/groups/jastadd/-/packages/maven'
+    }
+}
+
+configurations {
+    grammar2uml
+    relast
 }
 
 sourceSets {
@@ -27,8 +36,17 @@ sourceSets {
             srcDir "src/gen/java"
         }
     }
+    main {
+        compileClasspath += sourceSets.model.output
+    }
+    test {
+        runtimeClasspath += sourceSets.model.output
+    }
 }
 
+File genSrc = file("src/gen/java")
+idea.module.generatedSourceDirs += genSrc
+
 def versionFile = 'src/main/resources/preprocessor.properties'
 def versionProps = new Properties()
 
@@ -40,42 +58,20 @@ try {
     throw new GradleException("File ${versionFile} not found or unreadable. Aborting.", e)
 }
 
-task fatJar(type: Jar) {
-    group = "build"
-    archiveAppendix = "fatjar"
-    from sourceSets.main.output
-    from {
-        configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
-    }
-    manifest {
-        attributes "Main-Class": "${mainClassName}"
-    }
-}
-
-task modelJar(type: Jar) {
-    group = "build"
-    archiveAppendix = "model"
-    from sourceSets.model.output
-}
-
-artifacts {
-    archives modelJar
-    archives fatJar
-}
-
 dependencies {
 
-    modelImplementation group: 'org.jastadd', name: 'jastadd', version: '2.3.5'
     modelImplementation group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
 
-    implementation files(modelJar.archiveFile.get())
+    grammar2uml group: 'de.tudresden.inf.st', name: 'grammar2uml', version: "${grammar2uml_version}"
+    relast group: 'org.jastadd', name: 'relast', version: "${relast_version}"
+
     api group: 'org.jastadd', name: 'jastadd', version: '2.3.5'
     api group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
     implementation group: 'com.github.jknack', name: 'handlebars', version: '4.3.0'
     implementation group: 'org.yaml', name: 'snakeyaml', version: '1.27'
 
     // test
-    testRuntimeClasspath files(modelJar.archiveFile.get())
+//    testRuntimeClasspath files(modelJar.archiveFile.get())
 
     // test fixtures
     testFixturesApi group: 'org.slf4j', name: 'slf4j-jdk14', version: '1.7.30'
@@ -110,8 +106,9 @@ def relastOutputFiles = [
 ]
 
 task relast(type: JavaExec) {
-    classpath = files("libs/relast.jar")
     group = 'Build'
+    classpath = configurations.relast
+    mainClass = 'org.jastadd.relast.compiler.Compiler'
 
     doFirst {
         delete relastOutputFiles
@@ -190,12 +187,33 @@ jastadd {
     jastaddOptions = ["--lineColumnNumbers", "--List=JastAddList", "--safeLazy", "--visitCheck=true", "--rewrite=cnta", "--cache=all"]
 }
 
-generateAst.dependsOn relast
-
-clean.dependsOn(cleanGen)
+// publish gitlab project
+publishing {
+    publications {
+        maven(MavenPublication) {
+            artifactId = 'relast'
+            from components.java
+        }
+    }
+    repositories {
+        maven {
+            url "https://git-st.inf.tu-dresden.de/api/v4/projects/$System.env.CI_PROJECT_ID/packages/maven"
+            // Uncomment the following lines to publish manually (and comment out the other credentials section)
+//            credentials(HttpHeaderCredentials) {
+//                name = "Private-Token"
+//                value = gitLabPrivateToken // the variable resides in ~/.gradle/gradle.properties
+//            }
+            credentials(HttpHeaderCredentials) {
+                name = 'Job-Token'
+                value = System.getenv('CI_JOB_TOKEN')
+            }
+            authentication {
+                header(HttpHeaderAuthentication)
+            }
+        }
 
-modelJar.dependsOn(generateAst, modelClasses)
-modelClasses.dependsOn(generateAst)
-compileJava.dependsOn(modelJar)
+    }
+}
 
-jar.dependsOn(modelJar)
+generateAst.dependsOn relast
+clean.dependsOn cleanGen
diff --git a/libs/relast.jar b/libs/relast.jar
deleted file mode 100644
index 9f1d60c7c99a1e35d9cf5558d5f329c5aa7ba66e..0000000000000000000000000000000000000000
Binary files a/libs/relast.jar and /dev/null differ
diff --git a/pages/docs/using.md b/pages/docs/using.md
index a42891831f635201bd179762e0fa9fc01ed91774..5377ecae0873e6eed048be75a5381e2cd4a5e001 100644
--- a/pages/docs/using.md
+++ b/pages/docs/using.md
@@ -44,8 +44,9 @@ def relastOutputFiles = [
 ]
 
 task relast(type: JavaExec) {
-    classpath = files("relast.preprocessor/libs/relast.jar")
     group = 'Build'
+    classpath = configurations.relast
+    mainClass = 'org.jastadd.relast.compiler.Compiler'
 
     doFirst {
         delete relastOutputFiles