Gryt

Overview

The gryt.chat marketing site and blog — Vite, React, and MDX

The Gryt site (packages/site) is the public-facing website at gryt.chat. It serves the landing page, feature overview, and blog.

Stack

  • Vite for bundling and dev server
  • React 19 with React Router for SPA routing
  • MDX for blog posts (via @mdx-js/rollup with remark plugins)
  • Radix UI for accessible primitives (Dialog, Navigation Menu, Tooltip)
  • CSS Modules for scoped styling with CSS custom properties

Project structure

site/
├── content/
│   ├── blog/           # MDX blog posts
│   └── changelog/      # MDX release notes, one file per version
├── public/             # Static assets (images, videos, logo)
├── scripts/            # Image optimisation, prerendering, meta checks
├── src/
│   ├── components/     # Navbar, Footer, Hero, Download, Lightbox, etc.
│   ├── lib/
│   │   ├── blog.ts     # Blog loader (Vite glob import)
│   │   ├── changelog.ts
│   │   └── title.ts
│   ├── pages/          # Route components
│   ├── styles/
│   ├── App.tsx         # The route table
│   └── index.css       # Global styles and CSS variables
└── vite.config.ts

Routes

PathPage
/The landing page, including the download section
/why-grytThe longer argument
/blog, /blog/:slugBlog index and posts
/changelog, /changelog/:versionRelease notes, one MDX file per version
/privacy, /terms, /community-guidelinesThe policy pages. Each also answers a longer alias, /privacy-policy, /terms-of-use and /guidelines
/inviteWhere an invite link lands
/auth/callbackThe OIDC redirect target
*Not found

Getting started

cd packages/site
npm install
npm run dev

Open http://localhost:5173.

Build

npm run build     # production bundle → dist/
npm run preview   # preview the production build locally

build is more than a bundle. In order it typechecks with tsc -b, optimises images, runs the Vite build, prerenders the blog and changelog so each post has real HTML for crawlers and link unfurls, and finishes with check-meta, which fails the build if any page is missing a title suffix, an og:image or a consistent canonical.

On this page