# Getting Started

> Step-by-step guide to create your first Minecraft datapack with Kore. Set up a Kotlin project, write type-safe commands and functions, generate the datapack, and test in-game.

Updated 2026-10-21. Canonical: https://kore.ayfri.com/docs/getting-started

This guide takes you from zero to a real development workflow with Kore. Instead of stopping at a minimal "hello world,"
you will build a small but structured datapack, run it in-game, iterate quickly, and learn how to scale your project.

This guide targets the JVM, the primary way to build and export a datapack (`generate()` / `generateZip()`). The same
calls also work on Node.js; see [Multiplatform Support](https://kore.ayfri.com/docs/advanced/multiplatform.md) for that and for the
browser-only `exportAsStrings()` / `generateZipBytes()` alternatives.

If you already have solid datapack experience and want an architecture-first migration guide, jump to
[From Datapacks to Kore](https://kore.ayfri.com/docs/guides/from-datapacks-to-kore.md). To try Kore before setting anything up, the
[playground](https://kore.ayfri.com/playground) runs it in your browser and shows the generated pack.

## What you will build

By the end of this page, you will have:

- A Kotlin project configured for Kore.
- A datapack with metadata and multiple functions.
- A simple game loop entry point (`load` + user-triggered functions).
- A practical local development cycle to edit, regenerate, and test quickly.
- A clean starting structure you can keep expanding.

## Prerequisites

- [Java 25 (JDK 25)](https://jdk.java.net/25/) or higher, required by both Kore and Minecraft 26.3.
- Gradle (wrapper recommended: `./gradlew`).
- IntelliJ IDEA (recommended) or another IDE with Kotlin support.
- Basic understanding of Minecraft datapacks (helpful but not required).

## Kotlin basics you need before Kore

If you are new to Kotlin, do not worry. You only need a small subset to be productive with Kore.

### `val` and `var`

- `val` means read-only reference (preferred by default).
- `var` means mutable reference (use only when reassignment is needed).

```kotlin
val packName = "starter_kore"
var buildNumber = 1
buildNumber += 1
```

### Functions

You declare functions with `fun`. Kore code is mostly function calls inside builders.

```kotlin
fun greet(name: String): String {
	return "Hello, $name"
}
```

### Null safety

Kotlin distinguishes nullable (`String?`) and non-null (`String`) types.

```kotlin
val maybePlayer: String? = System.getenv("PLAYER_NAME")
val displayName = maybePlayer ?: "Player"
```

Use:

- `?.` for safe calls,
- `?:` for fallback values (Elvis operator).

### Lambdas and builder blocks

Kore uses Kotlin lambdas heavily:

```kotlin
function("hello") {
	tellraw(allPlayers(), textComponent("Hello"))
}
```

The `{ ... }` block is a lambda, and inside it Kore exposes a DSL context with helper functions.

### Extension functions (very important in Kore projects)

Kotlin lets you add functions to existing types without inheritance.
This is ideal for structuring large datapacks.

```kotlin
fun DataPack.registerWelcome() {
	function("feature/welcome") {
		tellraw(allPlayers(), textComponent("Welcome"))
	}
}
```

You can then call `registerWelcome()` inside your `dataPack {}` builder.

## Step 1: Create your project

You have two ways to start.

### Option A: Use the Kore Template (recommended)

The fastest option is the template repository, which is already configured for Kotlin + Gradle + Kore.

1. Open [Kore Template](https://github.com/Kore-Minecraft/Kore-Template).
2. Click "Use this template" (or clone directly).
3. Open it in IntelliJ IDEA.
4. Let Gradle sync.
5. Run the `main` function in `src/main/kotlin/Main.kt`.

### Option B: Add Kore to an existing Kotlin project

If you already have a Kotlin project, add Kore manually.

#### Core modules

- `kore` - core DSL to generate datapacks.
- `oop` - object-oriented gameplay abstractions.
- `helpers` - helper utilities built on top of Kore.
- `bindings` - experimental importer for existing datapacks.

For your first datapack, use only `kore`.

#### Gradle Kotlin DSL

```kotlin
dependencies {
	implementation("io.github.ayfri.kore:kore:2.28.0-26.3")
}
```

#### Gradle Groovy DSL

```groovy
dependencies {
    implementation 'io.github.ayfri.kore:kore:2.28.0-26.3'
}
```

`2.28.0-26.3` is the latest stable release, for Minecraft 26.3. Kore also publishes builds for
Minecraft snapshots, the newest release including them is `2.28.0-26.3`: snapshot features can still change
from one snapshot to the next, see [Version Support](https://kore.ayfri.com/docs/guides/version-support.md#snapshot-and-pre-release-builds).

#### Snapshot builds (latest unreleased changes)

If you want bleeding-edge features:

```kotlin
repositories {
	mavenCentral()
	maven("https://central.sonatype.com/repository/maven-snapshots/")
}

dependencies {
	implementation("io.github.ayfri.kore:kore:2.28.0-26.3-SNAPSHOT")
}
```

#### Kotlin compiler and JVM settings

Kore relies on context parameters, which are stable since Kotlin 2.4. Make sure your `build.gradle.kts` contains:

```kotlin
kotlin {
	jvmToolchain(25)
}
```

## Step 2: Write a first useful datapack

Instead of a single command, create a tiny but realistic pack with:

- metadata (`pack`),
- one function for player feedback,
- one function for setup behavior.

If you are new to Kotlin syntax, read the code like this:

- `val datapack = ...` stores the generated datapack object.
- `dataPack("starter_kore") { ... }` creates a builder context.
- each `function("...") { ... }` block writes one generated `.mcfunction` file.

Create `Main.kt`:

```kotlin
fun main() {
	val datapack = dataPack("starter_kore") {
		pack {
			description = textComponent("Starter datapack generated with Kore")
		}

		function("hello") {
			tellraw(allPlayers(), textComponent("Hello from Kore"))
		}

		function("setup") {
			tellraw(allPlayers(), textComponent("Setup complete"))
		}
	}

	datapack.generateZip()
}
```

Run `main`, then put the generated zip into your world's `datapacks` folder.

## Step 3: Load and test in Minecraft

1. Open your world.
2. Run `/reload`.
3. Trigger the function:

```mcfunction
/function starter_kore:hello
```

If everything is correct, chat displays your message.

## Step 4: Use `load {}` as your real entry point

In Kore, using `load {}` is usually better than manually naming a startup function and wiring tags yourself. It directly
creates and registers a function in `minecraft:load`, which makes your startup flow explicit and less error-prone.

Most datapacks become easier to maintain when you separate:

- initialization (`load`),
- recurring logic (`tick` when needed),
- feature functions (your own namespaced functions).

Add this structure in Kore by defining dedicated functions and using consistent names:

```kotlin
fun main() {
	val datapack = dataPack("starter_kore") {
		pack {
			description = textComponent("Starter datapack generated with Kore")
		}

		load("bootstrap") {
			tellraw(allPlayers(), textComponent("[starter_kore] datapack loaded"))
			function("feature/give_welcome")
		}

		function("feature/give_welcome") {
			tellraw(allPlayers(), textComponent("Welcome to the world"))
		}

		tick("runtime/checks") {
			// Keep tick lightweight. Route heavy logic to dedicated functions.
		}
	}

	datapack.generate()
}
```

With this approach:

- `load("bootstrap")` runs once after `/reload`.
- `tick("runtime/checks")` runs every game tick.
- `function("feature/...")` stays your reusable API surface.
- folder-like names keep generated files organized as the project grows.

## Step 5: Organize code before it gets messy

A common beginner mistake is placing everything in one `main` function. Prefer small helpers and focused files early.

Example using extensions:

```kotlin
fun DataPack.registerCoreFunctions() {
	load("bootstrap") {
		tellraw(allPlayers(), textComponent("[starter_kore] datapack loaded"))
	}
}

fun DataPack.registerFeatureFunctions() {
	function("feature/give_welcome") {
		tellraw(allPlayers(), textComponent("Welcome to the world"))
	}
}

fun main() {
	val datapack = dataPack("starter_kore") {
		pack {
			description = textComponent("Starter datapack generated with Kore")
		}

		registerCoreFunctions()
		registerFeatureFunctions()
	}

	datapack.generateZip()
}
```

This pattern scales much better than one giant builder block.

## Step 6: Use a fast development loop

During development, your loop should be:

1. Edit Kotlin code.
2. Re-run `main`.
3. Copy or regenerate output into your world datapack folder.
4. In-game: `/reload`.
5. Run the function you are testing.

Tips:

- Use `.generate()` when you want to inspect generated files locally.
- Use `.generateZip()` when you want easy distribution.
- Enable pretty JSON in [Configuration](https://kore.ayfri.com/docs/guides/configuration.md) when debugging generated resources.

## Step 7: Build an advanced mini-pack with a custom enchantment

At this point, create a pack that is closer to production structure:

- startup flow with `load`,
- runtime flow with regular functions,
- one custom data-driven feature (a custom enchantment).

Example:

```kotlin
fun main() {
	val datapack = dataPack("starter_kore") {
		pack {
			description = textComponent("Starter datapack with a custom enchantment")
		}

		// 1) Runtime functions
		function("feature/welcome") {
			tellraw(allPlayers(), textComponent("Welcome to starter_kore"))
		}

		function("feature/show_vampiric_hint") {
			tellraw(allPlayers(), textComponent("Try the Vampiric enchantment on a sword"))
		}

		// 2) Startup entry point
		load("bootstrap") {
			function("feature/welcome")
			function("feature/show_vampiric_hint")
		}

		// 3) Custom enchantment definition (data-driven content)
		enchantment("vampiric") {
			description("Vampiric")
			supportedItems(Tags.Item.SWORDS)
			primaryItems(Tags.Item.Enchantable.SHARP_WEAPON)
			weight = 2
			maxLevel = 3
			minCost(20, 15)
			maxCost(50, 15)
			anvilCost = 8
			slots(EquipmentSlot.MAINHAND)

			effects {
				// Bonus damage that scales by level
				damage {
					add(linearLevelBased(1, 1))
				}

				// Chance to heal attacker on hit
				postAttack {
					on(PostAttackSpecifier.ATTACKER, PostAttackSpecifier.ATTACKER) {
						applyMobEffect(Effects.INSTANT_HEALTH) {
							minAmplifier(0)
							maxAmplifier(0)
							minDuration(1)
							maxDuration(1)

							requirements {
								randomChance(enchantmentLevel(linearLevelBased(0.08f, 0.08f)))
							}
						}
					}
				}
			}
		}
	}

	datapack.generateZip()
}
```

What this gives you:

- a generated `data/starter_kore/enchantment/vampiric.json`,
- startup player feedback via `minecraft:load`,
- a clear split between command functions and data-driven definitions.

To validate in-game:

1. Regenerate your datapack.
2. Put it in your world.
3. Run `/reload`.
4. Check logs/chat for load output.
5. Test enchantment behavior with commands or controlled test scenarios.

## Going beyond a minimal datapack

Once your first commands work, move to data-driven features:

- Add recipes, loot tables, predicates, and tags.
- Create multiple function entry points per feature.
- Separate "bootstrap" code from "gameplay" code.
- Reuse helper functions to avoid duplicated command blocks.

Good expansion ideas after the custom enchantment:

- A welcome system with per-player conditions.
- A starter kit function with basic inventory setup.
- A scoreboard-based progression mechanic.
- A custom recipe that complements your enchantment.
- A balancing pass for enchantment costs, rarity, and max level.

## Kotlin tips that matter specifically in Kore projects

- Prefer `val` by default; immutable declarations reduce accidental state issues.
- Use extension functions on `DataPack` to keep your DSL composable.
- If your IDE imports the wrong DSL symbol, qualify temporarily with `this.` in the builder scope, then fix the import.
- Keep function names and file-like paths consistent (`feature/x`, `system/y`) to keep generated output predictable.
- Declare each function path once: two functions sharing a path with different bodies make generation throw.
- Prefer `load {}` and `tick {}` builders over manual tag wiring for standard lifecycle hooks.

### Quick Kotlin learning resources

- [Kotlin documentation](https://kotlinlang.org/docs/home.html)
- [Kotlin null safety](https://kotlinlang.org/docs/null-safety.html)
- [Kotlin extensions](https://kotlinlang.org/docs/extensions.html)
- [Learn X in Y Minutes - Kotlin](https://learnxinyminutes.com/kotlin/)
- [Kotlin Playground](https://play.kotlinlang.org/)

## Troubleshooting

### Unresolved Kore DSL symbols

- Check that the dependency exists in the correct module.
- Confirm you're on Kotlin 2.4 or higher (context parameters are stable there).
- Refresh/sync Gradle in your IDE.

### Java/Kotlin toolchain errors

- Confirm JDK 25 is installed and selected by Gradle.
- Confirm `jvmToolchain(25)` is configured.

### Datapack generates but does not work in-game

- Confirm the namespace/function path in `/function`.
- Run `/reload` after every regeneration.
- Check the world folder path and datapack placement.
- Open logs and verify no JSON or command syntax error is reported.

## Recommended learning path after this guide

Start here next:

1. [Creating a Datapack](https://kore.ayfri.com/docs/guides/creating-a-datapack.md)
2. [Runtime Logic](https://kore.ayfri.com/docs/concepts/runtime-logic.md) - how Kotlin `val`/`if`/`for` map to in-game scoreboards, storage, and
   `execute`
3. [Functions](https://kore.ayfri.com/docs/commands/functions.md)
4. [Commands](https://kore.ayfri.com/docs/commands/commands.md)
5. [Selectors](https://kore.ayfri.com/docs/concepts/selectors.md)
6. [Cookbook](https://kore.ayfri.com/docs/guides/cookbook.md)
7. [Recipes](https://kore.ayfri.com/docs/data-driven/recipes.md)
8. [Enchantments](https://kore.ayfri.com/docs/data-driven/enchantments.md)

For the full index, see [Home](https://kore.ayfri.com/docs/home.md), and for a tour of everything Kore covers, the [Features](https://kore.ayfri.com/features) page.

## See also

- [Kore Hello World](https://ayfri.com/articles/kore-hello-world/)
- [Kore on GitHub](https://github.com/Ayfri/Kore)
- [Kore on Maven Central](https://central.sonatype.com/search?q=io.github.ayfri.kore)
- [Kore on Discord](https://discord.ayfri.com)
- [Minecraft Wiki: Datapack](https://minecraft.wiki/w/Data_pack)
