@x-wave/blog 1.1.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,285 +1,54 @@
1
- # @x-wave/blog
1
+ # Staking Docs
2
2
 
3
- A responsive, multi-language documentation framework for React + Vite applications. Ships with TypeScript, i18n (i18next), MDX support, dark mode, and built-in navigation.
3
+ Multi-language documentation site built with Next.js App Router and MDX. This repo contains both the framework packages and a reference app used for local development and previews.
4
4
 
5
- ## Features
5
+ ## Repository structure
6
6
 
7
- - **Multi-language support**: Ship 3+ languages with a single codebase (en, es, zh included)
8
- - **MDX content**: Write docs in Markdown with React components
9
- - **Dark mode**: Built-in light/dark/system theme toggle with localStorage persistence
10
- - **Advanced mode**: Optional Simple/Advanced content variants for the same page
11
- - **Mobile responsive**: Automatic sidebar → mobile menu on small screens
12
- - **Headless**: No styling opinions—includes SCSS variables for full customization
13
- - **HMR-friendly**: Vite development with Hot Module Replacement for instant feedback
14
-
15
- ## Installation
16
-
17
- ### npm
18
-
19
- ```bash
20
- npm install @x-wave/blog
21
- ```
22
-
23
- ### pnpm
24
-
25
- ```bash
26
- pnpm add @x-wave/blog
27
- ```
28
-
29
- ### yarn
30
-
31
- ```bash
32
- yarn add @x-wave/blog
33
- ```
34
-
35
- ## Quick setup
36
-
37
- ### 1. Create your app structure
38
-
39
- ```
40
- src/
41
- ├── App.tsx # Your app component
42
- ├── main.tsx # Entry point
43
- ├── navigation.ts # Site navigation definition
44
- ├── utils.ts # Content loaders
45
- ├── logo.svg # Optional: your logo
46
- └── docs/
47
- ├── en/
48
- │ ├── welcome.mdx
49
- │ ├── glossary.mdx
50
- │ └── faq.mdx
51
- ├── es/
52
- │ ├── welcome.mdx
53
- │ ├── glossary.mdx
54
- │ └── faq.mdx
55
- └── zh/
56
- ├── welcome.mdx
57
- ├── glossary.mdx
58
- └── faq.mdx
59
- ```
60
-
61
- ### 2. Set up i18n and styles
62
-
63
- Import the i18n setup and framework styles in your app entry point:
64
-
65
- ```ts
66
- // src/main.tsx
67
- import '@x-wave/blog/locales' // Initialises i18next with en, es, zh
68
- import '@x-wave/blog/styles' // Compiled CSS with variables and component styles (required)
69
- import { createRoot } from 'react-dom/client'
70
- import App from './App'
71
-
72
- createRoot(document.getElementById('root')!).render(<App />)
73
- ```
74
-
75
- > **The styles import is required** for the UI components and layout to render correctly. This imports a single compiled CSS file (`index.css`) that contains all framework styles, CSS variables, and component styles.
76
-
77
- **Add custom translations:**
78
-
79
- ```ts
80
- // src/main.tsx
81
- import '@x-wave/blog/locales'
82
- import i18next from 'i18next'
83
-
84
- // Add French translations
85
- i18next.addResourceBundle('fr', 'translation', {
86
- language: 'Français',
87
- 'ui.simple': 'Simple',
88
- 'ui.advanced': 'Avancé',
89
- // ... other keys
90
- })
91
7
  ```
92
-
93
- ### 3. Define your navigation
94
-
95
- ```ts
96
- // src/navigation.ts
97
- import type { NavigationEntry } from '@x-wave/blog/types'
98
-
99
- export const NAVIGATION_DATA: NavigationEntry[] = [
100
- {
101
- title: 'docs.welcome',
102
- slug: 'welcome',
103
- },
104
- {
105
- title: 'Help',
106
- defaultOpen: true,
107
- items: [
108
- {
109
- title: 'docs.glossary',
110
- slug: 'glossary',
111
- showTableOfContents: true,
112
- },
113
- {
114
- title: 'docs.faq',
115
- slug: 'faq',
116
- },
117
- ],
118
- },
119
- ]
8
+ packages/
9
+ ├── app/ # Next.js reference app
10
+ ├── blog/ # Build orchestration package
11
+ ├── ui/ # UI components and client logic
12
+ ├── locales/ # i18n resources (i18next)
13
+ ├── consts/ # Navigation config + shared constants
14
+ ├── styles/ # SCSS + compiled CSS
15
+ └── types/ # Shared TypeScript types
120
16
  ```
121
17
 
122
- ### 4. Create content loaders
123
-
124
- ```ts
125
- // src/utils.ts
126
- import { createBlogUtils } from '@x-wave/blog'
127
-
128
- // Vite glob import – resolved relative to this file
129
- const mdxFiles = import.meta.glob('./docs/**/*.mdx', {
130
- query: '?raw',
131
- import: 'default',
132
- eager: false,
133
- })
18
+ ## Quick start
134
19
 
135
- // Export all blog utilities in a single object
136
- export const blog = createBlogUtils(mdxFiles)
137
- ```
138
-
139
- ### 5. Wrap your app with BlogProvider
140
-
141
- ```tsx
142
- // src/App.tsx
143
- import { BlogProvider, DocumentationRoutes } from '@x-wave/blog'
144
- import { Navigate, Route, HashRouter as Router, Routes } from 'react-router-dom'
145
- import { blog } from './utils'
146
- import { NAVIGATION_DATA } from './navigation'
147
-
148
- const SUPPORTED_LANGUAGES = ['en', 'es', 'zh'] as const
149
-
150
- export default function App() {
151
- return (
152
- <BlogProvider
153
- config={{
154
- title: 'My Documentation',
155
- siteUrl: 'https://docs.example.com',
156
- supportedLanguages: SUPPORTED_LANGUAGES,
157
- navigationData: NAVIGATION_DATA,
158
- header: {
159
- navLinks: [
160
- {
161
- label: 'Visit Site',
162
- url: 'https://example.com',
163
- target: '_blank',
164
- },
165
- ],
166
- },
167
- }}
168
- blog={blog}
169
- >
170
- <Router>
171
- <Routes>
172
- <Route path="/:language/*" element={<DocumentationRoutes />} />
173
- <Route path="/" element={<Navigate to="/en/welcome" replace />} />
174
- </Routes>
175
- </Router>
176
- </BlogProvider>
177
- )
178
- }
179
- ```
20
+ ### 1. Install dependencies
180
21
 
181
- > **Router flexibility**: Swap `HashRouter` for `BrowserRouter` to use cleaner URLs without the hash (`/en/welcome` vs `/#/en/welcome`). BrowserRouter requires server configuration to fallback to `index.html` for all routes.
182
-
183
- ### Using a base path
184
-
185
- To mount documentation under a subpath (e.g., `/blog` or `/docs`), set the `basePath` config option:
186
-
187
- ```tsx
188
- export default function App() {
189
- return (
190
- <BlogProvider
191
- config={{
192
- title: 'My Documentation',
193
- basePath: '/blog', // All routes will be prefixed with /blog
194
- supportedLanguages: SUPPORTED_LANGUAGES,
195
- navigationData: NAVIGATION_DATA,
196
- }}
197
- blog={blog}
198
- >
199
- <Router>
200
- <Routes>
201
- {/* Routes now mounted under /blog */}
202
- <Route path="/blog/:language/*" element={<DocumentationRoutes />} />
203
- <Route path="/blog" element={<Navigate to="/blog/en/welcome" replace />} />
204
-
205
- {/* Your other app routes */}
206
- <Route path="/" element={<HomePage />} />
207
- </Routes>
208
- </Router>
209
- </BlogProvider>
210
- )
211
- }
22
+ ```bash
23
+ pnpm install
212
24
  ```
213
25
 
214
- This ensures internal navigation (search, tags, language switching) uses the correct base path.
215
-
216
- ### Vite config helper (with SSG + basePath)
217
-
218
- The framework exports a reusable Vite config helper so consumers can plug in prerendering without re-implementing build logic.
219
-
220
- ```ts
221
- // vite.config.ts
222
- import { createBlogViteConfig } from '@x-wave/blog/vite'
223
-
224
- export default createBlogViteConfig({
225
- basePath: process.env.VITE_BASE_PATH || '/',
226
- docsDir: 'src/docs',
227
- renderTarget: '#root',
228
- renderAfterTime: 1200,
229
- })
230
- ```
26
+ ### 2. Run the Next.js app
231
27
 
232
- You can also extend an existing Vite config by passing `baseConfig`:
233
-
234
- ```ts
235
- // vite.config.ts
236
- import { createBlogViteConfig } from '@x-wave/blog/vite'
237
-
238
- export default createBlogViteConfig({
239
- basePath: process.env.VITE_BASE_PATH || '/',
240
- docsDir: 'src/docs',
241
- renderTarget: '#root',
242
- renderAfterTime: 1200,
243
- baseConfig: {
244
- // Your custom Vite config
245
- resolve: { /* ... */ },
246
- server: { /* ... */ },
247
- // etc.
248
- },
249
- })
28
+ ```bash
29
+ pnpm dev
250
30
  ```
251
31
 
252
- Options:
253
-
254
- - `basePath`: Public base path for deployed assets/routes (e.g. `/`, `/docs`, `/multilingual-documentation`)
255
- - `docsDir`: Relative path to language MDX folders (default: `src/docs`)
256
- - `renderTarget`: Selector where prerendered HTML is injected (default: `#root`)
257
- - `renderAfterTime`: Delay in ms before snapshotting pages in Puppeteer
258
- - `additionalPrerenderRoutes`: Extra non-MDX routes to prerender
259
- - `enableTypeChecker`: Enable/disable `vite-plugin-checker`
260
- - `baseConfig`: Optional. Extend the default Vite config with your own settings. The blog config intelligently merges with your base config (plugins, CSS, and optimizeDeps are combined)
261
-
262
- For local preview at root, keep `VITE_BASE_PATH=/` (default). For subpath deploys, set `VITE_BASE_PATH` in your build environment.
263
-
264
- ## Writing content
32
+ The app runs from [packages/app](packages/app). The default route is `/en/welcome`.
265
33
 
266
- ### File naming
34
+ ## Content structure
267
35
 
268
- Place your MDX files in language-specific directories:
36
+ MDX files live under the app package:
269
37
 
270
38
  ```
271
- src/docs/
272
- ├── en/welcome.mdx
273
- ├── es/welcome.mdx
274
- └── zh/welcome.mdx
39
+ packages/app/docs/
40
+ ├── en/
41
+ ├── welcome.mdx
42
+ │ ├── glossary.mdx
43
+ │ └── faq.mdx
44
+ ├── es/
45
+ └── zh/
275
46
  ```
276
47
 
277
- File names must match the `slug` field in your navigation definition.
48
+ File names must match the `slug` in the navigation config.
278
49
 
279
50
  ### Frontmatter
280
51
 
281
- Optional YAML at the top of your MDX file:
282
-
283
52
  ```mdx
284
53
  ---
285
54
  title: Getting Started
@@ -292,320 +61,68 @@ tags:
292
61
  ---
293
62
 
294
63
  # Welcome!
295
-
296
- Regular content here.
297
64
  ```
298
65
 
66
+ Supported fields:
67
+
299
68
  | Field | Type | Description |
300
69
  |---|---|---|
301
- | `title` | `string` | Document title (informational, not displayed by framework) |
302
- | `description` | `string` | Optional SEO description for the article. Used in the page `<meta name="description">` tag. Falls back to site-level description if not provided. |
303
- | `author` | `string` | Author name. Displayed below the page title with a user icon. |
304
- | `date` | `string` | Publication or update date. Displayed below the page title with "Last edited" label and calendar icon (i18n supported). |
305
- | `keywords` | `string[] \| string` | Optional array of keywords or comma-separated string for SEO. Inserted into the page `<meta name="keywords">` tag. |
306
- | `hasAdvanced` | `boolean` | Enables Simple/Advanced mode toggle. Requires a `-advanced.mdx` variant. |
307
- | `tags` | `string[]` | Array of tag strings for categorizing content. Tags are automatically indexed by the framework when you pass `mdxFiles` to BlogProvider. Tags are clickable and show search results. |
70
+ | `title` | `string` | Document title (informational, not displayed as the main heading) |
71
+ | `description` | `string` | SEO description override (used for `<meta name="description">`) |
72
+ | `author` | `string` | Author display under the title |
73
+ | `date` | `string` | Date shown under the title (i18n-aware label) |
74
+ | `keywords` | `string[] \| string` | Optional SEO keywords list |
75
+ | `hasAdvanced` | `boolean` | Enables Simple/Advanced toggle and `-advanced.mdx` variant |
76
+ | `tags` | `string[]` | Tag labels used by the tag index modal |
308
77
 
309
78
  ### Advanced mode variants
310
79
 
311
- Create `welcome-advanced.mdx` alongside `welcome.mdx`:
80
+ Create a paired file that ends with `-advanced.mdx`:
312
81
 
313
82
  ```
314
- src/docs/
315
- ├── en/
316
- │ ├── welcome.mdx
317
- │ └── welcome-advanced.mdx
83
+ packages/app/docs/en/
84
+ ├── welcome.mdx
85
+ └── welcome-advanced.mdx
318
86
  ```
319
87
 
320
- Set `hasAdvanced: true` in the simple version's frontmatter, and the framework automatically shows a toggle.
88
+ Set `hasAdvanced: true` in the simple version frontmatter.
321
89
 
322
- ## API reference
90
+ ## Navigation configuration
323
91
 
324
- ### Components
92
+ Navigation lives in [packages/consts/src/navigation.ts](packages/consts/src/navigation.ts) and is passed into `BlogProvider` via the app config. Each entry can specify `showTableOfContents` per item.
325
93
 
326
- All components are exported from `@x-wave/blog`:
94
+ ## Next.js implementation notes
327
95
 
328
- ```ts
329
- import {
330
- BlogProvider,
331
- DocumentationRoutes,
332
- DocumentationLayout,
333
- ContentPage,
334
- HomePage,
335
- Header,
336
- Sidebar,
337
- TableOfContents,
338
- AdvancedModeToggle,
339
- Metadata
340
- } from '@x-wave/blog'
341
- ```
342
-
343
- | Component | Purpose |
344
- |---|---|
345
- | `BlogProvider` | Root context wrapper (required) |
346
- | `DocumentationRoutes` | Pre-configured Routes for documentation pages (recommended) |
347
- | `DocumentationLayout` | Page layout: header + sidebar + content |
348
- | `ContentPage` | Loads and renders MDX pages |
349
- | `HomePage` | Lists latest articles with metadata (configurable via `defaultRoute`) |
350
- | `Header` | Top navigation bar |
351
- | `Sidebar` | Left navigation panel |
352
- | `TableOfContents` | "On this page" anchor panel |
353
- | `AdvancedModeToggle` | Simple/Advanced tab switch |
354
- | `Metadata` | Displays author and publication date with icons (used in HomePage and ContentPage) |
355
-
356
- ### Hooks
357
-
358
- ```ts
359
- import { useTheme } from '@x-wave/blog'
360
-
361
- const { theme, setTheme, effectiveTheme } = useTheme()
362
- ```
363
- Manages light/dark/system theme preference.
364
-
365
- ### Utilities
366
-
367
- ```ts
368
- import { createBlogUtils } from '@x-wave/blog'
369
-
370
- const blog = createBlogUtils(mdxFiles)
371
- ```
372
- Creates all blog utilities from a Vite glob import. This is the recommended approach as it bundles everything together.
373
-
374
- Returns an object with:
375
- - **`mdxFiles`**: The glob import (used internally for automatic tag indexing)
376
- - **`loadContent(language, slug, advanced?)`**: Loads MDX content for a specific language and slug
377
- - **`loadEnglishContent(slug, advanced?)`**: Loads English content for heading ID generation
378
-
379
- Pass the entire `blog` object to BlogProvider:
380
-
381
- ```tsx
382
- <BlogProvider config={config} blog={blog}>
383
- ```
384
-
385
- **Alternative: Advanced usage**
386
-
387
- ```ts
388
- import { createContentLoaders } from '@x-wave/blog'
389
-
390
- const { loadMDXContent, loadEnglishContent, buildTagIndex } = createContentLoaders(mdxFiles)
391
- ```
392
- For advanced use cases where you need more control over content loading and tag indexing.
393
-
394
- ### Types
395
-
396
- All TypeScript types are exported from `@x-wave/blog/types`:
397
-
398
- ```ts
399
- import type { NavigationEntry, BlogConfig, HeaderLink } from '@x-wave/blog/types'
400
- ```
96
+ - **Static params**: `generateStaticParams()` in [packages/app/app/[language]/[slug]/page.tsx](packages/app/app/%5Blanguage%5D/%5Bslug%5D/page.tsx)
97
+ - **Server-side content**: `readArticle()` and `readEnglishContent()` in [packages/app/lib/content.ts](packages/app/lib/content.ts)
98
+ - **Client render**: `ContentPage` in [packages/ui/src/components/ContentPage/index.tsx](packages/ui/src/components/ContentPage/index.tsx)
401
99
 
402
100
  ## Customization
403
101
 
404
- ### CSS variables
102
+ ### Styles
405
103
 
406
- The framework uses CSS custom properties (`--xw-*` prefix) for theming. These are automatically injected when the framework initializes, but you can override them:
104
+ The compiled CSS is exported from `@x-wave/blog/styles`. In the Next.js app, it is imported once in [packages/app/app/globals.scss](packages/app/app/globals.scss). Override CSS variables on `.xw-blog-root` to theme the UI.
407
105
 
408
- ```css
409
- /* In your app.css */
410
- .xw-blog-root {
411
- --xw-primary: #007bff;
412
- --xw-background: #fafafa;
413
- --xw-foreground: #1a1a1a;
414
- /* ... other variables */
415
- }
416
- ```
106
+ ### Base path
417
107
 
418
- Or in JavaScript:
108
+ If you mount the docs under a subpath, set `basePath` in the BlogProvider config. This ensures internal links and language switching include the prefix.
419
109
 
420
- ```javascript
421
- const blogRoot = document.querySelector('.xw-blog-root')
422
- blogRoot.style.setProperty('--xw-primary', '#007bff')
423
- blogRoot.style.setProperty('--xw-background', '#fafafa')
424
- ```
110
+ ### Custom header
425
111
 
426
- Available CSS variables include:
427
- - `--xw-primary`, `--xw-secondary`
428
- - `--xw-background`, `--xw-foreground`
429
- - `--xw-card`, `--xw-card-foreground`
430
- - `--xw-muted`, `--xw-muted-foreground`
431
- - `--xw-accent`, `--xw-accent-foreground`
432
- - `--xw-border`, `--xw-ring`
433
- - And more—defined in `packages/styles/main.scss`
434
-
435
- All CSS variables are scoped to `.xw-blog-root` for isolation and to prevent conflicts with your application styles.
436
-
437
- ### Config options
438
-
439
- **BlogConfig** properties:
440
-
441
- ```ts
442
- interface BlogConfig {
443
- title: string // Site title
444
- description?: string // Optional default description for SEO (used as fallback if article has no description)
445
- logo?: React.ComponentType<{ className?: string }> // Optional logo
446
- supportedLanguages: readonly string[] // e.g. ['en', 'es', 'zh']
447
- navigationData: NavigationEntry[] // Menu structure
448
- basePath?: string // Base path for all routes (default: '')
449
- contentMaxWidth?: string // Max width for content area (default: '80rem')
450
- defaultRoute?: string // Default route: 'latest' (home page) or article slug (default: 'latest')
451
- header?: { // Optional: omit to hide built-in header
452
- navLinks?: HeaderLink[] // Top-level nav links
453
- dropdownItems?: HeaderDropdownItem[] // Support dropdown menu
454
- }
455
- }
456
- ```
112
+ Omit the `header` config to hide the built-in header and use the hooks provided by the UI package (`useTheme`, `useSearchModal`).
457
113
 
458
- **Key properties:**
114
+ ## Scripts
459
115
 
460
- - **`header`**: Optional. If omitted entirely, the built-in header component will not be rendered. Use this when you want to implement a custom header.
461
- - **`description`**: Optional. Default SEO description used in the page `<meta name="description">` tag. Articles can override this with their own `description` in frontmatter.
462
- - **`contentMaxWidth`**: Optional. Set a custom maximum width for the main content area. Example: `'100rem'` or `'1400px'`. Default: `'80rem'`.
463
- - **`defaultRoute`**: Optional. Controls which page displays at the root path (`/`):
464
- - Set to `'latest'` (default) to show the HomePage listing the latest articles
465
- - Set to any article slug (e.g., `'welcome'`, `'getting-started'`) to redirect the root path to that article
116
+ From repo root:
466
117
 
467
- ### Home page feature
468
-
469
- The framework includes an optional home/latest posts page that lists articles sorted by publish date. Configure it with the `defaultRoute` option:
470
-
471
- ```tsx
472
- // Show home page at root path (lists latest articles)
473
- config: {
474
- defaultRoute: 'latest' // or omit (defaults to 'latest')
475
- }
476
-
477
- // Or redirect root path to a specific article
478
- config: {
479
- defaultRoute: 'welcome' // Root path goes to /welcome article
480
- }
481
- ```
482
-
483
- The home page displays:
484
- - **Title**: "Latest Posts" (i18n translated)
485
- - **Header metadata**: Author and date from the most recent article
486
- - **Article cards**: Recent articles with title, description, author, and date
487
- - **Sorting**: Articles sorted by date (newest first), limited to 50 articles
488
-
489
- Article metadata comes from MDX frontmatter:
490
- ```mdx
491
- ---
492
- title: Getting Started
493
- author: Jane Doe
494
- date: 2026-02-23
495
- description: Learn the basics in 5 minutes
496
- keywords: [getting started, tutorial, basics]
497
- ---
498
- ```
499
-
500
- ### Custom headers
501
-
502
- If you need a custom header instead of the built-in one, simply omit the `header` config and use the provided hooks:
503
-
504
- ```tsx
505
- import { useTheme, useSearchModal } from '@x-wave/blog'
506
- import { Moon, Sun, MagnifyingGlass } from '@phosphor-icons/react'
507
-
508
- function CustomHeader() {
509
- const { theme, setTheme } = useTheme()
510
- const { openSearchModal } = useSearchModal()
511
-
512
- return (
513
- <header>
514
- <h1>My Custom Header</h1>
515
-
516
- {/* Theme toggle button */}
517
- <button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
518
- {theme === 'dark' ? <Sun /> : <Moon />}
519
- </button>
520
-
521
- {/* Search button */}
522
- <button onClick={openSearchModal}>
523
- <MagnifyingGlass />
524
- </button>
525
- </header>
526
- )
527
- }
528
-
529
- function App() {
530
- return (
531
- <BlogProvider
532
- config={{
533
- title: 'My Docs',
534
- supportedLanguages: ['en'],
535
- navigationData: NAVIGATION_DATA,
536
- // No header config = no built-in header
537
- }}
538
- blog={blog}
539
- >
540
- <CustomHeader />
541
- <Router>
542
- <Routes>
543
- <Route path="/:language/*" element={<DocumentationRoutes />} />
544
- </Routes>
545
- </Router>
546
- </BlogProvider>
547
- )
548
- }
549
- ```
550
-
551
- ### Reusable components
552
-
553
- #### Metadata component
554
-
555
- The `Metadata` component displays article metadata (author and publication date) with icons and i18n support. It's used throughout the framework (HomePage and ContentPage) but is also exported for your own use:
556
-
557
- ```tsx
558
- import { Metadata } from '@x-wave/blog'
559
-
560
- function MyComponent() {
561
- return (
562
- <Metadata
563
- author="Jane Doe"
564
- date="2026-02-23"
565
- />
566
- )
567
- }
568
- ```
569
-
570
- The component:
571
- - Displays author with a user icon
572
- - Displays date with a calendar icon and "Last edited" label
573
- - Automatically formats the date using the user's locale
574
- - Returns `null` if both author and date are missing
575
- - Uses i18n for the "Last edited" label and date formatting
576
-
577
- **Available hooks:**
578
-
579
- - **`useTheme()`**: Returns `{ theme, setTheme, effectiveTheme }` for managing light/dark/system theme
580
- - **`useSearchModal()`**: Returns `{ openSearchModal, closeSearchModal }` for controlling the search modal
581
-
582
- These are the exact functions used by the built-in header, so you get the same functionality with full customization.
583
-
584
- **Key properties (continued):**
585
-
586
- | Property | Type | Required | Description |
587
- |---|---|---|---|
588
- | `title` | `string` | Yes | Site title displayed in header and sidebar |
589
- | `siteUrl` | `string` | Yes | Full canonical origin used for absolute SEO URLs (e.g., `https://docs.example.com`) |
590
- | `supportedLanguages` | `string[]` | Yes | Array of language codes (e.g., `['en', 'es', 'zh']`) |
591
- | `navigationData` | `NavigationEntry[]` | Yes | Sidebar navigation structure |
592
- | `basePath` | `string` | No | Base path prefix for all routes. Use when mounting docs under a subpath like `/blog` or `/docs`. Default: `''` (root) |
593
- | `logo` | `React.ComponentType` | No | SVG component for site logo |
594
- | `header` | `object` | No | Header configuration with nav links and dropdown items |
595
-
596
- ## Browser support
597
-
598
- - Chrome/Edge 90+
599
- - Firefox 88+
600
- - Safari 14+
601
- - Mobile browsers (iOS Safari 14.5+, Chrome Android 90+)
118
+ - `pnpm dev`: Starts the Next.js app and blog watcher
119
+ - `pnpm build`: Builds all packages and the app
120
+ - `pnpm build:blog`: Builds the blog package output
602
121
 
603
122
  ## License
604
123
 
605
- See LICENSE file in this repository.
606
-
607
- ---
124
+ See [LICENSE](LICENSE).
608
125
 
609
- ## For framework maintainers
126
+ ## Maintainers
610
127
 
611
- Contributing or maintaining this framework? See [DEVELOPMENT.md](./DEVELOPMENT.md) for setup, architecture, and build system details.
128
+ See [DEVELOPMENT.md](DEVELOPMENT.md) for build system details and contributor notes.
package/consts/index.ts CHANGED
@@ -6,6 +6,4 @@ export const GITHUB_REPO_URL = 'https://github.com/polkadot-cloud'
6
6
 
7
7
  export const STAKING_DASHBOARD_URL = 'https://staking.polkadot.cloud'
8
8
 
9
- export const DEFAULT_SITE_URL = 'https://staking.polkadot.cloud'
10
-
11
9
  export { NAVIGATION_DATA } from './navigation'