@activatus/code-standards 2.0.0 → 3.0.1

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.
Files changed (52) hide show
  1. package/README.md +12 -14
  2. package/docs/Guides/_category_.json +2 -2
  3. package/docs/Guides/migrating.md +50 -25
  4. package/docs/Guides/setup.md +52 -17
  5. package/docs/Standards/_category_.json +2 -2
  6. package/docs/Standards/agent-skills.md +29 -29
  7. package/docs/Standards/agent-specs.md +17 -32
  8. package/docs/Standards/direnv.mdx +8 -8
  9. package/docs/Standards/documentation.md +5 -2
  10. package/docs/Standards/editorconfig.md +23 -21
  11. package/docs/Standards/eslint.md +593 -402
  12. package/docs/Standards/human-readable-names.md +62 -22
  13. package/docs/Standards/lint-errors.md +3 -7
  14. package/docs/Standards/prettier.md +35 -26
  15. package/docs/Standards/readable-code.md +30 -0
  16. package/docs/Standards/stylelint.md +26 -11
  17. package/docs/Standards/styling.md +9 -3
  18. package/docs/Standards/tech-stack.md +3 -2
  19. package/docs/Structure/_category_.json +2 -2
  20. package/docs/Structure/component-organization.md +9 -2
  21. package/docs/Structure/folder-structure.md +26 -13
  22. package/docs/Structure/naming-conventions.md +0 -2
  23. package/docs/intro.md +1 -3
  24. package/docs/ontology.md +21 -26
  25. package/docs/templates.mdx +12 -49
  26. package/docs/version-history.md +143 -10
  27. package/package.json +6 -2
  28. package/scripts/renameSymbol.mjs +230 -0
  29. package/static/templates/.editorconfig +8 -11
  30. package/static/templates/AGENTS.md +16 -13
  31. package/static/templates/docs/development/coding-standards.md +4 -0
  32. package/static/templates/docsSite/docusaurus.config.mjs +144 -0
  33. package/static/templates/docsSite/sidebars.mjs +7 -0
  34. package/static/templates/docsSite/src/css/custom.css +6 -0
  35. package/static/templates/docsSite/tsconfig.json +5 -5
  36. package/static/templates/eslint/base/eslint.config.mjs +95 -70
  37. package/static/templates/eslint/nextjs/eslint.config.mjs +170 -126
  38. package/static/templates/eslint/react/eslint.config.mjs +160 -125
  39. package/static/templates/eslint/typescript/eslint.config.mjs +143 -115
  40. package/static/templates/globals.css +9 -9
  41. package/static/templates/next.config.mjs +13 -10
  42. package/static/templates/prettier.config.mjs +26 -0
  43. package/static/templates/stylelint/css/stylelint.config.mjs +37 -25
  44. package/static/templates/stylelint/scss/stylelint.config.mjs +10 -7
  45. package/docs/Standards/branch-naming.md +0 -66
  46. package/docs/Standards/conventional-commits.md +0 -189
  47. package/static/templates/.commitlintrc.json +0 -3
  48. package/static/templates/docsSite/docusaurus.config.ts +0 -119
  49. package/static/templates/docsSite/sidebars.ts +0 -8
  50. package/static/templates/husky/commit-msg +0 -1
  51. package/static/templates/husky/pre-commit +0 -1
  52. package/static/templates/prettier.config.js +0 -17
@@ -0,0 +1,230 @@
1
+ #!/usr/bin/env node
2
+ // Renames a TypeScript symbol everywhere it is used, with TypeScript's own rename: the same engine as an
3
+ // editor's Rename Symbol (F2). For agents working from the command line. Never use find-and-replace.
4
+ //
5
+ // Run it from the project root, with the file where the symbol is declared:
6
+ // node node_modules/@activatus/code-standards/scripts/renameSymbol.mjs <file> <currentName> <newName>
7
+ // For example:
8
+ // node node_modules/@activatus/code-standards/scripts/renameSymbol.mjs components/ui/button/types.ts ButtonProperties ButtonProps
9
+ //
10
+ // To do many renames in one run, list them in a text file, one per line: <file> <currentName> <newName>.
11
+ // Blank lines and lines starting with # are skipped. The renames run in order.
12
+ // node node_modules/@activatus/code-standards/scripts/renameSymbol.mjs --list renames.txt
13
+ import { readFileSync, writeFileSync } from "node:fs";
14
+ import { createRequire } from "node:module";
15
+ import path from "node:path";
16
+
17
+ // process.argv starts with the node binary and this script's path.
18
+ const FIRST_ARGUMENT_INDEX = 2;
19
+ const LIST_FLAG = "--list";
20
+ // A rename line has three parts: file, current name, new name.
21
+ const RENAME_PARTS = 3;
22
+ const USAGE = [
23
+ "Usage: node renameSymbol.mjs <file> <currentName> <newName>",
24
+ " or: node renameSymbol.mjs --list <file of renames>",
25
+ ].join("\n");
26
+
27
+ // Uses the project's own TypeScript, so the rename matches the project's compiler exactly.
28
+ const requireFromProject = createRequire(
29
+ path.join(process.cwd(), "package.json"),
30
+ );
31
+ const typescript = requireFromProject("typescript");
32
+
33
+ const readProjectSettings = () => {
34
+ const configPath = typescript.findConfigFile(
35
+ process.cwd(),
36
+ typescript.sys.fileExists,
37
+ "tsconfig.json",
38
+ );
39
+
40
+ if (!configPath) {
41
+ throw new Error(
42
+ "No tsconfig.json found. Run this from the project root.",
43
+ );
44
+ }
45
+
46
+ const configFile = typescript.readConfigFile(
47
+ configPath,
48
+ typescript.sys.readFile,
49
+ );
50
+
51
+ return typescript.parseJsonConfigFileContent(
52
+ configFile.config,
53
+ typescript.sys,
54
+ path.dirname(configPath),
55
+ );
56
+ };
57
+
58
+ const createLanguageService = ({ projectSettings }) => {
59
+ const host = {
60
+ getScriptFileNames: () => projectSettings.fileNames,
61
+ getScriptVersion: () => "0",
62
+ getScriptSnapshot: (fileName) =>
63
+ typescript.sys.fileExists(fileName)
64
+ ? typescript.ScriptSnapshot.fromString(
65
+ typescript.sys.readFile(fileName),
66
+ )
67
+ : undefined,
68
+ getCurrentDirectory: () => process.cwd(),
69
+ getCompilationSettings: () => projectSettings.options,
70
+ getDefaultLibFileName: (options) =>
71
+ typescript.getDefaultLibFilePath(options),
72
+ fileExists: typescript.sys.fileExists,
73
+ readFile: typescript.sys.readFile,
74
+ readDirectory: typescript.sys.readDirectory,
75
+ directoryExists: typescript.sys.directoryExists,
76
+ getDirectories: typescript.sys.getDirectories,
77
+ };
78
+
79
+ return typescript.createLanguageService(
80
+ host,
81
+ typescript.createDocumentRegistry(),
82
+ );
83
+ };
84
+
85
+ // The first place the name appears as a declaration in the file: an interface, type, function, variable or parameter.
86
+ const findDeclarationPosition = ({ sourceFile, currentName }) => {
87
+ const visit = (node) => {
88
+ const isDeclarationName =
89
+ typescript.isIdentifier(node) &&
90
+ node.text === currentName &&
91
+ node.parent?.name === node;
92
+
93
+ return isDeclarationName
94
+ ? node.getStart(sourceFile)
95
+ : typescript.forEachChild(node, visit);
96
+ };
97
+
98
+ return visit(sourceFile);
99
+ };
100
+
101
+ const endOf = (location) =>
102
+ location.textSpan.start + location.textSpan.length;
103
+
104
+ const applyEdits = ({ renameLocations, newName }) => {
105
+ const locationsByFile = Map.groupBy(
106
+ renameLocations,
107
+ (location) => location.fileName,
108
+ );
109
+
110
+ for (const [fileName, locations] of locationsByFile) {
111
+ const originalText = readFileSync(fileName, "utf8");
112
+ const sortedFromStart = locations.toSorted(
113
+ (first, second) => first.textSpan.start - second.textSpan.start,
114
+ );
115
+ const pieces = sortedFromStart.flatMap((location, index) => {
116
+ const previousEnd =
117
+ index === 0 ? 0 : endOf(sortedFromStart[index - 1]);
118
+ const replacement = `${location.prefixText ?? ""}${newName}${location.suffixText ?? ""}`;
119
+
120
+ return [
121
+ originalText.slice(previousEnd, location.textSpan.start),
122
+ replacement,
123
+ ];
124
+ });
125
+ const lastLocation = sortedFromStart.at(-1);
126
+
127
+ writeFileSync(
128
+ fileName,
129
+ pieces.join("") + originalText.slice(endOf(lastLocation)),
130
+ );
131
+ }
132
+
133
+ return locationsByFile.size;
134
+ };
135
+
136
+ const renameSymbol = ({ filePath, currentName, newName }) => {
137
+ const projectSettings = readProjectSettings();
138
+ const languageService = createLanguageService({ projectSettings });
139
+ const fileName = path.resolve(filePath);
140
+ const sourceFile = languageService
141
+ .getProgram()
142
+ ?.getSourceFile(fileName);
143
+
144
+ if (!sourceFile) {
145
+ throw new Error(
146
+ `${filePath} is not part of the TypeScript project in tsconfig.json.`,
147
+ );
148
+ }
149
+
150
+ const position = findDeclarationPosition({
151
+ sourceFile,
152
+ currentName,
153
+ });
154
+
155
+ if (position === undefined) {
156
+ throw new Error(`${currentName} is not declared in ${filePath}.`);
157
+ }
158
+
159
+ const renameInfo = languageService.getRenameInfo(
160
+ fileName,
161
+ position,
162
+ {
163
+ allowRenameOfImportPath: false,
164
+ },
165
+ );
166
+
167
+ if (!renameInfo.canRename) {
168
+ throw new Error(
169
+ `TypeScript cannot rename ${currentName}: ${renameInfo.localizedErrorMessage}`,
170
+ );
171
+ }
172
+
173
+ const renameLocations = languageService.findRenameLocations(
174
+ fileName,
175
+ position,
176
+ false,
177
+ false,
178
+ {
179
+ providePrefixAndSuffixTextForRename: true,
180
+ },
181
+ );
182
+ const fileCount = applyEdits({ renameLocations, newName });
183
+ const fileWord = fileCount === 1 ? "file" : "files";
184
+
185
+ return `Renamed ${currentName} to ${newName}: ${renameLocations.length} places in ${fileCount} ${fileWord}.`;
186
+ };
187
+
188
+ // Each line of a list file is one rename: <file> <currentName> <newName>.
189
+ const readRenameList = (listPath) =>
190
+ readFileSync(listPath, "utf8")
191
+ .split("\n")
192
+ .map((line) => line.trim())
193
+ .filter((line) => line !== "" && !line.startsWith("#"))
194
+ .map((line) => {
195
+ const [filePath, currentName, newName] = line.split(
196
+ /\s+/u,
197
+ RENAME_PARTS,
198
+ );
199
+
200
+ return { filePath, currentName, newName };
201
+ });
202
+
203
+ const isCompleteRename = ({ filePath, currentName, newName }) =>
204
+ Boolean(filePath && currentName && newName);
205
+
206
+ const commandArguments = process.argv.slice(FIRST_ARGUMENT_INDEX);
207
+ const [firstArgument, secondArgument] = commandArguments;
208
+ const renames =
209
+ firstArgument === LIST_FLAG && secondArgument
210
+ ? readRenameList(secondArgument)
211
+ : [
212
+ {
213
+ filePath: commandArguments[0],
214
+ currentName: commandArguments[1],
215
+ newName: commandArguments[2],
216
+ },
217
+ ];
218
+
219
+ if (
220
+ renames.length > 0 &&
221
+ renames.every((rename) => isCompleteRename(rename))
222
+ ) {
223
+ // Each rename reloads the project, so it sees the renames before it.
224
+ for (const rename of renames) {
225
+ console.log(renameSymbol(rename));
226
+ }
227
+ } else {
228
+ console.error(USAGE);
229
+ process.exitCode = 1;
230
+ }
@@ -4,25 +4,22 @@ root = true
4
4
  charset = utf-8
5
5
  end_of_line = lf
6
6
  indent_size = 2
7
- indent_style = space
7
+ indent_style = tab
8
8
  insert_final_newline = true
9
9
  trim_trailing_whitespace = true
10
10
 
11
- [*.md]
11
+ # Markdown reads a tab as four spaces, so it uses spaces.
12
+ [*.{md,mdx}]
13
+ indent_style = space
12
14
  trim_trailing_whitespace = false
13
15
  max_line_length = off
14
16
 
17
+ # YAML does not allow tabs.
15
18
  [*.{yml,yaml}]
19
+ indent_style = space
16
20
  indent_size = 2
17
21
 
18
- [*.json]
19
- indent_size = 2
20
-
21
- [Makefile]
22
- indent_style = tab
23
-
24
- [*.go]
25
- indent_style = tab
26
-
22
+ # Python's own style guide uses 4 spaces.
27
23
  [*.py]
24
+ indent_style = space
28
25
  indent_size = 4
@@ -1,6 +1,8 @@
1
1
  # [Project Name]
2
2
 
3
- > **NEVER COMMIT CODE.** Do not run `git commit`, `git push`, `git merge`, `git rebase` or `git stash`, and do not create, switch or delete branches. Make the changes, leave them uncommitted in the working tree, and tell the person what you changed. A person reviews and commits every change.
3
+ > [The project's most important rule for agents, stated first so every agent sees it. Usually whether an agent may commit, push or make branches. One line, or a short section if it needs more, such as which agents may commit, when, and how the others ask. See "Project workflow" below.]
4
+
5
+ > **"go" means carry on.** When the person sends only "go", carry on with the current task. It is never permission to commit, push or open a Pull Request, and it needs no reply asking what they meant.
4
6
 
5
7
  ## Project overview
6
8
 
@@ -35,12 +37,15 @@
35
37
  | Type-check | `pnpm typecheck` |
36
38
  | Docs site | `pnpm docs:dev` (then open `/docs`) |
37
39
 
38
- ## Development workflow
40
+ ## Project workflow
41
+
42
+ [How this project runs its work. These are the project's own decisions, not part of the code standards. Say where they are written up (usually `docs/development/`), then list the rules an agent must follow:]
39
43
 
40
- - **Branches**: `<type>/<short-description>` in kebab-case, e.g. `feat/invoice-export`, `fix/login-redirect-loop`. Types: `feat`, `fix`, `docs`, `refactor`, `test`, `chore`. Never work directly on `main`.
41
- - **Commits**: Conventional Commits (`feat: add invoice export`). **People commit — AI agents never do.**
42
- - **Pull requests**: [review and CI requirements]
43
- - **Merging**: [merge strategy, e.g. squash and merge]
44
+ - **Who commits**: [whether AI agents may commit, push or make branches, and when]
45
+ - **Branches**: [how branches are named]
46
+ - **Commit messages**: [the commit message format]
47
+ - **Pull requests**: [review and CI requirements, and where Pull Requests merge to]
48
+ - **Merging and releases**: [merge strategy, and how work reaches production]
44
49
 
45
50
  ## Environment variables
46
51
 
@@ -89,15 +94,15 @@ Follow these rules in every change:
89
94
  | Never | Always |
90
95
  | --- | --- |
91
96
  | `btn`, `msg`, `val`, `(e) =>`, `(item, i) =>` | `button`, `message`, `value`, `(event) =>`, `(item, index) =>` |
92
- | `inputRef` | `inputReference` |
93
- | `deps`, `repo`, `env`, `timeoutMs`, `MAX_` | `dependencies`, `repository`, `environment`, `timeoutMilliseconds`, `MAXIMUM_` |
97
+ | `deps`, `env`, `timeoutMs`, `MAX_` | `dependencies`, `environment`, `timeoutMilliseconds`, `MAXIMUM_` |
94
98
  | `<T>`, `"sm" \| "lg"` | `<ItemType>`, `"small" \| "large"` |
95
99
  | `name="email1"` | `name="emailAddress"` |
96
- | `lib/`, `helpers/`, `utilities/`, `helpers.ts` | `library/`, `utils/`, a file named after what it does |
100
+ | `helpers/`, `utilities/`, `helpers.ts` | `utils/`, a file named after what it does |
97
101
 
98
102
  - **`id` is a word.** Write `id`, `userId`, `user_id` — never `identifier` and never `userID`. `identifier` is only for an outside system's separate field of that name (Linear's readable `ACT-73`).
99
- - **Dictionary words stay short:** `id`, `docs`, `props`, `utils`, `app`, `url`, `api`, `uat`, `pdf`, `html`, `css`, `json`, `readme`. Case them as words: `imageUrl`, not `imageURL`. Any other short name is written in full. A new dictionary word is added to the Dictionary in the Human-Readable Names standard first (https://activatus-code-standards.vercel.app/Standards/human-readable-names#dictionary), never just used.
103
+ - **Dictionary words stay short:** `id`, `docs`, `lib`, `props`, `ref`, `repo`, `utils`, `app`, `url`, `api`, `uat`, `pdf`, `html`, `css`, `json`, `readme`. Case them as words: `imageUrl`, not `imageURL`. Any other short name is written in full. A new dictionary word is added to the Dictionary in the Human-Readable Names standard first (https://activatus-code-standards.vercel.app/Standards/human-readable-names#dictionary), never just used.
100
104
  - **Names owned by someone else stay exactly as they are** — Linear's `id` and `pageInfo`, Node's `cwd` option and `process.env`, React's `ref` and `children`, shadcn/ui's `cn` helper, Next.js's `params`, `searchParams` and `LayoutProps`, HTML attributes, Tailwind classes. The rule is for names we write, not names from someone else's code. Renaming them breaks the code. Give the value a full-word name as soon as it comes into our code: `const workingDirectory = process.cwd();`, then pass `{ cwd: workingDirectory }`.
105
+ - **When a name clashes with a third-party import, rename our own thing first**, to a more specific full-word name: our `createProjectDatabaseClient`, next to Supabase's `createClient`. Rename the import only when both names are third-party, or ours is fixed by a framework (a Next.js route's `GET`). Then use the owner plus the original name, `Link as LucideLinkIcon`. Never rename an import for taste, and never shorten it.
101
106
  - **Form fields especially.** A field has one name everywhere it goes: the input's `name` and `id`, the form schema, the API request, the type and the database column (`emailAddress` / `email_address`). Every field has a visible `<label>` in plain English — never a placeholder instead. Option values are words (`"monthly"`), not numbers. Validation messages name the field and say what to do.
102
107
  - **The linter only checks some names.** Folders, props, form fields, database columns, routes and environment variables are not linted — check every one of them yourself.
103
108
  - **Always `const`.** Never `var`. Use `let` only when a value must be reassigned, with `// eslint-disable-next-line no-restricted-syntax -- <reason>` on the line above.
@@ -112,7 +117,7 @@ Follow these rules in every change:
112
117
  - **No nested ternaries. No boolean flag parameters.**
113
118
  - **No `any`, no non-null `!`, no `as` cast without a comment saying why.**
114
119
  - **Named exports only**, except where a tool requires a default export.
115
- - **Type names end in `Props` or `Type`.**
120
+ - **Type names end in `Props` or `Type`**, and say what the thing is, not the job it does. A type that only describes one field of a function's props is written inside the `Props`: `StartAgentRunProps` holds its `dependencies`, with no separate `StartAgentRunDependenciesType`.
116
121
  - **One component per file.** Server and client components live in separate files.
117
122
  - **Component file order**: imports, component, variables, state, `useMemo` values, `useCallback` functions, effects, render. No inline functions in render.
118
123
  - **Reusable functions live in a `utils/` folder** — global, section or component level — one folder per function, with an `index.ts`.
@@ -152,8 +157,6 @@ Skill files live in `.agents/skills/`, mirrored to `.claude/commands/`.
152
157
 
153
158
  ## Out of scope for AI agents
154
159
 
155
- - **Never commit code.** No `git commit`, `git push`, `git merge`, `git rebase` or `git stash`. Leave every change uncommitted for a person to review.
156
- - Do not create, switch or delete branches.
157
160
  - Do not write secrets, tokens or `.env` values into any file.
158
161
  - Do not change dependencies or lockfiles unless the task requires it.
159
162
  - Do not edit generated files, or third-party code in `node_modules/` or `vendor/`.
@@ -12,6 +12,10 @@ This project follows the Activatus Code Standards, installed as the `@activatus/
12
12
 
13
13
  [For each standard this project skips or changes: its number and name from the setup list, what is different, and why. For example: "7. Prettier — skipped: the project uses Biome for formatting." If nothing differs, write "No differences".]
14
14
 
15
+ ## Unfinished changes
16
+
17
+ [Changes from a code standards version that are not done yet, each with its version and number, what is left, and where it is being done. For example: "Version 2, change 4: the standard ESLint config is not switched on yet. Being done in ACT-120." If there are none, write "None".]
18
+
15
19
  ## Related
16
20
 
17
21
  - [Writing Docs](../overview/writing-docs.md)
@@ -0,0 +1,144 @@
1
+ import { themes as prismThemes } from "prism-react-renderer";
2
+
3
+ const TITLE_SEPARATOR = " — ";
4
+ const FIRST_GROUP = "overview";
5
+
6
+ // Each doc is titled "# Group — Menu item". The folder is the menu group and the
7
+ // part after the dash is the menu item. Overview comes first; everything else is alphabetical.
8
+ const generateSidebarItems = async ({
9
+ defaultSidebarItemsGenerator,
10
+ docs: pages,
11
+ ...remainingArguments
12
+ }) => {
13
+ const items = await defaultSidebarItemsGenerator({
14
+ docs: pages,
15
+ ...remainingArguments,
16
+ });
17
+ const titleById = new Map(
18
+ pages.map((page) => [page.id, page.title]),
19
+ );
20
+
21
+ const labelled = items.map((item) => {
22
+ if (item.type !== "category") {
23
+ return item;
24
+ }
25
+
26
+ const children = item.items
27
+ .map((child) => {
28
+ if (child.type !== "doc") {
29
+ return child;
30
+ }
31
+ const title = titleById.get(child.id) ?? child.id;
32
+ const label = title.includes(TITLE_SEPARATOR)
33
+ ? title.split(TITLE_SEPARATOR)[1]
34
+ : title;
35
+ return { ...child, label };
36
+ })
37
+ .sort((first, second) =>
38
+ first.label.localeCompare(second.label),
39
+ );
40
+
41
+ const firstDoc = item.items.find((child) => child.type === "doc");
42
+ const firstTitle = firstDoc
43
+ ? (titleById.get(firstDoc.id) ?? "")
44
+ : "";
45
+ const label = firstTitle.includes(TITLE_SEPARATOR)
46
+ ? firstTitle.split(TITLE_SEPARATOR)[0]
47
+ : item.label;
48
+ const folder = firstDoc ? firstDoc.id.split("/")[0] : item.label;
49
+
50
+ return {
51
+ ...item,
52
+ label,
53
+ items: children,
54
+ customProps: { folder },
55
+ };
56
+ });
57
+
58
+ return labelled.sort((first, second) => {
59
+ const firstFolder = first.customProps?.folder ?? "";
60
+ const secondFolder = second.customProps?.folder ?? "";
61
+ if (firstFolder === FIRST_GROUP) {
62
+ return -1;
63
+ }
64
+ if (secondFolder === FIRST_GROUP) {
65
+ return 1;
66
+ }
67
+ return String(first.label).localeCompare(String(second.label));
68
+ });
69
+ };
70
+
71
+ // TODO: set the project name
72
+ const PROJECT_NAME = "Project Name";
73
+
74
+ /** @type {import('@docusaurus/types').Config} */
75
+ const config = {
76
+ title: `${PROJECT_NAME} Docs`,
77
+ favicon: "images/logo.svg",
78
+
79
+ // The docs are only ever served behind the app's /docs route, so this URL is a placeholder.
80
+ url: "http://localhost:3000",
81
+ baseUrl: "/docs/",
82
+
83
+ // Internal docs must never be indexed by search engines.
84
+ noIndex: true,
85
+
86
+ onBrokenLinks: "throw",
87
+
88
+ markdown: {
89
+ // Plain .md files are read as CommonMark, so < and { in a doc never break the build.
90
+ format: "detect",
91
+ mermaid: true,
92
+ },
93
+
94
+ presets: [
95
+ [
96
+ "classic",
97
+ /** @type {import('@docusaurus/preset-classic').Options} */ ({
98
+ docs: {
99
+ // The Markdown lives in the project's root docs/ folder, not inside this site.
100
+ path: "../docs",
101
+ routeBasePath: "/",
102
+ sidebarPath: "./sidebars.mjs",
103
+ sidebarItemsGenerator: generateSidebarItems,
104
+ },
105
+ blog: false,
106
+ theme: {
107
+ customCss: "./src/css/custom.css",
108
+ },
109
+ }),
110
+ ],
111
+ ],
112
+
113
+ themes: [
114
+ ["@getcanary/docusaurus-theme-search-pagefind", {}],
115
+ "@docusaurus/theme-mermaid",
116
+ ],
117
+
118
+ themeConfig:
119
+ /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ ({
120
+ tableOfContents: {
121
+ minHeadingLevel: 2,
122
+ maxHeadingLevel: 3,
123
+ },
124
+ colorMode: {
125
+ defaultMode: "light",
126
+ respectPrefersColorScheme: true,
127
+ },
128
+ navbar: {
129
+ title: `${PROJECT_NAME} Docs`,
130
+ logo: {
131
+ alt: "Logo",
132
+ src: "images/logo.svg",
133
+ },
134
+ items: [],
135
+ },
136
+ prism: {
137
+ theme: prismThemes.oneLight,
138
+ darkTheme: prismThemes.oneDark,
139
+ additionalLanguages: ["bash", "json"],
140
+ },
141
+ }),
142
+ };
143
+
144
+ export default config;
@@ -0,0 +1,7 @@
1
+ /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
2
+ const sidebars = {
3
+ // Built from the folder structure of the project's docs/ folder
4
+ docsSidebar: [{ type: "autogenerated", dirName: "." }],
5
+ };
6
+
7
+ export default sidebars;
@@ -1 +1,7 @@
1
1
  /* Theme overrides for the docs site. Empty by default: the stock theme is the standard look. */
2
+
3
+ /* Code is indented with tabs. Show each tab 2 characters wide, as the editors do. */
4
+ pre,
5
+ code {
6
+ tab-size: 2;
7
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
- "extends": "@docusaurus/tsconfig",
3
- "compilerOptions": {
4
- "baseUrl": "."
5
- },
6
- "exclude": [".docusaurus", "build"]
2
+ "extends": "@docusaurus/tsconfig",
3
+ "compilerOptions": {
4
+ "baseUrl": "."
5
+ },
6
+ "exclude": [".docusaurus", "build"]
7
7
  }