docs: streamline quickstart and add JavaScript snippets#815
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (67)
✅ Files skipped from review due to trivial changes (55)
WalkthroughReworks many documentation pages and snippets: replaces single-language auto-generated MDX snippets with multi-language Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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 |
|
| Filename | Overview |
|---|---|
| docs/src/quickstart.mdx | Major restructure: adds JSX fast-setup panel with clipboard copy button, adds agent-only step-by-step CLI instructions, moves SDK examples to concept-page card links; the setup prompt text is duplicated across three locations (JS array, accordion, agents visibility block) |
| docs/src/style.css | Adds 130 lines of CSS for the new .notte-fast-setup component; clean, well-structured with dark/light mode variants and responsive breakpoints |
| docs/src/index.mdx | Homepage compacted from 65 to 9 lines of prose; removes inline quickstart steps, replaces OpenAPI Spec card with API Reference card, adds wide mode |
| docs/src/snippets/agents/step_limits.mdx | Converts to CodeGroup with Python/JavaScript tabs; fixes the pre-existing bug where max_steps was passed to Agent constructor instead of run() — now correctly passed to agent.run() in both language tabs |
| docs/src/snippets/agents/structured_output_example.mdx | Adds JavaScript tab using zod for schema definition; response_format receives the Zod schema object, consistent with the Python Pydantic model pattern |
| docs/src/snippets/scraping/session_based.mdx | Adds JavaScript tab that correctly mirrors the Python session-based scraping pattern with login flow and session context manager equivalent |
| docs/src/docs.json | Banner text updated to reflect the recommended skill + SDK workflow; minor wording change only |
| docs/src/concepts/agents.mdx | Swaps AgentQuickstart snippet import for the new WebAgent quickstart snippet; one-line change |
| docs/src/concepts/scraping.mdx | Replaces generic Quickstart snippet with more specific ScrapingHackerNews example; updates section intro text accordingly |
| docs/src/concepts/sessions.mdx | Replaces SessionsPython snippet with CDPSession quickstart snippet; one-line swap |
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
docs/src/quickstart.mdx:100-113
`navigator.clipboard.writeText()` returns a Promise that can reject (e.g., if the page is served in a non-secure context, or the browser denies clipboard permission). Because the call isn't awaited and there's no `.catch()`, the button always shows "Copied" regardless of whether the write actually succeeded — leaving the user thinking the prompt is on their clipboard when it isn't.
```suggestion
navigator.clipboard.writeText(notteSetupPrompt).then(() => {
button.classList.add("is-copied");
if (label) {
label.textContent = "Copied";
}
window.setTimeout(() => {
button.classList.remove("is-copied");
if (label) {
label.textContent = "Copy setup prompt";
}
}, 1600);
}).catch(() => {
if (label) {
label.textContent = "Copy failed — try again";
}
window.setTimeout(() => {
if (label) {
label.textContent = "Copy setup prompt";
}
}, 2000);
});
```
### Issue 2 of 2
docs/src/quickstart.mdx:190-259
**Setup prompt duplicated in three places**
The setup prompt text lives in three separate locations: the `notteSetupPrompt` JS array (used for clipboard copy), the `<Accordion title="View setup prompt">` block, and the `<Visibility for="agents">` section. All three are currently in sync, but a future edit to one will silently diverge from the others — the clipboard payload will no longer match what the user reads on screen. If keeping these separate is intentional, a short comment noting they must be kept in sync would help future editors.
Reviews (2): Last reviewed commit: "Address PR review feedback" | Re-trigger Greptile
e2b353b to
47ccb61
Compare
|
✅ Eval complete for commit
Ran evals with prompts: 📈 +2.5 pts · Getting Started — B (80.2/100) from B (77.7) · View metricsPrompt text:
Verdict:
Friction points:
Result: B (80.2/100) delta vs baseline: +2.5 pts
Stats: 2m 9s · 21 tool calls · 0 errors · $1.05 Evaluating agent experience using 2027.dev · View dashboard |
067bcdf to
3743f20
Compare
3743f20 to
6752795
Compare
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/src/snippets/scraping/extract_lists.mdx (1)
16-16:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winConsider making API key handling consistent between examples.
The Python example creates
NotteClient()with no arguments (line 16), while the JavaScript example explicitly passesapiKey: process.env.NOTTE_API_KEY(lines 38-40). This inconsistency may confuse users about the recommended approach for API key configuration.Consider either:
- Adding explicit API key configuration to the Python example to match JavaScript
- Omitting the explicit API key in JavaScript if both SDKs auto-detect from environment variables
- Adding a comment explaining the difference if the SDKs have different conventions
📝 Suggested fix for consistency
If both SDKs support environment variable auto-detection:
const client = new NotteClient({ - apiKey: process.env.NOTTE_API_KEY, });Or if explicit configuration is preferred:
+import os + -client = NotteClient() +client = NotteClient(api_key=os.environ["NOTTE_API_KEY"])Also applies to: 38-40
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/src/snippets/scraping/extract_lists.mdx` at line 16, The examples are inconsistent: the Python snippet constructs NotteClient() with no args while the JavaScript example passes apiKey: process.env.NOTTE_API_KEY; pick one consistent approach and update both snippets accordingly (either explicitly pass the env var in Python NotteClient(api_key=os.environ["NOTTE_API_KEY"]) and mirror the same named parameter as in the JS example, or remove the explicit apiKey from the JS example so both rely on SDK auto-detection). If the SDKs differ, add a short comment next to NotteClient() and the JS client constructor explaining that one SDK auto-detects the environment variable while the other requires explicit config.
🧹 Nitpick comments (4)
docs/src/snippets/scraping/links_and_images.mdx (1)
2-14: ⚡ Quick winUse distinct variable names for clarity and consistency.
The Python examples reuse the variable name
markdownfor all four scrape calls, which obscures which result is which. The JavaScript examples use descriptive variable names (markdownWithLinks,markdownWithoutLinks, etc.), which is clearer and models better practice for readers.♻️ Align Python variable names with JavaScript pattern
```python Python # Include links (default) -markdown = client.scrape(url, scrape_links=True) +markdown_with_links = client.scrape(url, scrape_links=True) # Exclude links -markdown = client.scrape(url, scrape_links=False) +markdown_without_links = client.scrape(url, scrape_links=False) # Include images in markdown -markdown = client.scrape(url, scrape_images=True) +markdown_with_images = client.scrape(url, scrape_images=True) # Exclude images (default) -markdown = client.scrape(url, scrape_images=False) +markdown_without_images = client.scrape(url, scrape_images=False)</details> <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.In
@docs/src/snippets/scraping/links_and_images.mdxaround lines 2 - 14, Rename
the repeated variable markdown to distinct descriptive names to match the JS
examples: change the four client.scrape(...) results to markdown_with_links
(client.scrape(url, scrape_links=True)), markdown_without_links
(client.scrape(url, scrape_links=False)), markdown_with_images
(client.scrape(url, scrape_images=True)), and markdown_without_images
(client.scrape(url, scrape_images=False)) so callers can clearly see which
scrape options produced each value.</details> </blockquote></details> <details> <summary>docs/src/snippets/scraping/extract_lists.mdx (1)</summary><blockquote> `24-50`: _⚡ Quick win_ **Clarify async context requirement for JavaScript example.** The JavaScript snippet uses `await` on line 42 without an explicit async function wrapper. While top-level await is valid in ES modules, users who copy-paste this code into a non-module context (e.g., a CommonJS script or script tag) will encounter a syntax error. Consider one of these approaches: 1. Wrap the code in an async IIFE or function to make it universally compatible 2. Add a comment indicating this requires ES module context with top-level await support <details> <summary>♻️ Suggested approaches</summary> **Option 1: Wrap in async function (universally compatible)** ```diff ```javascript JavaScript import { z } from 'zod'; import { NotteClient } from 'notte-sdk'; const Article = z.object({ title: z.string(), url: z.string(), summary: z.string(), }); const ArticleList = z.object({ articles: z.array(Article), }); +(async () => { const client = new NotteClient({ apiKey: process.env.NOTTE_API_KEY, }); const articles = await client.scrape('https://news.example.com', { response_format: ArticleList, instructions: 'Extract all articles from the homepage', }); for (const article of articles.articles) { console.log(`${article.title}: ${article.url}`); } +})();**Option 2: Add clarifying comment** ```diff ```javascript JavaScript +// This example uses top-level await (requires ES modules) import { z } from 'zod'; import { NotteClient } from 'notte-sdk';🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/src/snippets/scraping/extract_lists.mdx` around lines 24 - 50, The snippet uses top-level await on client.scrape (with symbols NotteClient, client, and ArticleList) which will break in non-ESM contexts; wrap the usage of await (the client creation, the await client.scrape call, and the for-loop over articles.articles) inside an async IIFE (e.g., (async () => { ... })()) to make it universally compatible, or alternatively add a clear comment above the imports stating "requires ES modules / top-level await" if you prefer to leave top-level await in place.docs/src/snippets/scraping/instructions_only.mdx (1)
19-19: 💤 Low valueTop-level await may not work in all environments.
The example uses
awaitwithout an async function wrapper. While modern Node.js (v14.8+) and bundlers support top-level await, this may fail in older environments or certain module systems. For documentation examples aimed at broad compatibility, consider wrapping in an async IIFE or noting the requirement.♻️ Wrap in async function for broader compatibility
```javascript JavaScript import { NotteClient } from 'notte-sdk'; -const client = new NotteClient({ - apiKey: process.env.NOTTE_API_KEY, -}); - -const result = await client.scrape('https://example.com/article', { - instructions: 'Extract the article title, author, and publication date', -}); - -console.log(result); +(async () => { + const client = new NotteClient({ + apiKey: process.env.NOTTE_API_KEY, + }); + + const result = await client.scrape('https://example.com/article', { + instructions: 'Extract the article title, author, and publication date', + }); + + console.log(result); +})();</details> <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.In
@docs/src/snippets/scraping/instructions_only.mdxat line 19, The example
uses top-level await with client.scrape which can break in older runtimes; wrap
the snippet in an async function/IIFE (e.g., create a minimal async wrapper that
constructs NotteClient, calls client.scrape, and logs the result) or add a short
note that top-level await requires modern Node/bundler support so readers know
to run inside an async context when using NotteClient and the result variable.</details> </blockquote></details> <details> <summary>docs/src/snippets/scraping/structured_data_response.mdx (1)</summary><blockquote> `32-32`: _💤 Low value_ **Consider the same top-level await concern.** This example has the same top-level `await` usage as in `instructions_only.mdx`. For consistency and broader compatibility, consider applying the same async wrapper pattern if you address it in other JavaScript examples. <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.In
@docs/src/snippets/scraping/structured_data_response.mdxat line 32, Example
uses top-level await with client.scrape; wrap that call in an async function
(e.g., async function main() { ... } ) or an async IIFE (e.g., (async () => {
... })()) to avoid top-level await and match other examples; move the const
product = await client.scrape(url, { ... }) inside that async wrapper and invoke
the wrapper so the snippet runs in environments without top-level await while
keeping the same client.scrape usage.</details> </blockquote></details> </blockquote></details> <details> <summary>🤖 Prompt for all review comments with AI agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.Inline comments:
In@docs/src/quickstart.mdx:
- Around line 10-80: The same setup markdown is duplicated across the exported
notteSetupPrompt constant and two rendered blocks (the accordion markdown and
the agent-facing Visibility block); extract that markdown into a single shared
MDX snippet (e.g., SetupInstructions component in
snippets/quickstart/setup_instructions.mdx), import and render
in place of the inline accordion content and the
Visibility(for="agents") content, and then have notteSetupPrompt either be
generated programmatically from that shared source or kept as a minimal copy
that is produced from the shared snippet to avoid manual duplication; update
imports/references in the file to use the new SetupInstructions component and
remove the three inline copies.In
@docs/src/snippets/scraping/data_collection.mdx:
- Around line 26-53: The snippet incorrectly shows a JavaScript usage of a
non-existent JS package ("import { NotteClient } from 'notte-sdk'")—remove or
replace the entire JS block that defines ProductInfo, NotteClient, client.scrape
and response_format; instead provide a working Python example using the real pip
package (import from notte_sdk, instantiate NotteClient, call client.scrape in
Python and validate/output results) or remove the example entirely so docs don’t
reference the nonexistent JavaScript SDK. Ensure any identifiers from the diff
(ProductInfo, NotteClient, client.scrape, response_format) are removed or
replaced with their Python equivalents in the new snippet.In
@docs/src/snippets/scraping/image_extraction.mdx:
- Line 5: Update the Python snippet to explicitly pass the API key to
NotteClient by importing os and calling os.getenv("NOTTE_API_KEY") when
constructing NotteClient (replace the existing client = NotteClient() usage);
add the import os at the top of the snippet so the os.getenv call resolves.In
@docs/src/snippets/scraping/structured_data_response.mdx:
- Around line 18-38: The JavaScript example using NotteClient and client.scrape
with the Product zod schema is incorrect because notte-sdk is Python-only;
remove the JS code block or replace it with a clear note that the SDK currently
supports Python only and that NotteClient, client.scrape and the shown import
are not available in JavaScript/Node.js. Locate the snippet containing the
Product schema, NotteClient import, and client.scrape usage and either delete
that code block or prepend a short explanatory sentence clarifying Python-only
support and linking to the correct Python example instead.In
@docs/src/style.css:
- Line 150: The CSS uses the color keyword "currentColor" with uppercase C which
violates stylelint's value-keyword-case rule; update the value in the
declaration where "border: 0.13em solid currentColor;" is defined to use the
lowercase "currentcolor" so the property becomes "border: 0.13em solid
currentcolor;" ensuring consistent keyword casing for the border style.
Outside diff comments:
In@docs/src/snippets/scraping/extract_lists.mdx:
- Line 16: The examples are inconsistent: the Python snippet constructs
NotteClient() with no args while the JavaScript example passes apiKey:
process.env.NOTTE_API_KEY; pick one consistent approach and update both snippets
accordingly (either explicitly pass the env var in Python
NotteClient(api_key=os.environ["NOTTE_API_KEY"]) and mirror the same named
parameter as in the JS example, or remove the explicit apiKey from the JS
example so both rely on SDK auto-detection). If the SDKs differ, add a short
comment next to NotteClient() and the JS client constructor explaining that one
SDK auto-detects the environment variable while the other requires explicit
config.
Nitpick comments:
In@docs/src/snippets/scraping/extract_lists.mdx:
- Around line 24-50: The snippet uses top-level await on client.scrape (with
symbols NotteClient, client, and ArticleList) which will break in non-ESM
contexts; wrap the usage of await (the client creation, the await client.scrape
call, and the for-loop over articles.articles) inside an async IIFE (e.g.,
(async () => { ... })()) to make it universally compatible, or alternatively add
a clear comment above the imports stating "requires ES modules / top-level
await" if you prefer to leave top-level await in place.In
@docs/src/snippets/scraping/instructions_only.mdx:
- Line 19: The example uses top-level await with client.scrape which can break
in older runtimes; wrap the snippet in an async function/IIFE (e.g., create a
minimal async wrapper that constructs NotteClient, calls client.scrape, and logs
the result) or add a short note that top-level await requires modern
Node/bundler support so readers know to run inside an async context when using
NotteClient and the result variable.In
@docs/src/snippets/scraping/links_and_images.mdx:
- Around line 2-14: Rename the repeated variable markdown to distinct
descriptive names to match the JS examples: change the four client.scrape(...)
results to markdown_with_links (client.scrape(url, scrape_links=True)),
markdown_without_links (client.scrape(url, scrape_links=False)),
markdown_with_images (client.scrape(url, scrape_images=True)), and
markdown_without_images (client.scrape(url, scrape_images=False)) so callers can
clearly see which scrape options produced each value.In
@docs/src/snippets/scraping/structured_data_response.mdx:
- Line 32: Example uses top-level await with client.scrape; wrap that call in an
async function (e.g., async function main() { ... } ) or an async IIFE (e.g.,
(async () => { ... })()) to avoid top-level await and match other examples; move
the const product = await client.scrape(url, { ... }) inside that async wrapper
and invoke the wrapper so the snippet runs in environments without top-level
await while keeping the same client.scrape usage.</details> <details> <summary>🪄 Autofix (Beta)</summary> Fix all unresolved CodeRabbit comments on this PR: - [ ] <!-- {"checkboxId": "4b0d0e0a-96d7-4f10-b296-3a18ea78f0b9"} --> Push a commit to this branch (recommended) - [ ] <!-- {"checkboxId": "ff5b1114-7d8c-49e6-8ac1-43f82af23a33"} --> Create a new PR with the fixes </details> --- <details> <summary>ℹ️ Review info</summary> <details> <summary>⚙️ Run configuration</summary> **Configuration used**: Path: .coderabbit.yaml **Review profile**: CHILL **Plan**: Pro **Run ID**: `b5289bf8-4c24-483e-b772-d93fb6a6f946` </details> <details> <summary>📥 Commits</summary> Reviewing files that changed from the base of the PR and between 767ce1108436fc2d3a898564549c487b2376960a and 6752795550fce90fdc3a827c3d074cf3382cffa7. </details> <details> <summary>📒 Files selected for processing (32)</summary> * `docs/src/concepts/agents.mdx` * `docs/src/concepts/scraping.mdx` * `docs/src/concepts/sessions.mdx` * `docs/src/docs.json` * `docs/src/index.mdx` * `docs/src/quickstart.mdx` * `docs/src/snippets/agents/error_handling.mdx` * `docs/src/snippets/agents/natural_language_task.mdx` * `docs/src/snippets/agents/starting_url.mdx` * `docs/src/snippets/agents/step_limits.mdx` * `docs/src/snippets/agents/structured_output_example.mdx` * `docs/src/snippets/pages/linkedin_step.mdx` * `docs/src/snippets/scraping/content_filtering.mdx` * `docs/src/snippets/scraping/content_monitoring.mdx` * `docs/src/snippets/scraping/data_collection.mdx` * `docs/src/snippets/scraping/extract_lists.mdx` * `docs/src/snippets/scraping/handle_missing_data.mdx` * `docs/src/snippets/scraping/image_extraction.mdx` * `docs/src/snippets/scraping/instructions_only.mdx` * `docs/src/snippets/scraping/link_placeholders.mdx` * `docs/src/snippets/scraping/links_and_images.mdx` * `docs/src/snippets/scraping/nested_structures.mdx` * `docs/src/snippets/scraping/precise_schemas.mdx` * `docs/src/snippets/scraping/pydantic_model.mdx` * `docs/src/snippets/scraping/quick_scrape.mdx` * `docs/src/snippets/scraping/research_analysis.mdx` * `docs/src/snippets/scraping/scope_scrapes.mdx` * `docs/src/snippets/scraping/scoped_scraping.mdx` * `docs/src/snippets/scraping/session_based.mdx` * `docs/src/snippets/scraping/specific_instructions.mdx` * `docs/src/snippets/scraping/structured_data_response.mdx` * `docs/src/style.css` </details> </details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
- Add run() call to step_limits agent snippets (Python + JS) so max_steps is actually exercised - Fix currentColor → currentcolor CSS keyword casing Co-Authored-By: Claude <noreply@anthropic.com>
|
@greptileai review |
- Update step_limits.py tester to include run() call - Skip regenerating MDX files that were manually edited (no auto-generated header), preserving CodeGroup JS blocks - Change agent list to "etc." in quickstart copy Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/src/quickstart.mdx`:
- Around line 96-113: The onClick handler currently sets the copied UI state
immediately without checking navigator.clipboard.writeText; modify the handler
around notteSetupPrompt so the UI (button.classList.add("is-copied") and
label.textContent = "Copied") is only applied after writeText succeeds (use
await or .then), and add an error path (catch) that leaves the button unchanged
and updates the label or shows an error message (e.g., "Copy failed" or a
tooltip) so failures (permission/insecure context) are surfaced; ensure the
existing timeout that removes "is-copied" and resets the label only runs for the
success path.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: ac78660f-efe4-412b-8ff2-cb98a39fcf36
📒 Files selected for processing (3)
docs/src/quickstart.mdxdocs/src/sniptest/generate.pydocs/src/testers/agents/step_limits.py
There was a problem hiding this comment.
LGTM
The two follow-up commits (d48032e, cf12555) are SDK doc generation alignment fixes with no new logic. All previous feedback was addressed in earlier commits. PR is clean.
Tag @mendral-app with feedback or questions. View session
Summary
Checks
Stacked on #814.
Note
Streamlines the docs homepage and quickstart: collapses index.mdx to a compact intro + card group, adds a human-facing "fast setup" copy-prompt panel for AI coding agents, rewrites the agent-facing quickstart as step-by-step CLI instructions, converts concept-page code examples from Python-only to Python/JavaScript CodeGroups, and fixes the sniptest tooling to skip manually-edited MDX files.
Written by Mendral for commit cf12555.
Summary by CodeRabbit
Documentation
New Features
Style
Chores