docs(cloud): restructure the Cloud tab and add verified pricing pages - #33
Merged
Merged
Conversation
I deleted the BoxLite Cloud section from llms.txt in ffe3d36. The sync that landed that commit deliberately excluded `cloud/` and `docs.json` because both held content the source tree could not produce — but llms.txt is derived from the whole page set the same way, and I did not think of it, so the source-tree version overwrote it and took all 21 Cloud lines with it. Restoring those lines by hand would leave the underlying problem in place. llms.txt duplicates two facts that already live elsewhere: the navigation tree (docs.json) and each page's title and description (its own frontmatter). A hand-maintained third copy rots silently, and this one had: * five dead links — manage-sandbox/configuration, guides/production-best-practices, guides/building-from-source, guides/macos-sandbox-debugging, and architecture/internals, all renamed, moved, or deleted in earlier passes * group names from a superseded IA ("Manage Sandbox", "Guides", "Resources" against the live "Manage sandboxes", "From demo to production", "FAQ and releases") * the three use-case mode groups, flattened in the site long ago * no BoxLite Cloud section scripts/gen-llms-txt.py now derives the file from docs.json plus frontmatter. 85 entries, matching the 85 pages in the navigation, with no dead links. `--check` is wired into the docs-lint workflow so staleness fails CI rather than waiting for a reader to notice. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
The volumes page described an API that no longer exists. It was written against a checkout 147 commits behind origin/main, and volume support changed substantially in between. Verified against boxlite-sdk-main at d354470a, level with origin/main: * `VolumeInfo` carries a `name`, and a volume mounts by name or by id (volumes/store.rs:22-25). The page said `create()` took no arguments and that the id was the only handle. * An entire section, "Names live in the console, ids come from the SDK", argued a product difference that no longer exists. The console and the SDK now name volumes the same way. Removed. * The wire field is `managed_volume`; the `volume://` scheme has no remaining reference anywhere in the tree. * Host bind mounts are rejected before any network request goes out (rest/runtime.rs:167-177), not silently ignored as the page warned. The real error string is now quoted. * Read-only managed volumes are refused client-side with a specific message rather than becoming a server 400. * `size_bytes` is always empty: neither server response builder returns a size field (boxlite-volume.controller.ts:66-81). It was documented as a working field. * Mount paths are validated server-side — absolute, not root, no relative components, no consecutive slashes, no system directories. None of this was documented; there is now a table. Structure follows the progressive-disclosure order the style guide requires, which the previous version did not: Prerequisites, then a runnable Quick example, then concepts, then the parameter tables. The first code block a reader met used to be a fragment with undefined variables, four screens above anything runnable. Four sibling Cloud pages had a Prerequisites section; this one did not. Volume state and deletion move to cloud/volume-operations. They serve a different reader — someone whose volume is already carrying data — and the deletion poll depends on the `state` field the neighbouring section explains, so the two travel together. Troubleshooting rows that moved are not duplicated; the origin page keeps one pointer instead. This also fills the Volumes nav group, which shipped with an empty `pages` array and rendered as a chevron that expanded to nothing. Tab renamed from "BoxLite Opensource" to "BoxLite Open Source". "Opensource" is not a word, and it was the only place in the tree using that spelling: the seven other occurrences are all the `/cloud/vs-opensource` route slug, and prose already used `open source` and `open-source` correctly throughout. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Every nav group root is now a summary plus an index of its children, and the
substantive content moved into task-shaped sibling pages. Cloud goes from 12
pages to 24, still two levels deep.
root before after
cloud/index 115 45
cloud/boxes 299 41
cloud/volumes 531 39
cloud/network 461 44
cloud/pricing 281 45
The splits were scoped by measuring section sizes, not page length. One section
was 89% of cloud/network; two were 67% of cloud/volumes. cloud/boxes had no
dominant section, so it was split by topic rather than to relieve bloat.
New pricing pages, with rates read from Commerce's anonymous /usage-prices
rather than from the repo's test fixtures:
- cloud/pricing rates and section index
- cloud/box-costs formula, size costs, and which hours are counted
- cloud/cost-controls auto_stop/auto_delete, in Python, Node, and Go
- cloud/plans plan tiers and the $20/$161/$601 break-even points
- cloud/billing rewritten as account operations; adds automatic reload
Correctness fix carried in this change: cloud/boxes claimed a box created over
REST gets auto_stop=0 and "keeps running until you stop it". It does not. The
SDK omits the field when unset (serde skip_serializing_if), and the platform
resolves it to DEFAULT_AUTO_STOP_SECONDS = 900 (box.service.ts resolveLifecycle
Policy). The published page contradicted itself, warning elsewhere that a job is
stopped at 15 minutes. Corrected in three places, found by grepping for the
class rather than the instance.
cloud/volume-operations became an actual CRUD page. rt.volumes.get() had no
runnable code anywhere, list() only appeared incidentally inside a deletion
demo, and the headings named gotchas rather than operations. Also documents that
there is no update operation — create/list/get/remove is the whole surface.
Removed a dev-environment hostname that had been used to show the rate list was
checkable, and deleted cloud/index's runnable script, which duplicated
cloud/quickstart and cloud/vs-opensource.
Verified: mint broken-links clean, lint-docs 180 pages with no soft promises,
101 pages with every internal link and anchor resolving, llms.txt regenerated
and --check clean, all 24 Cloud routes rendering 200 locally, and the Go example
type-checking against the SDK with go vet.
Not verified: the Starter/Pro/Max price, quota, and concurrency figures on
cloud/plans. Commerce's /plan catalog requires authentication, so those three
rows carry over from the previously published page and the break-even table is
derived from them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
Two things: restructures the BoxLite Cloud tab so every navigation root is a summary plus an index, and adds the pricing documentation that was missing entirely.
Cloud goes from 12 pages to 24, still two levels deep.
Navigation roots are now summaries, not monoliths
cloud/indexcloud/boxescloud/volumescloud/networkcloud/pricingEach root now carries a value proposition, the single warning most likely to bite, an
In this sectioncard group, and a "Which page do I want?" intent table. Everything else moved to task-shaped siblings.The splits were scoped by measuring section sizes, not page length:
cloud/boxeswas therefore split by topic rather than to relieve bloat, and only after checking that its six inbound anchor links could be repointed.New structure:
No route that had shipped was deleted or renamed, so no redirects are needed. Anchors that moved were repointed across 10 files.
Pricing documentation
There was none. The old billing page listed plan tiers but never stated a single unit price — the only price signal was "the New Box dialog reports PRICE PER HOUR", which outsources the most-asked question to the product itself.
Rates come from Commerce's anonymous
/usage-prices, not from the repo's test fixtures (which happen to carry the same values — a trap worth naming):New pages:
cloud/box-costs— the formula, per-hour/per-month costs for every preset, and which hours are counted: compute billing stops when a stop is requested, disk billing stops when deletion is requested, and there is no minimum duration or hour-rounding.cloud/cost-controls—auto_stop/auto_delete, in Python, Node, and Go. The default configuration stops paying for compute automatically and pays for disk forever; this page closes that loop.cloud/plans— plan tiers plus the break-even points ($20 → Starter, $161 → Pro, $601 → Max) and the constant saving past quota ($11 / $101 / $401 per month).cloud/billing— rewritten as account operations. Adds automatic reload, which the old page never mentioned, and explains why the "available" balance drifts downward with no payment taken (it is the ongoing balance).The headline fact the old page omitted: a stopped box is still billed for its disk until it is deleted.
BOX_STATES_BILLING_DISK_ONLY = [STOPPING, STOPPED].Correctness fix
cloud/boxesclaimed that a box created over REST getsauto_stop=0and "keeps running until you stop it, and paying for it is your responsibility."It does not. The SDK omits the field when unset (
#[serde(skip_serializing_if = "Option::is_none")]), and the platform resolves the absence toDEFAULT_AUTO_STOP_SECONDS = 900:The
unwrap_or(0)that the earlier claim rested on is client-side validation, and its own comment says so: "validate only the caller's requested policy — not the server's auto_stop".This mattered in the dangerous direction: the page told readers a long unattended job would keep running, while the same page warned elsewhere that such a job is stopped at 15 minutes. Corrected in three places, found by grepping for the class rather than the instance.
Volume CRUD
cloud/volume-operationsis now an actual CRUD page. Before this change:rt.volumes.get()had no runnable code anywhere in the docslist()appeared only incidentally, inside a deletion demoWhat the SDK does not tell youandDeletion is asynchronous— a reader looking for "how do I list my volumes" would never find themIt now runs create → list → get → delete in one script, in Python, Node, and REST, and documents that there is no update operation:
create/list/get/removeis the entire surface, verified by grepping forupdate|rename|patch|resize|set_nameacross the Rust core, the Python bindings, and the Node contracts.Also
cloud/index's runnable script, which duplicatedcloud/quickstartandcloud/vs-opensource.cloud/network's outbound section, which duplicated the fuller one oncloud/network-policy.preview-urls→serve-http: "preview URL" is a distinct platform concept thatnetwork-policyowns, andnetwork-policysays so explicitly.llms.txtis now generated fromdocs.jsonand page frontmatter, with--checkwired into CI. It was hand-maintained and had drifted to five dead links and no Cloud section.Verification
mint broken-linksscripts/lint-docs.pygen-llms-txt.py --checkgo vetclean against the SDKorigin/mainafter confirming the checkout was currentNot verified
The Starter / Pro / Max price, quota, and concurrency figures on
cloud/plans. Commerce's/plancatalog requires authentication (401; a nonexistent route returns404, so the distinction is real). Those three rows carry over from the previously published page, and the break-even table is derived from them. Worth a glance in the console before merging.🤖 Generated with Claude Code