Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

> Manage and observe Apache Kafka clusters from a single Go binary — topics, messages, consumer groups, schemas and ACLs in one web UI.

**Status:** Pre-alpha (v0.0.x). APIs and on-disk formats may change without notice.
**Status:** Stable — v1.0, in production use.

kafkito is a free, open-source web UI for managing and observing Apache Kafka clusters — built in Go as a single binary, with a modern React frontend, Apache 2.0. It's an independent rewrite inspired by [`provectus/kafka-ui`](https://github.com/provectus/kafka-ui) (unmaintained since 2024); for a community-maintained continuation of the original Java codebase, see [`kafbat/kafka-ui`](https://github.com/kafbat/kafka-ui).

Expand Down
8 changes: 4 additions & 4 deletions frontend/src/components/whats-new-button.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,21 @@ describe("WhatsNewButton", () => {
beforeEach(() => {
window.localStorage.clear();
fetchInfo.mockReset();
fetchInfo.mockResolvedValue({ name: "kafkito", version: "0.0.0-rc17-btp" });
fetchInfo.mockResolvedValue({ name: "kafkito", version: "1.0.0-btp" });
});

it("auto-opens once for an unseen version and marks it seen", async () => {
renderButton();
expect(await screen.findByText("What's new")).toBeInTheDocument();
await waitFor(() =>
expect(window.localStorage.getItem("kafkito.whatsnew.lastSeen.v1")).toBe(
"0.0.0-rc17",
"1.0.0",
),
);
});

it("does not auto-open and shows no dot once the version is seen", async () => {
window.localStorage.setItem("kafkito.whatsnew.lastSeen.v1", "0.0.0-rc17");
window.localStorage.setItem("kafkito.whatsnew.lastSeen.v1", "1.0.0");
renderButton();
await screen.findByRole("button", { name: /what's new/i });
expect(screen.queryByText("What's new")).not.toBeInTheDocument();
Expand All @@ -51,7 +51,7 @@ describe("WhatsNewButton", () => {
});

it("opens on click", async () => {
window.localStorage.setItem("kafkito.whatsnew.lastSeen.v1", "0.0.0-rc17");
window.localStorage.setItem("kafkito.whatsnew.lastSeen.v1", "1.0.0");
const user = userEvent.setup();
renderButton();
await user.click(screen.getByRole("button", { name: /what's new/i }));
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/whats-new-modal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { WhatsNewModal } from "./whats-new-modal";

describe("WhatsNewModal", () => {
it("renders the title and the latest entry's items with type badges", () => {
render(<WhatsNewModal currentVersion="0.0.0-rc17-btp" onClose={vi.fn()} />);
render(<WhatsNewModal currentVersion="1.0.0-btp" onClose={vi.fn()} />);
expect(screen.getByText("What's new")).toBeInTheDocument();
expect(
screen.getByText(/create consumer groups bound to a topic/i),
Expand Down
10 changes: 5 additions & 5 deletions frontend/src/components/whats-new-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,22 @@ function EntryBlock({
<span className="text-xs text-subtle-text">{entry.date}</span>
</button>
{open && (
<ul className="mt-2 space-y-2">
<ul className="mt-2 grid grid-cols-[auto_1fr] items-start gap-x-3 gap-y-2 text-sm">
{entry.items.map((it, i) => (
<li key={i} className="flex gap-2 text-sm">
<li key={i} className="contents">
<span
className={`mt-0.5 h-fit rounded px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wider ${BADGE[it.type].cls}`}
className={`mt-0.5 justify-self-start rounded px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wider ${BADGE[it.type].cls}`}
>
{BADGE[it.type].label}
</span>
<span>
<div>
<span className="font-medium text-text">{it.title}</span>
{it.description ? (
<span className="mt-0.5 block text-muted">
{it.description}
</span>
) : null}
</span>
</div>
</li>
))}
</ul>
Expand Down
10 changes: 8 additions & 2 deletions frontend/src/content/changelog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,20 @@ export interface ChangelogEntry {
*/
export const CHANGELOG: ChangelogEntry[] = [
{
version: "0.0.0-rc17",
version: "1.0.0",
date: "2026-07-09",
items: [
{
type: "feature",
title: "kafkito 1.0.0 — first stable release",
description:
"kafkito is now used in production. This is the first stable release; versions from here follow semantic versioning.",
},
{
type: "feature",
title: "Create consumer groups bound to a topic",
description:
"Pre-create a consumer group on a topic with a chosen start position (earliest, latest, timestamp, or a specific offset), with a dry-run preview before committing.",
"Pre-create a consumer group on a topic with a chosen start position (earliest, latest, timestamp, or a specific offset).",
},
{
type: "security",
Expand Down
Loading