feat(website): simplify the reader journey and beginner setup (#3274)

Lead new readers from compact setup through the preserved dinosaur and
Calculator examples, with code, comparisons, and verification in disclosures.
Expand Windows, macOS, and Linux onboarding, client/provider choices,
on-site curl instructions, and the supplied first investigation.
Complete Get started translations while retaining executable literals,
historical evidence, and main's explicitly partial Greek fallback.

Verified the integrated website, its 12 maintenance regressions, all tracked
formatting, typecheck/lint, 38 locale/base-path browser combinations, and
the public Funnel preview. Native installers and providers were not run.
The separate manual production publication workflow is not triggered here.

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Assisted-by: Suika (gensokyo-skills:suika-scatter-gather-planning)
This commit is contained in:
authored and GitHub committed 2026-10-14 08:36:00 +00:00
1 parent 57290a01ac
commit 7c962cc70b
29 files changed
+58115 -24189

No files matched your search

+12 -3
View File
@@ -314,12 +314,21 @@ class WebsiteTranslationChecks(unittest.TestCase):
def test_broken_placeholders_and_inline_markup_fail_before_replacing_preview(self):
with self.translated_project() as root:
page = root / "website/public/index.html"
page.write_text(page.read_text().replace(
"</main>",
'<p>Translation test <a href="get-started/">read more</a>.</p></main>',
))
extract_catalogs(root)
path = root / "website/locales/zh-CN/messages.po"
catalog = polib.pofile(path)
entry = catalog.find("Translation test {ph0}read more{ph1}.", msgctxt="page:index.html")
self.assertIsNotNone(entry)
entry.msgstr = "翻译测试:{ph0}继续阅读{ph1}。"
catalog.save(path)
site = root / "website/_site"
build_translations(root, site)
before = (site / "zh-CN/index.html").read_bytes()
path = root / "website/locales/zh-CN/messages.po"
catalog = polib.pofile(path)
entry = catalog.find("Already know RE? {ph0}Skip to analysis guides →{ph1}", msgctxt="page:index.html")
original = entry.msgstr
for bad, reason in (("丢失链接", "changed placeholders"), ("{ph1}错误的链接{ph0}", "invalid inline markup")):
with self.subTest(reason=reason):
+31 -22
View File
@@ -160,7 +160,7 @@ describe its recorded investigation; update them only when repeating that work.
## Pages
- `public/index.html`: compact setup, reverse-engineering definition and purpose, manual/agent comparison, dinosaur and Calculator examples, and analysis-guide links.
- `public/index.html`: introduction and compact setup, a three-step overview, dinosaur and Calculator examples, case studies and analysis-guide links. Code-level comparisons and checks are optional disclosures.
- `public/examples/dino-lab/index.html`: adjustable-speed mini-game, recovered rule, original-game check and browser analysis steps.
- `public/first-investigation/index.html`: a guided Notes export investigation, from setup to a checked CSV prediction.
- `public/showcase/index.html`: the case-study index.
@@ -328,17 +328,22 @@ Evidence. [evidence/dx-ball-sound-pan.md](evidence/dx-ball-sound-pan.md) records
their provenance and the scope of the validation claims. The original executable
and complete private Evidence records are not website assets.
The homepage starts with a short installation prompt and the ordinary setup
command, then explains what reverse engineering is and why someone would use
it. The manual/agent comparison introduces REA’s role before the examples.
Its opening links directly to Showcases and lets experienced readers skip to
the analysis guides. A Blog link below that shortcut leads to reconstruction
methods and project notes. Case-study previews live on the Showcases page.
The closing section offers copyable project prompts, from cloning `rea.tools`
to reconstructing a game from its executable. The experienced-reader shortcut
lands directly on the guide links below these prompts.
“Any questions?” offers FAQ, Discord and issue-report links. The page ends
with “Join the community”, which links Discord and REA's X account.
The homepage pairs a short introduction with the installation prompt and
ordinary setup command. Get started is the primary action; a second link goes
straight to the first interactive example. Short Showcases and Blog descriptions
below those actions keep both reading paths available. The introduction and
setup retain the original equal-width desktop columns. Platform links go
directly to the Windows, macOS and Linux steps in Get started; the optional
curl installer is listed separately and links to its on-site instructions.
The setup-guide link
starts on its own line. A full-width definition and three steps explain the
workflow, followed by a short transition into the dinosaur and Calculator
cases. The detailed manual/agent comparison is folded,
as are each example's investigation flow and verification details. Plain
paragraphs introduce the cases without repeating goal and purpose panels.
Three case-study previews lead to further investigations. The closing sections
offer a guided first task and target-specific guides. FAQ, Discord and issue
links each have their own line explaining their purpose.
Every content page's header and footer link GitHub, Discord and X.
A right-side table of contents stays visible at widths of 1440px and above.
On narrower screens it becomes a sticky, native disclosure; selecting a link
@@ -347,20 +352,24 @@ the reading position and marks the current link. Without JavaScript, the
menu stays open and its fragment links remain usable.
The comparison uses the same Calculator question on both sides: three
selectable manual steps pair original instructions with an analyst illustration
and thought bubbles; the agent side begins with “One prompt.” and a copyable
question. Thoughts illustrate the reasoning behind the findings. The shared
code-step script selects the initial note on load, so all three notes remain
and thought bubbles; the agent side pairs a copyable question with an
illustrative answer. The outer disclosure opens the complete comparison, with
the original desktop column proportions and the agent explanation first on
mobile. Thoughts illustrate the reasoning behind the findings. The
shared code-step script selects the initial note on load, so all three notes remain
readable when JavaScript is disabled.
The original-instruction panel starts expanded on desktop. On narrow screens,
the homepage script collapses it; a native disclosure keeps the code available
while the thought bubble and agent prompt remain close together.
The original-instruction panel stays expanded when the comparison is opened,
including on mobile; its native disclosure can still be closed manually.
Dinosaur is the first example; Calculator follows as the native example.
Both name the goal and the reason to inspect the program before showing the
demo. A labeled finding explains what REA returned, and the flow distinguishes
REA’s inspection from the agent’s interpretation and implementation.
Its game precedes the prompt and code on small screens. Calculator’s excerpt
Each introduces the goal, then follows three named steps: ask a question,
find the rule, and try a reconstruction. The question and plain-language finding
are on the left, with the demo on the right; mobile keeps that reading order.
Code excerpts and source details join the optional investigation flow and checks
in each disclosure. Calculator’s excerpt
comes from an installed model DLL; Microsoft’s public implementation supplies
names and a crosscheck. Its controls apply the percentage rule to generic inputs.
The target guides end with an optional larger-project disclosure, preserving
the original website-cloning and game-reconstruction prompts.
The dinosaur example connects an inspected running script to a new playable
mini-game. `public/assets/dino-speed.js` owns the recovered speed rule and replay;
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+1831 -1042
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
-8
View File
@@ -57,13 +57,6 @@ function initializePercentDemo() {
render();
}
function initializeExpertAssembly() {
const excerpt = document.querySelector("[data-expert-assembly]");
if (excerpt && window.matchMedia("(max-width: 640px)").matches) {
excerpt.open = false;
}
}
function initializeHomeNavigation() {
const menu = document.querySelector("[data-home-nav]");
if (menu === null) return;
@@ -137,6 +130,5 @@ function initializeHomeNavigation() {
updateLayout();
}
initializeExpertAssembly();
initializePercentDemo();
initializeHomeNavigation();
+23 -13
View File
@@ -80,27 +80,37 @@ async function initializeWebsite() {
initializeStepComparisons();
function initializeFaqAnswers() {
const answers = document.querySelectorAll("[data-faq] details[id]");
if (answers.length === 0) return;
const revealAnswer = (fragment) => {
answers.forEach((answer) => {
if (`#${answer.id}` === fragment) answer.open = true;
});
function initializeLinkedDetails() {
const revealTarget = (fragment) => {
if (!fragment.startsWith("#")) return;
let id;
try {
id = decodeURIComponent(fragment.slice(1));
} catch {
return;
}
const target = document.getElementById(id);
let opened = false;
for (let element = target; element; element = element.parentElement) {
if (element instanceof HTMLDetailsElement && !element.open) {
element.open = true;
opened = true;
}
}
if (opened) target.scrollIntoView({ block: "start" });
};
window.addEventListener("hashchange", () =>
revealAnswer(window.location.hash),
revealTarget(window.location.hash),
);
document.querySelectorAll('[data-faq] a[href^="#"]').forEach((link) => {
document.querySelectorAll('a[href^="#"]').forEach((link) => {
link.addEventListener("click", () =>
revealAnswer(link.getAttribute("href")),
revealTarget(link.getAttribute("href")),
);
});
revealAnswer(window.location.hash);
revealTarget(window.location.hash);
}
initializeFaqAnswers();
initializeLinkedDetails();
function initializeBackToTop() {
const link = document.querySelector(".back-to-top");
+147 -118
View File
@@ -412,18 +412,6 @@ section[id] {
.button.secondary:hover {
background: var(--soft);
}
.button.home-setup-link {
gap: 0.5rem;
border-color: var(--accent);
color: var(--accent);
font-weight: 600;
}
.button.home-setup-link:hover {
background: var(--soft);
}
html[dir="rtl"] .home-setup-link .button-arrow {
transform: scaleX(-1);
}
.text-link {
font-size: 0.95rem;
font-weight: 500;
@@ -435,17 +423,6 @@ html[dir="rtl"] .home-setup-link .button-arrow {
.home-hero {
padding-block: 4rem 3.5rem;
}
.home-definition {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 3.5rem;
align-items: baseline;
margin-bottom: 2rem;
}
.home-definition h2,
.home-definition p {
margin: 0;
}
.home-calculation {
margin: 0;
}
@@ -641,6 +618,10 @@ pre code {
min-width: 0;
font-size: 0.875rem;
}
.code-inline .copy-button {
flex-shrink: 0;
white-space: nowrap;
}
.section {
padding-block: 3.8rem;
border-top: 1px solid var(--line);
@@ -1719,7 +1700,7 @@ pre code {
font-weight: 600;
}
.home-page section[id],
.home-role-comparison[id] {
.home-workflow[id] {
scroll-margin-top: 5.25rem;
}
.home-expert-shortcut {
@@ -1728,11 +1709,10 @@ pre code {
font-size: 0.9rem;
}
.home-expert-shortcut a {
display: block;
margin-top: 0.3rem;
white-space: normal;
}
.home-expert-shortcut + .home-expert-shortcut {
margin-top: 0.5rem;
}
@media (min-width: 1440px) {
.home-page-nav {
position: fixed;
@@ -1774,7 +1754,7 @@ pre code {
font-size: 0.78rem;
}
.home-page section[id],
.home-role-comparison[id] {
.home-workflow[id] {
scroll-margin-top: 2rem;
}
}
@@ -1783,20 +1763,57 @@ pre code {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
gap: 3.5rem;
align-items: baseline;
align-items: start;
}
.home-start-grid h1 {
font-size: clamp(2.8rem, 5vw, 4.2rem);
}
.home-reading-links {
margin-top: 1.75rem;
color: var(--muted);
font-size: 0.9rem;
}
.home-reading-links p {
margin-bottom: 0.5rem;
}
.home-reading-links p:last-child {
margin-bottom: 0;
}
.home-setup {
min-width: 0;
}
.home-start-grid .home-setup h2 {
font-size: 1.3rem;
letter-spacing: -0.02em;
margin-bottom: 0.7rem;
}
.home-start-grid .home-setup > p {
margin-bottom: 1rem;
font-size: 0.9rem;
.home-setup-agent > p,
.home-setup-command > p {
color: var(--muted);
font-size: 0.9rem;
}
.home-setup-agent > p {
margin-bottom: 1rem;
}
.home-setup-command > p:first-child {
margin-top: 1.5rem;
}
.home-install-resources {
display: flex;
flex-wrap: wrap;
gap: 0.6rem 1.25rem;
font-size: 0.85rem;
}
.home-install-resources > span {
color: var(--muted);
}
.home-install-resources a {
white-space: nowrap;
}
.home-other-install-options {
margin-top: 0.65rem;
color: var(--muted);
font-size: 0.85rem;
}
.home-question {
margin-block: 0 1.8rem;
@@ -1806,11 +1823,6 @@ pre code {
color: var(--ink);
font-weight: 500;
}
.home-purpose {
max-width: 850px;
margin-bottom: 2rem;
color: var(--muted);
}
.prose-highlight {
padding: 0.08em 0.35em;
border-radius: 4px;
@@ -1820,67 +1832,53 @@ pre code {
box-decoration-break: clone;
-webkit-box-decoration-break: clone;
}
.home-examples-intro {
max-width: 760px;
margin: 0 0 2.5rem;
.home-workflow {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 2.5rem;
margin-block: 2rem;
}
.home-workflow li + li {
margin-top: 0;
}
.home-workflow li::marker {
color: var(--muted);
font-size: 0.85rem;
}
.home-workflow h3 {
margin-bottom: 0.6rem;
font-size: 1.05rem;
}
.home-examples-intro strong {
display: block;
margin-bottom: 0.5rem;
color: var(--ink);
font-size: 1.5rem;
font-weight: 600;
}
.home-project-prompts {
margin-block: 2rem 2.5rem;
}
.home-project-prompts .agent-terminal {
.home-workflow p {
margin: 0;
}
.home-project-prompts .caption {
margin-block: 0.8rem 0;
color: var(--muted);
font-size: 0.95rem;
}
.home-page #analysis-guides {
scroll-margin-top: 5rem;
}
.case-brief {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr);
gap: 2.5rem;
margin: 0 0 2rem;
padding-block: 1.2rem;
border-top: 1px solid var(--line);
border-bottom: 1px solid var(--line);
.home-examples-intro {
margin-bottom: 2rem;
color: var(--muted);
font-size: 1.05rem;
}
.case-brief dt,
.finding-label {
margin-bottom: 0.45rem;
font-size: 0.8rem;
font-weight: 600;
color: var(--accent);
.home-case-story > h3,
.home-case-result > h3 {
font-size: 1.15rem;
}
.case-brief dd {
margin: 0;
.home-case-story > h3:not(:first-child) {
margin-top: 1.75rem;
}
.home-case-story > p,
.home-case-result > p {
color: var(--muted);
font-size: 0.95rem;
}
.case-brief dd strong {
color: var(--ink);
.home-help-links p {
margin-bottom: 0;
}
.rea-finding {
margin-bottom: 1.4rem;
padding-left: 1rem;
border-left: 2px solid var(--accent);
}
.rea-finding > :last-child {
margin: 0;
font-size: 0.95rem;
color: var(--muted);
}
.rea-finding strong {
color: var(--ink);
.home-help-links p + p {
margin-top: 0.9rem;
}
.home-role-comparison {
display: grid;
@@ -1888,6 +1886,10 @@ pre code {
gap: 0 2rem;
margin: 0;
}
.agent-investigation,
.manual-investigation {
min-width: 0;
}
.comparison-question {
margin-block: 1.8rem 1.2rem;
font-size: 1.05rem;
@@ -2059,18 +2061,6 @@ pre code {
.manual-work-summary strong {
font-weight: 500;
}
.agent-one-prompt {
margin: 1.2rem 0 0.3rem;
color: var(--accent);
font-size: clamp(1.8rem, 3vw, 2.5rem);
font-weight: 650;
letter-spacing: -0.045em;
}
.agent-intro {
margin: 0 0 1.2rem;
color: var(--muted);
font-size: 0.9rem;
}
.agent-percent-rule {
display: grid;
justify-items: start;
@@ -2109,11 +2099,54 @@ pre code {
font-size: 0.875rem;
}
.home-role-comparison figcaption {
order: 3;
grid-column: 1 / -1;
margin-top: 1.2rem;
font-size: 0.8rem;
color: var(--muted);
}
.home-showcase-heading {
display: flex;
justify-content: space-between;
align-items: end;
gap: 2rem;
margin-bottom: 2rem;
}
.home-showcase-heading .lede {
max-width: 680px;
margin-bottom: 0;
}
.home-case-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 1rem;
}
.home-case-card {
display: flex;
min-width: 0;
flex-direction: column;
padding: 1.5rem;
border: 1px solid var(--line);
border-radius: 5px;
}
.home-case-card .eyebrow {
margin-bottom: 0.8rem;
color: var(--accent);
}
.home-case-card h3 {
font-size: 1.25rem;
}
.home-case-card p:not(.eyebrow) {
color: var(--muted);
font-size: 0.9rem;
}
.home-case-card .text-link {
margin-top: auto;
padding-top: 0.7rem;
}
.home-page #community p {
color: var(--muted);
}
.home-example-grid {
display: grid;
grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
@@ -2198,12 +2231,6 @@ pre code {
color: var(--muted);
font-size: 0.8rem;
}
.percent-explanation h3 {
font-size: 1.2rem;
}
.percent-explanation > p {
color: var(--muted);
}
.percent-rules {
margin-bottom: 0;
}
@@ -2219,13 +2246,12 @@ pre code {
margin: 0;
font-size: 0.9rem;
}
.percent-rules dd strong,
.percent-rules dd span,
.percent-rules dd code {
display: block;
}
.percent-rules dd strong {
.percent-rules dd span {
margin-bottom: 0.25rem;
font-weight: 500;
}
.home-evidence-details {
margin-top: 2rem;
@@ -2350,8 +2376,9 @@ pre code {
grid-template-columns: minmax(0, 1fr);
gap: 2rem;
}
.home-start-grid .home-setup {
max-width: 620px;
.home-workflow,
.home-case-grid {
grid-template-columns: minmax(0, 1fr);
}
.home-start-grid h1 {
font-size: clamp(2.7rem, 9vw, 4.65rem);
@@ -2359,8 +2386,18 @@ pre code {
.home-role-comparison figcaption {
margin-top: 0;
}
.agent-investigation {
order: 1;
}
.manual-investigation {
order: 2;
}
}
@media (max-width: 640px) {
.home-showcase-heading {
align-items: flex-start;
flex-direction: column;
}
.home-start-grid .actions {
display: grid;
grid-template-columns: max-content max-content;
@@ -2371,6 +2408,9 @@ pre code {
grid-column: 1 / -1;
justify-self: start;
}
.home-install-resources > span {
flex-basis: 100%;
}
.expert-analysis-grid {
grid-template-columns: minmax(0, 1fr);
}
@@ -2404,10 +2444,6 @@ pre code {
display: block;
margin: 0 0 0.2rem;
}
.case-brief {
grid-template-columns: minmax(0, 1fr);
gap: 1.2rem;
}
.home-hero {
padding-block: 2.8rem;
}
@@ -2459,10 +2495,6 @@ pre code {
}
@media (max-width: 640px) {
.home-definition {
grid-template-columns: 1fr;
gap: 0.8rem;
}
.pan-examples {
grid-template-columns: 1fr;
gap: 1.3rem;
@@ -2703,9 +2735,6 @@ pre code {
:where(:root[data-theme="dark"]) .agent-terminal .copy-button:hover {
background: #313244;
}
:where(:root[data-theme="dark"]) .agent-one-prompt {
color: var(--ink);
}
:where(:root[data-theme="dark"]) .workflow-figure {
background: var(--soft);
}
+18 -7
View File
@@ -445,8 +445,7 @@
</p>
<div class="code-block">
<div class="code-header">
<span
><span translate="no">Node.js</span> · CSV formatter</span
<span translate="no">macOS / Linux · Bash / Zsh</span
><button
class="copy-button"
type="button"
@@ -461,11 +460,23 @@ const { toCsv } = require('./csv.js');
process.stdout.write(toCsv([{ id: 1, title: 'Hello, "REA"' }]));
JS</code></pre>
</div>
<p class="caption">
This command uses a shell with here-document support, such as
Bash or Zsh. Your agent can run the same JavaScript in your
platform’s shell.
</p>
<div class="code-block">
<div class="code-header">
<span translate="no">Windows · PowerShell</span>
<button
class="copy-button"
type="button"
data-copy="first-check-powershell"
aria-label="Copy formatter check command"
>
Copy
</button>
</div>
<pre><code id="first-check-powershell">@'
const { toCsv } = require('./csv.js');
process.stdout.write(toCsv([{ id: 1, title: 'Hello, "REA"' }]));
'@ | node</code></pre>
</div>
</details>
</section>
<section class="article-section" id="next">
File diff suppressed because it is too large. Load diff
+680 -649
View File
File diff suppressed because it is too large. Load diff
+20 -7
View File
@@ -89,13 +89,26 @@ Give long pages a short table of contents with concrete section names. Preserve
the reading width: the homepage uses the side gutter when it has room,
and a collapsible sticky menu on smaller screens. Highlight the current
section, keep fragment links usable without JavaScript, and leave room above
the destination for the sticky control. Offer experienced readers a direct
route from setup to the analysis guides. Keep full case-study previews on the
Showcases page, linked from the opening actions.
Use short labels, selective bold text and the shared blue highlight to make
those facts visible when scanning. Keep source, interpretation and new code
attributed to their respective roles. On mobile, the demo can precede its
supporting code once its purpose is clear.
the destination for the sticky control. Make Get started the primary opening
action. Keep short Showcases and Blog descriptions below the opening actions,
with the original equal-width introduction and setup columns on desktop.
Use a short introduction and one three-step overview before the examples.
Let introductory prose wrap naturally across the container, independently of
the narrower heading width. Add a brief transition before the worked examples.
Present each example in the same reading order: the question, the rule found
in the program, then a reconstruction to try. Use plain language in that path;
keep original code, source details and verification in the disclosure below it.
Prefer ordinary paragraphs to repeated goal, finding and role panels. Reserve
bold text and blue highlights for a meaningful code selection or action, not
every takeaway. Keep source, interpretation and new code attributed to their
respective roles. On mobile, the demo can precede its supporting code once its
purpose is clear. Put the detailed manual/agent comparison and verification
flows in native disclosures so the main reading path stays compact. Retain the
authored examples, source excerpts, investigation steps and useful prompts when
reordering the page. Opening an investigation should reveal its explanation
and code without another layer of hidden analysis.
Keep FAQ, community help and issue reports on separate lines. Describe what
each destination is for so readers can choose the right one.
Show how the reader's task changes using the same question on both sides of a
manual/agent comparison. Let returned evidence make REA's contribution visible.
When showing manual analysis, use authentic instructions and specific analyst