9.2 KiB
Contributing to Unyo Website
Thanks for your interest in contributing! This guide covers how the project works, how to set up your environment, and how to make changes.
How the Project Works
Architecture
The site is a Docusaurus 3 application — a React-based static site generator. It produces two types of pages:
- Landing page (
/) — a custom React page atwebsite/src/pages/index.jswith hand-written components (Hero, FeatureGrid, ScreenshotGallery) and a custom footer - Documentation pages (
/docs/*) — Markdown files inwebsite/docs/rendered by Docusaurus with a sidebar
Docusaurus provides:
- The navbar (top bar with logo, "Docs" link, "GitHub" link)
- The docs sidebar and previous/next navigation
- Markdown rendering with MDX support
- Static site generation via
npm run build
The theme is forced dark mode (no toggle). All color customization lives in website/src/css/custom.css.
Build Pipeline
Markdown (.md) + React components (.js)
↓
Docusaurus (Webpack 5)
↓
Static HTML/CSS/JS (website/build/)
↓
Docker (Node 20 build → Nginx Alpine serve)
↓
Production (port 80)
Key Files
| File | What it controls |
|---|---|
website/docusaurus.config.js |
Site metadata, navbar, theme config, presets |
website/sidebars.js |
Documentation sidebar order |
website/src/css/custom.css |
All theme colors and global styles |
website/src/pages/index.js |
Landing page composition |
website/src/components/*/ |
React components for the landing page |
website/docs/*.md |
Documentation content |
CSS Architecture
There are two layers of styling:
-
Infima — Docusaurus's base CSS framework (ships with
@docusaurus/preset-classic). Defines variables like--ifm-background-color,--ifm-color-primary, etc. under:rootandhtml[data-theme=dark]. -
custom.css — our overrides. Defines Unyo variables (
--unyo-*) and overrides Infima variables (--ifm-*).
Important: Dark mode overrides must be in html[data-theme=dark] to match Infima's specificity. Rules in :root will be overridden by Infima's html[data-theme=dark] block since that selector has higher specificity than :root.
Component styles use CSS Modules (.module.css files) for scoped class names — no global pollution.
Landing Page vs Docs
- The landing page does not use the Docusaurus footer. It has its own
<footer>element inindex.jsstyled byindex.module.css. The Docusaurus footer is disabled by removingfooterfromthemeConfigindocusaurus.config.js. - The docs pages use the Docusaurus sidebar, breadcrumbs, and pagination — styled by the global
custom.css.
Setup
# Clone the repo
git clone https://github.com/K3vinb5/Unyo.git
cd unyo-page/website
# Install dependencies
npm install
# Start dev server
npm start
The dev server runs at http://localhost:3000 with hot reloading.
Adding New Documentation
Step-by-step
1. Create the Markdown file
Add a new .md file in website/docs/:
touch website/docs/my-topic.md
2. Add frontmatter
Every doc file must have a title in its YAML frontmatter. Optionally add slug to customize the URL:
---
title: My Topic
slug: /custom-url
---
# My Topic
Your content here...
Without a slug, the URL will be /docs/my-topic (derived from the filename).
3. Add to the sidebar
Open website/sidebars.js and add the filename (without .md) in the position you want it to appear:
const sidebars = {
docs: [
'intro',
'installation',
'getting-started',
'extensions',
'my-topic', // <-- add here
],
};
The order in this array determines:
- The sidebar navigation order
- The "Previous" / "Next" links at the bottom of each doc page
4. Create content
Docusaurus supports standard Markdown plus MDX (Markdown with JSX). Some features:
Admonitions (callouts):
:::tip
Helpful tip here
:::
:::info
Informational note
:::
:::caution
Warning about potential issues
:::
Code blocks with syntax highlighting:
```bash
npm install
```
Tables:
| Column 1 | Column 2 |
|----------|----------|
| Value 1 | Value 2 |
Internal links — use relative paths within docs:
See the [installation guide](./installation) for setup instructions.
External links — use full URLs:
Check the [Unyo repo](https://github.com/K3vinb5/Unyo) for source code.
Images — place in website/static/img/ and reference with absolute paths:

5. Verify
cd website
npm start
# Navigate to http://localhost:3000/docs/my-topic
Modifying the Landing Page
Hero Section
Files: website/src/components/Hero/index.js and styles.module.css
- Mascot image:
website/static/img/mascot.png - CTA buttons: "Get Started" links to
/docs, "GitHub" links to the repo - Animations: CSS keyframes for fade-in, slide-up, floating mascot
Feature Grid
Files: website/src/components/FeatureGrid/index.js and styles.module.css
- Features are defined as a JS array of objects (
title,description,icon) - Icons are inline SVGs — edit them directly in the component
- Cards use staggered animation on intersection (CSS
animation-delay)
Screenshot Gallery
Files: website/src/components/ScreenshotGallery/index.js and styles.module.css
- Screenshots array is defined in the component
- Add/remove by editing the
screenshotsarray - The center slide scales to full size (
scale(1)) while side slides are dimmed (0.88scale,0.65opacity) - Clicking opens a lightbox
Custom Footer
The landing page footer is defined directly in website/src/pages/index.js (not using Docusaurus's footer system). Styles are in website/src/pages/index.module.css.
Modifying the Theme
All color changes go in website/src/css/custom.css. The file is organized into sections:
- CSS Variables (
:rootandhtml[data-theme=dark]) — all color definitions - Global styles —
html,body,::selection - Navbar —
.navbar,.navbar__title,.navbar__link - Sidebar —
.theme-doc-sidebar-container,.menu__link - Docs pages —
.theme-doc-markdown(headings, links, code, tables, blockquotes) - Breadcrumb —
.breadcrumbs__link - Pagination —
.pagination-nav__link - Search —
.DocSearch-Button - Mobile menu —
.menu--show
Adding a New Color Variable
-
Add it to
:rootwith the--unyo-prefix::root { --unyo-new-color: #ff6600; } -
Use it anywhere:
.my-element { color: var(--unyo-new-color); }
Overriding an Infima Variable
Infima variables must be overridden in the html[data-theme=dark] block — not in :root. This is because Infima defines its dark theme under html[data-theme=dark], which has higher specificity than :root.
html[data-theme=dark] {
--ifm-background-color: #0d0a1a; /* overrides Infima's #1b1b1d */
}
Building and Deploying
Local Build
cd website
npm run build
The static site is output to website/build/.
Docker Build
docker compose up --build
This runs the full multi-stage build:
- Node 20 Alpine installs deps and builds the Docusaurus site
- Nginx Alpine serves the static files
The container exposes port 80 by default.
Changing the Domain
Edit website/docusaurus.config.js:
url: 'https://your-domain.com',
Then rebuild.
Common Tasks
| Task | How |
|---|---|
| Add a new doc page | Create .md file in website/docs/, add to sidebars.js |
| Reorder docs sidebar | Edit the array in website/sidebars.js |
| Change navbar items | Edit themeConfig.navbar in docusaurus.config.js |
| Change theme colors | Edit variables in website/src/css/custom.css |
| Add a screenshot | Put image in website/static/img/, reference as /img/filename.png |
| Update the mascot | Replace website/static/img/mascot.png |
| Update the logo | Replace website/static/img/logo.png (also referenced in docusaurus.config.js) |
| Run dev server | cd website && npm start |
| Production build | cd website && npm run build |
| Docker deploy | docker compose up -d --build |
Gotchas
- Webpack compatibility: The project pins
webpack@^5.99.0inpackage.jsonbecause newer versions (5.106+) break Docusaurus's webpackbar ProgressPlugin. Do not upgrade webpack without testing the build. - Dark mode only: The
colorMode.disableSwitch: trueconfig removes the theme toggle. All CSS variables must work in dark mode. - Footer is disabled: The Docusaurus default footer (
themeConfig.footer) is intentionally removed. The landing page has its own footer. If you want a footer on docs pages, addfooterback tothemeConfigand style it incustom.css. html[data-theme=dark]specificity: Infima dark theme overrides must go underhtml[data-theme=dark]incustom.css, not:root. Otherwise Infima's dark variables will win.slug: /on intro.md: The intro doc usesslug: /which makes it accessible at/docs/instead of/docs/intro. Links to it should use/docsnot/docs/intro.