Skip to content

Commit 87586bb

Browse files
SEO improvements
1 parent 91637b7 commit 87586bb

30 files changed

Lines changed: 255 additions & 0 deletions

website/ARCHITECTURE.md

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# Site Architecture — The Salesforce CTA Exam Guide
2+
3+
How the Docusaurus rebuild ("Schematic on the Pad" design) fits together: what lives where,
4+
how a page gets built and deployed, and the invariants that keep the custom parts working.
5+
6+
Last updated: 2026-08-19 (initial Docusaurus rebuild).
7+
8+
---
9+
10+
## 1. The big picture
11+
12+
```mermaid
13+
flowchart LR
14+
subgraph repo["Repository (main branch)"]
15+
content["website/docs/*.md<br/>38 study guides"]
16+
config["website/docusaurus.config.ts<br/>website/sidebars.ts"]
17+
theme["website/src/<br/>homepage + theme + CSS"]
18+
assets["website/static/img/<br/>diagrams & ERDs (~13 MB)"]
19+
legacy["docs/ + mkdocs.yml<br/>(legacy mkdocs — retired,<br/>safe to delete)"]
20+
end
21+
22+
subgraph ci["GitHub Actions (.github/workflows/deploy-docs.yml)"]
23+
install["npm ci"] --> build["npm run build<br/>(docusaurus build, strict links)"]
24+
build --> artifact["upload-pages-artifact<br/>website/build/"]
25+
end
26+
27+
subgraph hosting["GitHub Pages"]
28+
deploy["deploy-pages (OIDC)"]
29+
domain["the-salesforce-cta-exam-guide.com<br/>(custom domain set in repo Pages settings)"]
30+
end
31+
32+
repo -- "push to main" --> ci
33+
artifact --> deploy --> domain
34+
```
35+
36+
- **Everything the live site needs is under [`website/`](.).** The old mkdocs files at the repo
37+
root (`docs/`, `mkdocs.yml`, `setup_docs.py`) are no longer used by the build and can be
38+
deleted once the new site is confirmed live.
39+
- The workflow builds with **strict link checking** (`onBrokenLinks: 'throw'`) — a broken
40+
internal link fails CI instead of shipping a 404.
41+
- The custom domain is configured in **GitHub repo Settings → Pages**, not in the repo.
42+
`url` in `docusaurus.config.ts` must stay `https://the-salesforce-cta-exam-guide.com`
43+
(it drives canonicals and the sitemap).
44+
45+
## 2. Source layout — what each piece does
46+
47+
```mermaid
48+
flowchart TB
49+
subgraph website["website/"]
50+
pkg["package.json<br/>Docusaurus 3 + theme-mermaid<br/>+ easyops local search"]
51+
cfg["docusaurus.config.ts<br/>site meta · navbar dropdowns ·<br/>footer · color modes · fonts"]
52+
side["sidebars.ts<br/>explicit sidebar: Start Here +<br/>8 categories (LDV appears twice via type: ref)"]
53+
54+
subgraph src["src/"]
55+
css["css/custom.css<br/>THE design system:<br/>pad light + Night Bench dark tokens,<br/>navbar/footer/doc-page styling,<br/>breakpoint media queries"]
56+
page["pages/index.tsx (+ .module.css)<br/>homepage: hero, FIG 1, section index,<br/>worked example, coaching"]
57+
comp["components/SchematicDiagram.tsx<br/>(+ .module.css)<br/>clickable SVG: §00 overview +<br/>§01–§07 domains wired to the board"]
58+
swz["theme/Navbar/MobileSidebar/index.tsx<br/>SWIZZLE: hamburger below 1500px<br/>instead of Docusaurus's 996px"]
59+
end
60+
61+
subgraph docsdir["docs/ (content — edit HERE, not root docs/)"]
62+
sh["start-here.md"]
63+
cats["exam-overview/ · system-architecture/ ·<br/>security/ · data/ · solution-architecture/ ·<br/>integration/ · development-lifecycle/ ·<br/>communication/"]
64+
end
65+
66+
static["static/img/<br/>CTA_Diagrams · CTA_OOTB_Object_ERDs ·<br/>CTA_Repo_Images · logo.svg · favicon.svg"]
67+
end
68+
69+
cfg --> side
70+
page --> comp
71+
cfg -. "customCss" .-> css
72+
cats -. "referenced as /img/... " .-> static
73+
```
74+
75+
Key relationships:
76+
77+
| Piece | Role | Notes |
78+
|---|---|---|
79+
| `docusaurus.config.ts` | Single source of site-wide config | Navbar's 8 category dropdowns are defined here and must mirror `sidebars.ts` when pages are added |
80+
| `sidebars.ts` | Doc sidebar structure | Adding a new guide = add the `.md` file **and** register it here (and in the navbar dropdown if desired) |
81+
| `src/css/custom.css` | The whole visual theme | All colors come from `--pad-*` / `--schematic-*` CSS variables; dark mode redefines the same variables under `[data-theme='dark']` |
82+
| `src/pages/index.tsx` | Homepage | Holds the `DOMAINS` array (numbers, blurbs, guide counts, links) — update counts here when guides are added |
83+
| `SchematicDiagram.tsx` | FIG 1 | Click a node → `onSelectDomain` → homepage scrolls to and pulse-highlights the matching card (`domain-<key>` ids); selection state flows back down to highlight the SVG node |
84+
| `theme/Navbar/MobileSidebar/` | Breakpoint override | See invariant #1 below |
85+
86+
## 3. Navigation at each screen width
87+
88+
```mermaid
89+
flowchart LR
90+
w1["≥ 1500px"] --> full["Full navbar:<br/>Start Here + 8 category dropdowns<br/>+ GitHub/YouTube icons.<br/>Navbar is static & wrap-safe."]
91+
w2["997–1499px"] --> ham1["Hamburger menu (top)<br/>+ regular doc sidebar (left)<br/>on doc pages"]
92+
w3["≤ 996px"] --> ham2["Docusaurus native mobile:<br/>hamburger opens the docs sidebar,<br/>'Back to main menu' → categories"]
93+
```
94+
95+
The search box (offline local search — no Algolia account) and the light/dark toggle are
96+
present at every width.
97+
98+
## 4. Invariants — read before touching the navbar or theme
99+
100+
1. **The 1500px hamburger breakpoint lives in TWO places** and they must match:
101+
`HAMBURGER_BELOW_PX` in `src/theme/Navbar/MobileSidebar/index.tsx` and the
102+
`1499px`/`1500px` media queries in `src/css/custom.css`. Docusaurus hard-codes its own
103+
switch at 996px; the swizzle exists solely to let the slide-out menu render above that.
104+
2. **Never put `filter`/`backdrop-filter` on `.navbar`.** The mobile slide-out menu is a
105+
`position: fixed` child of the navbar; a filter makes the navbar its containing block and
106+
clips the menu to the navbar's box.
107+
3. **Never set `overflow` on `.navbar-sidebar__items`.** Docusaurus slides that wrapper
108+
horizontally to switch main ↔ docs menu; a scroll container there blanks the menu on
109+
doc pages. Each panel inside it scrolls on its own.
110+
4. **At ≥1500px, `--ifm-navbar-height` is intentionally `0`** because the navbar is static
111+
(scrolls away) and allowed to wrap to two rows; the sticky doc sidebar/TOC offsets derive
112+
from that variable. Don't "fix" it back to 4rem without also making the navbar
113+
fixed-height again.
114+
5. **Markdown is CommonMark, not MDX** (`markdown.format: 'detect'` + `.md` extensions).
115+
That's what lets the migrated content keep raw HTML `<img>` tags and literal `{`/`<`
116+
characters. Don't rename content files to `.mdx` casually.
117+
6. **Mermaid code fences work in any guide** (```mermaid) via `@docusaurus/theme-mermaid`
118+
three exist today in `integration/oauth-flows-iam.md`.
119+
120+
## 5. Common tasks
121+
122+
| Task | Where |
123+
|---|---|
124+
| Add/edit a study guide | `website/docs/<category>/<slug>.md` + `sidebars.ts` (+ navbar dropdown in `docusaurus.config.ts`) |
125+
| Add an image | Drop under `website/static/img/…`, reference as `/img/…` |
126+
| Change colors/fonts | `src/css/custom.css` variables (light in `:root`, dark under `[data-theme='dark']`) |
127+
| Change homepage copy/counts | `src/pages/index.tsx` (`DOMAINS`, hero, stats) |
128+
| Change the FIG 1 diagram | `src/components/SchematicDiagram.tsx` (geometry mirrors `design-mockups/21-merge-schematic-on-pad-home.html`) |
129+
| Preview locally | `cd website && npm start` (dev) or `npm run build && npm run serve` (prod build) |
130+
| Deploy | Commit + push to `main` — CI does the rest |
131+
132+
## 6. SEO layer
133+
134+
- **Old-URL redirects**[`redirects.ts`](redirects.ts) maps every old mkdocs URL (e.g.
135+
`/06)-OAuth-Flows-&-Identity-and-Access-Management/`) to its new route via
136+
`@docusaurus/plugin-client-redirects`, preserving indexed rankings, backlinks, and
137+
bookmarks. **If a doc's route ever changes, add its old route here.**
138+
- **`trailingSlash: true`** — directory-style URLs so GitHub Pages serves pages without a
139+
301 hop, matching the old mkdocs URL style the redirects catch. Don't change it.
140+
- **Social card**`static/img/social-card.png` (1200×630, pad-style), wired via
141+
`themeConfig.image`; used as `og:image`/`twitter:image` on every page. Source SVG design
142+
mirrors the site theme; regenerate with any SVG→PNG rasterizer if it needs edits.
143+
- **`static/robots.txt`** — allows all crawlers and points at `/sitemap.xml` (generated
144+
automatically by the classic preset on every build).
145+
- **Images** — everything in `static/img/` is compressed (lossless-ish palette PNG /
146+
mozjpeg, ~12MB → ~4MB). Compress new images before committing; the pristine originals
147+
still exist under the legacy root `docs/assets/images/`.
148+
- **Manual/ongoing** (not in code): verify the domain in Google Search Console and submit
149+
the sitemap; add `description` front matter to docs; flesh out stub pages (Mulesoft,
150+
Service Cloud, Board Presentation Tips, Lucidchart Tips); keep external profiles
151+
(GitHub repo website field, YouTube) linking the custom domain.
152+
153+
## 7. Design lineage
154+
155+
The visual direction is **"Schematic on the Pad"** — mockup 21 in
156+
[`design-mockups/`](../design-mockups/index.html) (a merge of mockup 13 *Engineer's Pad* and
157+
mockup 20 *Schematic*). Dark mode is mockup 23 *Night Bench*. The mockup hub at
158+
`design-mockups/index.html` documents all 23 explored directions.

website/docusaurus.config.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,19 @@ import { themes as prismThemes } from 'prism-react-renderer';
22
import type { Config } from '@docusaurus/types';
33
import type * as Preset from '@docusaurus/preset-classic';
44

5+
import redirects from './redirects';
6+
57
const config: Config = {
68
title: 'The Salesforce CTA Exam Guide',
79
tagline: 'The unofficial complete guide to the Salesforce CTA Review Board',
810
favicon: 'img/favicon.svg',
911

1012
url: 'https://the-salesforce-cta-exam-guide.com',
1113
baseUrl: '/',
14+
// Directory-style URLs (/docs/foo/). GitHub Pages serves foo/index.html
15+
// directly for these, avoiding a 301 hop, and it matches the trailing-slash
16+
// style of the old mkdocs URLs our redirects catch.
17+
trailingSlash: true,
1218

1319
organizationName: 'Coding-With-The-Force',
1420
projectName: 'Salesforce-CTA-Study-Guide',
@@ -35,6 +41,15 @@ const config: Config = {
3541
},
3642
],
3743

44+
plugins: [
45+
[
46+
'@docusaurus/plugin-client-redirects',
47+
{
48+
redirects,
49+
},
50+
],
51+
],
52+
3853
themes: [
3954
'@docusaurus/theme-mermaid',
4055
[
@@ -67,6 +82,8 @@ const config: Config = {
6782
],
6883

6984
themeConfig: {
85+
// Social share card (og:image / twitter:image)
86+
image: 'img/social-card.png',
7087
colorMode: {
7188
defaultMode: 'light',
7289
disableSwitch: false,

website/package-lock.json

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

website/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
},
1515
"dependencies": {
1616
"@docusaurus/core": "^3.9.0",
17+
"@docusaurus/plugin-client-redirects": "^3.10.2",
1718
"@docusaurus/preset-classic": "^3.9.0",
1819
"@docusaurus/theme-mermaid": "^3.9.0",
1920
"@easyops-cn/docusaurus-search-local": "^0.52.0",

website/redirects.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* Redirects from the old mkdocs URLs (directory-style paths derived from the
3+
* original numbered filenames) to the new clean Docusaurus routes, so the
4+
* pages Google has indexed — and any bookmarks/backlinks — keep working
5+
* after the migration. Consumed by @docusaurus/plugin-client-redirects in
6+
* docusaurus.config.ts.
7+
*
8+
* If a doc ever moves again, add its old route here rather than deleting it.
9+
*/
10+
const redirects: { from: string; to: string }[] = [
11+
{ from: '/00)-CTA-Exam-Structure', to: '/docs/exam-overview/exam-structure' },
12+
{ from: '/01)-The-Diagrams', to: '/docs/exam-overview/the-diagrams' },
13+
{ from: '/02)-Licenses', to: '/docs/system-architecture/licenses' },
14+
{ from: '/03)-Org-Strategy-(Single-or-Multi-Org)', to: '/docs/system-architecture/org-strategy' },
15+
{ from: '/04)-Project-Governance-(COE)', to: '/docs/development-lifecycle/project-governance-coe' },
16+
{ from: '/05)-Data-Security', to: '/docs/security/data-security' },
17+
{ from: '/06)-OAuth-Flows-&-Identity-and-Access-Management', to: '/docs/integration/oauth-flows-iam' },
18+
{ from: '/07)-Mobile-Solutions', to: '/docs/system-architecture/mobile-solutions' },
19+
{ from: '/08)-Integration-Patterns', to: '/docs/integration/integration-patterns' },
20+
{ from: '/09)-Cryptography', to: '/docs/security/cryptography' },
21+
{ from: '/10)-Reporting', to: '/docs/solution-architecture/reporting' },
22+
{ from: '/11)-Sales-Cloud', to: '/docs/solution-architecture/sales-cloud' },
23+
{ from: '/12)-Service-Cloud', to: '/docs/solution-architecture/service-cloud' },
24+
{ from: '/13)-CPQ-Objects', to: '/docs/solution-architecture/cpq-objects' },
25+
{ from: '/14)-Field-Service-Lightning', to: '/docs/solution-architecture/field-service-lightning' },
26+
{ from: '/15)-Mulesoft-Notes', to: '/docs/solution-architecture/mulesoft-notes' },
27+
{ from: '/16)-Large-Data-Volume-Notes', to: '/docs/data/large-data-volumes' },
28+
{ from: '/17)-Google-Slides-Hotkey-Notes', to: '/docs/communication/lucidchart-tips' },
29+
{ from: '/18)-CTA-Board-Presentation-Tips', to: '/docs/communication/board-presentation-tips' },
30+
{ from: '/19)-Managed-Packages-(Useful-to-the-CTA)', to: '/docs/solution-architecture/managed-packages' },
31+
{ from: '/20)-Governor-Limits-and-Suggested-Best-Practices', to: '/docs/solution-architecture/governor-limits-best-practices' },
32+
{ from: "/21)-Standard-Objects-Oddities-(No-CRUD,-No-Quick-Action,-Can't-Be-Lookups,-Etc)", to: '/docs/solution-architecture/standard-object-oddities' },
33+
{ from: '/22)-Session-Settings', to: '/docs/security/session-settings' },
34+
{ from: '/23)-Partner-Relationship-Management-(Indirect-Sales)', to: '/docs/solution-architecture/partner-relationship-management' },
35+
{ from: '/24)-Multi-Currency', to: '/docs/system-architecture/multi-currency' },
36+
{ from: '/25)-Entitlement-Management-(Service-Cloud)', to: '/docs/solution-architecture/entitlement-management' },
37+
{ from: '/26)-Mutual-Transport-Layer-Security-(mTLS-or-2-way-SSL)', to: '/docs/security/mtls' },
38+
{ from: '/27)-Work-Order-and-Work-Order-Items-(Without-Field-Service-Lightning!)', to: '/docs/solution-architecture/work-orders-without-fsl' },
39+
{ from: "/28)-Networking-Basics-(Firewalls,-DMZ's,-Reverse-Proxies,-etc)", to: '/docs/security/networking-basics' },
40+
{ from: '/29)-Object,-Field-&-Record-Security', to: '/docs/security/object-field-record-security' },
41+
{ from: '/30)-Knowledge-Articles', to: '/docs/solution-architecture/knowledge-articles' },
42+
{ from: '/31)-Experience-Cloud-Features', to: '/docs/solution-architecture/experience-cloud-features' },
43+
{ from: '/32)-External-Services', to: '/docs/solution-architecture/external-services' },
44+
{ from: '/33)-Payment-Gateways-&-Processors---Chargent', to: '/docs/solution-architecture/payment-gateways-chargent' },
45+
{ from: '/34)-Document-Management-Systems-(DMS)', to: '/docs/solution-architecture/document-management-systems' },
46+
{ from: '/35)-Calculating-Data-Storage-In-Salesforce', to: '/docs/data/calculating-data-storage' },
47+
{ from: '/36)-Privacy-and-Consent-Management-Options', to: '/docs/solution-architecture/privacy-consent-management' },
48+
];
49+
50+
export default redirects;
-72.7 KB
Loading
-1.02 MB
Loading
-839 KB
Loading
-93.1 KB
Loading
-94.4 KB
Loading

0 commit comments

Comments
 (0)