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
6 changes: 4 additions & 2 deletions app/api/github/releases/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,10 @@ export async function GET(request: Request) {
const { searchParams } = new URL(request.url)
const repo = searchParams.get('repo') // Optional: filter by specific repo

const token = await getGithubToken()
const repositories = await getConfiguredRepositories()
const [token, repositories] = await Promise.all([
getGithubToken(),
getConfiguredRepositories(),
])

try {
const reposToFetch = repo
Expand Down
1 change: 0 additions & 1 deletion app/games/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { OG_CONFIGS, OG_CONTENT_TYPE, OG_SIZE, makeOGImage } from '../_og/image-generator'

export const runtime = 'edge'
export const alt = 'NodeByte Game Server Hosting — Minecraft, Rust, Hytale & more'
export const size = OG_SIZE
export const contentType = OG_CONTENT_TYPE
Expand Down
3 changes: 2 additions & 1 deletion app/games/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export default async function GamesPage() {
src={game.banner}
alt={game.name}
fill
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
className="object-cover transition-transform duration-300 group-hover:scale-105"
/>
<div className="absolute inset-0 bg-linear-to-t from-card to-transparent" />
Expand Down Expand Up @@ -124,7 +125,7 @@ export default async function GamesPage() {
{/* Features */}
<ul className="space-y-2 mb-6 flex-1">
{game.features.map((feature, i) => (
<li key={i} className="flex items-center gap-2 text-sm text-muted-foreground">
<li key={feature} className="flex items-center gap-2 text-sm text-muted-foreground">
<Check className="w-4 h-4 text-primary shrink-0" />
{feature}
</li>
Expand Down
1 change: 0 additions & 1 deletion app/games/twitter-image.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { OG_CONFIGS, OG_CONTENT_TYPE, OG_SIZE, makeOGImage } from '../_og/image-generator'

export const runtime = 'edge'
export const alt = 'NodeByte Game Server Hosting — Minecraft, Rust, Hytale & more'
export const size = OG_SIZE
export const contentType = OG_CONTENT_TYPE
Expand Down
12 changes: 7 additions & 5 deletions app/kb/[category]/[article]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,19 @@ export async function generateStaticParams() {
}

export default async function ArticlePage({ params }: ArticlePageProps) {
const t = await getTranslations();
const { category, article } = await params;
const articleData = await getArticle(category, article);
const [t, articleData, categories, articlesInCategory] = await Promise.all([
getTranslations(),
getArticle(category, article),
getCategories(),
getArticlesByCategory(category),
]);

if (!articleData) {
notFound();
}

const categories = await getCategories();
const categoryData = categories.find((c) => c.slug === category);
const articlesInCategory = await getArticlesByCategory(category);

// Prepare sidebar data
const sidebarCategories: SidebarCategory[] = await Promise.all(
Expand All @@ -82,7 +84,7 @@ export default async function ArticlePage({ params }: ArticlePageProps) {
const headings = extractHeadings(articleData.content);

// Find adjacent articles for navigation
const sortedArticles = [...articlesInCategory].sort((a, b) => a.order - b.order);
const sortedArticles = articlesInCategory.toSorted((a, b) => a.order - b.order);
const currentIndex = sortedArticles.findIndex((a) => a.slug === article);
const previousArticle =
currentIndex > 0
Expand Down
16 changes: 10 additions & 6 deletions app/kb/[category]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,11 @@ interface CategoryPageProps {
export async function generateMetadata({
params,
}: CategoryPageProps): Promise<Metadata> {
const { category } = await params;
const categories = await getCategories();
const [{ category }, categories] = await Promise.all([
params,
getCategories(),
]);

const categoryData = categories.find((c) => c.slug === category);

if (!categoryData) {
Expand All @@ -60,16 +63,17 @@ export async function generateStaticParams() {
}

export default async function CategoryPage({ params }: CategoryPageProps) {
const t = await getTranslations();
const { category } = await params;
const categories = await getCategories();
const [t, categories, articles] = await Promise.all([
getTranslations(),
getCategories(),
getArticlesByCategory(category),
]);
const categoryData = categories.find((c) => c.slug === category);

if (!categoryData) {
notFound();
}

const articles = await getArticlesByCategory(category);
const Icon = iconMap[categoryData.icon] || HelpCircle;

return (
Expand Down
12 changes: 7 additions & 5 deletions app/kb/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ export async function generateMetadata(): Promise<Metadata> {
}

export default async function KnowledgeBasePage() {
const t = await getTranslations();
const categories = await getCategories();
const allArticles = await getAllArticles();
const [t, categories, allArticles] = await Promise.all([
getTranslations(),
getCategories(),
getAllArticles(),
]);

// Get recent articles (last 5 by date)
const recentArticles = [...allArticles]
.sort((a, b) => {
const recentArticles = allArticles
.toSorted((a, b) => {
const dateA = new Date(a.lastUpdated || 0).getTime();
const dateB = new Date(b.lastUpdated || 0).getTime();
return dateB - dateA;
Expand Down
16 changes: 10 additions & 6 deletions app/maintenance/page.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
"use client"

import { useTranslations } from "next-intl"
import { getTranslations } from "next-intl/server"
import { Metadata } from "next"
import { AlertCircle, Wrench, Mail, MessageCircle } from "lucide-react"
import { Button } from "@/packages/ui/components/ui/button"
import { Card } from "@/packages/ui/components/ui/card"
import { Logo } from "@/packages/ui/components/logo"
import Link from "next/link"
import { LINKS } from "@/packages/core/constants/links"

export default function MaintenancePage() {
const t = useTranslations("admin")
export const metadata: Metadata = {
title: "Maintenance",
description: "We are currently performing scheduled maintenance.",
}

export default async function MaintenancePage() {
const t = await getTranslations("admin")

return (
<main className="min-h-screen flex items-center justify-center px-4 py-32 relative overflow-hidden">
Expand All @@ -32,7 +36,7 @@ export default function MaintenancePage() {
<div className="flex justify-center mb-6">
<div className="relative">
<div className="absolute inset-0 bg-primary/30 blur-2xl rounded-full"></div>
<Wrench className="h-24 w-24 text-primary relative z-10 animate-bounce" />
<Wrench className="h-24 w-24 text-primary relative z-10 motion-safe:animate-pulse" />
</div>
</div>
</div>
Expand Down
1 change: 0 additions & 1 deletion app/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { OG_CONFIGS, OG_CONTENT_TYPE, OG_SIZE, makeOGImage } from './_og/image-generator'

export const runtime = 'edge'
export const alt = 'NodeByte Hosting — Game Servers & VPS'
export const size = OG_SIZE
export const contentType = OG_CONTENT_TYPE
Expand Down
6 changes: 6 additions & 0 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { Metadata } from "next"
import { Hero } from "@/packages/ui/components/Layouts/Home/hero"
import { Features } from "@/packages/ui/components/Layouts/Home/features"
import { About } from "@/packages/ui/components/Layouts/Home/about"
import { Services } from "@/packages/ui/components/Layouts/Home/services"
import { FAQ } from "@/packages/ui/components/Layouts/Home/faq"
import { ScrollToHash } from "@/packages/ui/components/scroll-to-hash"

export const metadata: Metadata = {
title: "Home",
description: "Fast, reliable, and secure hosting for game servers and VPS. Instant deployment, enterprise DDoS protection, NVMe SSD storage, and 24/7 expert support.",
}

export default function Home() {
return (
<>
Expand Down
1 change: 0 additions & 1 deletion app/twitter-image.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { OG_CONFIGS, OG_CONTENT_TYPE, OG_SIZE, makeOGImage } from './_og/image-generator'

export const runtime = 'edge'
export const alt = 'NodeByte Hosting — Game Servers & VPS'
export const size = OG_SIZE
export const contentType = OG_CONTENT_TYPE
Expand Down
1 change: 0 additions & 1 deletion app/vps/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { OG_CONFIGS, OG_CONTENT_TYPE, OG_SIZE, makeOGImage } from '../_og/image-generator'

export const runtime = 'edge'
export const alt = 'NodeByte VPS Hosting — AMD & Intel KVM VPS'
export const size = OG_SIZE
export const contentType = OG_CONTENT_TYPE
Expand Down
1 change: 0 additions & 1 deletion app/vps/twitter-image.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { OG_CONFIGS, OG_CONTENT_TYPE, OG_SIZE, makeOGImage } from '../_og/image-generator'

export const runtime = 'edge'
export const alt = 'NodeByte VPS Hosting — AMD & Intel KVM VPS'
export const size = OG_SIZE
export const contentType = OG_CONTENT_TYPE
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"postinstall": "git submodule update --init --recursive --remote",
"translate": "bun run scripts/translate.ts",
"translate:force": "bun run scripts/translate.ts --force",
"translate:dry": "bun run scripts/translate.ts --dry-run"
"translate:dry": "bun run scripts/translate.ts --dry-run",
"doctor": "npx react-doctor@latest"
},
"dependencies": {
"@hookform/resolvers": "^3.10.0",
Expand Down
13 changes: 4 additions & 9 deletions packages/changelog/components/changelog-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,23 +56,17 @@ const TYPE_LABELS: Record<string, string> = {

export function ChangelogCard({ release, translations, isLatest, isLinked, className }: ChangelogCardProps) {
const [showAssets, setShowAssets] = useState(false)
const [expanded, setExpanded] = useState(isLinked ?? false)
const [linkCopied, setLinkCopied] = useState(false)
const [userExpanded, setUserExpanded] = useState(false)

const summary = extractSummary(release.body)
const hasLongBody = (release.body?.length || 0) > 300
const typeColor = TYPE_COLORS[release.type || 'improvement']
const publishedDate = new Date(release.published_at || release.created_at)

// Create a unique anchor ID for this release
const anchorId = `${release.repository.name}-${release.tag_name}`

// Expand when linked to directly
useEffect(() => {
if (isLinked) {
setExpanded(true)
}
}, [isLinked])
const expanded = userExpanded || (isLinked ?? false)

const handleCopyLink = async () => {
const url = `${window.location.origin}${window.location.pathname}#${anchorId}`
Expand Down Expand Up @@ -111,6 +105,7 @@ export function ChangelogCard({ release, translations, isLatest, isLinked, class
<Tooltip>
<TooltipTrigger asChild>
<button
type="button"
onClick={handleCopyLink}
className="flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground transition-colors"
>
Expand Down Expand Up @@ -217,7 +212,7 @@ export function ChangelogCard({ release, translations, isLatest, isLinked, class
<Button
variant="ghost"
size="sm"
onClick={() => setExpanded(!expanded)}
onClick={() => setUserExpanded((v) => !v)}
className="mt-2 h-7 px-2 text-xs"
>
{expanded ? (
Expand Down
Loading