docpensieve 0.1.0 → 0.1.2
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 +5 -2
- package/bin/docpensieve.js +1 -0
- package/package.json +8 -6
- package/src/commands/dev.js +1 -1
- package/src/commands/init.js +214 -39
- package/starter/01-guide/01-installation.md +79 -0
- package/starter/01-guide/02-first-site.md +97 -0
- package/starter/01-guide/03-writing-pages.md +138 -0
- package/starter/01-guide/04-versions.md +179 -0
- package/starter/01-guide/05-themes.md +116 -0
- package/starter/01-guide/06-deployment.md +124 -0
- package/starter/01-guide/index.md +38 -0
- package/starter/02-components/01-card.mdx +195 -0
- package/starter/02-components/02-columns.mdx +193 -0
- package/starter/02-components/03-time-timer.mdx +120 -0
- package/starter/02-components/04-tooltip.mdx +100 -0
- package/starter/02-components/05-tree.mdx +163 -0
- package/starter/02-components/06-scroll-to-top.mdx +103 -0
- package/starter/02-components/07-skill.mdx +214 -0
- package/starter/02-components/08-logo-icon.mdx +122 -0
- package/starter/02-components/icons/banner.svg +15 -0
- package/starter/02-components/icons/book.svg +4 -0
- package/starter/02-components/icons/lightning.svg +3 -0
- package/starter/02-components/icons/shield.svg +4 -0
- package/starter/02-components/icons/star.svg +3 -0
- package/starter/02-components/index.md +41 -0
- package/starter/03-reference/01-cli.md +134 -0
- package/starter/03-reference/02-configuration.md +132 -0
- package/starter/03-reference/03-frontmatter.md +110 -0
- package/starter/03-reference/04-theme.md +149 -0
- package/starter/03-reference/index.md +32 -0
- package/starter/04-architecture.md +106 -0
- package/starter/icons/blocks.svg +6 -0
- package/starter/icons/book.svg +4 -0
- package/starter/icons/branch.svg +6 -0
- package/starter/icons/compass.svg +4 -0
- package/starter/icons/lightning.svg +3 -0
- package/starter/icons/list.svg +4 -0
- package/starter/icons/shield.svg +4 -0
- package/starter/icons/star.svg +3 -0
- package/starter/index.mdx +244 -0
- package/types/commands/init.d.ts +7 -4
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Writing pages
|
|
3
|
+
description: Frontmatter, URLs, menu order, links and images.
|
|
4
|
+
tags: [guide, content]
|
|
5
|
+
|
|
6
|
+
jsonld:
|
|
7
|
+
type: TechArticle
|
|
8
|
+
breadcrumbs: true
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Writing pages
|
|
12
|
+
|
|
13
|
+
A page is a `.md` or `.mdx` file in the version folder. Both go through the
|
|
14
|
+
same chain: the extension does not change what is possible, it only states the
|
|
15
|
+
intent.
|
|
16
|
+
|
|
17
|
+
## The frontmatter
|
|
18
|
+
|
|
19
|
+
```yaml
|
|
20
|
+
---
|
|
21
|
+
title: Installation
|
|
22
|
+
description: What you need, and how to set up a project.
|
|
23
|
+
date: 2026-09-09
|
|
24
|
+
tags: [guide, installation]
|
|
25
|
+
---
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`title` becomes the `<title>` tag, the menu entry and the breadcrumb.
|
|
29
|
+
`description` feeds the metadata and the JSON-LD. Everything is optional:
|
|
30
|
+
without `title`, the project name stands in.
|
|
31
|
+
|
|
32
|
+
The fields are detailed in the [reference](../reference/frontmatter/).
|
|
33
|
+
|
|
34
|
+
## What the URL depends on
|
|
35
|
+
|
|
36
|
+
The file path gives the URL path, stripped of its extension and of its sorting
|
|
37
|
+
prefix:
|
|
38
|
+
|
|
39
|
+
| File | URL |
|
|
40
|
+
| --------------------------- | ---------------------- |
|
|
41
|
+
| `index.md` | `/` |
|
|
42
|
+
| `guide/01-installation.md` | `/guide/installation/` |
|
|
43
|
+
| `guide/index.md` | `/guide/` |
|
|
44
|
+
| `components/02-columns.mdx` | `/components/columns/` |
|
|
45
|
+
|
|
46
|
+
The `01-` prefix **orders the menu without appearing in the URL**. It is the
|
|
47
|
+
only way to sort pages other than alphabetically, and it saves keeping a
|
|
48
|
+
separate list.
|
|
49
|
+
|
|
50
|
+
## The menu order
|
|
51
|
+
|
|
52
|
+
The menu is derived from the file tree. Folders become sections, numeric
|
|
53
|
+
prefixes give the order, and an `index.md` in a folder provides the title of
|
|
54
|
+
the section.
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
docs/v1.0/
|
|
58
|
+
├── index.mdx → /
|
|
59
|
+
├── guide/
|
|
60
|
+
│ ├── index.md → /guide/ (title of the section)
|
|
61
|
+
│ ├── 01-installation.md
|
|
62
|
+
│ └── 02-first-site.md
|
|
63
|
+
└── components/
|
|
64
|
+
├── index.md
|
|
65
|
+
└── 01-card.mdx
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Internal links
|
|
69
|
+
|
|
70
|
+
Two spellings, two meanings:
|
|
71
|
+
|
|
72
|
+
- **relative** — `./sibling/`, `../guide/` — resolves against the folder of the
|
|
73
|
+
page's file, as between any two files;
|
|
74
|
+
- **absolute** — `/guide/installation/` — starts from the **version root**, not
|
|
75
|
+
from the domain root.
|
|
76
|
+
|
|
77
|
+
The second rule deserves a pause. A documentation does not know it may be
|
|
78
|
+
served under `/my-project/versions/v1.0/`: if `/guide/installation/` were taken
|
|
79
|
+
literally, every internal link would break as soon as a prefix comes into play.
|
|
80
|
+
They are therefore rewritten at build time.
|
|
81
|
+
|
|
82
|
+
To target a real domain URL, the full address remains.
|
|
83
|
+
|
|
84
|
+
## Images
|
|
85
|
+
|
|
86
|
+
An image sits next to the page and is written relatively:
|
|
87
|
+
|
|
88
|
+
```md
|
|
89
|
+

|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Files that are not pages are copied as is into the output, at the same
|
|
93
|
+
relative place. The path is rewritten like a link.
|
|
94
|
+
|
|
95
|
+
## Components
|
|
96
|
+
|
|
97
|
+
In an `.mdx` page, the shipped components are used **without an import**:
|
|
98
|
+
|
|
99
|
+
```mdx
|
|
100
|
+
<Columns>
|
|
101
|
+
<Column span={8}>The bulk of the point</Column>
|
|
102
|
+
<Column span={4}>A side remark</Column>
|
|
103
|
+
</Columns>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
They are rendered at build time: the delivered HTML only holds their result.
|
|
107
|
+
The list is in [Components](../components/).
|
|
108
|
+
|
|
109
|
+
## A trap to know
|
|
110
|
+
|
|
111
|
+
The content of a JSX tag **left alone on its own line** becomes a paragraph:
|
|
112
|
+
|
|
113
|
+
```mdx
|
|
114
|
+
<p className="flex gap-3">Some text</p>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
produces `<p class="flex gap-3"><p>Some text</p></p>` — two nested paragraphs,
|
|
118
|
+
which is invalid. The browser closes the first one by itself: the wrapper
|
|
119
|
+
disappears, and the intended layout with it.
|
|
120
|
+
|
|
121
|
+
The formatter makes the trap sneaky. A long string of classes ends up broken
|
|
122
|
+
over several lines, which leaves the text alone on its line **after the fact**,
|
|
123
|
+
without anyone having written it that way.
|
|
124
|
+
|
|
125
|
+
Three ways to guard against it:
|
|
126
|
+
|
|
127
|
+
- prefer `<div>` to `<p>` as a wrapper — a paragraph is valid inside it;
|
|
128
|
+
- write short content on the same line as its tags;
|
|
129
|
+
- for repeated cases, put a class in `theme.css` rather than a long string of
|
|
130
|
+
utilities, so that the line stays short.
|
|
131
|
+
|
|
132
|
+
`docpensieve check` reports these nestings on the produced site.
|
|
133
|
+
|
|
134
|
+
## What is not published
|
|
135
|
+
|
|
136
|
+
A page whose frontmatter carries `draft: true` is loaded but kept out of the
|
|
137
|
+
output. That is what lets a work-in-progress page stay in the repository
|
|
138
|
+
without being published.
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Versions
|
|
3
|
+
description: Keep the current version and the one being prepared side by side.
|
|
4
|
+
tags: [guide, versions]
|
|
5
|
+
|
|
6
|
+
jsonld:
|
|
7
|
+
type: TechArticle
|
|
8
|
+
breadcrumbs: true
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Versions
|
|
12
|
+
|
|
13
|
+
A version is a **source folder** and a **configuration entry**. Nothing else.
|
|
14
|
+
Everything else — URL, menu, switcher, branch — follows from them.
|
|
15
|
+
|
|
16
|
+
## The two-track model
|
|
17
|
+
|
|
18
|
+
It is the most common arrangement, and the one DocPensieve's own documentation uses:
|
|
19
|
+
|
|
20
|
+
| Version | Role | Who sees it |
|
|
21
|
+
| ----------- | ------------------------------------------- | -------------------- |
|
|
22
|
+
| **current** | the one that is online and being fixed | everyone, by default |
|
|
23
|
+
| **beta** | the one being prepared for the next release | those who pick it |
|
|
24
|
+
|
|
25
|
+
A visitor arriving at the root is sent to the **current** one. The beta exists,
|
|
26
|
+
it is reachable, but nobody lands there by chance.
|
|
27
|
+
|
|
28
|
+
## 1. Declaring the versions
|
|
29
|
+
|
|
30
|
+
In `docpensieve.config.mjs`:
|
|
31
|
+
|
|
32
|
+
```js
|
|
33
|
+
versions: [
|
|
34
|
+
{ slug: 'v1.1-beta', name: '1.1 (beta)', folder: 'docs/v1.1-beta', prerelease: true },
|
|
35
|
+
{ slug: 'v1.0', name: '1.0', folder: 'docs/v1.0', current: true },
|
|
36
|
+
],
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
| Field | Role |
|
|
40
|
+
| ------------ | ------------------------------------------------------------- |
|
|
41
|
+
| `slug` | URL and branch identifier. It shows up in `/versions/<slug>/` |
|
|
42
|
+
| `name` | What the visitor reads in the switcher |
|
|
43
|
+
| `folder` | Source folder, relative to the project root |
|
|
44
|
+
| `current` | The version served by default. **At most one** |
|
|
45
|
+
| `archived` | Version kept but no longer receiving fixes |
|
|
46
|
+
| `prerelease` | Version in preparation, not yet the current one |
|
|
47
|
+
|
|
48
|
+
Two rules to remember:
|
|
49
|
+
|
|
50
|
+
- **only one version can carry `current`** — two stop the build;
|
|
51
|
+
- if **none** carries it, the first in the list becomes current. A
|
|
52
|
+
single-version configuration therefore has nothing to specify.
|
|
53
|
+
|
|
54
|
+
The switcher only appears in the header from **two** versions on: a single
|
|
55
|
+
choice is not a choice.
|
|
56
|
+
|
|
57
|
+
## 2. Opening the beta
|
|
58
|
+
|
|
59
|
+
Start from the current version, and give it its own folder:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
cp -r docs/v1.0 docs/v1.1-beta
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Then declare the entry with `prerelease` — and **without** `current`, which the
|
|
66
|
+
current version keeps:
|
|
67
|
+
|
|
68
|
+
```js
|
|
69
|
+
versions: [
|
|
70
|
+
{ slug: 'v1.1-beta', name: '1.1 (beta)', folder: 'docs/v1.1-beta', prerelease: true },
|
|
71
|
+
{ slug: 'v1.0', name: '1.0', folder: 'docs/v1.0', current: true },
|
|
72
|
+
],
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`prerelease` is not just a label. It puts on **every page** of the version a
|
|
76
|
+
banner pointing to the current one, and a
|
|
77
|
+
`<meta name="robots" content="noindex, follow">` in the head.
|
|
78
|
+
|
|
79
|
+
This second point matters more than it seems. A beta is a near-identical copy
|
|
80
|
+
of the current version: without it, both compete for the same place in search
|
|
81
|
+
engines, and it is often the wrong one that comes up. Someone would then read a
|
|
82
|
+
documentation in progress while believing they read the one that counts.
|
|
83
|
+
`follow` still lets the page's links be followed.
|
|
84
|
+
|
|
85
|
+
A version cannot be both `current` and `prerelease`: the build stops. The
|
|
86
|
+
notice of one would contradict the role of the other.
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
npx docpensieve build
|
|
90
|
+
npx docpensieve serve
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The switcher now offers both. The root still leads to `1.0`.
|
|
94
|
+
|
|
95
|
+
From there, the two folders live their own lives: what you write in
|
|
96
|
+
`docs/v1.1-beta` does not touch the online documentation.
|
|
97
|
+
|
|
98
|
+
### A fix that applies to both
|
|
99
|
+
|
|
100
|
+
Fixing a typo in the current version does not fix it in the beta: they are two
|
|
101
|
+
separate folders. It is the price of frozen versions, and it is paid at every
|
|
102
|
+
fix — carrying it over into both folders is part of the work.
|
|
103
|
+
|
|
104
|
+
## 3. Promoting the beta
|
|
105
|
+
|
|
106
|
+
On release day, the beta becomes the current version. Only one thing changes:
|
|
107
|
+
**where `current` sits**.
|
|
108
|
+
|
|
109
|
+
```js
|
|
110
|
+
versions: [
|
|
111
|
+
{ slug: 'v1.1', name: '1.1', folder: 'docs/v1.1', current: true },
|
|
112
|
+
{ slug: 'v1.0', name: '1.0', folder: 'docs/v1.0', archived: true },
|
|
113
|
+
],
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
In practice, three steps:
|
|
117
|
+
|
|
118
|
+
1. rename the `docs/v1.1-beta` folder to `docs/v1.1`;
|
|
119
|
+
2. in the configuration, change the `slug`, the `name`, the `folder`, and move
|
|
120
|
+
`current`;
|
|
121
|
+
3. remove `prerelease` from the new one, and mark the old one `archived`.
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
npx docpensieve build
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
`archived` says the version will no longer receive fixes. It **stays online**:
|
|
128
|
+
it is not a shutdown, it is information. Its pages also carry a banner pointing
|
|
129
|
+
to the current version, but **stay indexed** — a past version still matters to
|
|
130
|
+
those who use it.
|
|
131
|
+
|
|
132
|
+
> **The `slug` changes along with the folder, and so does the URL.**
|
|
133
|
+
> `/versions/v1.1-beta/` disappears in favour of `/versions/v1.1/`, and the
|
|
134
|
+
> external links that pointed to the beta lead nowhere any more. To avoid this,
|
|
135
|
+
> keep the same slug from start to finish — `v1.1` from the start, with only
|
|
136
|
+
> the label mentioning the beta.
|
|
137
|
+
|
|
138
|
+
## What the build produces
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
dist/
|
|
142
|
+
├── index.html redirect to the current version
|
|
143
|
+
├── versions.json the list, for whoever wants to read it
|
|
144
|
+
└── versions/
|
|
145
|
+
├── v1.1-beta/
|
|
146
|
+
└── v1.0/
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
The root is an **HTML redirect**, not a server rule: the output stays
|
|
150
|
+
publishable on any static host, without configuration.
|
|
151
|
+
|
|
152
|
+
`versions.json` describes each version — its slug, its label, its URL, whether
|
|
153
|
+
it is current, whether it is archived.
|
|
154
|
+
|
|
155
|
+
## Building a single version
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
npx docpensieve build v1.1-beta
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Only this version is written, in `versions/v1.1-beta/`. The others are not
|
|
162
|
+
touched — handy when working on the beta without wanting to rebuild the rest.
|
|
163
|
+
|
|
164
|
+
One caveat: this form writes **neither the manifest nor the root redirect**,
|
|
165
|
+
which concern no version in particular. After adding, renaming or removing a
|
|
166
|
+
version, run a full build.
|
|
167
|
+
|
|
168
|
+
## One branch per version
|
|
169
|
+
|
|
170
|
+
The model goes further than the folder: each compiled version can live on its
|
|
171
|
+
**own orphan branch**, named after its slug, with a history separate from that
|
|
172
|
+
of the sources.
|
|
173
|
+
|
|
174
|
+
The point is not storage, it is time. A version published two years ago stays
|
|
175
|
+
what it was, in the state in which it was produced — without depending on
|
|
176
|
+
today's generator or today's sources. Rebuilding it is never necessary, and
|
|
177
|
+
nothing would guarantee it gives the same result.
|
|
178
|
+
|
|
179
|
+
The sources stay on the working branch. The two never mix.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Themes
|
|
3
|
+
description: Style the site, and change the classes without touching the HTML.
|
|
4
|
+
tags: [guide, theme]
|
|
5
|
+
|
|
6
|
+
jsonld:
|
|
7
|
+
type: TechArticle
|
|
8
|
+
breadcrumbs: true
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Themes
|
|
12
|
+
|
|
13
|
+
## Two stylings
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
theme: {
|
|
17
|
+
framework: 'tailwind',
|
|
18
|
+
darkMode: 'class',
|
|
19
|
+
},
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`tailwind` compiles on demand only the classes actually used in the produced
|
|
23
|
+
pages. `custom` does without it entirely: a stylesheet written in the package
|
|
24
|
+
styles the site, with no styling dependency.
|
|
25
|
+
|
|
26
|
+
The templates are the same in both cases. Switching values requires touching
|
|
27
|
+
no page.
|
|
28
|
+
|
|
29
|
+
## The principle: slots, not classes
|
|
30
|
+
|
|
31
|
+
The templates **hard-code no class**. They ask the theme for the class of each
|
|
32
|
+
slot — the header, the menu, a navigation link — and the theme answers.
|
|
33
|
+
|
|
34
|
+
The twenty-four slots are listed in the [reference](../reference/theme/).
|
|
35
|
+
|
|
36
|
+
That is what lets a utility styling and a classic styling share the same HTML:
|
|
37
|
+
one answers `dp-nav-link`, the other a handful of utilities. The template
|
|
38
|
+
itself does not change.
|
|
39
|
+
|
|
40
|
+
Components follow the same rule. When the theme does not answer, they fall
|
|
41
|
+
back on a `dp-*` class that their stylesheet styles from the `--dp-*` tokens:
|
|
42
|
+
they therefore follow the active palette without knowing anything about it.
|
|
43
|
+
|
|
44
|
+
## Changing the colours
|
|
45
|
+
|
|
46
|
+
The fifteen tokens are listed in the [reference](../reference/theme/). They are
|
|
47
|
+
redefined from the configuration:
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
theme: {
|
|
51
|
+
framework: 'tailwind',
|
|
52
|
+
tokens: {
|
|
53
|
+
'--dp-accent': 'oklch(55% 0.2 250)',
|
|
54
|
+
'--dp-radius': '0.75rem',
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
| Token | What it sets |
|
|
60
|
+
| -------------------------------------- | -------------------------------------------------------------- |
|
|
61
|
+
| `--dp-bg`, `--dp-bg-soft` | Backgrounds |
|
|
62
|
+
| `--dp-text`, `--dp-text-soft` | Text |
|
|
63
|
+
| `--dp-border`, `--dp-rule` | Borders and rules |
|
|
64
|
+
| `--dp-accent`, `--dp-accent-soft` | Accent colour |
|
|
65
|
+
| `--dp-radius` | Corner rounding |
|
|
66
|
+
| `--dp-font`, `--dp-font-mono` | Font families |
|
|
67
|
+
| `--dp-content-width` | Reading width. `none` by default: the content fills its column |
|
|
68
|
+
| `--dp-sidebar-width`, `--dp-toc-width` | Side columns |
|
|
69
|
+
|
|
70
|
+
A redefined token propagates everywhere: components included, without any of
|
|
71
|
+
them having to know.
|
|
72
|
+
|
|
73
|
+
## Adding CSS
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
theme: {
|
|
77
|
+
framework: 'tailwind',
|
|
78
|
+
css: '.dp-article h2 { letter-spacing: -0.01em; }',
|
|
79
|
+
},
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The content of `css` is appended to the produced stylesheet.
|
|
83
|
+
|
|
84
|
+
## Layer order
|
|
85
|
+
|
|
86
|
+
Under the `tailwind` theme, the stylesheet declares its layers in this order:
|
|
87
|
+
|
|
88
|
+
```css
|
|
89
|
+
@layer theme, base, components, utilities;
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Component rules live in `components`, **below** the utilities. A `className`
|
|
93
|
+
set at use therefore always wins, whatever the place of the rule in the file:
|
|
94
|
+
|
|
95
|
+
```mdx
|
|
96
|
+
<Card className="border-0 shadow-none">…</Card>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Without this layer, a component rule written after a utility would beat it at
|
|
100
|
+
equal specificity, and the author's `className` would be ignored without a
|
|
101
|
+
word.
|
|
102
|
+
|
|
103
|
+
The `custom` theme has no utilities: a `className` there designates your own
|
|
104
|
+
classes. Declare them in `theme.css` — outside any layer, they come before the
|
|
105
|
+
component rules.
|
|
106
|
+
|
|
107
|
+
## The stylesheet is compiled last
|
|
108
|
+
|
|
109
|
+
A utility theme only emits the rules of the classes actually used: it
|
|
110
|
+
therefore needs the rendered pages before it can compile. The build first
|
|
111
|
+
writes every page, collecting the classes along the way, then compiles the
|
|
112
|
+
stylesheet.
|
|
113
|
+
|
|
114
|
+
That is also why the slot classes are available **without** waiting for that
|
|
115
|
+
compilation: the templates need them to be rendered. The two things are kept
|
|
116
|
+
apart for this reason alone.
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Deployment
|
|
3
|
+
description: Publish the site, and keep past versions online.
|
|
4
|
+
tags: [guide, deployment]
|
|
5
|
+
|
|
6
|
+
jsonld:
|
|
7
|
+
type: TechArticle
|
|
8
|
+
breadcrumbs: true
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Deployment
|
|
12
|
+
|
|
13
|
+
## The deployment prefix
|
|
14
|
+
|
|
15
|
+
It is the setting that breaks the most sites, and the only one you really have
|
|
16
|
+
to understand.
|
|
17
|
+
|
|
18
|
+
A site served at the root of a domain has nothing to set. A site served under a
|
|
19
|
+
sub-path — `https://example.com/my-project/` — must know it, otherwise every
|
|
20
|
+
internal link will point one notch too high.
|
|
21
|
+
|
|
22
|
+
```js
|
|
23
|
+
siteUrl: 'https://example.com/my-project',
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The sub-path of `siteUrl` **is enough**: `baseUrl` is derived from it when it
|
|
27
|
+
is not set. Setting it only serves to depart from it.
|
|
28
|
+
|
|
29
|
+
```js
|
|
30
|
+
siteUrl: 'https://example.com/my-project',
|
|
31
|
+
baseUrl: '/other-path/',
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Building for going live
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx docpensieve build
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The output folder is self-contained: HTML files, one stylesheet per version,
|
|
41
|
+
the copied resources. No server rule is needed — the root is an HTML redirect,
|
|
42
|
+
and each page is a folder with its `index.html`.
|
|
43
|
+
|
|
44
|
+
## Continuous integration
|
|
45
|
+
|
|
46
|
+
```yaml
|
|
47
|
+
name: Deploy
|
|
48
|
+
|
|
49
|
+
on:
|
|
50
|
+
push:
|
|
51
|
+
branches: [main]
|
|
52
|
+
|
|
53
|
+
permissions:
|
|
54
|
+
contents: read
|
|
55
|
+
pages: write
|
|
56
|
+
id-token: write
|
|
57
|
+
|
|
58
|
+
jobs:
|
|
59
|
+
publish:
|
|
60
|
+
runs-on: ubuntu-latest
|
|
61
|
+
environment:
|
|
62
|
+
name: github-pages
|
|
63
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
64
|
+
steps:
|
|
65
|
+
- uses: actions/checkout@v7
|
|
66
|
+
- uses: actions/setup-node@v7
|
|
67
|
+
with:
|
|
68
|
+
node-version: '22'
|
|
69
|
+
|
|
70
|
+
- run: npx docpensieve build
|
|
71
|
+
|
|
72
|
+
# A successful build says nothing of a dead link.
|
|
73
|
+
- run: npx docpensieve check
|
|
74
|
+
|
|
75
|
+
- uses: actions/configure-pages@v6
|
|
76
|
+
- uses: actions/upload-pages-artifact@v5
|
|
77
|
+
with:
|
|
78
|
+
path: dist
|
|
79
|
+
- id: deployment
|
|
80
|
+
uses: actions/deploy-pages@v5
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The pages source must be set to "GitHub Actions" in the repository settings:
|
|
84
|
+
otherwise the artifact is produced but never served.
|
|
85
|
+
|
|
86
|
+
A project created by `init` has no `package.json`: the recipe therefore calls
|
|
87
|
+
the tool through `npx`, which takes the latest published version. To pin it
|
|
88
|
+
from one build to the next, declare `docpensieve` in a `package.json` and add
|
|
89
|
+
`npm ci` before the build.
|
|
90
|
+
|
|
91
|
+
## Reading back before publishing
|
|
92
|
+
|
|
93
|
+
A generated site can compile without error and contain dead links.
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
npx docpensieve check
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The command exits with code 1 if any remain: placed after the build, it stops
|
|
100
|
+
the publication rather than put online a site whose links lead nowhere. It is
|
|
101
|
+
the only safeguard that looks at the result rather than at the sources.
|
|
102
|
+
|
|
103
|
+
## A scheduled build
|
|
104
|
+
|
|
105
|
+
What depends on the moment is frozen at build time. A page that shows "the
|
|
106
|
+
offer ends tomorrow" will still say so in six months if the site has not been
|
|
107
|
+
rebuilt.
|
|
108
|
+
|
|
109
|
+
For those pages, a periodic build is enough:
|
|
110
|
+
|
|
111
|
+
```yaml
|
|
112
|
+
on:
|
|
113
|
+
schedule:
|
|
114
|
+
- cron: '0 4 * * *'
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Keeping past versions
|
|
118
|
+
|
|
119
|
+
Already published versions do not need to be rebuilt: their output is the one
|
|
120
|
+
produced at the time, and nothing would guarantee that a rebuild gives the same
|
|
121
|
+
result years later.
|
|
122
|
+
|
|
123
|
+
The branch model answers this — each compiled version on its own orphan branch,
|
|
124
|
+
with its history. See [Versions](./versions/).
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Guide
|
|
3
|
+
description: From installation to deployment, in order.
|
|
4
|
+
tags: [guide]
|
|
5
|
+
|
|
6
|
+
jsonld:
|
|
7
|
+
type: TechArticle
|
|
8
|
+
breadcrumbs: true
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Guide
|
|
12
|
+
|
|
13
|
+
These pages are read in order. Each one starts from what the previous one set
|
|
14
|
+
up.
|
|
15
|
+
|
|
16
|
+
1. **[Installation](./installation/)** — what you need, and how to set up
|
|
17
|
+
a project.
|
|
18
|
+
2. **[First site](./first-site/)** — build, serve, look at what was
|
|
19
|
+
produced.
|
|
20
|
+
3. **[Writing pages](./writing-pages/)** — frontmatter, URLs, menu, links,
|
|
21
|
+
images.
|
|
22
|
+
4. **[Versions](./versions/)** — several documentation versions, one
|
|
23
|
+
branch each.
|
|
24
|
+
5. **[Themes](./themes/)** — style the site, change the classes without
|
|
25
|
+
touching the HTML.
|
|
26
|
+
6. **[Deployment](./deployment/)** — publish, and keep past versions
|
|
27
|
+
online.
|
|
28
|
+
|
|
29
|
+
## What to know first
|
|
30
|
+
|
|
31
|
+
The produced site is **entirely static**. Each page is a complete HTML file,
|
|
32
|
+
served as is, along with a single stylesheet. Nothing is computed on the
|
|
33
|
+
reader's side.
|
|
34
|
+
|
|
35
|
+
This has a consequence to keep in mind throughout: what depends on the moment —
|
|
36
|
+
a date, a countdown — is frozen at build time, not at reading time.
|
|
37
|
+
[TimeTimer](../components/time-timer/) says so explicitly, and a scheduled build
|
|
38
|
+
is enough to keep it right.
|