Question
Add a Maven Repository URL in Gradle Kotlin DSL (build.gradle.kts)
Question
What is the Kotlin DSL equivalent of this Groovy Gradle configuration for adding Maven Central and a custom Maven repository URL?
repositories {
mavenCentral()
maven {
url '<MAVEN REPO URL>'
}
}
How should this be written in a build.gradle.kts file?
Short Answer
You will learn how Gradle Kotlin DSL configures repositories, why repository URLs are converted with uri(...), and how to add Maven Central alongside a private or third-party Maven repository in build.gradle.kts.
Concept
Gradle needs to know where to download dependencies such as libraries, plugins, and their metadata. The repositories block defines those locations.
In Groovy Gradle scripts (build.gradle), Gradle allows a compact dynamic syntax:
url 'https://example.com/repository/maven-releases/'
Kotlin DSL (build.gradle.kts) is statically typed. The url property of a Maven repository expects a URI, not a plain String. Therefore, convert the URL string with Gradle's uri(...) helper:
url = uri("https://example.com/repository/maven-releases/")
This matters because Kotlin DSL catches more configuration mistakes earlier and provides better IDE completion and navigation than dynamic Groovy syntax.
Mental Model
Think of repositories as package warehouses.
mavenCentral()registers the large public Maven Central warehouse.maven { ... }registers another warehouse.url = uri("...")writes the warehouse's precise address in a format Gradle understands.
A dependency declaration tells Gradle what package you need; a repository declaration tells Gradle where to look for it.
Syntax and Examples
Use a repositories block and assign the Maven repository's url property with uri(...).
repositories {
mavenCentral()
maven {
url = uri("https://repo.example.com/maven/")
}
}
The Kotlin DSL equivalent of the original configuration is:
repositories {
mavenCentral()
maven {
url = uri("<MAVEN REPO URL>")
}
}
For example, a project that retrieves dependencies from Maven Central and an internal company repository might use:
repositories {
mavenCentral()
maven {
name = "company-releases"
url = uri("https://packages.example.com/repository/releases/")
}
}
Giving a repository a name is optional, but it makes Gradle logs and build diagnostics easier to read.
Step by Step Execution
Consider this build script:
repositories {
mavenCentral()
maven {
name = "company-releases"
url = uri("https://packages.example.com/repository/releases/")
}
}
dependencies {
implementation("com.example:reporting-sdk:1.2.0")
}
When Gradle resolves com.example:reporting-sdk:1.2.0, it generally does the following:
- It reads the
repositoriesblock and registers Maven Central. - It creates another Maven repository named
company-releases. uri(...)converts the text URL into aURIobject and assigns it to the repository.- It reads the dependency coordinate: group
com.example, artifactreporting-sdk, version1.2.0. - Gradle searches the configured repositories in their declared order until it finds matching metadata and the artifact.
- Gradle downloads the dependency into its local cache, then compiles or runs the project with it.
Repository order can matter if more than one repository contains the same group, artifact, and version.
Real World Use Cases
Custom Maven repositories are common when dependencies are not published to Maven Central.
- Private company libraries: A team publishes shared authentication, logging, or UI libraries to an internal repository.
- Third-party package hosting: Some vendors host their Android, JVM, or Kotlin libraries in a dedicated Maven repository.
- Release and snapshot separation: Stable versions may be stored in one URL and development snapshots in another.
- Internal build infrastructure: An organization may proxy Maven Central through Nexus or Artifactory for caching, auditing, and access control.
- Plugin and library distribution: A project can publish its own artifacts and allow other applications to consume them through a Maven-compatible URL.
Real Codebase Usage
In production projects, repository configuration is usually kept deliberate and centralized.
Name custom repositories
repositories {
mavenCentral()
maven {
name = "internal"
url = uri("https://repo.example.com/maven-public/")
}
}
A name improves error messages and makes it easier to identify the source of a dependency.
Read the URL from a Gradle property
Avoid hard-coding environment-specific URLs when builds run locally and in CI.
val internalRepoUrl: String by project
repositories {
mavenCentral()
maven {
name = "internal"
url = uri(internalRepoUrl)
}
}
Then provide the value in gradle.properties or through a CI environment configuration:
internalRepoUrl=https://repo.example.com/maven-public/
Use credentials without committing secrets
val repoUser: String? by project
val repoPassword: String? by project
repositories {
maven {
name = "private-repository"
url = uri("https://repo.example.com/maven-private/")
credentials {
username = repoUser
password = repoPassword
}
}
}
Store real credentials in a local, uncommitted Gradle properties file, environment variables, or a CI secret manager—not directly in the build script.
Centralize repositories in multi-project builds
Modern Gradle builds often declare dependency repositories in settings.gradle.kts so all modules follow the same policy:
// settings.gradle.kts
dependencyResolutionManagement {
repositories {
mavenCentral()
maven {
name = "internal"
url = uri("https://repo.example.com/maven-public/")
}
}
}
This prevents one module from silently adding an unexpected repository.
Common Mistakes
Using Groovy assignment syntax in Kotlin DSL
This is valid in Groovy, but not Kotlin DSL:
maven {
url "https://repo.example.com/maven/"
}
Use an assignment and uri(...) instead:
maven {
url = uri("https://repo.example.com/maven/")
}
Assigning a plain string to url
This does not match the expected URI type:
maven {
url = "https://repo.example.com/maven/"
}
Correct version:
maven {
url = uri("https://repo.example.com/maven/")
}
Putting repositories inside dependencies
repositories and dependencies are separate Gradle blocks:
// Incorrect
dependencies {
repositories {
mavenCentral()
}
}
Place them at the project level, or configure them centrally in settings.gradle.kts.
Confusing dependency repositories with plugin repositories
Libraries declared in dependencies {} use dependency repositories. Plugins declared in plugins {} may need repositories under pluginManagement in settings.gradle.kts.
Committing repository passwords
Do not write secrets directly in source-controlled build files:
// Unsafe
password = "my-secret-password"
Use Gradle properties, environment variables, or your CI platform's secret storage instead.
Adding untrusted repositories unnecessarily
Every added repository expands the places from which Gradle can resolve artifacts. Prefer known repositories, use a repository manager where appropriate, and keep the list minimal.
Comparisons
| Task | Groovy DSL (build.gradle) | Kotlin DSL (build.gradle.kts) |
|---|---|---|
| Add Maven Central | mavenCentral() | mavenCentral() |
| Add custom Maven repository | maven { url 'https://...' } | maven { url = uri("https://...") } |
| Set a repository name | name 'internal' | name = "internal" |
| URL value type | Groovy can coerce a string dynamically | Kotlin DSL expects a URI |
| Repository method | Best use |
|---|---|
mavenCentral() | Public libraries available from Maven Central |
mavenLocal() | Testing artifacts published to your local Maven cache; avoid as a default for reproducible builds |
maven { url = uri(...) } | Private, company, vendor, release, or snapshot Maven repositories |
google() | Android and Google artifacts in Android projects |
Cheat Sheet
repositories {
mavenCentral()
maven {
name = "optional-readable-name"
url = uri("https://repo.example.com/maven/")
}
}
- Use
build.gradle.ktsfor Kotlin DSL. - Use
=for property assignment. - Wrap repository URL strings in
uri(...). nameis optional but useful for diagnostics.- Repository order affects where Gradle searches first.
- Put dependency repositories in
repositories {}. - Configure plugin repositories separately with
pluginManagement { repositories { ... } }when needed. - Do not commit usernames, passwords, tokens, or private repository credentials.
FAQ
What is the Kotlin DSL syntax for a Maven repository URL?
maven {
url = uri("https://repo.example.com/maven/")
}
Why is uri(...) required in build.gradle.kts?
The Maven repository url property expects a URI. uri(...) converts a string URL into the required type.
Can I use mavenCentral() and a custom Maven repository together?
Yes. Add both inside the same repositories block.
repositories {
mavenCentral()
maven { url = uri("https://repo.example.com/maven/") }
}
Is the repository name required?
No. name = "internal" is optional, but it makes logs and errors clearer.
Where should I place the repositories block?
For a single project, place it in build.gradle.kts. For multi-module projects, dependency repositories are often centralized in settings.gradle.kts using dependencyResolutionManagement.
How do I add credentials for a private Maven repository?
Use the credentials block and load values from Gradle properties, environment variables, or CI secrets. Do not hard-code secrets in the script.
Does a custom dependency repository also configure Gradle plugins?
Not necessarily. Plugin resolution can require repository configuration under pluginManagement in settings.gradle.kts.
Mini Project
Description
Create a small Kotlin/JVM Gradle build that resolves normal dependencies from Maven Central and is ready to resolve organization-specific libraries from a custom Maven repository. This mirrors the setup used by many internal applications.
Goal
Configure a build.gradle.kts file with Maven Central, a named custom Maven repository, and one dependency.
Requirements
Requirement 1
Keep learning
Related questions
Accessing Kotlin Extension Functions from Java
Learn how Kotlin extension functions are compiled and how to call them correctly from Java with clear examples and common pitfalls.
Allow HTTP and HTTPS in Android 9 Pie with Network Security Configuration
Learn how Android 9 Pie handles cleartext HTTP traffic and how to allow HTTP and HTTPS safely using network security config.
Android AlarmManager Example: Scheduling Tasks with AlarmManager
Learn how to use Android AlarmManager to schedule tasks, set alarms, and handle broadcasts with a simple beginner example.