From 607e1077598f21320951f31e487c6f0530bf3ddf Mon Sep 17 00:00:00 2001 From: Honza Javorek Date: Wed, 16 Sep 2026 10:02:08 +0200 Subject: [PATCH 01/17] remove unused import --- sources/platform/actors/development/quick-start/locally.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/sources/platform/actors/development/quick-start/locally.mdx b/sources/platform/actors/development/quick-start/locally.mdx index 1b3482d8e2..5de3b76c69 100644 --- a/sources/platform/actors/development/quick-start/locally.mdx +++ b/sources/platform/actors/development/quick-start/locally.mdx @@ -8,7 +8,6 @@ pagination_next: null pagination_prev: null --- -import PromptButton from "@site/src/components/PromptButton"; import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem"; From d561ea60a0302a64458c87217ac8fb0834feae71 Mon Sep 17 00:00:00 2001 From: Honza Javorek Date: Wed, 16 Sep 2026 10:05:28 +0200 Subject: [PATCH 02/17] drop the default prompt (unused anyway) --- src/components/PromptButton.jsx | 3 +- src/utils/quick-start-prompt.js | 59 --------------------------------- 2 files changed, 1 insertion(+), 61 deletions(-) delete mode 100644 src/utils/quick-start-prompt.js diff --git a/src/components/PromptButton.jsx b/src/components/PromptButton.jsx index 3c2a666c1e..495e04d658 100644 --- a/src/components/PromptButton.jsx +++ b/src/components/PromptButton.jsx @@ -1,10 +1,9 @@ import React, { useEffect, useRef, useState } from 'react'; -import { QUICK_START_PROMPT } from '../utils/quick-start-prompt'; import styles from './PromptButton.module.css'; export default function PromptButton({ - prompt = QUICK_START_PROMPT, + prompt, title = 'Use pre-built prompt to get started faster.', }) { const [copied, setCopied] = useState(false); diff --git a/src/utils/quick-start-prompt.js b/src/utils/quick-start-prompt.js deleted file mode 100644 index e62631d242..0000000000 --- a/src/utils/quick-start-prompt.js +++ /dev/null @@ -1,59 +0,0 @@ -export const QUICK_START_PROMPT = `Follow this step-by-step workflow:: - -**Step 1: Verify prerequisites** - -First, verify the user's environment by running these commands: - -\`\`\`bash -node --version # Requires Node.js 20 or higher -npm --version -apify --version # Check if Apify CLI is already installed -\`\`\` - -If any prerequisites are missing, guide the user through installation before proceeding. - -**Step 2: Install/Update Apify CLI** -\`\`\`bash -npm install -g apify-cli -\`\`\` - -**Step 3: Create a new Actor** - -**Note for AI tools**: If you're an AI assistant that cannot run interactive commands (like the Gemini CLI), inform the user that the \`apify create\` command requires interactive input and cannot be executed automatically. Suggest they run this workflow in tools that support interactive commands like Cursor, or GitHub Copilot. - -Explain that this will prompt for actor name and template selection. - -\`\`\`bash -apify create -\`\`\` - -Direct users to explore templates at https://apify.com/templates. - -**Step 4: Navigate to the Actor directory** - -\`\`\`bash -cd [actor-name] # Use the actual name they chose in step 3 -\`\`\` - -**Step 5: Run the Actor locally** - -Explain that this will run the actor locally. - -\`\`\`bash -apify run -\`\`\` - -**Step 6: Next steps** - -Explain that the user can deploy the actor to Apify, but they first need to log in to Apify: - -\`\`\`bash -apify login -\`\`\` - -After logging in, you can deploy the actor to Apify: - -\`\`\`bash -apify push -\`\`\` -`; From aecda0d1cf2eab933d17949e3eaff30eb43ee848 Mon Sep 17 00:00:00 2001 From: Honza Javorek Date: Wed, 16 Sep 2026 10:08:40 +0200 Subject: [PATCH 03/17] change default title and use it --- .../promoting-your-actor/checklist.md | 22 +++++++++---------- src/components/PromptButton.jsx | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/sources/academy/build-and-publish/promoting-your-actor/checklist.md b/sources/academy/build-and-publish/promoting-your-actor/checklist.md index 9516305485..6dd2624457 100644 --- a/sources/academy/build-and-publish/promoting-your-actor/checklist.md +++ b/sources/academy/build-and-publish/promoting-your-actor/checklist.md @@ -41,7 +41,7 @@ Twitter's developer community is active and engaged. A well-crafted tweet with a Create a 30-60-second demo video or gif showing your Actor in action. Include relevant hashtags like #webscraping, #API, #automation, and #buildinpublic. - + ### Share on LinkedIn with a demo @@ -49,7 +49,7 @@ LinkedIn reaches professionals, decision-makers, and business users with purchas Create a 30-90-second demo video showing your Actor delivering business value. Upload the video directly to LinkedIn (native videos perform better than YouTube links). Focus your post on the business problem solved, not technical features. Use 3-5 relevant hashtags like #BusinessAutomation, #Productivity, #DataIntelligence, #Efficiency, or #MarketResearch. - + ### Post in relevant Discord and Slack communities @@ -168,7 +168,7 @@ Write a comprehensive "Best [CATEGORY]" roundup article (1,800-2,500 words) feat Write in first person with a conversational yet professional tone. Include pros and cons for each solution, add a comparison table, and share your genuine perspective. - + ### Create a "Best X" article for dev.to @@ -178,7 +178,7 @@ Write a developer-focused "Best [CATEGORY] for Developers" article (1,500-2,000 Write like you're advising a fellow developer: casual and helpful. Be genuinely objective about all tools, include code examples or API snippets where relevant, and use markdown formatting with H2/H3 headers. - + ### Create a "Best X" article for Hashnode @@ -188,7 +188,7 @@ Write a technical "Best [CATEGORY] for [SPECIFIC USE CASE]: A Developer's Guide" Include a TL;DR section at the top, use proper heading hierarchy for auto-generated table of contents, and add code examples with proper syntax highlighting. Write with technical authority but remain accessible. - + ### Create a "Best X" article for LinkedIn @@ -198,7 +198,7 @@ Write a business-focused "Best [CATEGORY] for [BUSINESS OUTCOME]" article (1,200 Use a professional, authoritative but accessible tone. Focus on business impact like time savings, cost efficiency, ROI, and productivity gains rather than technical features. Include comparison tables with business-relevant metrics. - + ### Create a "How to use [Actor]" tutorial for dev.to @@ -208,7 +208,7 @@ Write a step-by-step tutorial (1,200-2,000 words) showing developers how to use Structure: Introduction with hook, prerequisites, what they'll achieve, step-by-step guide (access the Actor, configure inputs, run it, view results, download data), understanding results, pro tips, troubleshooting, and next steps. Write like you're helping a friend get started. - + ### Create a "How to use [Actor]" tutorial for Hashnode @@ -218,7 +218,7 @@ Write a comprehensive "Complete Guide: How to [ACHIEVE OUTCOME] Using [YOUR ACTO Include a TL;DR section, detailed step-by-step walkthrough with screenshots, API integration examples with code blocks, advanced usage patterns, troubleshooting guide, and best practices. Write with technical authority, but be thorough and maintain clarity. - + ### Create a "How to use [Actor]" tutorial for Medium @@ -228,7 +228,7 @@ Write an accessible, engaging tutorial "How I [ACHIEVED OUTCOME] in Minutes Usin Take a story-driven approach with personal context. Write in first person, use simple jargon-free language, and make readers feel "I can do this too." Focus on the outcome and value, not technical complexity. - + ### Create a "How to use [Actor]" tutorial for LinkedIn @@ -238,7 +238,7 @@ Write a professional "How to [ACHIEVE BUSINESS OUTCOME] in [TIME] Using [YOUR AC Use professional, consultative tone focused on business value. Emphasize time savings, efficiency, and ROI. Include sections on business case, measuring success, professional best practices, and real-world business applications. Address common professional questions about security, cost, reliability, and team adoption. - + --- @@ -252,7 +252,7 @@ Create a GitHub repo with code examples, integration guides, or sample projects Your README should include: project title with badges, short description, key features, quick start guide, installation and setup instructions, usage examples with code snippets, use cases section, configuration options, common questions and troubleshooting, links to Apify Store and documentation, contributing guidelines, and license. - + --- diff --git a/src/components/PromptButton.jsx b/src/components/PromptButton.jsx index 495e04d658..a214138f56 100644 --- a/src/components/PromptButton.jsx +++ b/src/components/PromptButton.jsx @@ -4,7 +4,7 @@ import styles from './PromptButton.module.css'; export default function PromptButton({ prompt, - title = 'Use pre-built prompt to get started faster.', + title = 'Use pre-built prompt for your AI assistant', }) { const [copied, setCopied] = useState(false); const [showPrompt, setShowPrompt] = useState(false); From a4112083e97cd9b23d1cf8d81bf23682013213f8 Mon Sep 17 00:00:00 2001 From: Honza Javorek Date: Wed, 16 Sep 2026 10:10:12 +0200 Subject: [PATCH 04/17] the word 'coding' is not worth setting an explicit title --- .../platform/actors/development/quick-start/build-with-ai.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/platform/actors/development/quick-start/build-with-ai.md b/sources/platform/actors/development/quick-start/build-with-ai.md index 71ab1eb640..25bf191cfe 100644 --- a/sources/platform/actors/development/quick-start/build-with-ai.md +++ b/sources/platform/actors/development/quick-start/build-with-ai.md @@ -53,7 +53,7 @@ The methods on this page are complementary. Start with the [AI coding assistant Use the following prompt in your AI coding assistant such as [Cursor](https://cursor.com/), [Claude Code](https://claude.com/product/claude-code), or [GitHub Copilot](https://github.com/features/copilot): - + The prompt guides your AI coding assistant to create and deploy an Apify Actor step by step. It walks through setting up the Actor structure, configuring all required files, installing dependencies, running it locally, logging in, and pushing it to the Apify platform. From 0ec30af3f6d2d8813d7044a664c95e98462c8bae Mon Sep 17 00:00:00 2001 From: Honza Javorek Date: Wed, 16 Sep 2026 10:16:12 +0200 Subject: [PATCH 05/17] change the default prompt title --- src/components/PromptButton.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/PromptButton.jsx b/src/components/PromptButton.jsx index a214138f56..f8ff2f1710 100644 --- a/src/components/PromptButton.jsx +++ b/src/components/PromptButton.jsx @@ -4,7 +4,7 @@ import styles from './PromptButton.module.css'; export default function PromptButton({ prompt, - title = 'Use pre-built prompt for your AI assistant', + title = 'Ready-to-use prompt for your AI assistant', }) { const [copied, setCopied] = useState(false); const [showPrompt, setShowPrompt] = useState(false); From 2fd09f60c55d11e42b4f3f8c01b1f774050773ca Mon Sep 17 00:00:00 2001 From: Honza Javorek Date: Wed, 16 Sep 2026 10:24:11 +0200 Subject: [PATCH 06/17] make the two boxes appear as one when open --- src/components/PromptButton.jsx | 2 +- src/components/PromptButton.module.css | 21 +++++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/components/PromptButton.jsx b/src/components/PromptButton.jsx index f8ff2f1710..9cfd5412ac 100644 --- a/src/components/PromptButton.jsx +++ b/src/components/PromptButton.jsx @@ -47,7 +47,7 @@ export default function PromptButton({ return ( <> -
+
{title} diff --git a/src/components/PromptButton.module.css b/src/components/PromptButton.module.css index 598a6c9e3b..aef6f2686e 100644 --- a/src/components/PromptButton.module.css +++ b/src/components/PromptButton.module.css @@ -13,8 +13,20 @@ margin-bottom: 0; } +/* Flatten the shared edge so the toggle card and the revealed prompt read as one box */ +.prompt-card.open { + border-bottom: none; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +.prompt-card.open::before { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + /* Apply margin-bottom only when the next sibling is not a heading */ -.prompt-card:not(:has(+ h1, + h2, + h3, + h4, + h5, + h6)), +.prompt-card:not(.open):not(:has(+ h1, + h2, + h3, + h4, + h5, + h6)), .full-prompt-container:not(:has(+ h1, + h2, + h3, + h4, + h5, + h6)) { margin-bottom: var(--ifm-leading); } @@ -158,7 +170,7 @@ html[data-theme='dark'] .toggle-button:hover { } .full-prompt-container { - margin-top: 1.2rem; + margin-top: 0; width: 100%; } @@ -166,8 +178,9 @@ html[data-theme='dark'] .toggle-button:hover { margin-top: 0; background: var(--ifm-background-color); border: 1px solid var(--ifm-color-emphasis-200); - border-radius: 8px; - box-shadow: 0 1.5px 3px 0 rgb(0 0 0 / 15%); + border-top: none; + border-radius: 0 0 8px 8px; + box-shadow: none; } .full-prompt pre { From ce34901cc86e5a87e614dd4e323afa4f0f1eb65b Mon Sep 17 00:00:00 2001 From: Honza Javorek Date: Wed, 16 Sep 2026 13:34:54 +0200 Subject: [PATCH 07/17] add a new component for prompt example --- src/components/PromptExample.jsx | 56 ++++++++++++++++++++++++ src/components/PromptExample.module.css | 57 +++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 src/components/PromptExample.jsx create mode 100644 src/components/PromptExample.module.css diff --git a/src/components/PromptExample.jsx b/src/components/PromptExample.jsx new file mode 100644 index 0000000000..ac33fb97c5 --- /dev/null +++ b/src/components/PromptExample.jsx @@ -0,0 +1,56 @@ +import React, { useEffect, useRef, useState } from 'react'; + +import styles from './PromptExample.module.css'; + +export default function PromptExample({ children }) { + const [copied, setCopied] = useState(false); + const timeoutRef = useRef(null); + const blockquoteRef = useRef(null); + + useEffect(() => { + return () => { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + } + }; + }, []); + + const handleCopy = async () => { + if (window.analytics) { + window.analytics.track('Clicked', { + app: 'docs', + button_text: 'Copy prompt', + element: 'prompt-example.copyButton', + }); + } + + try { + await navigator.clipboard.writeText(blockquoteRef.current.textContent); + + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + } + + setCopied(true); + timeoutRef.current = setTimeout(() => setCopied(false), 2000); + } catch (err) { + console.error('Failed to copy prompt:', err); + } + }; + + return ( +
+
+ {children} +
+
+ +
+
+ ); +} diff --git a/src/components/PromptExample.module.css b/src/components/PromptExample.module.css new file mode 100644 index 0000000000..a2abddf802 --- /dev/null +++ b/src/components/PromptExample.module.css @@ -0,0 +1,57 @@ +.prompt-example-container { + background: var(--ifm-background-color); + border: 1px solid var(--ifm-color-emphasis-200); + border-radius: 8px; + padding: 1.6rem; + box-shadow: 0 1.5px 3px 0 rgb(0 0 0 / 15%); + margin-bottom: var(--ifm-leading); +} + +.prompt-example.prompt-example { + background: var(--ifm-pre-background); + border: none; + border-radius: 4px; + box-shadow: none; + margin: 0 0 1.2rem; + padding: 1rem; + color: var(--ifm-color-content); + font-family: var(--ifm-font-family-monospace); + font-size: 1.3rem; + line-height: 1.5; + white-space: pre-wrap; + word-wrap: break-word; +} + +.button-container { + display: flex; + justify-content: flex-end; +} + +.copy-button { + width: 150px; + background: var(--ifm-color-primary); + color: var(--ifm-color-primary-contrast-background); + border: 1px solid var(--ifm-color-primary); + border-radius: 6px; + padding: 0.8rem 1.6rem; + font-size: 1.4rem; + font-weight: 500; + cursor: pointer; + transition: all var(--ifm-transition-fast) ease; + white-space: nowrap; +} + +.copy-button:hover { + background: var(--ifm-color-primary-darker); + border-color: var(--ifm-color-primary-darker); +} + +.copy-button.copied { + background: var(--ifm-color-success); + border-color: var(--ifm-color-success); +} + +.copy-button.copied:hover { + background: var(--ifm-color-success-darker); + border-color: var(--ifm-color-success-darker); +} From 6e52a70c73483b67439b93672fe58af7c8ba2668 Mon Sep 17 00:00:00 2001 From: Honza Javorek Date: Wed, 16 Sep 2026 13:35:14 +0200 Subject: [PATCH 08/17] use the new component (just once for a test) --- .../02_developing_scraper_ai_agent.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sources/academy/platform/scraping_with_apify_and_ai/02_developing_scraper_ai_agent.md b/sources/academy/platform/scraping_with_apify_and_ai/02_developing_scraper_ai_agent.md index 28a08866fe..f94ed9f1f2 100644 --- a/sources/academy/platform/scraping_with_apify_and_ai/02_developing_scraper_ai_agent.md +++ b/sources/academy/platform/scraping_with_apify_and_ai/02_developing_scraper_ai_agent.md @@ -5,6 +5,8 @@ slug: /scraping-with-apify-and-ai/developing-scraper-with-ai-agent unlisted: true --- +import PromptExample from '@site/src/components/PromptExample'; + **In this lesson, we'll keep improving our app for tracking prices on an e-commerce website. We'll get its code onto our computer and use Cursor to streamline how we update our scraper.** --- @@ -228,10 +230,8 @@ In the previous lesson, we noticed that the prices in our resulting dataset are Let's change that. We'll prompt the agent like this, with a clear example of what we want: -```text -Change the code so that the Actor saves prices as numbers. -Because some prices are "from", let's call the "price" field -"minPrice" instead, as in minimum price. Example follows. + +Change the code so that the Actor saves prices as numbers. Because some prices are "from", let's call the "price" field "minPrice" instead, as in minimum price. Example follows. Before: Sale price$74.95 @@ -242,7 +242,7 @@ After: 74.95 1398.00 158.00 -``` + When the agent is done, we'll approve the changes and verify in the command line that the Actor runs locally: From 716c14029128cefca3d1757753ebe48bdc2e6d63 Mon Sep 17 00:00:00 2001 From: Honza Javorek Date: Wed, 16 Sep 2026 15:05:41 +0200 Subject: [PATCH 09/17] make linters happy --- src/components/PromptButton.jsx | 5 +---- src/components/PromptExample.jsx | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/components/PromptButton.jsx b/src/components/PromptButton.jsx index 9cfd5412ac..0cf832ab7e 100644 --- a/src/components/PromptButton.jsx +++ b/src/components/PromptButton.jsx @@ -2,10 +2,7 @@ import React, { useEffect, useRef, useState } from 'react'; import styles from './PromptButton.module.css'; -export default function PromptButton({ - prompt, - title = 'Ready-to-use prompt for your AI assistant', -}) { +export default function PromptButton({ prompt, title = 'Ready-to-use prompt for your AI assistant' }) { const [copied, setCopied] = useState(false); const [showPrompt, setShowPrompt] = useState(false); const timeoutRef = useRef(null); diff --git a/src/components/PromptExample.jsx b/src/components/PromptExample.jsx index ac33fb97c5..9f543b085b 100644 --- a/src/components/PromptExample.jsx +++ b/src/components/PromptExample.jsx @@ -44,10 +44,7 @@ export default function PromptExample({ children }) { {children}
-
From 82c731b19ba4312b895a787fef82fd59d550f66c Mon Sep 17 00:00:00 2001 From: Honza Javorek Date: Wed, 16 Sep 2026 15:06:45 +0200 Subject: [PATCH 10/17] fix for prompt not being present in llm.txt --- src/components/PromptButton.jsx | 13 +++++++------ src/components/PromptButton.module.css | 5 +++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/components/PromptButton.jsx b/src/components/PromptButton.jsx index 0cf832ab7e..78b7bcb7b1 100644 --- a/src/components/PromptButton.jsx +++ b/src/components/PromptButton.jsx @@ -59,13 +59,14 @@ export default function PromptButton({ prompt, title = 'Ready-to-use prompt for
- {showPrompt && ( -
-
-
{prompt}
-
+ {/* Always rendered (not gated on showPrompt) so the prompt text is present in the + static HTML and gets picked up by the llms.txt generator; visibility for human + readers is controlled purely by CSS via the "visible" class below. */} +
+
+
{prompt}
- )} +
); } diff --git a/src/components/PromptButton.module.css b/src/components/PromptButton.module.css index aef6f2686e..f8ea695739 100644 --- a/src/components/PromptButton.module.css +++ b/src/components/PromptButton.module.css @@ -170,10 +170,15 @@ html[data-theme='dark'] .toggle-button:hover { } .full-prompt-container { + display: none; margin-top: 0; width: 100%; } +.full-prompt-container.visible { + display: block; +} + .full-prompt-container .full-prompt { margin-top: 0; background: var(--ifm-background-color); From a6faf2c8fd9d8dc19d850b8d23d5d6f6952fd561 Mon Sep 17 00:00:00 2001 From: Honza Javorek Date: Wed, 16 Sep 2026 15:23:39 +0200 Subject: [PATCH 11/17] allow PromptButton not to be collapsed --- .../promoting-your-actor/checklist.md | 22 +++++++++---------- .../development/quick-start/build-with-ai.md | 2 +- src/components/PromptButton.jsx | 16 +++++++++----- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/sources/academy/build-and-publish/promoting-your-actor/checklist.md b/sources/academy/build-and-publish/promoting-your-actor/checklist.md index 6dd2624457..f593f952d9 100644 --- a/sources/academy/build-and-publish/promoting-your-actor/checklist.md +++ b/sources/academy/build-and-publish/promoting-your-actor/checklist.md @@ -41,7 +41,7 @@ Twitter's developer community is active and engaged. A well-crafted tweet with a Create a 30-60-second demo video or gif showing your Actor in action. Include relevant hashtags like #webscraping, #API, #automation, and #buildinpublic. - + ### Share on LinkedIn with a demo @@ -49,7 +49,7 @@ LinkedIn reaches professionals, decision-makers, and business users with purchas Create a 30-90-second demo video showing your Actor delivering business value. Upload the video directly to LinkedIn (native videos perform better than YouTube links). Focus your post on the business problem solved, not technical features. Use 3-5 relevant hashtags like #BusinessAutomation, #Productivity, #DataIntelligence, #Efficiency, or #MarketResearch. - + ### Post in relevant Discord and Slack communities @@ -168,7 +168,7 @@ Write a comprehensive "Best [CATEGORY]" roundup article (1,800-2,500 words) feat Write in first person with a conversational yet professional tone. Include pros and cons for each solution, add a comparison table, and share your genuine perspective. - + ### Create a "Best X" article for dev.to @@ -178,7 +178,7 @@ Write a developer-focused "Best [CATEGORY] for Developers" article (1,500-2,000 Write like you're advising a fellow developer: casual and helpful. Be genuinely objective about all tools, include code examples or API snippets where relevant, and use markdown formatting with H2/H3 headers. - + ### Create a "Best X" article for Hashnode @@ -188,7 +188,7 @@ Write a technical "Best [CATEGORY] for [SPECIFIC USE CASE]: A Developer's Guide" Include a TL;DR section at the top, use proper heading hierarchy for auto-generated table of contents, and add code examples with proper syntax highlighting. Write with technical authority but remain accessible. - + ### Create a "Best X" article for LinkedIn @@ -198,7 +198,7 @@ Write a business-focused "Best [CATEGORY] for [BUSINESS OUTCOME]" article (1,200 Use a professional, authoritative but accessible tone. Focus on business impact like time savings, cost efficiency, ROI, and productivity gains rather than technical features. Include comparison tables with business-relevant metrics. - + ### Create a "How to use [Actor]" tutorial for dev.to @@ -208,7 +208,7 @@ Write a step-by-step tutorial (1,200-2,000 words) showing developers how to use Structure: Introduction with hook, prerequisites, what they'll achieve, step-by-step guide (access the Actor, configure inputs, run it, view results, download data), understanding results, pro tips, troubleshooting, and next steps. Write like you're helping a friend get started. - + ### Create a "How to use [Actor]" tutorial for Hashnode @@ -218,7 +218,7 @@ Write a comprehensive "Complete Guide: How to [ACHIEVE OUTCOME] Using [YOUR ACTO Include a TL;DR section, detailed step-by-step walkthrough with screenshots, API integration examples with code blocks, advanced usage patterns, troubleshooting guide, and best practices. Write with technical authority, but be thorough and maintain clarity. - + ### Create a "How to use [Actor]" tutorial for Medium @@ -228,7 +228,7 @@ Write an accessible, engaging tutorial "How I [ACHIEVED OUTCOME] in Minutes Usin Take a story-driven approach with personal context. Write in first person, use simple jargon-free language, and make readers feel "I can do this too." Focus on the outcome and value, not technical complexity. - + ### Create a "How to use [Actor]" tutorial for LinkedIn @@ -238,7 +238,7 @@ Write a professional "How to [ACHIEVE BUSINESS OUTCOME] in [TIME] Using [YOUR AC Use professional, consultative tone focused on business value. Emphasize time savings, efficiency, and ROI. Include sections on business case, measuring success, professional best practices, and real-world business applications. Address common professional questions about security, cost, reliability, and team adoption. - + --- @@ -252,7 +252,7 @@ Create a GitHub repo with code examples, integration guides, or sample projects Your README should include: project title with badges, short description, key features, quick start guide, installation and setup instructions, usage examples with code snippets, use cases section, configuration options, common questions and troubleshooting, links to Apify Store and documentation, contributing guidelines, and license. - + --- diff --git a/sources/platform/actors/development/quick-start/build-with-ai.md b/sources/platform/actors/development/quick-start/build-with-ai.md index 25bf191cfe..18af327f04 100644 --- a/sources/platform/actors/development/quick-start/build-with-ai.md +++ b/sources/platform/actors/development/quick-start/build-with-ai.md @@ -53,7 +53,7 @@ The methods on this page are complementary. Start with the [AI coding assistant Use the following prompt in your AI coding assistant such as [Cursor](https://cursor.com/), [Claude Code](https://claude.com/product/claude-code), or [GitHub Copilot](https://github.com/features/copilot): - + The prompt guides your AI coding assistant to create and deploy an Apify Actor step by step. It walks through setting up the Actor structure, configuring all required files, installing dependencies, running it locally, logging in, and pushing it to the Apify platform. diff --git a/src/components/PromptButton.jsx b/src/components/PromptButton.jsx index 78b7bcb7b1..0269df7f7d 100644 --- a/src/components/PromptButton.jsx +++ b/src/components/PromptButton.jsx @@ -2,9 +2,13 @@ import React, { useEffect, useRef, useState } from 'react'; import styles from './PromptButton.module.css'; -export default function PromptButton({ prompt, title = 'Ready-to-use prompt for your AI assistant' }) { +export default function PromptButton({ + prompt, + title = 'Ready-to-use prompt for your AI assistant', + collapsed = false, +}) { const [copied, setCopied] = useState(false); - const [showPrompt, setShowPrompt] = useState(false); + const [showPrompt, setShowPrompt] = useState(!collapsed); const timeoutRef = useRef(null); useEffect(() => { @@ -51,9 +55,11 @@ export default function PromptButton({ prompt, title = 'Ready-to-use prompt for
- + {collapsed && ( + + )} From 48f4be44434e67d68417e26709ab575f3699d7bb Mon Sep 17 00:00:00 2001 From: Honza Javorek Date: Wed, 16 Sep 2026 15:29:12 +0200 Subject: [PATCH 12/17] use blockquote inside the PromptButton, so that words wrap better than inside
 and llm.txt reads nicer

---
 src/components/PromptButton.jsx         |  2 +-
 src/components/PromptButton.module.css  | 10 ++++++++--
 src/components/PromptExample.module.css |  2 +-
 3 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/src/components/PromptButton.jsx b/src/components/PromptButton.jsx
index 0269df7f7d..07185f8097 100644
--- a/src/components/PromptButton.jsx
+++ b/src/components/PromptButton.jsx
@@ -70,7 +70,7 @@ export default function PromptButton({
                 readers is controlled purely by CSS via the "visible" class below. */}
             
-
{prompt}
+
{prompt}
diff --git a/src/components/PromptButton.module.css b/src/components/PromptButton.module.css index f8ea695739..a5192ae809 100644 --- a/src/components/PromptButton.module.css +++ b/src/components/PromptButton.module.css @@ -188,11 +188,17 @@ html[data-theme='dark'] .toggle-button:hover { box-shadow: none; } -.full-prompt pre { +.full-prompt-blockquote.full-prompt-blockquote { + background: var(--ifm-pre-background); + border: none; + border-radius: 4px; + box-shadow: none; margin: 0; + padding: var(--ifm-pre-padding); + color: var(--ifm-color-content); + font-family: var(--ifm-font-family-monospace); font-size: 1.3rem; line-height: 1.5; - color: var(--ifm-color-content); white-space: pre-wrap; word-wrap: break-word; } diff --git a/src/components/PromptExample.module.css b/src/components/PromptExample.module.css index a2abddf802..19aca96e13 100644 --- a/src/components/PromptExample.module.css +++ b/src/components/PromptExample.module.css @@ -13,7 +13,7 @@ border-radius: 4px; box-shadow: none; margin: 0 0 1.2rem; - padding: 1rem; + padding: var(--ifm-pre-padding); color: var(--ifm-color-content); font-family: var(--ifm-font-family-monospace); font-size: 1.3rem; From 9c8668b24b8174c0451ff57d5bdd75c8c2243c4a Mon Sep 17 00:00:00 2001 From: Honza Javorek Date: Wed, 16 Sep 2026 16:08:15 +0200 Subject: [PATCH 13/17] allow using PromptButton as a ```prompt, oh yeah baby --- src/theme/MDXComponents/Code.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/theme/MDXComponents/Code.js diff --git a/src/theme/MDXComponents/Code.js b/src/theme/MDXComponents/Code.js new file mode 100644 index 0000000000..59149c937b --- /dev/null +++ b/src/theme/MDXComponents/Code.js @@ -0,0 +1,15 @@ +import React from 'react'; + +import MDXCode from '@theme-original/MDXComponents/Code'; + +import PromptButton from '@site/src/components/PromptButton'; + +const PROMPT_LANGUAGE_CLASS = 'language-prompt'; + +export default function Code(props) { + if (props.className === PROMPT_LANGUAGE_CLASS && typeof props.children === 'string') { + return ; + } + + return ; +} From 04a46cd675f850f5a1740f039b7c26dbf55de08f Mon Sep 17 00:00:00 2001 From: Honza Javorek Date: Wed, 16 Sep 2026 16:12:36 +0200 Subject: [PATCH 14/17] nuke PromptExample --- .../02_developing_scraper_ai_agent.md | 6 +- src/components/PromptExample.jsx | 53 ----------------- src/components/PromptExample.module.css | 57 ------------------- 3 files changed, 2 insertions(+), 114 deletions(-) delete mode 100644 src/components/PromptExample.jsx delete mode 100644 src/components/PromptExample.module.css diff --git a/sources/academy/platform/scraping_with_apify_and_ai/02_developing_scraper_ai_agent.md b/sources/academy/platform/scraping_with_apify_and_ai/02_developing_scraper_ai_agent.md index f94ed9f1f2..fa796dba11 100644 --- a/sources/academy/platform/scraping_with_apify_and_ai/02_developing_scraper_ai_agent.md +++ b/sources/academy/platform/scraping_with_apify_and_ai/02_developing_scraper_ai_agent.md @@ -5,8 +5,6 @@ slug: /scraping-with-apify-and-ai/developing-scraper-with-ai-agent unlisted: true --- -import PromptExample from '@site/src/components/PromptExample'; - **In this lesson, we'll keep improving our app for tracking prices on an e-commerce website. We'll get its code onto our computer and use Cursor to streamline how we update our scraper.** --- @@ -230,7 +228,7 @@ In the previous lesson, we noticed that the prices in our resulting dataset are Let's change that. We'll prompt the agent like this, with a clear example of what we want: - +```prompt Change the code so that the Actor saves prices as numbers. Because some prices are "from", let's call the "price" field "minPrice" instead, as in minimum price. Example follows. Before: @@ -242,7 +240,7 @@ After: 74.95 1398.00 158.00 - +``` When the agent is done, we'll approve the changes and verify in the command line that the Actor runs locally: diff --git a/src/components/PromptExample.jsx b/src/components/PromptExample.jsx deleted file mode 100644 index 9f543b085b..0000000000 --- a/src/components/PromptExample.jsx +++ /dev/null @@ -1,53 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react'; - -import styles from './PromptExample.module.css'; - -export default function PromptExample({ children }) { - const [copied, setCopied] = useState(false); - const timeoutRef = useRef(null); - const blockquoteRef = useRef(null); - - useEffect(() => { - return () => { - if (timeoutRef.current) { - clearTimeout(timeoutRef.current); - } - }; - }, []); - - const handleCopy = async () => { - if (window.analytics) { - window.analytics.track('Clicked', { - app: 'docs', - button_text: 'Copy prompt', - element: 'prompt-example.copyButton', - }); - } - - try { - await navigator.clipboard.writeText(blockquoteRef.current.textContent); - - if (timeoutRef.current) { - clearTimeout(timeoutRef.current); - } - - setCopied(true); - timeoutRef.current = setTimeout(() => setCopied(false), 2000); - } catch (err) { - console.error('Failed to copy prompt:', err); - } - }; - - return ( -
-
- {children} -
-
- -
-
- ); -} diff --git a/src/components/PromptExample.module.css b/src/components/PromptExample.module.css deleted file mode 100644 index 19aca96e13..0000000000 --- a/src/components/PromptExample.module.css +++ /dev/null @@ -1,57 +0,0 @@ -.prompt-example-container { - background: var(--ifm-background-color); - border: 1px solid var(--ifm-color-emphasis-200); - border-radius: 8px; - padding: 1.6rem; - box-shadow: 0 1.5px 3px 0 rgb(0 0 0 / 15%); - margin-bottom: var(--ifm-leading); -} - -.prompt-example.prompt-example { - background: var(--ifm-pre-background); - border: none; - border-radius: 4px; - box-shadow: none; - margin: 0 0 1.2rem; - padding: var(--ifm-pre-padding); - color: var(--ifm-color-content); - font-family: var(--ifm-font-family-monospace); - font-size: 1.3rem; - line-height: 1.5; - white-space: pre-wrap; - word-wrap: break-word; -} - -.button-container { - display: flex; - justify-content: flex-end; -} - -.copy-button { - width: 150px; - background: var(--ifm-color-primary); - color: var(--ifm-color-primary-contrast-background); - border: 1px solid var(--ifm-color-primary); - border-radius: 6px; - padding: 0.8rem 1.6rem; - font-size: 1.4rem; - font-weight: 500; - cursor: pointer; - transition: all var(--ifm-transition-fast) ease; - white-space: nowrap; -} - -.copy-button:hover { - background: var(--ifm-color-primary-darker); - border-color: var(--ifm-color-primary-darker); -} - -.copy-button.copied { - background: var(--ifm-color-success); - border-color: var(--ifm-color-success); -} - -.copy-button.copied:hover { - background: var(--ifm-color-success-darker); - border-color: var(--ifm-color-success-darker); -} From 62f52e58ae64f7f60d973ce381edc129d7cb8658 Mon Sep 17 00:00:00 2001 From: Honza Javorek Date: Wed, 16 Sep 2026 16:24:00 +0200 Subject: [PATCH 15/17] support custom titles --- .../02_developing_scraper_ai_agent.md | 2 +- src/theme/MDXComponents/Code.js | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sources/academy/platform/scraping_with_apify_and_ai/02_developing_scraper_ai_agent.md b/sources/academy/platform/scraping_with_apify_and_ai/02_developing_scraper_ai_agent.md index fa796dba11..18f51d0849 100644 --- a/sources/academy/platform/scraping_with_apify_and_ai/02_developing_scraper_ai_agent.md +++ b/sources/academy/platform/scraping_with_apify_and_ai/02_developing_scraper_ai_agent.md @@ -228,7 +228,7 @@ In the previous lesson, we noticed that the prices in our resulting dataset are Let's change that. We'll prompt the agent like this, with a clear example of what we want: -```prompt +```prompt title="Clean up price data prompt" Change the code so that the Actor saves prices as numbers. Because some prices are "from", let's call the "price" field "minPrice" instead, as in minimum price. Example follows. Before: diff --git a/src/theme/MDXComponents/Code.js b/src/theme/MDXComponents/Code.js index 59149c937b..379442f44f 100644 --- a/src/theme/MDXComponents/Code.js +++ b/src/theme/MDXComponents/Code.js @@ -1,5 +1,6 @@ import React from 'react'; +import { parseCodeBlockTitle } from '@docusaurus/theme-common/internal'; import MDXCode from '@theme-original/MDXComponents/Code'; import PromptButton from '@site/src/components/PromptButton'; @@ -8,7 +9,8 @@ const PROMPT_LANGUAGE_CLASS = 'language-prompt'; export default function Code(props) { if (props.className === PROMPT_LANGUAGE_CLASS && typeof props.children === 'string') { - return ; + const title = parseCodeBlockTitle(props.metastring); + return ; } return ; From b785a76a09965fb41585cec535f8444e22d3393a Mon Sep 17 00:00:00 2001 From: Honza Javorek Date: Wed, 16 Sep 2026 16:26:32 +0200 Subject: [PATCH 16/17] change the name of PromptButton to PromptBlock --- .../promoting-your-actor/checklist.md | 24 +++++++++---------- .../development/quick-start/build-with-ai.md | 4 ++-- .../{PromptButton.jsx => PromptBlock.jsx} | 6 ++--- ...tton.module.css => PromptBlock.module.css} | 0 src/theme/MDXComponents/Code.js | 4 ++-- 5 files changed, 19 insertions(+), 19 deletions(-) rename src/components/{PromptButton.jsx => PromptBlock.jsx} (94%) rename src/components/{PromptButton.module.css => PromptBlock.module.css} (100%) diff --git a/sources/academy/build-and-publish/promoting-your-actor/checklist.md b/sources/academy/build-and-publish/promoting-your-actor/checklist.md index f593f952d9..43e7663c03 100644 --- a/sources/academy/build-and-publish/promoting-your-actor/checklist.md +++ b/sources/academy/build-and-publish/promoting-your-actor/checklist.md @@ -18,7 +18,7 @@ Tag @apify when you share content on X.com (Twitter) or LinkedIn to potentially --- -import PromptButton from "@site/src/components/PromptButton"; +import PromptBlock from "@site/src/components/PromptBlock"; import { TWITTER_POST_PROMPT } from "@site/src/utils/twitter-post-prompt"; import { LINKEDIN_POST_PROMPT } from "@site/src/utils/linkedin-post-prompt"; import { MEDIUM_ARTICLE_PROMPT } from "@site/src/utils/medium-article-prompt"; @@ -41,7 +41,7 @@ Twitter's developer community is active and engaged. A well-crafted tweet with a Create a 30-60-second demo video or gif showing your Actor in action. Include relevant hashtags like #webscraping, #API, #automation, and #buildinpublic. - + ### Share on LinkedIn with a demo @@ -49,7 +49,7 @@ LinkedIn reaches professionals, decision-makers, and business users with purchas Create a 30-90-second demo video showing your Actor delivering business value. Upload the video directly to LinkedIn (native videos perform better than YouTube links). Focus your post on the business problem solved, not technical features. Use 3-5 relevant hashtags like #BusinessAutomation, #Productivity, #DataIntelligence, #Efficiency, or #MarketResearch. - + ### Post in relevant Discord and Slack communities @@ -168,7 +168,7 @@ Write a comprehensive "Best [CATEGORY]" roundup article (1,800-2,500 words) feat Write in first person with a conversational yet professional tone. Include pros and cons for each solution, add a comparison table, and share your genuine perspective. - + ### Create a "Best X" article for dev.to @@ -178,7 +178,7 @@ Write a developer-focused "Best [CATEGORY] for Developers" article (1,500-2,000 Write like you're advising a fellow developer: casual and helpful. Be genuinely objective about all tools, include code examples or API snippets where relevant, and use markdown formatting with H2/H3 headers. - + ### Create a "Best X" article for Hashnode @@ -188,7 +188,7 @@ Write a technical "Best [CATEGORY] for [SPECIFIC USE CASE]: A Developer's Guide" Include a TL;DR section at the top, use proper heading hierarchy for auto-generated table of contents, and add code examples with proper syntax highlighting. Write with technical authority but remain accessible. - + ### Create a "Best X" article for LinkedIn @@ -198,7 +198,7 @@ Write a business-focused "Best [CATEGORY] for [BUSINESS OUTCOME]" article (1,200 Use a professional, authoritative but accessible tone. Focus on business impact like time savings, cost efficiency, ROI, and productivity gains rather than technical features. Include comparison tables with business-relevant metrics. - + ### Create a "How to use [Actor]" tutorial for dev.to @@ -208,7 +208,7 @@ Write a step-by-step tutorial (1,200-2,000 words) showing developers how to use Structure: Introduction with hook, prerequisites, what they'll achieve, step-by-step guide (access the Actor, configure inputs, run it, view results, download data), understanding results, pro tips, troubleshooting, and next steps. Write like you're helping a friend get started. - + ### Create a "How to use [Actor]" tutorial for Hashnode @@ -218,7 +218,7 @@ Write a comprehensive "Complete Guide: How to [ACHIEVE OUTCOME] Using [YOUR ACTO Include a TL;DR section, detailed step-by-step walkthrough with screenshots, API integration examples with code blocks, advanced usage patterns, troubleshooting guide, and best practices. Write with technical authority, but be thorough and maintain clarity. - + ### Create a "How to use [Actor]" tutorial for Medium @@ -228,7 +228,7 @@ Write an accessible, engaging tutorial "How I [ACHIEVED OUTCOME] in Minutes Usin Take a story-driven approach with personal context. Write in first person, use simple jargon-free language, and make readers feel "I can do this too." Focus on the outcome and value, not technical complexity. - + ### Create a "How to use [Actor]" tutorial for LinkedIn @@ -238,7 +238,7 @@ Write a professional "How to [ACHIEVE BUSINESS OUTCOME] in [TIME] Using [YOUR AC Use professional, consultative tone focused on business value. Emphasize time savings, efficiency, and ROI. Include sections on business case, measuring success, professional best practices, and real-world business applications. Address common professional questions about security, cost, reliability, and team adoption. - + --- @@ -252,7 +252,7 @@ Create a GitHub repo with code examples, integration guides, or sample projects Your README should include: project title with badges, short description, key features, quick start guide, installation and setup instructions, usage examples with code snippets, use cases section, configuration options, common questions and troubleshooting, links to Apify Store and documentation, contributing guidelines, and license. - + --- diff --git a/sources/platform/actors/development/quick-start/build-with-ai.md b/sources/platform/actors/development/quick-start/build-with-ai.md index 18af327f04..813499bdf6 100644 --- a/sources/platform/actors/development/quick-start/build-with-ai.md +++ b/sources/platform/actors/development/quick-start/build-with-ai.md @@ -10,7 +10,7 @@ pagination_prev: null --- import { AGENTS_PROMPT } from "@site/src/utils/agents-prompt"; -import PromptButton from "@site/src/components/PromptButton"; +import PromptBlock from "@site/src/components/PromptBlock"; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import ClaudeCodeWebEgress from '@site/sources/_partials/_claude-code-web-egress.mdx'; @@ -53,7 +53,7 @@ The methods on this page are complementary. Start with the [AI coding assistant Use the following prompt in your AI coding assistant such as [Cursor](https://cursor.com/), [Claude Code](https://claude.com/product/claude-code), or [GitHub Copilot](https://github.com/features/copilot): - + The prompt guides your AI coding assistant to create and deploy an Apify Actor step by step. It walks through setting up the Actor structure, configuring all required files, installing dependencies, running it locally, logging in, and pushing it to the Apify platform. diff --git a/src/components/PromptButton.jsx b/src/components/PromptBlock.jsx similarity index 94% rename from src/components/PromptButton.jsx rename to src/components/PromptBlock.jsx index 07185f8097..fd307aca32 100644 --- a/src/components/PromptButton.jsx +++ b/src/components/PromptBlock.jsx @@ -1,8 +1,8 @@ import React, { useEffect, useRef, useState } from 'react'; -import styles from './PromptButton.module.css'; +import styles from './PromptBlock.module.css'; -export default function PromptButton({ +export default function PromptBlock({ prompt, title = 'Ready-to-use prompt for your AI assistant', collapsed = false, @@ -24,7 +24,7 @@ export default function PromptButton({ window.analytics.track('Clicked', { app: 'docs', button_text: 'Copy prompt', - element: 'prompt-button.copyButton', + element: 'prompt-block.copyButton', }); } diff --git a/src/components/PromptButton.module.css b/src/components/PromptBlock.module.css similarity index 100% rename from src/components/PromptButton.module.css rename to src/components/PromptBlock.module.css diff --git a/src/theme/MDXComponents/Code.js b/src/theme/MDXComponents/Code.js index 379442f44f..2de58be6a7 100644 --- a/src/theme/MDXComponents/Code.js +++ b/src/theme/MDXComponents/Code.js @@ -3,14 +3,14 @@ import React from 'react'; import { parseCodeBlockTitle } from '@docusaurus/theme-common/internal'; import MDXCode from '@theme-original/MDXComponents/Code'; -import PromptButton from '@site/src/components/PromptButton'; +import PromptBlock from '@site/src/components/PromptBlock'; const PROMPT_LANGUAGE_CLASS = 'language-prompt'; export default function Code(props) { if (props.className === PROMPT_LANGUAGE_CLASS && typeof props.children === 'string') { const title = parseCodeBlockTitle(props.metastring); - return ; + return ; } return ; From df05ee8db372e164c187213fcaa86ef05ee22a6f Mon Sep 17 00:00:00 2001 From: Honza Javorek Date: Thu, 17 Sep 2026 10:48:58 +0200 Subject: [PATCH 17/17] use the new prompt component throughout the AI course --- .../01_developing_scraper_ai_chat.md | 19 +++++-------------- .../02_developing_scraper_ai_agent.md | 10 ++++------ .../03_docs_driven_prompting.md | 4 ++-- .../04_tests_driven_prompting.md | 10 ++++------ 4 files changed, 15 insertions(+), 28 deletions(-) diff --git a/sources/academy/platform/scraping_with_apify_and_ai/01_developing_scraper_ai_chat.md b/sources/academy/platform/scraping_with_apify_and_ai/01_developing_scraper_ai_chat.md index 9590084b84..b979f4b891 100644 --- a/sources/academy/platform/scraping_with_apify_and_ai/01_developing_scraper_ai_chat.md +++ b/sources/academy/platform/scraping_with_apify_and_ai/01_developing_scraper_ai_chat.md @@ -11,11 +11,8 @@ unlisted: true Want to extract data from a website? Even without knowing how to code, we can open [ChatGPT](https://chatgpt.com/) and have a scraper ready. Let's say you want to track prices from [this Sales page](https://warehouse-theme-metal.myshopify.com/collections/sales). You'd type something like: -```text -Create a scraper in JavaScript which downloads -https://warehouse-theme-metal.myshopify.com/collections/sales, -extracts all the products in Sales and saves a CSV file, -which contains: +```prompt title="Initial prompt" +Create a scraper in JavaScript which downloads https://warehouse-theme-metal.myshopify.com/collections/sales, extracts all the products in Sales and saves a CSV file, which contains: - Product name - Product detail page URL @@ -96,20 +93,14 @@ In this course, we'll scrape a real e-commerce site instead of artificial playgr We'll open **New chat** in [ChatGPT](https://chatgpt.com/) and prepare a beginning of a prompt like this: -```text -I'm building an Apify Actor that will run on the Apify platform. -I need to modify a sample template project so it downloads -https://warehouse-theme-metal.myshopify.com/collections/sales, -extracts all products in Sales, and returns data with -the following information for each product: +```prompt title="Update routes.js prompt" +I'm building an Apify Actor that will run on the Apify platform. I need to modify a sample template project so it downloads https://warehouse-theme-metal.myshopify.com/collections/sales, extracts all products in Sales, and returns data with the following information for each product: - Product name - Product detail page URL - Price -Before the program ends, it should log how many products it collected. -Code from routes.js follows. Reply with a code block containing -a new version of that file. +Before the program ends, it should log how many products it collected. Code from routes.js follows. Reply with a code block containing a new version of that file. ``` Now let's switch back to Apify. In **Source** → **Code**, where we have the Web IDE, we'll select a file called `routes.js` inside the `src` folder. We'll see code similar to this: diff --git a/sources/academy/platform/scraping_with_apify_and_ai/02_developing_scraper_ai_agent.md b/sources/academy/platform/scraping_with_apify_and_ai/02_developing_scraper_ai_agent.md index 18f51d0849..8a5c9fcdee 100644 --- a/sources/academy/platform/scraping_with_apify_and_ai/02_developing_scraper_ai_agent.md +++ b/sources/academy/platform/scraping_with_apify_and_ai/02_developing_scraper_ai_agent.md @@ -189,7 +189,7 @@ Finally, onto some agentic coding! First, let's simplify how we can run the Actor. This will be our prompt: -```text +```prompt title="Change input URL prompt" Change the default input URL of the Actor to https://warehouse-theme-metal.myshopify.com/collections/sales ``` @@ -250,7 +250,7 @@ apify run It runs, that's nice! But looking at the output, we can't really verify what exactly gets scraped! While we're at it, let's change that with another prompt: -```text +```prompt title="Log items prompt" I want the scraper to log each item before it's saved. ``` @@ -306,10 +306,8 @@ We've done it, the prices save as numbers! If we didn't want to always click on **All fields** to see full items, we need to specify an [output schema](https://docs.apify.com/actors/development/actor-definition/output-schema) so that the platform knows what it can expect and how it should display it in the interface. With Cursor, such change is just a single prompt away: -```text -Change the output schema of the Actor -so that it represents the items being -saved the best way in the Apify interface. +```prompt title="Change output schema prompt" +Change the output schema of the Actor so that it represents the items being saved the best way in the Apify interface. ``` ::: diff --git a/sources/academy/platform/scraping_with_apify_and_ai/03_docs_driven_prompting.md b/sources/academy/platform/scraping_with_apify_and_ai/03_docs_driven_prompting.md index 3a3d83a45b..2f92d5ca88 100644 --- a/sources/academy/platform/scraping_with_apify_and_ai/03_docs_driven_prompting.md +++ b/sources/academy/platform/scraping_with_apify_and_ai/03_docs_driven_prompting.md @@ -123,7 +123,7 @@ The README documents what we already have. Now let's use it as a spec for what c We'll save the file with Ctrl+S (or ⌘+S on macOS), then send this prompt to the AI agent: -```text +```prompt title="Implement README prompt" Ensure all behavior documented in README is correctly implemented. ``` @@ -181,7 +181,7 @@ Saves SKU as a number. Examples: We'll save the file again and repeat the same prompt as before to turn our spec into code: -```text +```prompt title="Implement README prompt" Ensure all behavior documented in README is correctly implemented. ``` diff --git a/sources/academy/platform/scraping_with_apify_and_ai/04_tests_driven_prompting.md b/sources/academy/platform/scraping_with_apify_and_ai/04_tests_driven_prompting.md index 9112708872..99abfeb997 100644 --- a/sources/academy/platform/scraping_with_apify_and_ai/04_tests_driven_prompting.md +++ b/sources/academy/platform/scraping_with_apify_and_ai/04_tests_driven_prompting.md @@ -41,9 +41,8 @@ _Red-green test-driven development_, often shortened to TDD, means that whenever Now let's send this prompt to the AI agent: -```text -Read the Testing section in README and set up a test suite -covering the behavior we already have. +```prompt title="Set up test suite prompt" +Read the Testing section in README and set up a test suite covering the behavior we already have. ``` When the AI agent gets to work, you should see it create a new directory called `tests`. To create an HTML snapshot of the Sales listing, it'll probably use `curl`, a command-line program for downloading files. @@ -108,9 +107,8 @@ Let's save the README and prepare a prompt for the AI agent. We'll tell it which It's best to focus each fixture on a single situation. Our findings give us five snapshots, although some will contain the same HTML: -```text -Read the new Variants handling section and change -the project accordingly. Use red-green TDD. Fixtures: +```prompt title="Handle variants prompt" +Read the new Variants handling section and change the project accordingly. Use red-green TDD. Fixtures: one-price-no-variants.html https://warehouse-theme-metal.myshopify.com/products/sony-sacs9-10-inch-active-subwoofer