Kotlin Packages and Directories

Jeen Broekstra · March 23, 2026

My team consists of a number of very experienced Ruby developers. Recently, however, we’ve started building a new greenfields project using Kotlin and Gradle. My own background being in Java, I hadn’t fully appreciated how alien some aspects of Java/Kotlin project organization are to someone coming from a Ruby background.

Kotlin’s approach to packages and directory structure can feel Byzantine if you’re coming from a language like Ruby. Unlike Ruby, where files are organized by convention and autoloading handles the rest, Kotlin requires explicit package declarations and a more structured directory layout. Several people in the team jokingly remarked that “Java engineers must really like directories”, and questioned the need for all this verbosity.

However, the setup is a deliberate design choice that brings clarity, scalability, and tooling support to large projects. In this article, I’ll explore how this all works in a little more detail.

Packages: More Than Just Folders

In Kotlin, a package is a namespace that groups related code and prevents naming collisions. Unlike Ruby, where you might rely on modules or Rails’ autoloading, Kotlin requires you to declare the package at the top of every file:

// src/main/kotlin/com/example/project/User.kt
package com.example.project

class User {
    // ...
}

Some of the advantages of packages:

  • Avoiding Collisions: Packages act like unique identifiers. For example, com.example.project.User and com.another.project.User can coexist without conflict. This is critical in large projects or when integrating third-party libraries.
  • Explicit Imports: You must explicitly import classes from other packages, making dependencies clear and avoiding hidden magic.
  • Logical Grouping: Packages help organize code by feature, layer, or domain (e.g., com.example.project.repository, com.example.project.service).

Mirroring the package and the directory structure

Here’s a bit of a difference between Java and Kotlin by the way: in Java, having the package name mirrored in the directory structure (so class com.example.project.User is in source file com/example/project/User.java) is a hard requirement at the language level: the Java compiler expects this setup and will fail to compile the project if this doesn’t align.

In Kotlin, however, this isn’t a hard requirement: the Kotlin compiler only cares about the package declaration at the top of the file, not about the physical location of the file itself.

However, Kotlin projects do commonly still follow the convention, because it makes the code easier to navigate for new developers, aligns with defaults of common tools like Gradle or Maven, and just generally avoids confusion.

Rules of thumb for good package names

Package naming in Kotlin should follow a few clear rules to keep your codebase organized and intuitive.

  • use your organization’s reverse domain name as the base (e.g., com.example.project);
  • keep package names all lowercase, with words concatenated (no underscores or hyphens);
  • use nouns to reflect what the package contains (e.g., models, repositories, utils). Avoid verbs or action phrases (e.g., logging is fine, but log or parsing is not);
  • be specific and intentional: name packages after their purpose or domain (e.g., com.example.project.auth, com.example.project.database);
  • avoid generic or vague terms like helpers, misc, or common;
  • skip deep nesting unless your project is very large;
  • never use Java/Kotlin reserved words.

Directory Structure: The Standard Layout

Kotlin projects typically follow a standard directory structure, especially when using build tools like Gradle or Maven:

Directory Purpose
src/main/kotlin Main Kotlin source code (production code).
src/main/resources Non-code resources (config files, images, etc.).
src/test/kotlin Kotlin test source code (unit tests, integration tests).
src/test/resources Resources needed for testing (test configs, mock data, etc.).

The structure has a number of advantages:

  • Separation of Concerns: Production code, tests, and resources are clearly separated.
  • Tooling Support: Gradle, Maven, and IntelliJ IDEA are pre-configured to recognize this layout. For example:
    • IntelliJ automatically marks these directories as source roots.
    • Gradle knows where to look for files during builds.
  • Scalability: This structure works for projects of any size, from small scripts to enterprise applications.

Can You Customize It?

Yes. Like I mentioned above, Kotlin only cares about the package declaration in your files, not the directory structure. You can flatten directories (e.g., omit the common root package) or reorganize as needed, but you may need to configure your build tool or IDE to avoid warnings.

My personal opinion: stick with the defaults. It’s easier to grok, and less hassle to set up, even if it comes at the cost of a slightly deeper folder structure.

Omitting the Common Root Package

One possible small simplification that might be useful to adopt: unlike Java, Kotlin allows you to omit the common root package in your directory structure. For example, if all your code is under com.example.project, you can structure your directories like this:

src/
  main/
    kotlin/
      project/
        User.kt  // package com.example.project

Instead of:

src/
  main/
    kotlin/
      com/
        example/
          project/
            User.kt  // package com.example.project

This is a nice bit of simplification that removes some verbosity: fewer nested directories mean less clicking in your IDE or file explorer.

Summary

  • Packages are namespaces that prevent collisions and organize code logically.
  • Directory structure is a convention that supports tooling and scalability.
  • You can customize it, but sticking to the standard layout simplifies tooling and collaboration.

If you’re coming from Ruby or another dynamic language, the explicitness might feel verbose at first. But once you see how it enables clarity and scalability, it starts to make sense.

Next Steps

In the next article, I’ll dive into how to use Gradle modules to further organize and scale your Kotlin projects.