Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
56495fc
feat: implement blog functionality
LuggaPugga Oct 12, 2025
f501950
Merge branch 'main' into blog
LuggaPugga Oct 12, 2025
8f04f49
refactor(blog): update date handling in blog posts to use last edit date
LuggaPugga Oct 12, 2025
09c1399
refactor(blog): use last edit date for blog post timestamps
LuggaPugga Oct 12, 2025
cef2fde
chore: add Blog to home links
LuggaPugga Oct 12, 2025
651fd22
chore: add more favicon variants
LuggaPugga Oct 12, 2025
7c78f4e
fix(rss): update blog description for clarity
NonSwag Oct 12, 2025
0543b14
chore: add VSCode settings to .gitignore
NonSwag Oct 12, 2025
6124012
feat(blog): add future plans and current projects overview
NonSwag Oct 12, 2025
5ab5473
Merge branch 'blog' of https://github.com/TheNextLvl-net/docs into blog
NonSwag Oct 12, 2025
290609c
chore: remove site.webmanifest and update layout icons for better fav…
LuggaPugga Oct 12, 2025
84a1ffd
refactor(blog): enhance blog post layout
LuggaPugga Oct 12, 2025
796f221
refactor(layout): clean up layout code and improve formatting
LuggaPugga Oct 12, 2025
3989202
fix: fix multiple linting issues
LuggaPugga Oct 13, 2025
395266c
refactor(rss): update getRSS to use lastEdit for accurate date handling
NonSwag Oct 13, 2025
2cdc5fe
Merge branch 'main' into blog
LuggaPugga Oct 13, 2025
e353171
feat(blog): add optional keywords field to blog post schema and enhan…
LuggaPugga Oct 13, 2025
3246a61
feat(blog): add keywords field to enhance SEO and discoverability of …
LuggaPugga Oct 13, 2025
eac9b96
refactor(blog): remove unused parameter from metadata generation func…
LuggaPugga Oct 13, 2025
e47be71
feat(layout): add Blog icon link to layout configuration
LuggaPugga Oct 13, 2025
4359498
refactor(blog): update styling and structure of blog page and sidebar…
LuggaPugga Oct 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# vscode

.vscode/settings.json

# jetbrains
.idea

Expand Down
7 changes: 7 additions & 0 deletions bun.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"dependencies": {
"@icons-pack/react-simple-icons": "^13.7.0",
"@shikijs/types": "^3.11.0",
"feed": "^5.1.0",
"fumadocs-core": "15.8.5",
"fumadocs-mdx": "12.0.3",
"fumadocs-ui": "15.8.5",
Expand Down Expand Up @@ -832,6 +833,8 @@

"fdir": ["[email protected]", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],

"feed": ["[email protected]", "", { "dependencies": { "xml-js": "^1.6.11" } }, "sha512-qGNhgYygnefSkAHHrNHqC7p3R8J0/xQDS/cYUud8er/qD9EFGWyCdUDfULHTJQN1d3H3WprzVwMc9MfB4J50Wg=="],

"file-entry-cache": ["[email protected]", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],

"fill-range": ["[email protected]", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
Expand Down Expand Up @@ -1358,6 +1361,8 @@

"safer-buffer": ["[email protected]", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],

"sax": ["[email protected]", "", {}, "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg=="],

"scheduler": ["[email protected]", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="],

"scroll-into-view-if-needed": ["[email protected]", "", { "dependencies": { "compute-scroll-into-view": "^3.0.2" } }, "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ=="],
Expand Down Expand Up @@ -1524,6 +1529,8 @@

"word-wrap": ["[email protected]", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],

"xml-js": ["[email protected]", "", { "dependencies": { "sax": "^1.2.4" }, "bin": { "xml-js": "./bin/cli.js" } }, "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g=="],

"yallist": ["[email protected]", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],

"yocto-queue": ["[email protected]", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
Expand Down
69 changes: 69 additions & 0 deletions content/blog/future-plans.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
title: Future and current plans for our plugins
description: In this post we are discussing what plugins we are currently working on and what the plans for the future are
author: NonSwag
category: updates
keywords:
[
"minecraft plugins",
"plugin development",
"Portals plugin",
"Holograms plugin",
"PerWorlds plugin",
"minecraft server tools",
"plugin news",
"plugin roadmap",
"minecraft development"
]
---

# What are we currently working on?

## Portals

As some of you may already know, we started working on a new plugin called [Portals](https://github.com/TheNextLvl-net/portals).
The API already works but commands and actual functionality is yet to come.
Beta builds will probably arrive within the next couple of weeks, so stay tuned.

## Holograms

_Previously known as HologramAPI_

HologramAPI got a huge rebranding and is now called [Holograms](https://github.com/TheNextLvl-net/holograms).
Instead of just an API developers could use to create holograms,
it is now going to be a proper plugin, everyone can use and enjoy.

There already is an alpha build out, but only to supersede the discontinued HologramAPI.
The plugin still lacks all commands and interaction points from within the game,
but hopefully we are able to ship the first usable release this year.

## PerWorlds

A long requested feature is currently in the making: **Data import from other plugins.**
_(e.g. Multiverse-Inventories, MultiInv…)_

---

# Our future plans and ideas

## Broader version support

A big critique point we are often facing is about the game versions we support.
To make development and support easier for ourselves we generally only support the most recent game version.
But with Mojang dropping more and more updates in a shorter period of time, the amount of users we leave behind is growing with every new version.
From a user standpoint I can see how you are not always able to be on the most recent version, especially because of plugins that still want to support Spigot.

The idea now is to only support the last 3 most recent major versions of the game.
(At the time of writing 1.21.10 is the latest version, meaning 1.21.8 and 1.21.6 would also still be supported)

This comes with a few technical challenges and downsides, we might not be able to immediately support new features as they come out.
But on the other hand when a feature finally gets introduced it will be better tested, developed and more stable.

## Backwards compatibility

This is a tough topic for many developers…
Personally I always said that no backwards compatibility will ever be provided – BUT, I saw that a lot of users of our plugins are still on 1.21.4
(especially with the plugin Worlds)

Due to that we are planning on **TEMPORARILY** bringing back compatibility for that specific version.
This does not inherently mean you are always getting new features, **only bug fixes**.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"dependencies": {
"@icons-pack/react-simple-icons": "^13.7.0",
"@shikijs/types": "^3.11.0",
"feed": "^5.1.0",
"fumadocs-core": "15.8.5",
"fumadocs-mdx": "12.0.3",
"fumadocs-ui": "15.8.5",
Expand Down
Binary file added public/android-chrome-192x192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/android-chrome-512x512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/apple-touch-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/favicon-16x16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/favicon-32x32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/favicon.ico
Binary file not shown.
19 changes: 18 additions & 1 deletion source.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { defineConfig, defineDocs, frontmatterSchema, metaSchema } from "fumadocs-mdx/config"
import {
defineConfig,
defineDocs,
defineCollections,
frontmatterSchema,
metaSchema,
} from "fumadocs-mdx/config"
import { transformerCommandColor } from "./src/lib/command-transformer"
import { remarkMdxMermaid } from "fumadocs-core/mdx-plugins"
import { z } from "zod"

// You can customise Zod schemas for frontmatter and `meta.json` here
// see https://fumadocs.vercel.app/docs/mdx/collections#define-docs
Expand All @@ -13,6 +20,16 @@ export const docs = defineDocs({
},
})

export const blogPosts = defineCollections({
type: "doc",
dir: "content/blog",
schema: frontmatterSchema.extend({
author: z.string(),
category: z.enum(["devlog", "updates", "other"]),
keywords: z.string().array().optional(),
}),
})

export default defineConfig({
mdxOptions: {
rehypeCodeOptions: {
Expand Down
104 changes: 104 additions & 0 deletions src/app/(home)/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { lastEdit } from "@/lib/api"
import { blog } from "@/lib/source"
import { getMDXComponents } from "@/mdx-components"
import { PathUtils } from "fumadocs-core/source"
import type { Metadata } from "next"
import Link from "next/link"
import { notFound } from "next/navigation"

export async function generateMetadata({ params }: PageProps<"/blog/[slug]">): Promise<Metadata> {
const { slug } = await params
const page = blog.getPage([slug])

return {
title: page?.data.title,
description: page?.data.description,
keywords: page?.data.keywords,
}
}

export default async function Page(props: PageProps<"/blog/[slug]">) {
const params = await props.params
const page = blog.getPage([params.slug])
if (!page) notFound()
const { body: Mdx, toc } = page.data
return (
<>
<header className="border-b border-fd-border">
<div className="container mx-auto px-4 py-12 md:py-16">
<div className="mx-auto max-w-7xl">
<div className="grid gap-10 lg:grid-cols-[minmax(0,1fr)_280px]">
<div className="max-w-3xl">
<nav className="mb-6 text-sm text-fd-muted-foreground">
<Link className="hover:text-fd-foreground" href="/blog">
Blog
</Link>
<span className="mx-2">/</span>
<span className="text-fd-foreground">{page?.data.title}</span>
</nav>
<h1 className="text-4xl font-bold tracking-tight text-fd-foreground md:text-5xl">
{page?.data.title}
</h1>
{page?.data.description && (
<p className="mt-4 text-lg leading-relaxed text-fd-muted-foreground">
{page?.data.description}
</p>
)}
<div className="mt-6 flex flex-wrap items-center gap-4 text-sm text-fd-muted-foreground">
{page.data.author && (
<div className="flex items-center gap-2">
<span className="text-fd-muted-foreground">By</span>
<span className="font-medium text-fd-foreground">{page.data.author}</span>
</div>
)}
<div className="h-4 w-px bg-fd-muted-foreground" />
<time>
{new Date(
(await lastEdit(page)) ??
PathUtils.basename(page.path, PathUtils.extname(page.path)),
).toLocaleDateString("en-US", {
month: "long",
day: "numeric",
year: "numeric",
})}
</time>
</div>
</div>
</div>
</div>
</div>
</header>

<main className="container mx-auto px-4 py-10">
<div className="mx-auto max-w-7xl">
<div className="grid gap-10 lg:grid-cols-[minmax(0,1fr)_280px]">
<article className="prose prose-invert max-w-3xl">
<Mdx components={getMDXComponents()} />
</article>
{toc.length > 0 && (
<aside className="hidden lg:block">
<div className="sticky top-24 rounded-lg border border-fd-border p-4">
<h3 className="mb-3 text-xs font-semibold uppercase tracking-wider text-fd-secondary-foreground">
On This Page
</h3>
<nav className="space-y-1">
{toc.map((item) => (
<Link
key={item.url}
href={item.url}
className="block rounded-md py-1.5 text-sm text-fd-muted-foreground hover:text-fd-foreground"
style={{ paddingLeft: `${(item.depth - 1) * 12}px` }}
>
{item.title}
</Link>
))}
</nav>
</div>
</aside>
)}
</div>
</div>
</main>
</>
)
}
46 changes: 46 additions & 0 deletions src/app/(home)/blog/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"use server"

import { blog } from "@/lib/source"
import { PathUtils } from "fumadocs-core/source"
import { BlogSidebar } from "@/components/blog/blog-sidebar"
import { lastEdit } from "@/lib/api"

function getName(path: string) {
return PathUtils.basename(path, PathUtils.extname(path))
}

export default async function Blog() {
const pages = blog.getPages()

const postsWithDates = await Promise.all(
pages.map(async (page) => ({
page,
lastEditDate: await lastEdit(page),
})),
)

const posts = postsWithDates.sort(
(a, b) =>
new Date(b.lastEditDate ?? getName(b.page.path)).getTime() -
new Date(a.lastEditDate ?? getName(a.page.path)).getTime(),
)

const serializablePosts = await Promise.all(
posts.map(async (p) => ({
path: p.page.path,
data: {
title: p.page.data.title,
description: p.page.data.description,
category: p.page.data.category,
url: p.page.url,
date: p.lastEditDate,
},
})),
)

return (
<>
<BlogSidebar posts={serializablePosts} />
</>
)
}
9 changes: 8 additions & 1 deletion src/app/(home)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,24 @@ import type { ReactNode } from "react"
import { HomeLayout } from "fumadocs-ui/layouts/home"
import { baseOptions } from "@/app/layout.config"
import { SiDiscord } from "@icons-pack/react-simple-icons"
import { RssIcon } from "lucide-react"

export default function Layout({ children }: { children: ReactNode }) {
return (
<HomeLayout
{...baseOptions}
links={[
{
type: "icon",
icon: <RssIcon />,
text: "Blog",
url: "/blog",
},
{
type: "icon",
icon: <SiDiscord />,
text: "Discord",
url: "https://thenextlvl.net/discord",
url: "/discord",
},
]}
>
Expand Down
8 changes: 8 additions & 0 deletions src/app/layout.config.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { BaseLayoutProps } from "fumadocs-ui/layouts/shared"
import Image from "next/image"
import { SiDiscord } from "@icons-pack/react-simple-icons"
import { RssIcon } from "lucide-react"
/**
* Shared layout configurations
*
Expand All @@ -18,6 +19,13 @@ export const baseOptions: BaseLayoutProps = {
),
},
links: [
{
type: "icon",
label: "Blog",
icon: <RssIcon />,
text: "Blog",
url: "/blog",
},
{
type: "icon",
label: "Discord",
Expand Down
9 changes: 8 additions & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@ export const metadata: Metadata = {
description:
"TheNextLvl is a community-driven Minecraft server that provides a safe and fun environment for players of all ages.",
icons: {
icon: "/favicon.ico",
icon: [
{ url: "/favicon.ico" },
{ url: "/favicon-16x16.png", sizes: "16x16" },
{ url: "/favicon-32x32.png", sizes: "32x32" },
{ url: "/android-chrome-192x192.png", sizes: "192x192" },
{ url: "/android-chrome-512x512.png", sizes: "512x512" },
],
apple: [{ url: "/apple-touch-icon.png" }],
},
}

Expand Down
7 changes: 7 additions & 0 deletions src/app/rss.xml/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { getRSS } from "@/lib/rss"

export const revalidate = false

export async function GET() {
return new Response(await getRSS())
}
Loading