diff --git a/.claude/skills/documentation/SKILL.md b/.claude/skills/documentation/SKILL.md
deleted file mode 100644
index 479e32a6a..000000000
--- a/.claude/skills/documentation/SKILL.md
+++ /dev/null
@@ -1,49 +0,0 @@
----
-name: documentation
-description: Generate, update, or review Glific user-facing documentation. Use when a developer asks to document a feature, write a doc page, update existing docs, or after a PR ships to refresh affected docs.
----
-
-# Documentation Skill
-
-Reference and workflow for generating Glific's user-facing Docusaurus documentation. This repo is `glific/docs`.
-
-## When to use
-
-Trigger when the user asks to:
-- Generate or update a doc page for a feature ("write docs for Flows", "document HSM Templates")
-- Refresh docs after a PR ships ("update docs for #142 in glific-frontend")
-- Review existing docs for completeness or accuracy
-
-Start by reading `workflow.md`.
-
-## IA Principles
-
-The docs have 8 top-level sections. Each has a different audience and purpose — read `sections.md` before placing any content.
-
-### Primary audience
-
-NGO program managers and field workers. They are **not technical users**. They need:
-- Plain language explanations
-- Step-by-step instructions with screenshots
-- To know what something does and how to use it — not how it works internally
-
-### Frontend code location
-
-The Glific frontend lives at `../glific-frontend/` relative to this repo.
-
-| Path | What it contains |
-|------|-----------------|
-| `../glific-frontend/src/containers/` | Feature-level UI components (one dir per feature) |
-| `../glific-frontend/src/routes/AuthenticatedRoute/AuthenticatedRoute.tsx` | All route paths (maps feature name → URL) |
-| `../glific-frontend/src/graphql/queries/` | GraphQL queries (understand data a feature displays) |
-
-## File index
-
-| File | Purpose |
-|------|---------|
-| `workflow.md` | Step-by-step process from research to published markdown |
-| `sections.md` | All 8 doc sections: audience, purpose, what belongs where |
-| `style-writing.md` | Audience, voice, instructions format, anti-patterns |
-| `style-page.md` | Page structure templates for each section type |
-| `style-images.md` | Image naming, directory mapping, static/img/ conventions |
-| `screenshots.md` | Playwright recipe system for automated screenshots |
diff --git a/.claude/skills/documentation/screenshots.md b/.claude/skills/documentation/screenshots.md
deleted file mode 100644
index f1af05df0..000000000
--- a/.claude/skills/documentation/screenshots.md
+++ /dev/null
@@ -1,132 +0,0 @@
-# Screenshot System
-
-Automated Playwright-based screenshot capture. Recipes define what to capture; `scripts/screenshot.js` runs them.
-
-## Local setup (one-time)
-
-### 1. Install Playwright
-
-```bash
-cd /path/to/glific/docs
-yarn add --dev playwright js-yaml
-npx playwright install chromium
-```
-
-### 2. Add credentials to `.env`
-
-Create a `.env` file in the root of this repo (it is gitignored):
-
-```
-GLIFIC_URL=https://glific.test:3000
-GLIFIC_PHONE=+91XXXXXXXXXX
-GLIFIC_PASSWORD=your_password
-```
-
-Use a **test/demo account** — not a production account. The script will log in and navigate through the UI.
-
-### 3. Local Glific must be running
-
-Before running the screenshot script:
-- Start the backend: follow `glific/glific` setup (Elixir/Phoenix on port 4001)
-- Start the frontend: `cd ../glific-frontend && yarn dev` (runs at `https://glific.test:3000`)
-
-The script ignores HTTPS certificate errors from `mkcert`, so the self-signed cert is fine.
-
-## Running the script
-
-```bash
-# Single feature
-node scripts/screenshot.js flows
-
-# All recipes
-node scripts/screenshot.js
-
-# Output lands in static/img/{output_dir}/
-```
-
-## Recipe format
-
-Each recipe is a YAML file in `scripts/recipes/{feature-slug}.yaml`.
-
-```yaml
-name: flows # Human-readable name
-output_dir: flows # Maps to static/img/{output_dir}/
-flows:
- - name: flow_list # Slug for this flow
- description: The list of all flows
- required: true # If true, failure aborts the recipe. If false, logs warning and continues.
- steps:
- - navigate: /flow # Navigate to this path
- - wait: '[data-testid="flow-list"]' # Wait for selector (CSS or data-testid)
- - snap: flows_list.png # Take screenshot, save as this filename
- - click: '[data-testid="add-flow"]' # Click a selector
- - wait_text: Create Flow # Wait for visible text to appear
- - snap: flows_create_dialog.png
-```
-
-### Step types
-
-| Step key | What it does |
-|----------|-------------|
-| `navigate: /path` | Go to `GLIFIC_URL + path` |
-| `wait: 'selector'` | Wait for CSS selector to appear (8s timeout) |
-| `wait_text: 'text'` | Wait for visible text to appear on the page |
-| `click: 'selector'` | Click a CSS selector |
-| `snap: filename.png` | Take a full-viewport screenshot |
-| `snap: filename.png` + `element: 'selector'` | Crop to that element only — hides sidebar, nav, unrelated UI |
-| `sleep: 500` | Wait N milliseconds (use sparingly, prefer `wait`) |
-
-### Element cropping
-
-**Always add `element:` when the screenshot should show only one section.** This keeps docs focused and avoids capturing sidebar/nav that may change independently.
-
-```yaml
-# Full viewport — only for canvas/editor views where context matters
-- snap: flows_editor_canvas.png
-
-# Cropped to element — use for lists, forms, dialogs, cards
-- snap: flows_list.png
- element: '[data-testid="flow-list"]'
-
-- snap: flows_create_dialog.png
- element: '[role="dialog"]'
-```
-
-Common element selectors:
-- Dialog/modal → `[role="dialog"]`
-- Named section → `[data-testid="..."]`
-- Main content only (no sidebar) → `main`
-
-### Selector strategy
-
-Prefer in this order:
-1. `[data-testid="..."]` — most stable, survives CSS refactors
-2. ARIA role + name: `role=button[name="Create Flow"]`
-3. Visible text: use `wait_text` step, then screenshot
-4. CSS class — **avoid**, breaks on any style change
-
-Glific's frontend has `data-testid` on most interactive elements. Check the container's `.tsx` file to find them.
-
-### Auth flow
-
-The script authenticates once per run using phone + password (Glific uses phone number login, not email). The session cookie is reused across all flows in the recipe.
-
-Login selectors (from `Auth.tsx` / `Login.tsx`):
-- Phone field: `input[name="phoneNumber"]`
-- Password field: `input[name="password"]`
-- Submit button: `[data-testid="SubmitButton"]`
-- Post-login: waits for URL to contain `/chat`
-
-### Nuances
-
-- The PhoneInput component renders a flag picker + text input. The script fills the text portion with `input[name="phoneNumber"]`. If the phone field has a different rendered `name`, inspect the DOM and update the selector in `scripts/screenshot.js`.
-- After login, some features require seed data (e.g., Flow list needs existing flows). Use a demo account with pre-created data.
-- The frontend uses Apollo Client with WebSocket subscriptions — some pages load data asynchronously. Use `wait` steps (not `sleep`) to wait for data to appear.
-
-## Adding a new recipe
-
-1. Find the feature's route in `../glific-frontend/src/routes/AuthenticatedRoute/AuthenticatedRoute.tsx`
-2. Find `data-testid` attributes in `../glific-frontend/src/containers/{Feature}/`
-3. Create `scripts/recipes/{feature-slug}.yaml`
-4. Run `node scripts/screenshot.js {feature-slug}` and iterate on selectors until all snaps land
-5. Commit the recipe + screenshots together with the doc page
diff --git a/.claude/skills/documentation/sections.md b/.claude/skills/documentation/sections.md
deleted file mode 100644
index 434d445a5..000000000
--- a/.claude/skills/documentation/sections.md
+++ /dev/null
@@ -1,64 +0,0 @@
-# Glific Docs Sections
-
-The sidebar is autogenerated from the `docs/` directory tree. Folder names with number prefixes control order.
-
-## Section map
-
-| Folder | Audience | Purpose | Content type |
-|--------|----------|---------|--------------|
-| `2. Pre Onboarding/` | Implementation partners, technical staff | Steps to complete *before* Glific onboarding — external platform setup | Procedural guides (numbered steps, external links) |
-| `3. Starter Kit/` | NGO managers | Pre-launch checklists and best practices before going live | Checklists, short guides |
-| `4. Product Features/` | Day-to-day users | Reference docs for every UI feature in Glific | Feature reference pages |
-| `5. Integrations/` | Technical staff | How to connect and use third-party tools (OpenAI, Sheets, etc.) | Setup + usage guides |
-| `6. WhatsApp Groups Automation/` | NGOs using WA Groups | Features specific to WhatsApp Groups (not 1:1 chats) | Feature + setup guides |
-| `7. Use Cases/` | All users | Scenario-based problem → solution guides | Narrative walkthroughs |
-| `8. FAQ/` | All users | Quick answers to specific how-to questions | Short Q&A pages |
-
-## Deciding where a new page belongs
-
-1. Is it about a UI screen or button in the Glific web app? → **4. Product Features/**
-2. Is it about connecting an external service to Glific? → **5. Integrations/**
-3. Is it specific to WhatsApp Groups (not regular chats)? → **6. WhatsApp Groups Automation/**
-4. Is it a step required *before* going live (Gupshup, GCS, Facebook)? → **2. Pre Onboarding/**
-5. Is it a real-world scenario showing how to accomplish a goal? → **7. Use Cases/**
-6. Is it a specific question that doesn't fit anywhere else? → **8. FAQ/**
-
-## Product Features sub-structure
-
-Current files under `4. Product Features/`:
-```
-01. Chats.md
-02. Speed Sends.md
-03. Flows/ ← subdirectory when a feature has multiple pages
-04. Triggers.md
-05. Searches.md
-06. HSM Templates.md
-07. Interactive Messages.md
-08. Notifications.md
-09. Reporting & Dashboard/
-10. Others/
-```
-
-Rules:
-- Top-level feature → numbered `.md` file (`11. Feature Name.md`)
-- Feature with multiple sub-pages → numbered directory (`11. Feature Name/`) with an `index.md` inside
-- Unnumbered files at the end are legacy; new pages must be numbered
-
-## Route → section mapping
-
-From `../glific-frontend/src/routes/AuthenticatedRoute/AuthenticatedRoute.tsx`:
-
-| Route | Feature | Section |
-|-------|---------|---------|
-| `/chat` | Chats | 4. Product Features |
-| `/speed-send` | Speed Sends | 4. Product Features |
-| `/flow` | Flows | 4. Product Features |
-| `/trigger` | Triggers | 4. Product Features |
-| `/search` | Searches | 4. Product Features |
-| `/template` | HSM Templates | 4. Product Features |
-| `/notifications` | Notifications | 4. Product Features |
-| `/collection` | Collections | 4. Product Features > Others |
-| `/contact-management` | Contact Management | 4. Product Features > Others |
-| `/staff-management` | Staff Management | 4. Product Features > Others |
-| `/settings` | Settings | 4. Product Features > Others |
-| `/sheet-integration` | Sheet Integration | 5. Integrations |
diff --git a/.claude/skills/documentation/style-images.md b/.claude/skills/documentation/style-images.md
deleted file mode 100644
index 78e5e6d53..000000000
--- a/.claude/skills/documentation/style-images.md
+++ /dev/null
@@ -1,76 +0,0 @@
-# Style: Images
-
-## Storage policy
-
-| Image type | Where to store |
-|------------|----------------|
-| New screenshots (all new pages) | `static/img/{feature}/` in this repo |
-| Existing GitHub CDN images on old pages | Leave as-is — do not migrate unless rewriting the page |
-
-**Never add new GitHub CDN image URLs to a page.** Use local `static/img/` for all new content.
-
-## Directory mapping
-
-One directory per feature area under `static/img/`:
-
-| Feature | Directory |
-|---------|-----------|
-| Chats | `static/img/chats/` |
-| Speed Sends | `static/img/speed-sends/` |
-| Flows | `static/img/flows/` |
-| Triggers | `static/img/triggers/` |
-| Searches | `static/img/searches/` |
-| HSM Templates | `static/img/hsm-templates/` |
-| Interactive Messages | `static/img/interactive-messages/` |
-| Notifications | `static/img/notifications/` |
-| Collections | `static/img/collections/` |
-| Contact Management | `static/img/contact-management/` |
-| Staff Management | `static/img/staff-management/` |
-| Settings | `static/img/settings/` |
-| Integrations (OpenAI) | `static/img/integrations/openai/` |
-| Integrations (Sheets) | `static/img/integrations/sheets/` |
-| WhatsApp Groups | `static/img/wa-groups/` |
-
-If a feature doesn't have a directory yet, create it. The screenshot script creates it automatically.
-
-## File naming
-
-Format: `{feature}_{description}.png` — lowercase, underscores, no spaces.
-
-Examples:
-- `flows_list.png` — the list of flows
-- `flows_create_dialog.png` — the create flow dialog
-- `hsm-templates_new_template_form.png` — the new template form
-- `chats_session_timer.png` — the session timer in the chat window
-
-## Markdown syntax
-
-Docusaurus serves `static/` at the site root. Always use `/img/` prefix (not `static/img/`):
-
-```markdown
-
-```
-
-Never use:
-- `import Image from ...` + JSX
-- Absolute GitHub CDN URLs for new images
-- Relative paths like `../../static/img/...`
-
-## Screenshot placement
-
-Screenshot goes **after** the step it illustrates, never before. One screenshot per major step or UI state.
-
-## Missing screenshots
-
-If the feature isn't built yet or requires backend data that can't be seeded locally:
-
-```markdown
-:::info Screenshot coming soon
-:::
-```
-
-Never use HTML comment placeholders (``).
-
-## Image dimensions
-
-Capture at **1440×900 viewport** (set in `scripts/screenshot.js`). Do not resize or compress — Docusaurus serves them at natural size and the browser scales them.
diff --git a/.claude/skills/documentation/style-page.md b/.claude/skills/documentation/style-page.md
deleted file mode 100644
index 568d1bd65..000000000
--- a/.claude/skills/documentation/style-page.md
+++ /dev/null
@@ -1,142 +0,0 @@
-# Style: Page Structure
-
-Different sections use different templates. Match the template to the section type.
-
----
-
-## Template 1: Product Feature page (`4. Product Features/`)
-
-```markdown
-###**{N} minute read {padding} `{Level}`**
-
----
-
-**{One-sentence summary of what this feature does.}**
-
-{1–2 sentences of context: when you'd use this, how it fits into Glific.}
-
-## {First capability or action}
-
-{Step-by-step instructions or explanation.}
-
-
-
-## {Second capability or action}
-
-{Continue as needed.}
-
----
-
-You can read more about related features here:
-- [{Related feature}]({../path/page.md})
-```
-
-**Rules:**
-- H2 headings are task-focused: "Creating a Flow", "Editing a Template", "Viewing Reports"
-- One screenshot per major action, placed after the step it shows
-- End with cross-links to related Product Feature pages
-
----
-
-## Template 2: Integration page (`5. Integrations/`)
-
-```markdown
-###**{N} minute read {padding} `{Level}`**
-
----
-
-**{What this integration does and why you'd use it.}**
-
-## Prerequisites
-
-- {List what the user needs before starting: API keys, accounts, etc.}
-
-## Setup
-
-1. ...
-2. ...
-
-## Using {Integration Name} in Glific
-
-{How to use the integration once it's set up.}
-
-:::note
-{Any important limitations or caveats.}
-:::
-```
-
----
-
-## Template 3: FAQ page (`8. FAQ/`)
-
-```markdown
-###**{N} minute read {padding} `{Level}`**
-
----
-
-**{Restate the question as a one-sentence answer.}**
-
-## Steps
-
-1. ...
-2. ...
-
-{Screenshot if helpful.}
-```
-
-FAQ pages are short. If the answer needs more than 5 steps or 2 screenshots, it belongs in Product Features instead.
-
----
-
-## Template 4: Use Case page (`7. Use Cases/`)
-
-```markdown
-###**{N} minute read {padding} `{Level}`**
-
----
-
-**{The problem this use case solves, in one sentence.}**
-
-## The situation
-
-{1–2 sentences describing the real-world scenario.}
-
-## Solution
-
-{Walk through the solution. Reference existing Product Feature pages rather than re-explaining how each feature works.}
-
-## Steps
-
-1. ...
-2. ...
-```
-
----
-
-## Template 5: Pre Onboarding guide (`2. Pre Onboarding/`)
-
-```markdown
-###**{N} minute read {padding} `{Level}`**
-
----
-
-**{What this guide helps the user accomplish.}**
-
-## Prerequisites
-
-- {External account or info needed before starting.}
-
-## Steps
-
-1. ...
-
-:::note
-{Common issues or things to watch out for.}
-:::
-```
-
----
-
-## Read-time estimation
-
-Count images × 10 seconds + word count ÷ 200 wpm. Round to nearest minute. Minimum: 1 minute.
diff --git a/.claude/skills/documentation/style-writing.md b/.claude/skills/documentation/style-writing.md
deleted file mode 100644
index da4e62955..000000000
--- a/.claude/skills/documentation/style-writing.md
+++ /dev/null
@@ -1,87 +0,0 @@
-# Style: Writing
-
-Read at least two existing pages in the same section before writing a new one — match their tone and density.
-
-## Audience
-
-Primary: **NGO program managers and field workers** using Glific daily. Non-technical. Need to know *what* to do, not *why* the code works.
-
-Secondary: **Implementation partners** setting up Glific for NGOs. More technical, but still prefer step-by-step clarity.
-
-**Plain language rules:**
-- High-school reading level.
-- One idea per sentence.
-- Explain what things do, not how they work internally.
-- If a technical term is unavoidable ("flow", "template", "collection"), explain it in context on first use or link to another doc.
-- Use "you" and "your". Active voice, present tense.
-
-## Voice
-
-| Don't | Do instead |
-|---|---|
-| "Click the button" | "Select **Create Flow**" |
-| "The user should navigate to" | "Open **Flows** from the left menu" |
-| "It is possible to" | "You can" |
-| "In order to" | "To" |
-| Passive voice | Active, second-person, present tense |
-| "Please note that" | Just say it |
-
-## Page header format
-
-Every page starts with a read-time and difficulty badge, matching the existing Glific style:
-
-```markdown
-###**{N} minute read ... `{Level}`**
-```
-
-Use these levels:
-- `Beginner` — anyone can follow with no prior Glific knowledge
-- `Intermediate` — assumes familiarity with basic Glific features
-- `Advanced` — requires understanding of flows, APIs, or technical setup
-
-Example (copy the spacing exactly — the ` ` padding pushes the badge to the right):
-```markdown
-###**3 minute read `Beginner`**
-```
-
-## Instructions format
-
-Numbered steps for sequential actions. Each step = one action.
-
-**Rules:**
-1. **Bold every UI element** the user interacts with: button labels, menu items, tab names, field labels.
-2. Place a screenshot *after* the step it illustrates, not before.
-3. Keep steps atomic — one click or one fill per step.
-4. Use "Select" not "Click" (works for touchscreens too).
-5. Use quotes for exact text the user types; bold for UI labels they select.
-
-**Example:**
-```markdown
-1. Open **Flows** from the left menu.
-
-
-
-2. Select **+ Create Flow**.
-3. Enter a name for your flow and select **Save**.
-```
-
-## Section intro pattern
-
-After the header badge, start with a **bold one-liner** that tells the reader exactly what this feature does:
-
-```markdown
-**Flows let you build automated conversation sequences that run without staff involvement.**
-```
-
-Then 1–2 sentences of context if needed. Then jump straight into steps or sub-sections.
-
-## Anti-patterns
-
-| Don't | Why |
-|---|---|
-| GitHub CDN image URLs in new pages | Images can break; use `static/img/` instead |
-| `
` tags with GitHub asset URLs for new screenshots | Use standard markdown `` |
-| Long intros before the first action | Badge → bold one-liner → steps |
-| Duplicating WhatsApp/Meta documentation | Link to official docs instead |
-| Explaining GraphQL, Apollo, or internal architecture | Audience doesn't need this |
-| `Note:` in plain text | Use `:::note` admonition |
diff --git a/.claude/skills/documentation/workflow.md b/.claude/skills/documentation/workflow.md
deleted file mode 100644
index ec1c876d5..000000000
--- a/.claude/skills/documentation/workflow.md
+++ /dev/null
@@ -1,91 +0,0 @@
-# Documentation Workflow
-
-Process to generate or update a doc page — from research to published markdown.
-
-## 1. Parse Input & Determine Mode
-
-**Mode A — Feature Name** (default): input is a feature name (e.g. "Flows", "HSM Templates", "Speed Send").
-
-**Mode B — PR Number**: input matches `#\d+`, a GitHub PR URL for `glific/glific-frontend`, or a commit range.
-
-## 2. Load Reference Files
-
-Read what's needed for the task:
-- `sections.md` — to determine which of the 8 sections the content belongs in
-- `style-writing.md`, `style-page.md` — for writing conventions and templates
-- `style-images.md`, `screenshots.md` — for image handling and screenshot recipes
-
-## 3. Research the Feature
-
-**Mode A — Feature Name:**
-1. Find the container: `../glific-frontend/src/containers/{FeatureName}/`
-2. Read the main list and form components (e.g. `FlowList.tsx`, `Flow.tsx`) to understand what the UI shows and does
-3. Read `../glific-frontend/src/routes/AuthenticatedRoute/AuthenticatedRoute.tsx` to find the URL route
-4. Check existing docs in `docs/` for the feature (search for the feature name in file names and content)
-5. Optionally read `../glific-frontend/src/graphql/queries/{Feature}.ts` to understand what data the feature displays
-
-**Mode B — PR Number:**
-1. `gh pr diff #PR_NUMBER --repo glific/glific-frontend` to see what changed
-2. Identify affected containers from the changed file paths
-3. Read the changed files in full to understand new behavior
-4. Check existing docs for the affected area
-
-## 4. Determine Placement
-
-Use `sections.md` to map the feature to the right section. For Product Features, check the existing numbered file list to determine the next number.
-
-Print the placement plan and **ask the user to confirm** before writing anything:
-
-```
-Placement plan:
-- Doc: docs/{section}/{filename}.md
-- Images: static/img/{feature}/
-- Action: {new page | update existing | add sub-page to existing dir}
-- Recipe: scripts/recipes/{feature-slug}.yaml ({exists | needs creating})
-```
-
-## 5. Capture Screenshots
-
-Check for an existing recipe at `scripts/recipes/{feature-slug}.yaml`.
-
-**Recipe missing** → create it. Read `screenshots.md` for the exact format. Find `data-testid` values in the relevant container files.
-
-**Recipe exists** → review it against what you read in step 3. Add or update flows for any user path the doc will reference. Fix selectors if the UI has changed.
-
-Then run:
-```bash
-node scripts/screenshot.js {feature-slug}
-```
-
-Verify all expected files land in `static/img/{feature}/`. Iterate on any selector that misses — never ship a doc that references a non-existent image.
-
-Use `:::info Screenshot coming soon` only when the feature requires backend data that cannot be seeded (e.g., live WhatsApp delivery receipts, billing pages).
-
-## 6. Write Documentation
-
-Choose the correct template from `style-page.md` based on the section. Save to the confirmed path from step 4.
-
-Follow `style-writing.md` for voice and format. The most common mistake: writing for a technical audience. Imagine explaining this to an NGO field worker on their first day.
-
-## 7. Validate
-
-- [ ] All images referenced in the doc exist in `static/img/{feature}/`
-- [ ] Image paths use `/img/` prefix (Docusaurus convention), not `static/img/`
-- [ ] No new GitHub CDN image URLs (only old untouched pages keep those)
-- [ ] Page header has the read-time badge and difficulty level
-- [ ] Page matches the correct section template from `style-page.md`
-- [ ] Numbered file prefix is correct and doesn't conflict with existing files
-
-## 8. Print Next Steps
-
-```
-Documentation generated:
-- Doc: docs/{section}/{filename}.md
-- Images: static/img/{feature}/ ({N} screenshots captured)
-- Recipe: scripts/recipes/{feature-slug}.yaml
-
-Next:
-1. Preview: yarn start (in this repo)
-2. Review at http://localhost:3000/docs/{slug}
-3. Commit doc + recipe + screenshots together, then open a PR
-```
diff --git a/package.json b/package.json
index 83daec080..89398bb14 100644
--- a/package.json
+++ b/package.json
@@ -12,10 +12,7 @@
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
- "typecheck": "tsc",
- "screenshot": "node scripts/screenshot.js",
- "screenshot:video": "node scripts/screenshot.js --video",
- "screenshot:install": "npx playwright install chromium"
+ "typecheck": "tsc"
},
"dependencies": {
"@cmfcmf/docusaurus-search-local": "^0.11.0",
@@ -32,9 +29,6 @@
"@docusaurus/module-type-aliases": "^3.8.1",
"@docusaurus/tsconfig": "^3.8.1",
"@types/react": "^18.2.29",
- "dotenv": "^16.0.3",
- "js-yaml": "^4.1.0",
- "playwright": "^1.48.0",
"typescript": "~5.2.2"
},
"browserslist": {
diff --git a/scripts/recipes/chats.yaml b/scripts/recipes/chats.yaml
deleted file mode 100644
index d0c48414a..000000000
--- a/scripts/recipes/chats.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
-name: chats
-output_dir: chats
-flows:
- - name: chat_interface
- description: The main chat interface with contact list
- required: true
- steps:
- - navigate: /chat
- - wait: '.chat-container, [class*="ChatInterface"]'
- - snap: chats_interface.png
-
- - name: chat_window
- description: An open chat conversation
- required: false
- steps:
- - navigate: /chat
- - wait: '[class*="ContactCard"], [class*="contactCard"]'
- - click: '[class*="ContactCard"]:first-child, [class*="contactCard"]:first-child'
- - sleep: 1000
- - snap: chats_conversation_window.png
-
- - name: chat_shortcuts
- description: The Speed Send / Template shortcuts at the bottom of the chat
- required: false
- steps:
- - navigate: /chat
- - wait: '[class*="ContactCard"], [class*="contactCard"]'
- - click: '[class*="ContactCard"]:first-child, [class*="contactCard"]:first-child'
- - wait_text: Speed Send
- - snap: chats_shortcuts_bar.png
diff --git a/scripts/recipes/flows.yaml b/scripts/recipes/flows.yaml
deleted file mode 100644
index f1a873999..000000000
--- a/scripts/recipes/flows.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
-name: flows
-output_dir: flows
-flows:
- - name: flow_list
- description: The list of all flows
- required: true
- steps:
- - navigate: /flow
- - wait: '[data-testid="flow-list"]'
- - snap: flows_list.png
-
- - name: flow_create
- description: The create flow dialog
- required: false
- steps:
- - navigate: /flow
- - wait: '[data-testid="flow-list"]'
- - click: '[data-testid="newItemButton"]'
- - wait_text: Create Flow
- - snap: flows_create_dialog.png
-
- - name: flow_editor
- description: The flow editor canvas (requires an existing flow)
- required: false
- steps:
- - navigate: /flow
- - wait: '[data-testid="flow-list"]'
- - click: '[data-testid="configure-icon"]'
- - sleep: 2000
- - snap: flows_editor_canvas.png
diff --git a/scripts/screenshot.js b/scripts/screenshot.js
deleted file mode 100644
index 65036b74c..000000000
--- a/scripts/screenshot.js
+++ /dev/null
@@ -1,182 +0,0 @@
-#!/usr/bin/env node
-/**
- * Playwright screenshot + video runner for Glific docs.
- *
- * Usage:
- * node scripts/screenshot.js flows — screenshots only
- * node scripts/screenshot.js flows --video — screenshots + video recording
- * node scripts/screenshot.js --video — all recipes with video
- *
- * Requires: playwright, js-yaml, dotenv (install with: yarn add --dev playwright js-yaml)
- * Also run: npx playwright install chromium
- *
- * Credentials (.env at repo root, gitignored):
- * GLIFIC_URL=https://glific.test:3000
- * GLIFIC_PHONE=+91XXXXXXXXXX
- * GLIFIC_PASSWORD=your_password
- *
- * Videos are saved to static/videos/{output_dir}/ as .webm files.
- * Use in docs:
- */
-
-'use strict';
-
-const { chromium } = require('playwright');
-const yaml = require('js-yaml');
-const fs = require('fs');
-const path = require('path');
-
-require('dotenv').config({ path: path.join(__dirname, '..', '.env') });
-
-const ROOT = path.join(__dirname, '..');
-const RECIPES_DIR = path.join(__dirname, 'recipes');
-const STATIC_IMG = path.join(ROOT, 'static', 'img');
-const STATIC_VIDEO = path.join(ROOT, 'static', 'videos');
-
-const GLIFIC_URL = (process.env.GLIFIC_URL || 'https://glific.test:3000').replace(/\/$/, '');
-const GLIFIC_PHONE = process.env.GLIFIC_PHONE;
-const GLIFIC_PASSWORD = process.env.GLIFIC_PASSWORD;
-
-if (!GLIFIC_PHONE || !GLIFIC_PASSWORD) {
- console.error('Missing GLIFIC_PHONE or GLIFIC_PASSWORD in .env');
- process.exit(1);
-}
-
-async function authenticate(page) {
- console.log(' Authenticating...');
- await page.goto(`${GLIFIC_URL}/login`, { waitUntil: 'networkidle' });
- await page.waitForSelector('[data-testid="AuthContainer"]', { timeout: 10000 });
-
- // PhoneInput renders a text input with name="phoneNumber"
- await page.fill('input[name="phoneNumber"]', GLIFIC_PHONE);
- await page.fill('input[name="password"]', GLIFIC_PASSWORD);
- await page.click('[data-testid="SubmitButton"]');
-
- // Wait for redirect to /chat after successful login
- await page.waitForURL(`${GLIFIC_URL}/chat**`, { timeout: 15000 });
- console.log(' Authenticated.');
-}
-
-async function runStep(page, step, outputDir) {
- if (step.navigate !== undefined) {
- await page.goto(`${GLIFIC_URL}${step.navigate}`, { waitUntil: 'networkidle' });
-
- } else if (step.wait !== undefined) {
- await page.waitForSelector(step.wait, { timeout: 8000 });
-
- } else if (step.wait_text !== undefined) {
- await page.waitForFunction(
- (text) => document.body.innerText.includes(text),
- step.wait_text,
- { timeout: 8000 }
- );
-
- } else if (step.click !== undefined) {
- await page.click(step.click);
-
- } else if (step.sleep !== undefined) {
- await page.waitForTimeout(step.sleep);
-
- } else if (step.snap !== undefined) {
- const snapPath = path.join(outputDir, step.snap);
- if (step.element) {
- // Crop to a specific element — hides sidebar, nav, and unrelated UI
- await page.locator(step.element).screenshot({ path: snapPath });
- } else {
- await page.screenshot({ path: snapPath, fullPage: false });
- }
- console.log(` ✓ ${step.snap}${step.element ? ` (cropped to ${step.element})` : ''}`);
- }
-}
-
-async function runRecipe(recipePath, recordVideo) {
- const content = fs.readFileSync(recipePath, 'utf-8');
- const recipe = yaml.load(content);
-
- const imgDir = path.join(STATIC_IMG, recipe.output_dir);
- if (!fs.existsSync(imgDir)) fs.mkdirSync(imgDir, { recursive: true });
-
- const videoDir = path.join(STATIC_VIDEO, recipe.output_dir);
- if (recordVideo && !fs.existsSync(videoDir)) fs.mkdirSync(videoDir, { recursive: true });
-
- console.log(`\nRecipe: ${recipe.name}${recordVideo ? ' (+ video)' : ''}`);
-
- const browser = await chromium.launch({ headless: false });
-
- for (const flow of recipe.flows) {
- // Each flow gets its own context so videos are saved per-flow
- const contextOptions = {
- viewport: { width: 1440, height: 900 },
- ignoreHTTPSErrors: true,
- };
- if (recordVideo) {
- contextOptions.recordVideo = {
- dir: videoDir,
- size: { width: 1440, height: 900 },
- };
- }
-
- const context = await browser.newContext(contextOptions);
- const page = await context.newPage();
-
- console.log(` Flow: ${flow.name} — ${flow.description}`);
- try {
- await authenticate(page);
- for (const step of flow.steps) {
- await runStep(page, step, imgDir);
- }
-
- // Rename the auto-generated video to flow name
- if (recordVideo) {
- const videoPath = await page.video().path();
- await context.close();
- const dest = path.join(videoDir, `${flow.name}.webm`);
- fs.renameSync(videoPath, dest);
- console.log(` ✓ video: ${flow.name}.webm`);
- } else {
- await context.close();
- }
- } catch (err) {
- await context.close();
- if (flow.required) {
- throw new Error(`Required flow "${flow.name}" failed: ${err.message}`);
- } else {
- console.warn(` Warning: optional flow "${flow.name}" skipped — ${err.message}`);
- }
- }
- }
-
- await browser.close();
- console.log(` Done → static/img/${recipe.output_dir}/${recordVideo ? ` + static/videos/${recipe.output_dir}/` : ''}`);
-}
-
-async function main() {
- const args = process.argv.slice(2);
- const recordVideo = args.includes('--video');
- const slug = args.find((a) => !a.startsWith('--'));
-
- let recipes;
- if (slug) {
- const recipePath = path.join(RECIPES_DIR, `${slug}.yaml`);
- if (!fs.existsSync(recipePath)) {
- console.error(`Recipe not found: ${recipePath}`);
- process.exit(1);
- }
- recipes = [recipePath];
- } else {
- recipes = fs.readdirSync(RECIPES_DIR)
- .filter((f) => f.endsWith('.yaml'))
- .map((f) => path.join(RECIPES_DIR, f));
- }
-
- for (const recipePath of recipes) {
- await runRecipe(recipePath, recordVideo);
- }
-
- console.log('\nAll done.');
-}
-
-main().catch((err) => {
- console.error(err.message);
- process.exit(1);
-});
diff --git a/yarn.lock b/yarn.lock
index e6b0a068d..afc5f70a9 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4446,11 +4446,6 @@ dot-prop@^6.0.1:
dependencies:
is-obj "^2.0.0"
-dotenv@^16.0.3:
- version "16.0.3"
- resolved "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz"
- integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==
-
duplexer@^0.1.2:
version "0.1.2"
resolved "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz"
@@ -4933,7 +4928,7 @@ fs.realpath@^1.0.0:
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
-fsevents@2.3.2, fsevents@~2.3.2:
+fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
@@ -7150,20 +7145,6 @@ pkg-dir@^7.0.0:
dependencies:
find-up "^6.3.0"
-playwright-core@1.61.0:
- version "1.61.0"
- resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.61.0.tgz#caf8078b2a39cd7738dc75ec11cb3b47f385c3f0"
- integrity sha512-caX7TrY3Ml6egyDX0WUcTHDxodl/b51y5wJOdCEA36QviK/s2g081hvmGs8eaE3DWb6NYZQ6BjO/QkNRPenoPA==
-
-playwright@^1.48.0:
- version "1.61.0"
- resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.61.0.tgz#7082df3df08ffa82b11420ea5fae84a40bd16e3f"
- integrity sha512-Z+7BeeqQPRRzklHsVFP4KTGIyMxKUmfeRA4WisM6G3/XW6nwGeX6fX9qYaDa+CiUqpOkb2f6X3nar05R3kSuJQ==
- dependencies:
- playwright-core "1.61.0"
- optionalDependencies:
- fsevents "2.3.2"
-
postcss-attribute-case-insensitive@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-7.0.1.tgz#0c4500e3bcb2141848e89382c05b5a31c23033a3"