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
32 changes: 32 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,38 @@ All notable changes to the NodeByte Hosting website will be documented in this f
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [3.8.0] - 2026-07-20

### Added

- **Object Storage Hosting** — new `/object-storage` product category backed by live Paymenter billing data, following the same hub pattern as VPS/Dedicated
- `packages/core/types/servers/object-storage.ts` — `ObjectStoragePlanSpec` interface (storage limit, access keys, egress, API requests, auto-archive policy, feature bullets)
- `packages/core/lib/spec-parser.ts` — `parseObjectStorageSpecs()`, a label/value bullet parser distinct from the CPU/RAM-oriented `parseDescriptionSpecs()` used by Game/VPS/Dedicated
- `packages/core/products/billing-service.ts` — `getObjectStoragePlans(categorySlug)`
- `packages/ui/components/Layouts/ObjectStorage/object-storage-hub.tsx` — search/sort/filter listing with storage, access key, egress, and archive policy rows
- `packages/core/constants/catalog-hubs.ts` — `OBJECT_STORAGE_HUB_SLUGS`
- Navigation, footer, sitemap, and homepage service cards all updated to include Object Storage alongside Game/VPS/Dedicated
- **Status page migrated to our own status platform** — the site's live status integration (`/nodes`, footer status badge) now reads from our self-hosted status API (`nodebytestat.us/api/status`) instead of the previous third-party-hosted status page, with no auth required
- `packages/core/lib/status.ts` — rewritten around the new API's `ComponentStatus`/`Indicator` shape; node discovery now walks the API's recursive `groups` tree instead of a hardcoded monitor map
- `packages/core/constants/status-mapping.ts` — `NODE_DISPLAY_OVERRIDES` / `LOCATION_MONITOR_MAP` keep location metadata the new API doesn't carry
- **Brand & Press Kit page** (`/brand`) — logo downloads (SVG/PNG) with usage guidelines, the full color palette across all 47 themes (click-to-copy hex values), typography specimen, and official name/voice reference for partners, advertisers, and press
- Downloadable background template (`/brand/background`) reusing the site's existing OG-image generator (`app/_og/image-generator.tsx`) so the template always matches our real social preview cards
- **Footer reorganized** — Services now lists every live product (including Object Storage and Network & Nodes); Resources gained a genuine System Status link (previously only a small badge); Company gained the new Brand & Press page; the old link mislabeled "System Status" that actually pointed at the network looking-glass tool was corrected

### Changed

- Homepage service cards switched from a cramped 4-column grid back to 3 columns, giving each card more room to breathe
- VPS/Dedicated/Object Storage "no results" empty states now distinguish "nothing in stock" (destructive styling, no Clear Filters button) from "your filters excluded everything" (neutral styling, Clear Filters button) — previously both cases showed the same generic "no matches" message even when a category was genuinely empty

### Fixed

- **Plan count duplication** — VPS, Dedicated, and Object Storage were double-counting the hub category against itself (`getCategoryHub()` already includes the hub as a leaf inside `hub.children`; page-level code was additionally prepending `hub.slug`), showing e.g. "8 of 8 plans" for 4 real products. Fixed across all three hub pages and the homepage's live starting-price resolver
- **Object Storage plan sizes displaying as long floats** (e.g. "1.953125 TB") — the display formatter divided by 1024 against plan sizes that were defined in round decimal GB (2000 GB, 2500 GB); switched to a 1000-based conversion so these render as clean "2 TB" / "2.5 TB"
- **Mobile nav "Company" section cut off items** — its expand animation was capped at a fixed `max-h-[300px]`, too short for 5 menu items; raised to match the other sections
- VPS hub category discovery — `VPS_HUB_SLUGS` didn't include the live Paymenter category's actual slug (`vps-servers`), so `/vps` rendered empty despite correctly configured billing data

---

## [3.7.0] - 2026-07-13

### Added
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@nodebyte/hosting-site",
"description": "The official website for NodeByte Hosting.",
"license": "AGPL-3.0-only",
"version": "3.7.0",
"version": "3.8.0",
"scripts": {
"build": "next build",
"dev": "next dev",
Expand Down
5 changes: 5 additions & 0 deletions packages/ui/components/Layouts/About/about-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ export function AboutPage() {
title: t("aboutPage.timeline.vpsLaunch.title"),
description: t("aboutPage.timeline.vpsLaunch.description"),
},
{
year: "Q3/4 - 2026",
title: t("aboutPage.timeline.dedicatedAndStorage.title"),
description: t("aboutPage.timeline.dedicatedAndStorage.description"),
},
]

return (
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/components/Static/navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ export function Navigation() {
</button>
<div className={cn(
"overflow-hidden transition-all duration-300 ease-out",
mobileCompanyOpen ? "max-h-[300px] opacity-100" : "max-h-0 opacity-0"
mobileCompanyOpen ? "max-h-[400px] opacity-100" : "max-h-0 opacity-0"
)}>
<div className="pl-2 pr-1 py-2 space-y-1">
{company.map((item) => (
Expand Down Expand Up @@ -554,7 +554,7 @@ export function Navigation() {
</button>
<div className={cn(
"overflow-hidden transition-all duration-300 ease-out",
mobileServicesOpen ? "max-h-[300px] opacity-100" : "max-h-0 opacity-0"
mobileServicesOpen ? "max-h-[400px] opacity-100" : "max-h-0 opacity-0"
)}>
<div className="pl-2 pr-1 py-2 space-y-1">
{services.map((service) => (
Expand Down