-
Notifications
You must be signed in to change notification settings - Fork 35
Add foundational docs: Getting Started, API Reference, History #321
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c11c217
2004e80
391951b
a31bc59
1041996
c8f9d05
0b78748
28cb2e7
df0d2ef
c7108ee
5425ba0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| # Plan: Write fresh docs for critical gaps | ||
|
|
||
| **Risk class:** LOW — new documentation pages only, no code changes | ||
| **Owner:** brianmhunt | ||
|
|
||
| ## Context | ||
|
|
||
| TKO's Starlight docs cover bindings, observables, computed, components, and binding context thoroughly — but lack foundational pages that new users need: installation, API reference, browser support, utility functions, and data serialization. Legacy Knockout docs covered these topics but are outdated. We're writing fresh content informed by the legacy structure. | ||
|
|
||
| ## New pages (5 files) | ||
|
|
||
| ### 1. `tko.io/src/content/docs/getting-started/index.md` — Installation & Setup | ||
| - Sidebar: `label: Overview, order: 0` | ||
| - CDN (ES module + classic script) for `build.reference` | ||
| - Package manager install (npm/bun/pnpm/yarn tabs) | ||
| - `build.knockout` as migration option with link to `/3to4/` | ||
| - First binding example (standalone HTML) | ||
| - TypeScript setup notes | ||
| - Landing page quick start stays as-is (quick taste vs full guide) | ||
|
|
||
| ### 2. `tko.io/src/content/docs/getting-started/browser-support.md` — Browser Support | ||
| - Modern browser engine coverage (Chromium, WebKit, Gecko) | ||
| - ES module support requirements | ||
| - Classic script fallback for older environments | ||
| - How TKO is tested (Vitest + Playwright, 3 engines in CI) | ||
|
|
||
| ### 3. `tko.io/src/content/docs/observables/utilities.md` — Utility Functions | ||
| - `ko.toJS` / `ko.toJSON` serialization | ||
| - `ko.unwrap` / `ko.isObservable` / `ko.isWritableObservable` / `ko.isComputed` | ||
| - `.fn` extensibility (`ko.observable.fn`, `ko.observableArray.fn`, etc.) | ||
| - Type hierarchy: subscribable → observable → observableArray/computed | ||
| - Working examples | ||
|
|
||
| ### 4. `tko.io/src/content/docs/observables/json-data.md` — Loading & Saving Data | ||
| - Serializing view models with `ko.toJS` / `ko.toJSON` | ||
| - Loading data into observables (manual assignment patterns) | ||
| - Fetch API examples (replacing legacy jQuery patterns) | ||
| - Debugging: rendering JSON in the UI | ||
|
|
||
| ### 5. `tko.io/src/content/docs/api.md` — API Reference | ||
| - Root-level page (add to sidebar config) | ||
| - Index/lookup table format: function name, one-liner, link to detailed page | ||
| - Organized by category: Observables, Computed, Components, Bindings, Utilities | ||
| - No full signatures — just names + links for quick navigation | ||
|
|
||
| ## Sidebar config update | ||
|
|
||
| Edit `tko.io/astro.config.mjs` to add: | ||
| ```js | ||
| { label: 'Getting Started', autogenerate: { directory: 'getting-started' } }, | ||
| // ... existing sections ... | ||
| { label: 'API Reference', slug: 'api' }, | ||
| ``` | ||
|
|
||
| Place "Getting Started" right after Introduction. Place "API Reference" before "Knockout 3 → 4 Guide". | ||
|
|
||
| ## Conventions to follow | ||
| - Frontmatter: `title` required, `description` + `sidebar` on index pages | ||
| - Filenames: kebab-case `.md` | ||
| - Code examples: use `<Tabs>` from `@astrojs/starlight/components` for multi-variant snippets (`.mdx` extension when using imports) | ||
| - Link to existing docs pages with relative paths | ||
| - Keep pages concise — reference detailed pages rather than duplicating | ||
|
|
||
| ## Files to modify | ||
| - `tko.io/astro.config.mjs` — sidebar config | ||
| - 5 new files as listed above | ||
|
|
||
| ## Verification | ||
| 1. Run `bun run dev` in `tko.io/` and check all new pages render | ||
| 2. Verify sidebar navigation order is correct | ||
| 3. Check all internal links resolve | ||
| 4. Review on mobile viewport |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| --- | ||
| title: API Reference | ||
| description: Quick-lookup index of TKO's public API. | ||
| --- | ||
|
|
||
| # API Reference | ||
|
|
||
| Quick-lookup table for TKO's public API. Each entry links to its detailed documentation. | ||
|
|
||
| ## Observables | ||
|
|
||
| | Function | Description | | ||
| |----------|-------------| | ||
| | `ko.observable(value?)` | Create a reactive value. [Docs](/observables/) | | ||
| | `ko.observableArray(array?)` | Observable wrapper around an array with mutation methods. [Docs](/observables/observablearrays/) | | ||
| | `ko.isObservable(value)` | Check if a value is an observable. [Docs](/observables/utilities/) | | ||
| | `ko.isObservableArray(value)` | Check if a value is an observable array. [Docs](/observables/utilities/) | | ||
| | `ko.isWritableObservable(value)` | Check if a value is a writable observable. [Docs](/observables/utilities/) | | ||
| | `ko.isSubscribable(value)` | Check if a value is any subscribable type. [Docs](/observables/utilities/) | | ||
| | `ko.peek(value)` | Read an observable's value without creating a dependency. | | ||
| | `ko.unwrap(value)` | Read an observable's value, or return a plain value as-is. [Docs](/observables/utilities/) | | ||
| | `ko.toJS(object)` | Clone an object tree, replacing observables with their values. [Docs](/observables/utilities/) | | ||
| | `ko.toJSON(object, replacer?, space?)` | `ko.toJS` + `JSON.stringify`. [Docs](/observables/utilities/) | | ||
|
|
||
| ## Computed | ||
|
|
||
| | Function | Description | | ||
| |----------|-------------| | ||
| | `ko.computed(evaluatorOrOptions, owner?, options?)` | Create a value that depends on other observables. Accepts a function or `{ read, write }` options object. [Docs](/computed/computedobservables/) | | ||
| | `ko.pureComputed(evaluator, owner?)` | Computed that sleeps when it has no subscribers. [Docs](/computed/computed-pure/) | | ||
| | `ko.isComputed(value)` | Check if a value is a computed observable. [Docs](/observables/utilities/) | | ||
| | `ko.isPureComputed(value)` | Check if a value is a pure computed. | | ||
| | `ko.ignoreDependencies(callback, owner?, args?)` | Run a function without tracking dependencies. | | ||
| | `ko.when(predicate, callback?, context?)` | Resolve when the predicate becomes truthy. Returns a promise, or calls callback if provided. [Docs](/observables/) | | ||
|
|
||
| ## Subscribable instance methods | ||
|
|
||
| Every observable, computed, and observable array inherits these from `subscribable.fn`: | ||
|
|
||
| | Method | Description | | ||
| |--------|-------------| | ||
| | `.subscribe(callback, target?, event?)` | Register a callback for changes. [Docs](/observables/) | | ||
| | `.when(testOrValue, returnValue?)` | Promise that resolves when the test passes. [Docs](/observables/) | | ||
| | `.yet(testOrValue, returnValue?)` | Promise that resolves when the test *fails* (negated `.when`). [Docs](/observables/) | | ||
| | `.next()` | Promise that resolves on the next value change. [Docs](/observables/) | | ||
| | `.once(callback)` | Call the callback on the next change, then auto-dispose. [Docs](/observables/) | | ||
| | `.peek()` | Read the current value without creating a dependency. | | ||
| | `.dispose()` | Tear down all subscriptions. | | ||
|
|
||
| ## Extenders | ||
|
|
||
| | Function | Description | | ||
| |----------|-------------| | ||
| | `observable.extend(extenders)` | Apply extenders to an observable or computed. [Docs](/observables/extenders/) | | ||
| | `rateLimit` | Throttle change notifications. [Docs](/observables/ratelimit-observable/) | | ||
| | `notify: 'always'` | Force notification even when value hasn't changed. [Docs](/observables/) | | ||
|
|
||
| ## Bindings | ||
|
|
||
| | Function | Description | | ||
| |----------|-------------| | ||
| | `ko.applyBindings(viewModel, rootNode?)` | Activate bindings on a DOM subtree. [Docs](/observables/#activating-knockout) | | ||
| | `ko.applyBindingsToNode(node, bindings, viewModelOrContext?)` | Apply bindings to a single node programmatically. | | ||
| | `ko.applyBindingsToDescendants(viewModelOrContext, rootNode)` | Apply bindings to descendants only (used in custom bindings). [Docs](/binding-context/custom-bindings-controlling-descendant-bindings/) | | ||
| | `ko.contextFor(node)` | Get the binding context for a DOM node. | | ||
| | `ko.dataFor(node)` | Get the view model bound to a DOM node. | | ||
| | `ko.cleanNode(node)` | Remove all TKO data and bindings from a node. | | ||
| | `ko.bindingHandlers` | Registry of built-in and custom binding handlers. [Docs](/binding-context/custom-bindings/) | | ||
| | `ko.bindingEvent` | Binding lifecycle event constants (e.g., `childrenComplete`, `descendantsComplete`). | | ||
| | `ko.BindingHandler` | Base class for class-based custom binding handlers. [Docs](/binding-context/custom-bindings/) | | ||
| | `ko.AsyncBindingHandler` | Async variant of `BindingHandler` for bindings that load resources. [Docs](/binding-context/custom-bindings/) | | ||
|
|
||
| ### Built-in bindings | ||
|
|
||
| **Text & HTML:** [`text`](/bindings/text-binding/), [`html`](/bindings/html-binding/), [`textInput`](/bindings/textinput-binding/), [`value`](/bindings/value-binding/) | ||
|
|
||
| **Appearance:** [`visible`](/bindings/visible-binding/), `hidden`, [`css`](/bindings/css-binding/) (alias: `class`), [`style`](/bindings/style-binding/), [`attr`](/bindings/attr-binding/) | ||
|
|
||
| **Control flow:** [`if`](/bindings/if-binding/), [`ifnot`](/bindings/ifnot-binding/) (alias: `unless`), `else`, `elseif`, [`foreach`](/bindings/foreach-binding/) (alias: `each`), [`with`](/bindings/with-binding/), [`template`](/bindings/template-binding/) | ||
|
|
||
| **Context:** `let`, `using` | ||
|
|
||
| **Form:** [`click`](/bindings/click-binding/), [`event`](/bindings/event-binding/) (alias: `on`), [`submit`](/bindings/submit-binding/), [`enable`](/bindings/enable-binding/), [`disable`](/bindings/disable-binding/), [`checked`](/bindings/checked-binding/), `checkedValue`, [`options`](/bindings/options-binding/), [`selectedOptions`](/bindings/selectedoptions-binding/), [`hasfocus`](/bindings/hasfocus-binding/), [`uniqueName`](/bindings/uniquename-binding/) | ||
|
|
||
| **Components:** `component`, `slot` | ||
|
|
||
| **Lifecycle:** `descendantsComplete` | ||
|
|
||
| ## Components | ||
|
|
||
| | Function | Description | | ||
| |----------|-------------| | ||
| | `ko.components.register(name, config)` | Register a component. [Docs](/components/component-registration/) | | ||
| | `ko.components.get(name)` | Retrieve a registered component definition. [Docs](/components/component-loaders/) | | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This API row omits the callback parameter, but Useful? React with 👍 / 👎. |
||
| | `ko.components.isRegistered(name)` | Check if a component name is registered. | | ||
| | `ko.components.unregister(name)` | Remove a component registration. | | ||
| | `ko.components.clearCachedDefinition(name)` | Clear a cached component definition. | | ||
| | `ko.Component` | Base class for class-based components (`ComponentABC`). [Docs](/components/) | | ||
|
|
||
| ## JSX (build.reference only) | ||
|
|
||
| | Function | Description | | ||
| |----------|-------------| | ||
| | `ko.jsx.createElement(tag, props, ...children)` | Create a JSX element. Used as the JSX factory. | | ||
| | `ko.jsx.Fragment` | Fragment component for grouping elements without a wrapper node. | | ||
| | `ko.jsx.render(jsx)` | Render JSX to DOM nodes. Returns `{ node, dispose }`. | | ||
|
|
||
| ## DOM disposal | ||
|
|
||
| | Function | Description | | ||
| |----------|-------------| | ||
| | `ko.domNodeDisposal.addDisposeCallback(node, callback)` | Run a callback when a DOM node is removed by TKO. | | ||
| | `ko.domNodeDisposal.removeDisposeCallback(node, callback)` | Remove a previously registered disposal callback. | | ||
|
|
||
| ## Extensibility | ||
|
|
||
| | Function | Description | | ||
| |----------|-------------| | ||
| | `ko.subscribable.fn` | Prototype for all subscribables. [Docs](/observables/utilities/) | | ||
| | `ko.observable.fn` | Prototype for all observables — add methods here. [Docs](/observables/utilities/) | | ||
| | `ko.observableArray.fn` | Prototype for observable arrays (`remove`, `replace`, etc.). [Docs](/observables/utilities/) | | ||
| | `ko.computed.fn` | Prototype for all computeds. [Docs](/observables/utilities/) | | ||
|
Comment on lines
+1
to
+122
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sync This PR adds substantial API and behavioral documentation, but the provided changes do not include corresponding agent-guide updates. That creates human/agent documentation drift. If helpful, I can draft the matching updates for 🤖 Prompt for AI Agents |
||
| | `ko.tasks` | Microtask scheduler for batching async work. | | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,46 @@ | ||||||
| --- | ||||||
| title: Browser Support | ||||||
| --- | ||||||
|
|
||||||
| TKO targets modern browsers — any browser that supports ES2020 and `<script type="module">`. | ||||||
|
||||||
| TKO targets modern browsers — any browser that supports ES2020 and `<script type="module">`. | |
| TKO's recommended ES module build targets modern browsers that support ES2020 and `<script type="module">`. For older non-module environments, the `dist/browser*.js` IIFE build is also available and is transpiled to ES6. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| --- | ||
| title: Deploy in Seconds | ||
| description: Deploy a TKO app to static hosting — no build step required. | ||
| --- | ||
|
|
||
| A TKO app can be as simple as a single HTML file. No bundler, no server runtime, no build step — just upload to any static hosting provider and you're live. | ||
|
|
||
| ## The simplest deploy | ||
|
|
||
| Save this as `index.html`: | ||
|
|
||
| ```html | ||
| <!doctype html> | ||
| <html> | ||
| <body> | ||
| <div id="app"> | ||
| <input data-bind="textInput: name" /> | ||
| <p>Hello, <strong data-bind="text: name"></strong>.</p> | ||
| </div> | ||
| <script src="https://cdn.jsdelivr.net/npm/@tko/build.reference/dist/browser.min.js"></script> | ||
| <script> | ||
| const ko = globalThis.tko | ||
| ko.applyBindings({ name: ko.observable('TKO') }, document.getElementById('app')) | ||
| </script> | ||
| </body> | ||
| </html> | ||
| ``` | ||
|
|
||
| Or as an ES module (no IIFE needed): | ||
|
|
||
| ```html | ||
| <script type="module"> | ||
| import ko from 'https://esm.run/@tko/build.reference' | ||
| ko.applyBindings({ name: ko.observable('TKO') }, document.getElementById('app')) | ||
| </script> | ||
| ``` | ||
|
|
||
| Upload that single file to any of the platforms below. That's it — a live, reactive web UI. | ||
|
|
||
| ## GitHub Pages | ||
|
|
||
| Free, deploys from a git push. | ||
|
|
||
| 1. Create a repo and add your `index.html` | ||
| 2. Go to **Settings → Pages → Source** and select your branch | ||
| 3. Your site is live at `https://username.github.io/repo/` | ||
|
|
||
| Or use the `gh` CLI: | ||
|
|
||
| ```sh | ||
| gh repo create my-app --public --clone | ||
| # add index.html | ||
| git add index.html && git commit -m "init" && git push | ||
| gh browse --settings # enable Pages under Settings → Pages | ||
| ``` | ||
|
|
||
| ## Cloudflare Pages | ||
|
|
||
| Free tier, global CDN, automatic HTTPS. | ||
|
|
||
| 1. Push your files to a GitHub or GitLab repo | ||
| 2. Connect the repo at [dash.cloudflare.com](https://dash.cloudflare.com) → **Pages → Create** | ||
| 3. No build command needed — just set the output directory to `/` (or wherever your HTML lives) | ||
|
|
||
| Or deploy directly from the CLI: | ||
|
|
||
| ```sh | ||
| npx wrangler pages deploy . --project-name my-app | ||
| ``` | ||
|
|
||
| ## Google Cloud Storage | ||
|
|
||
| Good for projects already on GCP. | ||
|
|
||
| ```sh | ||
| gcloud storage buckets create gs://my-app.example.com | ||
| gcloud storage buckets update gs://my-app.example.com --web-main-page-suffix=index.html | ||
| gcloud storage cp index.html gs://my-app.example.com/ | ||
| ``` | ||
|
|
||
| Add a load balancer or use [Firebase Hosting](https://firebase.google.com/docs/hosting) for automatic HTTPS and CDN. | ||
|
|
||
| ## Firebase Hosting | ||
|
|
||
| Free tier, automatic HTTPS, global CDN. | ||
|
|
||
| ```sh | ||
| npm install -g firebase-tools | ||
| firebase init hosting # select your project, set public dir to "." | ||
| firebase deploy | ||
| ``` | ||
|
|
||
| ## Netlify | ||
|
|
||
| Free tier, drag-and-drop or git-based deploys. | ||
|
|
||
| 1. Go to [app.netlify.com/drop](https://app.netlify.com/drop) | ||
| 2. Drag your project folder onto the page | ||
| 3. Live in seconds | ||
|
|
||
| Or via CLI: | ||
|
|
||
| ```sh | ||
| npx netlify-cli deploy --dir . --prod | ||
| ``` | ||
|
|
||
| ## Why this works | ||
|
|
||
| TKO loads from a CDN (`esm.run` or `jsdelivr`). Your app is just HTML + the browser's ES module loader. No server-side rendering, no Node.js, no build artifacts. The entire deploy is one file. | ||
|
|
||
| As your app grows you can add a bundler, but you don't *have* to. Many production TKO apps are a handful of HTML files and a CSS stylesheet. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per
/workspace/tko/AGENTS.md, documentation updates involving new APIs/patterns must update both Starlight docs and the agent guide (tko.io/public/agents/guide.md). This commit adds major new pages (Getting Started, API Reference, utilities/data patterns, history) but does not update the agent-facing guide, which leaves agent documentation stale and out of sync with the new canonical docs.Useful? React with 👍 / 👎.