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..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/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 28a08866fe..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
```
@@ -228,10 +228,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.
+```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:
Sale price$74.95
@@ -252,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.
```
@@ -308,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
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..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/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";
diff --git a/src/components/PromptButton.jsx b/src/components/PromptBlock.jsx
similarity index 57%
rename from src/components/PromptButton.jsx
rename to src/components/PromptBlock.jsx
index 3c2a666c1e..fd307aca32 100644
--- a/src/components/PromptButton.jsx
+++ b/src/components/PromptBlock.jsx
@@ -1,14 +1,14 @@
import React, { useEffect, useRef, useState } from 'react';
-import { QUICK_START_PROMPT } from '../utils/quick-start-prompt';
-import styles from './PromptButton.module.css';
+import styles from './PromptBlock.module.css';
-export default function PromptButton({
- prompt = QUICK_START_PROMPT,
- title = 'Use pre-built prompt to get started faster.',
+export default function PromptBlock({
+ 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(() => {
@@ -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',
});
}
@@ -48,28 +48,31 @@ export default function PromptButton({
return (
<>
-
+
{title}
-
+ {collapsed && (
+
+ )}
- {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/PromptBlock.module.css
similarity index 84%
rename from src/components/PromptButton.module.css
rename to src/components/PromptBlock.module.css
index 598a6c9e3b..a5192ae809 100644
--- a/src/components/PromptButton.module.css
+++ b/src/components/PromptBlock.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,23 +170,35 @@ html[data-theme='dark'] .toggle-button:hover {
}
.full-prompt-container {
- margin-top: 1.2rem;
+ 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);
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 {
+.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/theme/MDXComponents/Code.js b/src/theme/MDXComponents/Code.js
new file mode 100644
index 0000000000..2de58be6a7
--- /dev/null
+++ b/src/theme/MDXComponents/Code.js
@@ -0,0 +1,17 @@
+import React from 'react';
+
+import { parseCodeBlockTitle } from '@docusaurus/theme-common/internal';
+import MDXCode from '@theme-original/MDXComponents/Code';
+
+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 ;
+}
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
-\`\`\`
-`;