Skip to content

Group Arc's documentation by backend language, and show shared pages in both - #2708

Merged
woksin merged 11 commits into
mainfrom
docs/arc-multi-implementation
Sep 21, 2026
Merged

woksin merged 11 commits into
mainfrom
docs/arc-multi-implementation

Conversation

@woksin

@woksin woksin commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

Arc has two backend implementations. The documentation was shaped for one, so a Kotlin or Java reader had nowhere to land and no way to tell which pages applied to them.

Added

  • A shared glossary defining Arc's vocabulary once and naming both spellings where they differ, such as [Key] and @CommandKey.
  • A shared HTTP contract reference: the wire protocol both backends speak, plus a section recording where they genuinely differ. It was documented only from the JVM side before, so C# readers had nothing.
  • A backend overview naming both implementations and what they agree on.
  • Language tabs on the shared pages. Twenty examples across the scenario recipes, the real-time tutorial chapter, the proxy boundary and identity and access now show C# and Kotlin side by side.
  • A snippet validator that compiles every C# documentation example against real Arc source, with a self-test that plants a reference to a type that does not exist and fails unless the build rejects it.

Changed

  • C# backend pages moved under backend/csharp/, and the two pages that only ever described the C# stack moved with them. Chronicle moved under C# as well, since it documents the .NET client exclusively. Every moved route is redirected.
  • The landing page offers both stacks as equal starting points instead of presenting the .NET host as the only way in.
  • The proxy generator explanation describes both mechanisms rather than asserting the post-build executable is the only one.
  • Command operation recommendations are scoped to C#. The JVM has no operation mechanism, so seven shared pages were recommending something half their readers cannot use.
  • The tutorial and troubleshooting pages say which backend they assume, and where a JVM reader should go instead.
  • Sections are ordered to match the JVM documentation, so switching language keeps the same sequence.

Fixed

  • The proxy configuration reference was unreachable. A page and a sibling folder differed only in case, and the site lowercases path segments, so a fourteen-line "this has moved" stub won the route and linked back to itself.
  • Eight section landing pages existed as routes but appeared in no table of contents, reachable only by deleting path segments in the address bar.
  • Two pages linked to a section index as though it documented domain concepts, when it was a table about local development principals.
  • Authoring validation reported success when it examined zero files, and missed page and folder collisions that differ only in case, which is exactly the collision the site creates.

Notes for review

This is one of three coordinated pull requests. Merge order matters: this and Cratis/Arc.Kotlin#<pr> must land before Cratis/Documentation#<pr>, because the documentation site checks out product repositories at main.

The checker reported success the same way whether it validated every page
or none at all, so a path that resolved to an empty tree printed "passed
for 0 files" and exited clean.

That is the failure the script exists to catch, and it becomes far more
likely while pages are moving between folders. Refuse to pass vacuously.
Arc now has two backend implementations, and the documentation was shaped
for one. Everything under backend/ was C#, so a JVM reader had nowhere to
land and no way to tell which pages applied to them.

Move the C# pages to backend/csharp/ and add a backend overview that names
both implementations and says what they agree on. The two pages that only
ever described the C# stack — the MediatR and MVC comparison and the
Screenplay generator, which has no JVM equivalent — move under C# as well,
so Concepts and architecture holds only pages that are true of Arc rather
than of one stack.

Fold Chronicle in under C# too. It was a top-level Integrations section
documenting the .NET Chronicle client exclusively, which stops being
honest once a second backend exists with its own Chronicle integration.

Put the MVVM pages and the React getting-started under React, so
everything React-shaped sits together and a future frontend framework
becomes a sibling rather than a special case.

Links were repaired against what actually resolves on disk rather than by
pattern, and the moved routes are redirected on the site.
Identity enrichment, authorization attributes and tenant resolution are the
same ideas whichever backend runs them, and the page explaining them showed
only C#. A JVM reader had to translate the examples themselves and guess
whether the behaviour matched.

Move the two examples into snippet files per language and render them as
selectable tabs, so the explanation is written once and the code is shown
in the reader's language. The Kotlin side is taken from the JVM
implementation's own documented API rather than transliterated from C#.
The scenario recipes, the real-time tutorial chapter and the proxy
boundary explanation showed C# only, so a JVM reader had to translate
every example and hope the behaviour carried over. Each example now
renders as a tab per backend language, drawn from a snippet file the
implementation owns.

Where the backends genuinely differ the prose says so rather than
implying symmetry: a suspending provide has no cancellation token, a JVM
handler carries validation feedback out through an exception because it
exposes a single client response leaf, and the shared fluent validator
accepts only literal rules.

Scope the command-operation recommendations to C#. The JVM has no
operation mechanism at all — no match in any module or ABI baseline — so
seven shared pages were recommending something half their readers cannot
use. Rewrite the proxy-generator step for the same reason: it described a
post-build executable reading the compiled assembly as though that were
the only way, when the JVM discovers the same artifacts with a compile-time
annotation processor. Both are now named.

Compile the C# snippets. The JVM side has been checked against source all
along, so the two languages were held to different standards; the
validator builds every snippet against the real Arc projects, and its
self-test plants a reference to a type that does not exist and fails
unless the build rejects it.
Arc had no glossary at all on the C# side, and the JVM side's was written
in JVM terms, so there was nowhere a reader could learn what Arc means by
a command key, an execution scope or an observable query without also
learning one implementation's spelling of it.

Add a shared glossary that defines the idea and names both spellings where
they differ, and leave each implementation's own glossary to the terms
that genuinely belong to it.
A page and a sibling folder differed only in case, and the site lowercases
every path segment when it builds a slug, so both claimed the same route.
The fourteen-line "this has moved" stub won it, which meant the
configuration overview in the sidebar served a notice telling the reader
the documentation had moved and linking back to itself. The reference it
was pointing at had no reachable landing page at all.

Delete the stub. The route is unchanged because both spellings always
produced it; it now serves the reference that was being shadowed.

Teach the authoring check to compare names rather than asking the
filesystem. It derived the folder path and stat'ed it, which finds nothing
on a case-sensitive volume and lets exactly this collision through — the
one place it matters most, since that is what CI runs on.
The local-development principal fixture is an ASP.NET Core concern, and it
sat at the shared level under a "General" section that held nothing else,
so a JVM reader met a C#-only page among the pages that are meant to be
true of Arc. Move it under C# and retire the section, redirecting both old
routes.

Signpost the JVM troubleshooting page from the shared one the same way the
tutorial now does: the symptoms are the same on either backend, the fixes
are not.

Two pages linked to that section's index as though it documented domain
concepts, when it was a one-row table about principals. Point them at the
glossary, which actually defines the term.
Eight landing pages existed as routes but appeared in no table of
contents, so the sidebar offered no way to reach them — the frontend
overview, the Core and React overviews, the MVVM landing, and the
ASP.NET Core, Arc.Core, MongoDB and Entity Framework section landings.
A reader could only get there by deleting path segments in the address
bar.

Give each section an entry pointing at its own landing page. Nothing is
unreachable from the navigation now.
Two shared pages showed C# without saying so. The standalone-slice
walkthrough leans on the C# MongoDB integration and test library, and a
CommandForm page showed a C# validator fragment as though it were the only
way to declare the rule.

Neither point is C#-specific — a slice needs no event log either way, and
both backends generate the same client from the same kind of rule — so
name the stack being shown and link to the JVM equivalent rather than
leaving a reader to assume the page is not for them.
Same topics, same sequence: setup, then commands and queries, then
authorization, identity and tenancy, then persistence, then the proxy
boundary and its analysis, then testing and Chronicle. Only the order
changes; no page moves and no URL changes.
The two backends are one product because they speak one protocol: a
TypeScript client generated from C# has to work against a JVM backend.
That contract was documented only from the JVM side, and the C# side had
no equivalent page, so the one artifact that must be identical was
described in a place half its audience would not look.

State it once, verified against both implementations rather than inherited
from either. Claims that could not be confirmed for C# are not asserted as
contract; several moved to a section recording where the two genuinely
differ, which until now could only be discovered by reading both
repositories.

One of those differences deserves attention rather than only
documentation: the C# SSE control endpoints look a connection up by id and
never check that the caller owns it, while the JVM compares the principal
and tenant and returns 404 on a mismatch.
@woksin woksin added the no-release Merging publishes no package, image, release, or deployment label Sep 21, 2026
@woksin
woksin merged commit 61d0876 into main Sep 21, 2026
9 of 10 checks passed
@cratis-direct
cratis-direct Bot deleted the docs/arc-multi-implementation branch September 21, 2026 21:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no-release Merging publishes no package, image, release, or deployment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant