---
url: https://docs.sunlicense.com/guide/templates.md
description: >-
  Starter templates with SunLicense built in - Paper and Velocity plugins, a
  Fabric mod, a FiveM resource and Discord bots in JavaScript and Java.
---

# Templates

Start a new project from a template that already checks its license the right way: the official SDK, your
API key kept out of git, a stable machine id, clear messages for every result, re-checks so a revoke
reaches running copies, and it keeps working when SunLicense can't be reached. Each one builds and runs
its tests in CI and has an `AGENTS.md`, so an [AI coding assistant](/guide/ai-assistants) can work in it
without weakening the check.

| Template | For | Stack | Offline file |
|---|---|---|---|
| [Paper plugin](/guide/paper-plugin) · [repo](https://github.com/sunlicense-com/example-paper-plugin) | Minecraft servers (Paper 1.21 and 26.x) | Java 21, Gradle | ✓ |
| [Velocity plugin](https://github.com/sunlicense-com/example-velocity-plugin) | Minecraft proxies (Velocity 3.5 and 4.x) | Java 21, Gradle | ✓ |
| [Fabric mod](https://github.com/sunlicense-com/example-fabric-mod) | Minecraft servers with Fabric (26.3) | Java 25, Fabric Loom | ✓ |
| [FiveM resource](https://github.com/sunlicense-com/example-fivem-resource) | GTA V roleplay servers (RedM too) | Lua 5.4 | |
| [Discord bot, JavaScript](https://github.com/sunlicense-com/example-discord-bot-js) | Bots sold to server owners | Node.js 22, discord.js 14 | ✓ |
| [Discord bot, Java](https://github.com/sunlicense-com/example-discord-bot-jda) | Bots sold to server owners | Java 21, JDA 6 | ✓ |

On GitHub, click **Use this template** (or download the folder), then follow its README: create a
product, a policy and an API key, put the key in your build settings, build, and sell.

## What they have in common

* **The key reaches the buyer's copy** from a config file (or `.env`, or a FiveM convar), or for the Java
  templates sold on [BuiltByBit](/integrations/builtbybit) and [Voxel Shop](/integrations/voxel-shop)
  through a `%%__SUNLICENSE__%%` placeholder the store fills in on download.
* **Your API key is baked into the build you sell**, from Gradle properties, environment variables or a
  packaging script, never from the repository. It can only validate licenses.
* **Each copy has a random machine id** stored next to it, so restarts count as the same machine and
  the policy's machine limit works.
* **A rejection stops the product** (disables, switches features off or exits) with a message for the
  result code: expired, revoked, suspended, unknown key, too many machines or blacklisted. Keys are
  always masked in logs.
* **No answer is not a no.** On a network error, a 5xx or a 429, the template uses a signed
  [offline license file](/guide/offline-licenses) if there is one, otherwise keeps running and retries
  every 10 minutes. One constant (`ALLOW_WHEN_UNREACHABLE`) makes it wait instead.
* **Re-checks every 6 hours** by default, so revoking a leaked key reaches copies that are already
  running.

Testing with your own license? Add an [exclusion](/guide/access-rules) for your machine so test runs don't
use up slots. Selling something else? Every [SDK](/guide/sdks) works the same way, and
[a prompt for your AI assistant](/guide/ai-assistants#a-prompt-to-paste) gets you started in any language.
