# OneLessTool — full content (data version 1c3df44d0d3f)
Evidence statuses: verified, editorial, estimate, illustrative, ai_suggested, unverified. Structured access: https://onelesstool.com/api/v1 and MCP at https://onelesstool.com/api/mcp.
---
# Workflows
# Build and host a small business website with AI coding tools instead of Webflow, Squarespace or Wix
> For a simple 3–8 page marketing site: write a site brief, have Claude Code or Cursor (or a chat assistant, for non-coders) build plain HTML/CSS, and host it on Cloudflare's free plan with Workers static assets. Includes the agent prompt, deployment commands, a form option, redirect handling and an honest list of what you give up.
- Outcome: I want a fast, professional website for my business without paying a monthly website-builder subscription.
- Replaces: Webflow (full), Squarespace (full), Wix (full)
- Uses: Claude — Claude Code (included in Claude's paid plans) builds and edits the site files from the brief; Claude chat works for non-coders who copy files by hand.; Cursor (optional) — Alternative AI code editor if you already pay for it.; ChatGPT (optional) — Alternative chat assistant for generating pages and copy.; Cloudflare Workers & Pages — Free hosting for the static files (Workers static assets), custom domain, HTTPS and redirects.; Google Workspace (optional) — Google Forms + Sheets for the simplest contact-form option.
- Extra monthly cost: $0 — Cloudflare's Free plan serves static asset requests free and without a request limit; Worker code (only needed for a custom form handler) gets 100,000 requests a day on Free. Assumes you already pay for an AI coding tool. Your domain renewal is unchanged — but if your domain was bundled with the website builder, you will need to pay for it at a registrar after moving.
- Difficulty: moderate; skill: technical; setup: 1–2 days for a 5-page site including content migration, review and DNS changes
- Evidence: editorial; illustrative example: true; last reviewed 2026-10-13
- Canonical: https://onelesstool.com/workflows/business-website-with-ai-coding
## Good fit for
- Service businesses, consultants, clinics and trades with a brochure-style site that changes a few times a month
- Founders comfortable running a few terminal commands, or with a technical friend for the first deploy
- Sites where speed, low cost and full ownership of the files matter more than a visual editor
## Not a fit for
- Teams where non-technical marketers publish pages or blog posts weekly and expect a visual editor
- Ecommerce stores, booking systems, member areas or anything with payments and logins
- Sites with large blogs or CMS collections that non-developers update
- Owners who need phone or chat support from their website provider
## Before
Pay a monthly or annual website-builder plan. Edit pages in the visual editor, use its built-in contact form, and rely on its hosting, SSL, templates and support.
## After
The site is a folder of HTML/CSS files you own. An AI coding tool builds and edits it from a written brief; `npx wrangler deploy` publishes it to Cloudflare's free plan on your own domain. Forms go to a Google Form or a small Worker. Edits are made by asking the AI and redeploying.
## Steps
### 1. Inventory the current site before touching anything
List every page, its URL, page title and meta description, every form and where its submissions go, and every integration (booking widget, newsletter signup, chat, analytics, store).
Copy all text into a Google Doc and download all images you own the rights to. Check your builder's own export options; exports are often partial, so a manual copy is the safe baseline.
Note who controls the **domain** (registrar login) and the **DNS**. If the domain was bought through the website builder, plan to transfer it or point it elsewhere before cancelling.
### 2. Write the site brief
Fill in the **site brief template** (artifact below) and save it as `SITE_BRIEF.md` in a new, empty project folder. Include the old URL for each page so redirects can be created.
The brief is what keeps the AI from inventing content. Anything you leave blank becomes a placeholder you'll fill later.
### 3. Have the AI build the site
**Coders / comfortable with a terminal:** open the folder in Claude Code (included in Claude's paid plans) or Cursor and paste the **Agent build prompt**. Review the home page in the browser before letting it build the rest. Run it locally with `npx wrangler dev` or by opening the HTML files.
**Non-coders:** use Claude or ChatGPT chat with the **Single-page generator prompt**, one page at a time. Save each answer as a file with the exact name the AI gives (e.g. `index.html`, `styles.css`) in a `public` folder. Ask for a fixed list of files up front so nothing is missed.
Keep the site **plain HTML + CSS** unless you have a reason not to; it's easiest for any AI or developer to edit later.
### 4. Review it like a visitor
Use the **QA prompt** to have the AI check for broken links, missing alt text and titles. Then check yourself:
- On your phone: menu works, text readable, buttons tappable, no sideways scrolling.
- Every claim, price and testimonial is real and approved.
- Contact details match your Google Business Profile and other listings exactly.
### 5. Deploy to Cloudflare's free plan
Cloudflare's docs now say to start new projects on **Workers** (Pages still works). For a static site:
1. Create a free Cloudflare account.
2. In the project folder, make sure `wrangler.jsonc` contains your project name, a `compatibility_date` and `"assets": { "directory": "./public" }`.
3. Run `npx wrangler deploy`. The first run asks you to log in. You get a `*.workers.dev` URL to test.
4. **Custom domain:** a Workers Custom Domain needs the domain added to Cloudflare as an active zone (free plan is fine), which usually means switching your domain's nameservers to Cloudflare. Recreate any email DNS records (MX, SPF, DKIM) **before** switching, or your email will break.
5. Add the domain under the Worker's **Settings > Domains & Routes**.
Free plan limits that matter (checked today): requests for static assets are free and unlimited; up to 20,000 files per version and 25 MiB per file; Worker code (only if you add a form handler) has 100,000 requests a day.
### 6. Handle forms and redirects
**Forms, simplest option:** create a Google Form (responses go to a Sheet, with email notifications) and link to it or embed it on the contact page. Looks less integrated but needs no code.
**Forms, integrated option:** ask the AI to add a small Worker route that receives the form POST, checks a Cloudflare Turnstile token to block spam, and forwards the message to you (for example to a Google Sheet via Apps Script, or by email). This uses Worker requests, which count toward the 100,000/day free limit.
**Redirects:** a `_redirects` file in `public/` maps old builder URLs to new ones (e.g. `/about-us /about 301`). Cloudflare allows up to 2,000 static and 100 dynamic redirects. This protects your search rankings.
### 7. Run both sites in parallel, then cancel
Keep the old builder subscription until the new site has been live on your domain for at least a week and the verification checklist passes. Submit the new `sitemap.xml` in Google Search Console and watch for crawl errors.
Save the project folder somewhere backed up (a private Git repo is ideal). That folder *is* your website now.
## Prompts
### Agent build prompt (Claude Code / Cursor)
Have an AI coding agent build the whole site from the brief, with checkpoints.
```text
You are building a static marketing website for {{business_name}}. Read SITE_BRIEF.md in this folder first; it is the source of truth.
Requirements
- Pages: {{page_list}}. One HTML file per page in ./public (e.g. public/index.html, public/services/index.html) so URLs have no .html extension.
- Plain HTML + one shared CSS file (public/styles.css). No framework and no build step unless I ask. Minimal JavaScript (mobile menu only).
- Shared header/nav and footer must be identical on every page. Footer: {{footer_contents}}.
- Design: colours {{brand_colors}}, fonts {{fonts}}, tone {{design_tone}}. Mobile-first, readable at 375px wide, no horizontal scroll.
- Accessibility: semantic headings (one h1 per page), alt text on every image, visible focus states, colour contrast at least WCAG AA.
- SEO: unique
and meta description per page (use the ones in the brief), Open Graph tags, a sitemap.xml and robots.txt in public/, canonical URLs on {{domain}}.
- Contact form: {{form_approach}}.
- Redirects: create public/_redirects with 301s from each old URL in the brief to its new path.
- Images: put them in public/images, sized for the web (max ~1600px wide, compressed), with width/height attributes.
- Hosting: Cloudflare Workers static assets. Create wrangler.jsonc with name "{{worker_name}}", today's compatibility_date and "assets": {"directory": "./public"}. No Worker script unless the form approach needs one.
Process
1. Propose the file structure and a one-paragraph design direction. Wait for my OK.
2. Build the home page first. Stop so I can review it in the browser.
3. Build the remaining pages, then run a self-check: broken internal links, missing alt text, missing titles, pages wider than the viewport at 375px. Report what you found and fixed.
Do not invent testimonials, client names, prices, awards or statistics. Use clearly marked placeholders where content is missing.
```
### Single-page generator prompt (chat, for non-coders)
Generate one page at a time in a chat assistant and save it as a file.
```text
I'm building a simple static website for {{business_name}} with these pages: {{page_list}}. All pages share one stylesheet called styles.css.
Here is my site brief:
{{site_brief}}
Now write the complete file for the "{{page_name}}" page, saved as {{file_path}}. Use plain HTML, link to /styles.css, include the shared header and footer exactly as in previous pages: {{shared_header_footer_or_none}}.
Use only content from the brief; mark anything missing as [PLACEHOLDER: ...]. Give me the whole file in one code block and nothing else.
```
### QA prompt
Have the AI audit the finished site before launch.
```text
Review every file in ./public for launch readiness on {{domain}}. Check and fix: broken internal links; images without alt text or width/height; pages missing a unique title or meta description; more than one h1; layout overflow at 375px; contrast below WCAG AA for {{brand_colors}}; any invented testimonials, numbers or client names; _redirects entries for these old URLs: {{old_urls}}.
Report a table of issues found, what you changed, and anything that needs my decision.
```
### Content edit prompt (after launch)
Make routine changes safely and redeploy.
```text
Change request for the {{business_name}} site: {{change_description}}.
Only edit the files needed. Keep header/footer identical across pages. Show me a summary of the diff, then run `npx wrangler deploy` once I confirm.
```
## Templates and scripts
### Site brief template (template)
```markdown
# Site brief – {{business_name}}
_Fill this in before you prompt the AI. The more specific, the less rework._
## 1. Basics
- Business name: {{business_name}}
- One-sentence description: {{one_liner}}
- Primary audience: {{audience}}
- Main action we want visitors to take: {{primary_cta}} (e.g. book a call, request a quote, call us)
- Domain: {{domain}} — registrar: ______ — DNS currently managed by: ______
- Current site URL (to migrate from): {{current_site_url}}
## 2. Pages (3–8)
| Page | URL path | Purpose | Key content | Old URL to redirect from |
|---|---|---|---|---|
| Home | / | Explain what we do, prove it, CTA | Hero, 3 services, testimonials, CTA | / |
| Services | /services | Detail each service | 3 sections + FAQ | /what-we-do |
| About | /about | Trust | Story, team photos, credentials | /about-us |
| Contact | /contact | Convert | Form, phone, address, map link, hours | /contact |
| (optional) Work / Case studies | /work | Proof | 3 short case studies | |
| Privacy | /privacy | Legal | Your privacy policy text | |
## 3. Brand
- Colours (hex): primary ____ accent ____ text ____ background ____
- Fonts: ____ (or "system fonts")
- Logo files: SVG/PNG paths
- Sites we like the look of (and why): ____
- Tone of voice: ____
## 4. Content inventory
- Copy: where it lives now (export from old site, Google Doc link)
- Images: folder link; all images we have rights to use? yes/no
- Testimonials (with permission): ____
- Legal: privacy policy, cookie notice needed? (depends on analytics/forms used and your location)
## 5. Forms and integrations
- Contact form fields: name, email, phone (optional), message, how did you hear
- Where submissions go: Google Form + Sheet / email via a small Worker / other
- Booking link (e.g. existing scheduler): ____
- Analytics: none / privacy-friendly analytics / Google Analytics
- Anything else from the old builder we rely on: blog, store, member area, newsletter signup, chat widget
## 6. SEO essentials
- Page titles and meta descriptions: keep the current ones? (copy them from the old site)
- Business address and phone shown consistently on every page footer
- Old URLs that get traffic (from your analytics) → redirect targets
## 7. Who maintains it
- Who will edit text after launch: ____
- How often: ____
- Their comfort level: edits in a code editor / asks the AI / needs a visual editor
```
### Minimal wrangler.jsonc for a static site (config)
```jsonc
{
"$schema": "./node_modules/wrangler/config-schema.json",
"name": "{{worker_name}}",
// Set to the date you create the project
"compatibility_date": "{{compatibility_date}}",
"assets": {
"directory": "./public"
}
}
```
## Limitations
- No visual drag-and-drop editor: changes go through an AI tool or code, which suits founders more than marketing teams.
- No built-in CMS or blog management for non-technical editors.
- No built-in forms, ecommerce, bookings, memberships or email marketing; each needs a separate tool or custom code.
- No vendor support desk; when something breaks you rely on the AI tool, docs, or a developer.
- Domain and DNS changes are on you; mistakes can take a site or email offline for hours.
- Builder templates, apps and some content may not export cleanly; expect manual copying.
## Risks
- **migration_complexity** (medium): Moving DNS can break email if MX/SPF/DKIM records aren't recreated first. Check every record before switching nameservers.
- **functionality_loss** (medium): Builder-native features (forms, store, scheduling, newsletter popups) disappear on cancel; each must be inventoried and replaced.
- **security** (low): Static HTML has a small attack surface, but a custom form handler must validate input and use spam protection such as Turnstile.
- **reliability** (low): AI-generated code can contain subtle layout or accessibility bugs; the QA step and a mobile check are essential.
- **vendor_lock_in** (low): Plain HTML files are portable to any host, which reduces lock-in compared with a builder.
## Verification checklist (run before cancelling)
- [ ] Every page from your inventory exists on the new site and old URLs return a 301 to the right new page (test each in a private window).
- [ ] The `*.workers.dev` preview works on a phone at 375px wide with no horizontal scrolling and a working menu.
- [ ] A test contact-form submission arrives where you expect (Sheet, inbox) within minutes, and a blank or spammy submission is rejected.
- [ ] Email still sends and receives on your domain after DNS changes (send a test both ways).
- [ ] Page titles and meta descriptions match or improve on the old site's; sitemap.xml loads and is submitted in Search Console.
- [ ] You (or whoever maintains the site) made a text change and redeployed it unaided in under 15 minutes.
- [ ] The project folder is backed up outside your laptop.
- [ ] The old builder stays active until the new site has run on your domain for at least a week without issues.
## Savings methodology
Savings = your website-builder plan (monthly, or annual price ÷ 12) − incremental cost ($0 hosting on Cloudflare's Free plan; $0 for the AI tool if you already pay for it). If the builder bundled your domain, subtract the domain's annual registrar price ÷ 12. If you'd need to buy an AI coding subscription only for this, subtract that too. Setup time (1–2 days) and later editing time are not monetised.
Example (illustrative): A 5-page consultancy site on a website-builder plan billed annually, owner already pays for Claude Pro and has the domain at a separate registrar. $25/mo → $0/mo. Assumptions: Illustrative: $25/month is a round placeholder for a mid-tier builder plan. Webflow, Squarespace and Wix pricing pages showed non-US currencies or JavaScript-rendered prices to our fetcher on 2026-10-13, so no builder price was verified. Cloudflare Free plan limits (static asset requests free and unlimited; 20,000 files/version; 25 MiB per file) were verified on developers.cloudflare.com on 2026-10-13. Claude Pro is already paid for other work; Claude's pricing page lists Claude Code as included in all paid plans. The domain renewal is unchanged and not counted.
## Sources
- Cloudflare Workers static assets: billing and limitations: https://developers.cloudflare.com/workers/static-assets/billing-and-limitations/ (accessed 2026-10-13)
- Cloudflare Workers limits: https://developers.cloudflare.com/workers/platform/limits/ (accessed 2026-10-13)
- Cloudflare Pages limits: https://developers.cloudflare.com/pages/platform/limits/ (accessed 2026-10-13)
- Cloudflare Pages docs: https://developers.cloudflare.com/pages/ (accessed 2026-10-13)
- Cloudflare Workers static assets: https://developers.cloudflare.com/workers/static-assets/ (accessed 2026-10-13)
- Cloudflare Workers static assets: get started: https://developers.cloudflare.com/workers/static-assets/get-started/ (accessed 2026-10-13)
- Cloudflare Workers static assets: redirects: https://developers.cloudflare.com/workers/static-assets/redirects/ (accessed 2026-10-13)
- Cloudflare Workers Custom Domains: https://developers.cloudflare.com/workers/configuration/routing/custom-domains/ (accessed 2026-10-13)
- Claude pricing: https://claude.com/pricing (accessed 2026-10-13)
- Squarespace pricing: https://www.squarespace.com/pricing (accessed 2026-10-13)
- Wix plans: https://www.wix.com/plans (accessed 2026-10-13)
# Write client proposals with AI and Google Docs instead of PandaDoc
> Turn discovery-call notes into a scoped, priced proposal with a four-step AI prompt sequence, lay it out in a reusable Google Docs template, and collect signatures with Google Docs eSignature (if your Workspace plan includes it) or a DocuSign account you already have. Replaces PandaDoc's writing and template work; not its analytics, CRM sync or payments.
- Outcome: I want to send professional, accurate proposals quickly and get them signed without paying for PandaDoc.
- Replaces: PandaDoc (partial)
- Uses: Claude — Turn discovery notes into scope, pricing table and risks; review the draft like a sceptical client.; ChatGPT (optional) — Alternative assistant for the same prompt sequence.; Google Workspace — Google Docs proposal template, Drive folder per client, and (on eligible plans, when the admin enables it) Docs eSignature.; DocuSign eSignature (optional) — Signature option if your Google Workspace plan lacks eSignature and you already pay for DocuSign.
- Extra monthly cost: $0 — Assumes you already pay for an AI assistant and a Google Workspace plan. Google Docs eSignature is listed for Workspace Individual, Business Standard and Plus, and several Enterprise/Education editions when the admin turns it on; it is not listed for Business Starter. If you don't have it and don't already pay for DocuSign or similar, you'll need a separate e-signature tool, which is an extra cost.
- Difficulty: easy; skill: basic; setup: 2–3 hours to build the template, pricing rate card and saved prompts
- Evidence: editorial; illustrative example: false; last reviewed 2026-10-13
- Canonical: https://onelesstool.com/workflows/client-proposals-with-ai-docs
## Good fit for
- Freelancers, consultancies and agencies sending a handful of custom proposals a month
- Teams already on Google Workspace Business Standard or higher (eSignature included when enabled)
- Service businesses whose proposals are mostly custom scope rather than catalogue quotes
## Not a fit for
- Sales teams that rely on PandaDoc's CRM sync to create documents from deals and update deal stages automatically
- Businesses that collect payment inside the proposal at signing
- Teams that need view tracking (who opened what, for how long) to time follow-ups
- Organisations with formal approval chains and a shared, governed content library
- Regulated agreements where your legal team requires a specific e-signature provider
## Before
Create a PandaDoc document from a template or CRM deal, drag in content-library blocks, build the pricing table, route it for internal approval, send it, watch view analytics, and collect signature and payment in PandaDoc.
## After
Paste discovery notes into Claude and run four prompts (brief → scope → pricing → risks), paste the result into a copy of your Google Docs proposal template, check every number against your rate card, export or share, and request signatures with Docs eSignature (or DocuSign). Follow-ups are scheduled in your calendar instead of triggered by view alerts.
## Steps
### 1. Check what you'll lose and what you'll use instead
List the PandaDoc features you use weekly. PandaDoc's own plan comparison puts **CRM integrations, content library, document analytics and approval workflows on Business** (not Starter), and **payment collection** on both Starter and Business. If any of those drive your sales process, this workflow is only a partial replacement.
Then confirm your signature route:
- **Google Docs eSignature**: listed for Workspace Individual, Business Standard/Plus and some Enterprise/Education editions, **only when your admin enables it**. Up to 10 signers and 200 fields per request; an audit-trail page is added to the signed PDF. Not listed for Business Starter.
- **DocuSign** or another e-signature tool you already pay for.
- If you have neither, budget for one before cancelling PandaDoc.
### 2. Build your Google Docs template and rate card
Paste the **proposal template** (artifact below) into a new Google Doc: turn on Markdown (Tools > Preferences), then right-click > **Paste from Markdown**. Add your logo, set heading styles and brand colours, and save it in a Drive folder named `Templates`.
Keep a **rate card** in a Google Sheet: service, unit, price, minimum, notes. The AI will only use prices from this sheet. This is the most important control in the workflow.
Move your reusable blocks (case studies, team bios, terms) into one `Proposal library` Doc. It's a manual content library: copy, don't link.
### 3. Run the prompt sequence on your discovery notes
In one conversation (or a Claude Project / ChatGPT Project holding your rate card, library and template):
1. **Discovery → brief**: structure the messy notes and list unknowns.
2. **Brief → scope**: phases, deliverables, acceptance criteria, out of scope.
3. **Scope → pricing table**: line items priced *only* from your rate card, with the arithmetic shown.
4. **Risks and assumptions**, then the **executive summary** last.
Answer the unknowns the AI lists before moving on. Don't paste confidential client data your agreement or your AI plan's data settings don't allow.
### 4. Assemble the document and check every number
Make a copy of the template in the client's Drive folder (`Proposals//`). Paste each section in using Paste from Markdown.
Then verify by hand:
- Each line item's price matches the rate card; recalculate totals in the Sheet, not in your head.
- Dates are achievable and dependencies are stated.
- Names, company details and the validity date are correct.
Finally, run the **Sceptical client review prompt** and fix what's fair.
### 5. Send and collect signatures
**Google Docs eSignature** (if enabled): in the Doc, go to **Tools > eSignature**, choose each signer under "Insert fields for", drag in Signature and Date signed fields, then click **Request signature**, add signer emails and optionally turn on automatic reminders. When everyone has signed, the final PDF (with its audit trail page) is saved in the same Drive folder as the original Doc, and linked in the completion email.
**DocuSign**: download the Doc as PDF (**File > Download > PDF**), upload it to DocuSign, place fields and send.
Either way, also email the client a short cover note with the summary and a deadline for questions.
### 6. Replace the missing tracking and payment steps
- **Follow-ups**: without view analytics, add a calendar reminder 2 and 5 business days after sending. Use the **Follow-up email prompt** with the proposal summary.
- **CRM**: paste the proposal link and value into the deal record by hand (or with an automation tool you already use).
- **Deposits**: send the deposit invoice from your accounting/invoicing tool when the signed PDF arrives.
## Prompts
### 1. Discovery notes → structured brief
Turn raw call notes into a clean brief and surface what you still need to ask.
```text
You are helping me write a proposal for {{client_company}}. My company: {{your_company}}, which does {{your_services}}.
Here are my raw discovery notes:
{{discovery_notes}}
Produce: 1) the client's situation in 3 sentences; 2) their goals, each with a measurable success indicator; 3) constraints (budget hints, deadlines, decision-makers, approvals); 4) a numbered list of open questions I must answer before scoping. Don't fill gaps with assumptions; list them as questions.
```
### 2. Brief → scope of work
Define phases, deliverables, acceptance criteria and exclusions.
```text
Using the brief above and my answers to the open questions ({{answers_to_open_questions}}), write the scope of work:
- {{phase_count}} phases, each with duration estimate, deliverables (with format), and an acceptance criterion per deliverable.
- An "Out of scope" list of at least 5 items the client might reasonably assume are included.
- Dependencies on the client (inputs, approvals, access) with deadlines.
Use plain language. Match how we usually deliver: {{delivery_approach}}.
```
### 3. Scope → pricing table (rate card only)
Price the scope strictly from your own rate card, with arithmetic shown.
```text
Price the scope above using ONLY this rate card. Never invent a price or discount:
{{rate_card}}
Output a Markdown table: item | qty | unit | unit price | line total. Then subtotal, tax at {{tax_rate}}, and total in {{currency}}.
Show your quantity reasoning for each line in one short sentence underneath. If something in scope has no rate-card entry, put "PRICE NEEDED" instead of a number.
Add a separate "Optional add-ons" table for: {{optional_items}}.
Payment terms to state: {{payment_terms}}.
```
### 4. Risks, assumptions and executive summary
Protect the project with explicit assumptions, then write the summary last.
```text
For this proposal:
1) List 5–8 assumptions that, if wrong, would change cost or timeline (inputs, feedback rounds, access, third-party tools).
2) A risk table: risk | likelihood | impact | mitigation. Include at least one risk on the client side and one on ours.
3) Then write a 4–5 sentence executive summary for {{decision_maker_role}}: their situation, outcome, our approach, total investment of {{total_price}}, and the next step ({{next_step}}). No superlatives, no claims we can't prove.
```
### Sceptical client review prompt
Stress-test the draft before sending.
```text
Act as {{decision_maker_role}} at {{client_company}} reading this proposal for the first time, with a budget of about {{client_budget_hint}}. Be sceptical.
List: anything unclear; anything that looks padded; questions you'd ask before signing; places where scope and price don't match; and the single biggest reason you might say no. Then suggest the smallest edits that fix each point.
Proposal:
{{proposal_text}}
```
### Follow-up email prompt
Replace view-triggered follow-ups with a scheduled, helpful nudge.
```text
Write a short follow-up email (under 90 words) to {{client_name}} about the {{project_name}} proposal I sent on {{sent_date}}. Mention one specific benefit from the summary: {{key_benefit}}. Offer a 15-minute call to answer questions and note the proposal is valid until {{valid_until}}. Friendly, no pressure, no "just checking in".
```
## Templates and scripts
### Proposal template (Markdown — paste into Google Docs with Paste from Markdown) (template)
```markdown
# Proposal: {{project_name}}
**Prepared for:** {{client_name}}, {{client_company}}
**Prepared by:** {{your_name}}, {{your_company}}
**Date:** {{date}} · **Valid until:** {{valid_until}} · **Reference:** {{proposal_id}}
---
## 1. Summary
_Three to five sentences: their situation, the outcome they want, what you'll do, the investment, and the next step._
## 2. Your goals (as we understood them)
- Goal 1 — how we'll know it's achieved: ____
- Goal 2 — ____
- Constraints we heard: budget, deadline, internal capacity, approvals
## 3. Scope of work
### Phase 1 – {{phase_1_name}} ({{phase_1_duration}})
- Deliverable: ____ — format: ____ — acceptance: ____
### Phase 2 – {{phase_2_name}} ({{phase_2_duration}})
- Deliverable: ____
### Out of scope
- ____ (anything the client might reasonably assume is included)
## 4. Timeline
| Milestone | Target date | Depends on |
|---|---|---|
| Kick-off | ____ | Signed proposal + deposit |
| Phase 1 complete | ____ | Client feedback within 3 business days |
| Final delivery | ____ | ____ |
## 5. Investment
| Item | Qty | Unit price | Total |
|---|---|---|---|
| ____ | 1 | ____ | ____ |
| **Subtotal** | | | ____ |
| Tax ({{tax_rate}}) | | | ____ |
| **Total** | | | **____** |
**Optional add-ons** (not included in total)
| Option | Price | Notes |
|---|---|---|
| ____ | ____ | ____ |
**Payment terms:** {{payment_terms}} (e.g. 50% on signature, 50% on delivery; net 14). Invoices sent from {{invoicing_tool}}.
## 6. Assumptions
- Client provides ____ by ____.
- One round of consolidated feedback per deliverable; extra rounds billed at {{hourly_rate}}.
## 7. Risks and how we'll handle them
| Risk | Likelihood | Mitigation |
|---|---|---|
| ____ | Low/Med/High | ____ |
## 8. Why us
- Relevant result 1 (real, approved for reference)
- Relevant result 2
## 9. Terms
{{terms_reference}} (link to or attach your standard terms; have a lawyer review them once.)
## 10. Acceptance
By signing, {{client_company}} accepts this proposal and the terms referenced above.
| | {{client_company}} | {{your_company}} |
|---|---|---|
| Name | | |
| Title | | |
| Signature | | |
| Date | | |
```
## Limitations
- No document view analytics (opens, time per page); follow-ups are scheduled by hand.
- No automatic CRM sync of documents, values or deal stages.
- No payment collection at signing; deposits are invoiced separately.
- No governed content library or approval workflow; reusable blocks live in a Doc and approvals are manual.
- Pricing tables in Docs are static; there are no client-selectable optional items or automatic totals.
- Google Docs eSignature is only available on certain Workspace editions and only when your admin enables it; it allows up to 10 signers and 200 fields per request.
## Risks
- **reliability** (high): AI can miscalculate totals or invent prices. Price only from your rate card, mark gaps 'PRICE NEEDED', and recalculate totals in a spreadsheet.
- **sensitive_data** (medium): Discovery notes may include confidential client information. Check your client agreements and your AI plan's data settings before pasting them in.
- **compliance** (medium): Some contracts or industries require a particular e-signature provider or audit standard. Confirm Google Docs eSignature meets your legal requirements before relying on it.
- **functionality_loss** (medium): Losing CRM sync and view tracking can slow follow-ups for sales-led teams.
- **data_portability** (low): Export signed PandaDoc documents and your templates' text before cancelling; they won't be accessible afterwards.
## Verification checklist (run before cancelling)
- [ ] You rebuilt your last real proposal with this workflow and every price, total and date matches the original (or is knowingly updated).
- [ ] You confirmed in Google Docs that the eSignature option appears on your account (or you have an existing DocuSign/e-signature account), and completed a test signature with a colleague.
- [ ] The signed test PDF includes the audit trail and is saved in the right Drive folder.
- [ ] A full proposal took you under 60 minutes from notes to send.
- [ ] Your team agrees which lost features (view tracking, CRM sync, payments, approvals) you can live without, and has a manual replacement for each.
- [ ] All active and signed PandaDoc documents and template content are exported before cancelling.
## Savings methodology
Savings = PandaDoc seats × price per seat (monthly, or annual ÷ 12) − incremental cost. Incremental cost is $0 when you already pay for an AI assistant and a Google Workspace plan with eSignature, or for an existing DocuSign account. If you must buy a separate e-signature tool, subtract its monthly cost. Setup and per-proposal time are not monetised.
Example: A two-person consultancy on PandaDoc Business (billed annually) that sends 6–8 proposals a month, uses Google Workspace Business Standard and already pays for Claude. $98/mo → $0/mo. Assumptions: PandaDoc Business is $49 per seat per month billed annually ($65 billed monthly) per PandaDoc's plan comparison page, checked 2026-10-13: 2 seats × $49 = $98. Google Workspace Business Standard lists eSignature in Docs and the admin enables it; Workspace is already paid for and not counted. Claude is already paid for other work and not counted. The consultancy doesn't rely on PandaDoc's CRM sync, analytics or in-document payments.
## Sources
- PandaDoc Help: Compare subscription plan features: https://support.pandadoc.com/en/articles/9715033-compare-subscription-plan-features (accessed 2026-10-13)
- Google Docs Help: Request eSignatures: https://support.google.com/docs/answer/12315692 (accessed 2026-10-13)
- Google Workspace pricing: https://workspace.google.com/pricing (accessed 2026-10-13)
- Google Docs Help: Use Markdown in Docs: https://support.google.com/docs/answer/12014036 (accessed 2026-10-13)
# Run your company wiki in Google Workspace or Microsoft 365 instead of paying for Notion or Confluence
> For teams of up to about 15 who already pay for Google Workspace or Microsoft 365: move the wiki into a shared drive of Google Docs with a Google Sites front page (or SharePoint/OneNote on Microsoft 365). Includes an information architecture template, a Notion export-and-import checklist, AI prompts for cleanup, and the honest list of what you lose — mainly databases, Notion AI and slick page linking.
- Outcome: I want one place where my team finds policies, how-tos and onboarding, without a separate Notion or Confluence subscription.
- Replaces: Notion (full), Confluence (full)
- Uses: Google Workspace — Shared drive for wiki docs, Google Docs for pages, Google Sites (listed on all Business plans) as the internal front page, Drive search.; Microsoft 365 (optional) — Alternative stack: a SharePoint team or communication site with pages and a document library, plus a team OneNote notebook for informal notes.; Claude (optional) — Clean up exported pages, rename files, draft the IA and rewrite stale docs during migration.; ChatGPT (optional) — Alternative assistant for the same cleanup prompts.
- Extra monthly cost: $0 — Uses Google Workspace or Microsoft 365 you already pay for. Google says shared drives became available on Business Starter from September 2024 (with fewer admin controls than higher plans), and Google Sites is listed on all Business plans. On Microsoft 365, SharePoint is included in plans that license it (check your admin centre).
- Difficulty: moderate; skill: basic; setup: 1–3 days for a typical small-team wiki (export, restructure, import, relink, front page)
- Evidence: editorial; illustrative example: false; last reviewed 2026-10-13
- Canonical: https://onelesstool.com/workflows/company-wiki-with-existing-suite
## Good fit for
- Teams of up to ~15 using Notion or Confluence mainly as a wiki: policies, how-tos, onboarding, meeting notes
- Companies already on Google Workspace (Business Starter and up) or a Microsoft 365 plan with SharePoint
- Teams that already write most documents in Google Docs or Word and keep copying them into the wiki
## Not a fit for
- Teams that rely on Notion databases as an app — relations, rollups, formulas, boards and views updated daily (CRM, project tracker, content calendar)
- Engineering teams that depend on Confluence's Jira integration and page trees tied to tickets
- Organisations that heavily use Notion AI or Notion Agent over their workspace
- Large orgs needing granular page-level permissions, page analytics and verified-page workflows
## Before
Pay per member for Notion (or Confluence). Pages, nested sub-pages and databases live there; people search Notion, @-link pages, and use Notion AI to summarise. Many documents also exist in Google Docs or Word, so content is split across two places.
## After
All wiki content lives as Google Docs in one shared drive with a simple folder tree and owners. An internal Google Site acts as the front page with search, a 'Start here' link and the top docs. People find things with Drive or Sites search and link docs with @-mentions. The paid wiki subscription is cancelled.
## Steps
### 1. Decide what moves and what doesn't
List every Notion teamspace/top-level page (or Confluence space) and every **database**. Sort databases into two groups:
- **Document lists** (meeting notes, policies, how-tos): these become folders of Docs.
- **Apps** (relations, rollups, formulas, kanban boards updated daily): these don't fit a wiki. Move them to Google Sheets, a tool you already have, or keep a smaller Notion plan for that team. If most of your Notion is apps, stop here; this workflow isn't for you.
Also note integrations and embeds pointing at Notion.
### 2. Design the structure before importing
Use the **information architecture template** (artifact below): one shared drive called `Wiki`, numbered top folders, max two levels deep, an owner and review date on every doc.
Run the **IA draft prompt** with your Notion sidebar (copy the page titles) to get a proposed mapping from old pages to new folders. Edit it with one or two colleagues; agreement here saves weeks of "where is it?" later.
On Google Workspace **Business Starter**, shared drives work but with fewer admin and security controls than higher plans; check your admin console settings.
### 3. Export from Notion (or Confluence)
In Notion, a workspace owner exports the **entire workspace** as **Markdown & CSV** (desktop or web only), including subpages. Export an **HTML** copy too as an archive.
Things Notion's help centre warns about:
- Download links **expire after 7 days**; big exports can take **up to 30 hours**.
- Other members' **private pages are not included**; ask people to export their own.
- Full-page databases export as a **CSV plus one Markdown file per row/page**; only the current or default view is exported.
- Callout blocks come out as HTML.
For Confluence, use its space export options and expect similar cleanup.
### 4. Clean up and import into Google Docs
Work through the **migration checklist** (artifact below). In short:
1. Rename files (Notion adds long IDs) and arrange them in the new folder tree locally.
2. Use the **Page cleanup prompt** on messy pages: fix headings, convert HTML leftovers, flag outdated content.
3. Import: in Google Docs, **File > Open > Upload** a `.md` file to convert it into a Google Doc, or upload to Drive and **Open with > Google Docs**. Google started rolling out native `.md` viewing and editing in Docs in October 2026; convert the docs people edit often so comments and smart chips work as usual.
4. Open each database CSV in Google Sheets.
### 5. Relink and build the front page
Exported internal links point at local `.md` files, not at the new Docs. Fix the **top 20 most-used docs first**, replacing links with links or @-mention chips to the new Google Docs. Fix the rest as people report them.
Create an internal **Google Site** (restricted to your organisation) as the front page: search box, a "Start here" button, the top 8 docs, team sections and an "ask here" line. On Microsoft 365, use a SharePoint communication site home page with quick links and a document library web part instead.
### 6. Microsoft 365 variant
If you're on Microsoft 365 instead of Google:
- Create a **SharePoint team site** called Wiki. Use **pages** for front-door content (Start here, policies people read) and a **document library** with the same folder tree for Word docs.
- Use the site's **team OneNote notebook** for informal notes and meeting notes.
- Import Notion Markdown by converting to Word (ask your AI assistant to convert each `.md` to clean `.docx`-ready text, or open the HTML export in Word) and uploading to the library.
- Microsoft Copilot Chat (included with eligible business plans at no extra cost) can help draft and summarise; grounding answers on your organisation's files depends on licensing.
### 7. Cut over, verify, then cancel
Set a cut-over date. Put a "Moved to …" banner on the Notion home page and make it read-only. Ask three colleagues who weren't involved to find 10 common answers using only the new wiki (see verification checklist).
Cancel or downgrade Notion/Confluence at the **renewal date**, keeping the export zip in a restricted archive shared drive.
## Prompts
### IA draft prompt
Map your existing Notion/Confluence pages onto the new folder structure.
```text
We're a {{team_size}}-person {{company_type}} moving our wiki from {{old_tool}} to {{new_suite}}.
Here is our current page tree (indentation = nesting):
{{page_tree}}
Using this target structure: {{target_folder_tree}}
Produce a table: old page | new folder | new doc title (phrased as people would search) | action (migrate / merge with X / archive / delete) | suggested owner role.
Flag pages that look like databases used as apps, duplicates, and anything that looks out of date.
```
### Page cleanup prompt
Tidy an exported Markdown page before importing it into Google Docs.
```text
Clean up this page exported from {{old_tool}} so it imports well into Google Docs. Rules:
- Keep all facts. Don't add new information.
- One H1 title: "{{new_doc_title}}". Logical H2/H3 headings.
- Convert any HTML (e.g. callouts) into Markdown: callouts become a bold "Note:" paragraph.
- Replace internal links to .md files with [[LINK: page name]] placeholders so I can relink them.
- Add this header table at the top: Owner {{owner}} | Last reviewed {{review_date}} | Review every {{review_interval}} | Status Current.
- At the end, list anything that looks outdated (old dates, people who may have left, retired tools).
Page:
{{page_markdown}}
```
### Stale content review prompt
Run the quarterly review faster.
```text
Here is a list of wiki docs with owner and last-modified date: {{doc_list}}
Today is {{today}}. Flag every doc not modified in {{stale_months}} months, group by owner, and draft a short message to each owner asking them to confirm, update or archive their docs by {{deadline}}.
```
### Find-it test prompt
Generate realistic questions to test whether people can find things in the new wiki.
```text
We're a {{team_size}}-person {{company_type}}. Based on this wiki folder tree: {{folder_tree}}
Write 15 realistic questions employees ask in their first 3 months (e.g. "How do I claim expenses?"). For each, name the doc that should answer it. I'll ask colleagues to find each answer and time them.
```
## Templates and scripts
### Wiki information architecture template (template)
```markdown
# Company wiki – information architecture template ({{company_name}}, ≤15 people)
## Where things live
- **Front page:** Google Site "{{company_name}} Wiki" (internal-only), or a SharePoint communication site / team site home page on Microsoft 365.
- **Content:** one shared drive (Google) or one document library (SharePoint) called `Wiki`. Docs, not pages, hold the content.
- **Rule:** every wiki doc lives in `Wiki`, never in someone's My Drive / OneDrive. Personal drafts move in when they're ready.
## Folder tree (max 2 levels deep)
Wiki/
├── 00 Start here/ → Welcome, How this wiki works, Who to ask for what, Glossary
├── 01 Company/ → Mission & values, Org chart, Holidays & time off, Benefits, Expenses
├── 02 Policies/ → Security & passwords, Data handling, Remote work, Code of conduct
├── 03 How we work/ → Meetings & rituals, Tools we use (and who owns each), Writing guide
├── 04 Teams/
│ ├── Sales/ → Playbook, Pricing rules, Proposal templates
│ ├── Delivery/ → Project kickoff checklist, QA checklist, Client handover
│ └── Ops & Finance/ → Month-end close, Invoicing, Vendor list
├── 05 Onboarding/ → First day, First week, Role checklists
├── 06 Templates/ → Meeting notes, Project brief, Decision record, Post-mortem
├── 07 Decisions/ → YYYY-MM-DD decision records (one doc each)
└── 99 Archive/ → Outdated docs (moved, never deleted, prefix "ARCHIVED – ")
## Naming conventions
- Doc titles are questions or nouns people search for: "How do I submit expenses?", "Expense policy".
- No dates in titles except decision records and meeting notes: `2026-10-13 – Decision – Switch wiki to Google Drive`.
- No "final", "v2", "new" in titles. Version history handles that.
## Every doc starts with this header block
| Owner | Last reviewed | Review every | Status |
|---|---|---|---|
| @name | YYYY-MM-DD | 6 months | Current / Draft / Archived |
## Front page (Google Sites / SharePoint) sections
1. Search box (Sites search, or SharePoint search)
2. "Start here" button → 00 Start here
3. Top 8 most-used docs (embed or link) — check the list quarterly
4. Team sections → link to each 04 Teams subfolder
5. "Recently changed" — a manually updated list or an embedded Drive folder view
6. "Can't find it? Ask in {{chat_channel}}" with the wiki owner's name
## Permissions
- Shared drive / library members: everyone in the company as Contributor (Google) or Member (SharePoint); 2 people as Managers/Owners.
- Sensitive areas (HR cases, salaries) do NOT go in the wiki. Use a separate restricted shared drive or library.
- Guests/contractors: share individual folders, not the whole wiki.
## Ownership & upkeep
- Wiki owner: {{wiki_owner}} — runs a 30-minute review each quarter.
- Each folder has an owner listed in "00 Start here/Who to ask for what".
- Docs not reviewed in 12 months get flagged; owner updates or archives.
```
### Notion → Google Workspace migration checklist (checklist)
```markdown
# Notion → Google Workspace migration checklist
## A. Before exporting (week 1)
- [ ] List every Notion top-level page and teamspace; mark each: migrate / archive only / delete.
- [ ] List every Notion **database**. For each: is it a document list (fine as a folder) or an app (relations, rollups, formulas, boards people update daily)? Apps need a separate plan (Google Sheets, AppSheet, or keep Notion for that team).
- [ ] List integrations, automations, embeds and forms that point at Notion.
- [ ] Note who has private pages they want to keep (exports skip other people's private pages).
- [ ] Freeze big restructures in Notion until the move is done.
## B. Export
- [ ] Workspace owner: Settings → export **entire workspace** (desktop or web only) as **Markdown & CSV**, with subpages. Also export as **HTML** as an archival copy that keeps the look.
- [ ] Download promptly: Notion's export links expire after 7 days, and a large export can take up to 30 hours to arrive.
- [ ] Each member exports their own private pages they want kept.
- [ ] Unzip into a local folder; keep the original zip in a restricted "Notion archive" shared drive.
## C. Prepare files
- [ ] Rename files to drop the long ID suffix Notion adds (ask an AI assistant or use a bulk-rename tool).
- [ ] Map Notion's folder tree to the new IA (see IA template). Move files locally first.
- [ ] Databases: open each CSV in Google Sheets; delete columns nobody uses; keep the CSV as the record.
- [ ] Images and attachments: check they're in the export folder next to each page.
## D. Import into Google Docs
- [ ] Small batches: Google Docs → File → Open → Upload the `.md` file (it converts to a Google Doc). Or upload to Drive, right-click → Open with → Google Docs.
- [ ] Large batches: upload `.md` files to the shared drive and convert the most-used ones first; leave rarely used pages as Markdown files (Drive can preview and Docs can now open .md files without converting, rolling out from October 2026).
- [ ] Spot-check 10 converted docs: headings, tables, code blocks, images, callouts (Notion exports callouts as HTML).
- [ ] Re-insert images that didn't come across.
## E. Fix links
- [ ] Internal links in the export point at local files, not Google Docs. Search each doc for links ending in `.md` and replace them with links (or @-mention smart chips) to the new Google Docs. Start with "Start here" and the top 20 docs.
- [ ] Update links in chat tools, email signatures, bookmarks and other docs that pointed at Notion URLs.
## F. Build the front page
- [ ] Create the internal Google Site; add the sections from the IA template; restrict it to your organisation.
- [ ] Add the shared drive folders and top docs.
## G. Cut over
- [ ] Announce the date; for 2 weeks, add a banner at the top of the Notion home page: "Moved to . Read-only from ."
- [ ] Run the verification checklist with 3 colleagues who weren't involved.
- [ ] Downgrade or cancel Notion at the renewal date; keep the export archive.
```
## Limitations
- No Notion-style databases: relations, rollups, formulas and multiple views don't exist in Docs; Sheets covers only simple tables.
- No Notion AI or Notion Agent over the whole wiki. Gemini in Docs is listed on Workspace Business Standard and Plus, not Starter; Copilot's work-data grounding depends on Microsoft licensing.
- Page linking is clunkier: no backlinks or nested sub-pages inside a page; you rely on folders, links and @-mention chips.
- Exported internal links break and must be relinked by hand.
- Google Sites is a simple front page; it isn't a full wiki engine with page trees and inline editing of every doc.
- On Business Starter, shared drives lack some admin and security controls available on higher plans.
## Risks
- **migration_complexity** (medium): Large or deeply nested workspaces take longer than expected; broken links and missing images are common. Migrate the top-used content first.
- **data_portability** (medium): Exports skip other members' private pages and only export one database view. Have each person export what they need and keep the original zip archived.
- **functionality_loss** (high): Teams using Notion databases as apps lose them. Identify these before cancelling and give them a new home.
- **collaboration** (low): People may keep docs in personal drives. The 'everything lives in the Wiki shared drive' rule and a named owner prevent sprawl.
- **security** (low): Check sharing settings on the shared drive and Site so internal content isn't shared publicly or with the wrong guests.
## Verification checklist (run before cancelling)
- [ ] Every Notion database has been classified, and each one used as an app has a working new home (or a deliberate decision to keep a small Notion plan).
- [ ] The full workspace export (Markdown & CSV plus HTML archive) is downloaded and stored in a restricted archive location.
- [ ] The top 20 most-used docs are in the shared drive with working internal links and images.
- [ ] Three colleagues not involved in the migration found answers to 10 'find-it test' questions in under 2 minutes each using Drive or Sites search.
- [ ] The Google Site (or SharePoint home page) is restricted to your organisation, and guests can only see folders shared with them.
- [ ] Every top-level folder has a named owner and a review date.
- [ ] Notion has been read-only for at least two weeks with no requests to switch back before you cancel at renewal.
## Savings methodology
Savings = paid wiki seats × price per seat per month (annual ÷ 12 if billed annually) − incremental cost ($0, since Google Workspace or Microsoft 365 is already paid). If you keep a smaller Notion plan for a team using databases as apps, subtract those seats. Migration time (1–3 days) and quarterly upkeep are not monetised.
Example: A 10-person agency on Notion Plus (billed annually) used purely as a wiki, already paying for Google Workspace Business Standard. $100/mo → $0/mo. Assumptions: Notion Plus is $10 per member per month on yearly billing, per notion.com/pricing on 2026-10-13 (the page's default billing toggle is yearly; monthly billing costs more). 10 members × $10 = $100. Google Workspace is already paid for; shared drives and Google Sites are available on its Business plans. No Notion databases are used as apps, so no Notion seats are kept.
## Sources
- Notion pricing: https://www.notion.com/pricing (accessed 2026-10-13)
- Notion Help: Export your content: https://www.notion.com/help/export-your-content (accessed 2026-10-13)
- Google Workspace Updates: Shared drives for Business Starter: https://workspaceupdates.googleblog.com/2024/08/shared-drive-access-business-starter.html (accessed 2026-10-13)
- Google Workspace Updates: Markdown files natively in Drive and Docs: https://workspaceupdates.googleblog.com/2026/10/preview-edit-and-collaborate-on-Markdown-files-natively-across-Drive-and-Docs.html (accessed 2026-10-13)
- Google Docs Help: Use Markdown in Docs: https://support.google.com/docs/answer/12014036 (accessed 2026-10-13)
- Google Workspace pricing: https://workspace.google.com/pricing (accessed 2026-10-13)
- Microsoft Learn: SharePoint service description: https://learn.microsoft.com/en-us/office365/servicedescriptions/sharepoint-online-service-description/sharepoint-online-service-description (accessed 2026-10-13)
- Microsoft Learn: Manage Microsoft Copilot Chat: https://learn.microsoft.com/en-us/copilot/manage (accessed 2026-10-13)
# Consolidate overlapping AI assistant subscriptions (ChatGPT, Claude, Gemini, Perplexity, Grok, Copilot)
> If you pay for two to four AI assistants, run a one-week, side-by-side test on your real tasks with a provided prompt set and scoring sheet, check which assistant your Google Workspace or Microsoft 365 plan already includes, and cancel the rest at their renewal dates. Some heavy users will rightly keep two; the test tells you which.
- Outcome: I pay for several AI chat subscriptions and want to keep only the one(s) I actually need.
- Replaces: ChatGPT (full), Claude (full), Google Gemini (full), Perplexity (full), Grok (full), Microsoft 365 Copilot (full)
- Uses: Google Workspace (optional) — Google Sheets for the scoring sheet. If your organisation uses Workspace, the Gemini app and Gemini in Gmail are listed on Business plans (Gemini in Docs on Standard and Plus).; Microsoft 365 (optional) — Excel for the scoring sheet. Eligible Microsoft 365 business and enterprise plans include Microsoft Copilot Chat at no extra cost when you sign in with a work account.; Claude (optional) — One of the candidates you test and may keep.; ChatGPT (optional) — One of the candidates you test and may keep.
- Extra monthly cost: $0 — No new tools are bought. You keep one (sometimes two) of the subscriptions you already have, plus whatever assistant your existing Google Workspace or Microsoft 365 plan includes.
- Difficulty: easy; skill: none; setup: 1 hour to set up, plus about 20–30 minutes a day of testing for one week
- Evidence: editorial; illustrative example: false; last reviewed 2026-10-13
- Canonical: https://onelesstool.com/workflows/consolidate-ai-assistants
## Good fit for
- Individuals paying for two or more AI chat subscriptions out of habit or FOMO
- Small teams where people expense different assistants with no shared standard
- Companies on Google Workspace or Microsoft 365 that also pay for separate AI chat seats
## Not a fit for
- Developers who rely on a specific coding agent tied to one subscription and use another assistant for a distinct job — keeping two can be rational
- Teams with a compliance requirement to use one approved vendor (the decision is made by policy, not a taste test)
- People who use one assistant lightly; just keep the free tier of the others
## Before
Pay for several assistants (for example ChatGPT Plus, Claude Pro and Perplexity Pro), switch between them by habit, and forget that your work suite already includes Gemini or Copilot Chat.
## After
One primary paid assistant chosen by evidence from your own tasks, the assistant bundled with your work suite used for email and documents, free tiers for occasional second opinions, and cancelled subscriptions timed to their renewal dates.
## Steps
### 1. List every AI subscription, its price and renewal date
Check card statements, App Store / Google Play subscriptions and company expense reports. For each assistant record: **plan, monthly cost, monthly or annual billing, renewal date, who uses it**.
Annual plans usually can't be refunded mid-term, so the renewal date decides *when* you save, not *whether*.
### 2. Check what your work suite already includes
- **Google Workspace**: Google's plan page lists Gemini in Gmail and the Gemini app on Business Starter, Standard and Plus (basic access on Starter, expanded on Standard and Plus), with **Gemini in Docs** on Standard and Plus. Ask your admin which apps are switched on.
- **Microsoft 365**: Microsoft Copilot Chat (recently renamed from Microsoft 365 Copilot Chat) is available **at no extra cost** to users signing in with a **work or school (Entra) account** on qualifying plans, including Microsoft 365 Business Basic, Standard and Premium and E3/E5. The separately licensed Copilot add-on adds Copilot inside the Office apps and work-data grounding; Copilot Chat is the baseline.
Include the bundled assistant in your test as a candidate. It may cover email and document work well enough on its own.
### 3. Log your real tasks for 3–5 days
Every time you use an AI assistant, note one line: **task, which assistant, why that one, was the result usable**. Typical categories: writing/editing, summarising documents, web research with sources, data analysis, coding, images, voice.
This list prevents the test from being decided by benchmark hype instead of your work. Weight tasks by how often you do them and how much they matter.
### 4. Run the one-week side-by-side test
Use the **evaluation set** (artifact below): pick at least 6 tasks and replace the placeholders with your real material. Run each task in **every** assistant in a **fresh chat**, with the same files.
Paste outputs into a doc labelled A/B/C rather than by product so you score them blind (ask someone else to label them if you can). Fill in the **scoring sheet** CSV. Use the **Blind judge prompt** for a second opinion, but your own scores decide.
Also note features you can't score with a single prompt but genuinely rely on: projects/memory, file limits, voice mode, deep research, image generation, coding agents, integrations.
### 5. Check data and privacy settings for the finalists
For the assistant(s) you might keep, check data controls: whether chats are used for model training on your plan and how to opt out, retention, and whether business plans give contractual protections your work needs. If you handle client or personal data, a business/team plan or the bundled work assistant may be the only acceptable option.
### 6. Decide: one primary, maybe one specialist
Rules of thumb:
- Keep the assistant with the **highest weighted score on your top-3 tasks**.
- Keep a **second** only if it wins clearly on a task you do **weekly** that the first can't do acceptably (e.g. a coding agent, or cited research), and the time saved is worth its price.
- Use the **bundled** Gemini or Copilot Chat for email and document chores, and **free tiers** for occasional second opinions.
### 7. Export, then cancel at renewal
Before cancelling each subscription:
1. Export your data (most assistants offer a data export in settings) and copy any custom instructions, project instructions, custom GPTs/Gems or saved prompts into a doc.
2. Move important ongoing projects to the assistant you keep and test them there.
3. Cancel auto-renew now so the plan ends at the paid-through date. Put a reminder a week before the date to confirm.
## Prompts
### Task inventory prompt
Turn your rough task log into a weighted test plan.
```text
Here is my log of AI tasks from the last {{days_logged}} days:
{{task_log}}
Group these into 5–8 task types. For each give: how often I do it per week, how important it is (1–3), and one representative test task I could run in several assistants with the same inputs. Output a table I can paste into a spreadsheet.
```
### Blind judge prompt
Get a structured second opinion on anonymised outputs (run it in an assistant you're not testing, or in each and compare).
```text
You are judging answers from anonymous assistants A, B and C to the same task. Don't guess which product wrote which.
Task given to each: {{task_prompt}}
What a great answer must include: {{success_criteria}}
A: {{output_a}}
B: {{output_b}}
C: {{output_c}}
For each, score 1–5 on accuracy, completeness, and usefulness for {{audience}}, and list factual errors or unsupported claims. Then rank them and give the deciding reason in one sentence.
```
### Citation check prompt
Audit the sources a research answer gave you.
```text
Below is an answer with citations, and the text I copied from each cited page.
Answer: {{research_answer}}
Source texts: {{source_texts}}
For each claim, say whether the cited source supports it (yes / partly / no / source missing). Count the unsupported claims.
```
### Decision memo prompt
Summarise the test into a decision you (or your manager) can sign off.
```text
Here is my scoring sheet: {{scoring_sheet_csv}}
Subscriptions and costs: {{subscriptions_with_prices_and_renewal_dates}}
Bundled assistants available through work: {{bundled_assistants}}
Write a short decision memo: which assistant to keep as primary and why; whether a second is justified (only if it wins clearly on a weekly task); which to cancel and on what date; the monthly saving; and the risks (lost features, data to export).
```
## Templates and scripts
### One-week evaluation prompt set (template)
```markdown
# AI assistant evaluation set – one week
Run each task in EVERY assistant you're testing, in a fresh chat, with the same inputs.
Replace {{placeholders}} with your real material. Use at least 6 of the 10; add your own from your task log.
Paste outputs into a doc labelled A/B/C (not by product) so you score them blind.
## T1 – Summarise a real document (reading & accuracy)
Attach: {{a_real_10_to_30_page_pdf}}
"Summarise this for {{audience}} in 8 bullets. Then list 3 things that are easy to miss, each with the page number."
Check: are page numbers and facts correct? Did it miss anything you know matters?
## T2 – Write in your voice (writing)
"Here are 3 emails I wrote: {{three_sample_emails}}. Write a reply to this message in my style: {{incoming_message}}."
Check: would you send it with fewer than 3 edits?
## T3 – Current-events research with sources (web research)
"What changed in {{topic_in_your_field}} in the last 3 months? Give 5 points, each with a source link and date."
Check: open every link. Count dead, wrong or unsupported citations.
## T4 – Spreadsheet analysis (data)
Attach: {{a_csv_or_xlsx_you_know_well}}
"Which 3 {{rows_entity}} changed most between {{period_a}} and {{period_b}}? Show the calculation and a chart."
Check: verify one number by hand.
## T5 – Your hardest recurring task (domain)
"{{your_hardest_recurring_task_prompt}}"
Check: score against what an expert colleague would produce.
## T6 – Code or formula (technical)
"{{a_formula_script_or_code_task_you_actually_need}}"
Check: does it run first time? How many follow-ups to make it work?
## T7 – Long conversation memory (context)
Paste a 3,000+ word brief, then ask 5 follow-up questions over 15 minutes, including one that depends on a detail from the start.
Check: did it keep the early detail right?
## T8 – Image or visual (only if you need it)
"{{an_image_or_diagram_you_actually_need}}"
Check: usable without another tool?
## T9 – Work-data question (only for bundled work assistants)
In Gemini (Workspace) or Copilot Chat (Microsoft 365): "{{question_about_your_own_files_or_email}}"
Check: does it find the right file/email? (Depends on your plan and admin settings.)
## T10 – Refusal and honesty
"{{a_question_where_the_honest_answer_is_i_dont_know}}"
Check: does it admit uncertainty instead of inventing an answer?
```
### Scoring sheet (CSV, import into Google Sheets or Excel) (template)
```csv
task_id,task,weight(1-3),assistant_label,quality(1-5),accuracy(1-5),edits_needed(0=none;5=rewrite),minutes_to_usable,would_pay_for_this_alone(y/n),notes
T1,Summarise document,3,A,,,,,,
T1,Summarise document,3,B,,,,,,
T1,Summarise document,3,C,,,,,,
T2,Write in my voice,2,A,,,,,,
T2,Write in my voice,2,B,,,,,,
T2,Write in my voice,2,C,,,,,,
T3,Research with sources,2,A,,,,,,
T3,Research with sources,2,B,,,,,,
T3,Research with sources,2,C,,,,,,
T4,Spreadsheet analysis,1,A,,,,,,
T4,Spreadsheet analysis,1,B,,,,,,
T4,Spreadsheet analysis,1,C,,,,,,
T5,Hardest recurring task,3,A,,,,,,
T5,Hardest recurring task,3,B,,,,,,
T5,Hardest recurring task,3,C,,,,,,
,,,,,,,,,
# Score per assistant = SUM(weight * (quality + accuracy + (5 - edits_needed))) / SUM(weight)
# In Google Sheets / Excel, put this in a summary tab:
# =SUMPRODUCT((D2:D16="A")*C2:C16*(E2:E16+F2:F16+(5-G2:G16)))/SUMPRODUCT((D2:D16="A")*C2:C16)
# Then list, per assistant: monthly cost, billing type (monthly/annual), renewal date, unique features you used this week.
```
## Limitations
- A one-week test reflects today's models; vendors update models and plans often, so re-run it every 6–12 months.
- Blind scoring is imperfect: answer styles can give away the product.
- Bundled work assistants (Gemini in Workspace, Copilot Chat) vary by plan and admin settings, and may not include features of the consumer paid plans.
- Some unique features (a specific coding agent, deep-research mode, image generation, voice) can't be replaced by another assistant one-for-one.
- Chat history, custom GPTs/Gems and project setups don't transfer between vendors automatically.
## Risks
- **functionality_loss** (medium): Cancelling can remove a feature you only notice later (for example a coding agent or deep research). Keep the free tier of cancelled assistants for occasional use.
- **data_portability** (medium): Chat histories, custom instructions and project files stay with the vendor. Export them before cancelling.
- **sensitive_data** (medium): Testing with real documents sends them to every assistant. Use non-confidential material or business plans with suitable data terms.
- **compliance** (low): Employers may have an approved-tools policy; consolidating onto a bundled work assistant can simplify compliance.
## Verification checklist (run before cancelling)
- [ ] Your list shows every AI subscription with price, billing type and renewal date, and you've checked your Workspace or Microsoft 365 plan for an included assistant.
- [ ] You ran at least 6 tasks from your own log in every candidate, in fresh chats, with the same inputs.
- [ ] The scoring sheet has a weighted score per assistant, and the winner also wins (or ties) on your single most important task.
- [ ] For one full working day you used only the assistant you plan to keep (plus the bundled one) and didn't hit a blocker.
- [ ] Data exports and copies of custom instructions/projects exist for each assistant you will cancel.
- [ ] Auto-renew is switched off for the cancelled plans, with a calendar reminder before each end date.
## Savings methodology
Savings = sum of monthly costs of the subscriptions you cancel (annual prices ÷ 12). Incremental cost is $0 because you keep a subscription you already pay for and any assistant bundled in your existing suite. Savings start at each plan's renewal date; annual plans are not assumed to refund. Testing time is not monetised.
Example: A consultant on Google Workspace pays for Claude Pro monthly and Perplexity Pro annually. After the test, Claude wins on writing and document work, Perplexity's cited research is only slightly better on a weekly task, and Gemini in Gmail handles email chores. $37/mo → $20/mo. Assumptions: Claude Pro: $20/month billed monthly, per claude.com/pricing on 2026-10-13. Perplexity Pro: $17/month billed annually, per perplexity.ai/hub/pricing on 2026-10-13. The saving starts at the annual renewal date. Google Workspace is already paid for; Gemini in Gmail and the Gemini app are listed on its Business plans, so no new cost. If the consultant also paid for ChatGPT Plus, cancelling it would add to the saving; its price wasn't verified today because OpenAI's pages blocked our fetcher.
## Sources
- Claude pricing: https://claude.com/pricing (accessed 2026-10-13)
- Perplexity pricing: https://www.perplexity.ai/hub/pricing (accessed 2026-10-13)
- Google Workspace pricing: https://workspace.google.com/pricing (accessed 2026-10-13)
- Microsoft Learn: Manage Microsoft Copilot Chat: https://learn.microsoft.com/en-us/copilot/manage (accessed 2026-10-13)
- ChatGPT pricing: https://openai.com/chatgpt/pricing/ (accessed 2026-10-13)
# Replace Tableau Creator seats with Data Studio (Looker Studio) dashboards on Google Sheets
> For SMB reporting on spreadsheet-sized data: prep your Sheets properly, build the dashboard in Google's free Data Studio (renamed from Looker Studio in 2026), use Claude or ChatGPT for analysis and formulas, and schedule PDF email delivery. Microsoft 365 shops can use free Power BI Desktop, but sharing needs Power BI Pro.
- Outcome: A refreshable, shareable dashboard of the business's key numbers, emailed on a schedule, without paying for Tableau Creator licences.
- Replaces: Tableau (partial)
- Uses: Looker Studio — Free dashboarding tool (now called Data Studio) with a native Google Sheets connector, calculated fields, sharing and scheduled email delivery.; Google Workspace — Google Sheets as the data source and Drive for sharing. A free Google account also works with lower email-delivery quotas.; Claude (optional) — Data cleaning formulas, calculated-field syntax, SQL if you move to BigQuery, and narrative analysis of exported data.; ChatGPT (optional) — Alternative for formula help and analysing CSV exports.; Microsoft 365 (optional) — Alternative path: Excel PivotTables/charts and the free Power BI Desktop app. Sharing Power BI reports requires Power BI Pro (included in Microsoft 365 E5) or Premium Per User.
- Extra monthly cost: $0 — Data Studio's standard tier and Google Sheets cost nothing extra. Data Studio Pro (team workspaces, organisation-owned content, more schedules) is a paid upgrade you only need for governance. On the Microsoft path, Power BI Desktop is free but sharing needs Power BI Pro ($14/user/month paid yearly per Microsoft's pricing page) unless you're on E5.
- Difficulty: moderate; skill: basic; setup: 1–2 days for the first dashboard (data prep is most of it); a few hours for each after
- Evidence: editorial; illustrative example: true; last reviewed 2026-10-13
- Canonical: https://onelesstool.com/workflows/dashboards-from-spreadsheets
## Good fit for
- Small and mid-sized businesses whose data already lives in Google Sheets, CSV exports or Google products
- A handful of standard dashboards (sales, marketing, operations) rather than heavy ad-hoc exploration
- Teams paying for one or two Tableau Creator seats mainly to publish a few recurring reports
- Anyone comfortable with spreadsheets who can learn calculated fields
## Not a fit for
- Row-level security (each viewer sees only their own rows), certified data sources and formal governance — stay on a BI platform or use Data Studio Pro plus BigQuery with care
- Large data (millions of rows) living in spreadsheets — Sheets and the Sheets connector aren't built for it; use a warehouse
- Analysts who rely on Tableau's advanced visual analytics (LOD expressions, complex table calcs, custom geocoding, extensive drag-and-drop exploration)
- Regulated reporting that needs audit trails on metric definitions and data lineage
## Before
One or two people hold Tableau Creator licences to connect to spreadsheets/CSVs, build workbooks and publish dashboards; others view them with Viewer/Explorer licences. Most of the dashboards are a few scorecards, trend lines and a table refreshed from spreadsheets.
## After
Clean, append-only Google Sheets tabs feed a Data Studio report built from a written dashboard spec. Calculated fields define metrics once (win rate, net revenue). Viewers open a link; owners get a scheduled PDF every Monday. When someone asks 'why did revenue drop?', you export the table and ask Claude or ChatGPT for an analysis — and verify its numbers against the sheet.
## Steps
### 1. List what your Tableau dashboards actually do
For each published workbook, note: viewers, how often it's opened, data sources, row counts, and any feature you'd miss — **row-level security, LOD expressions, extracts from databases, subscriptions**. If a dashboard relies on row-level security or millions of rows, keep it on Tableau (or plan a warehouse) and migrate the rest. Many SMBs find most dashboards are scorecards, trends and tables — those move easily.
### 2. Prepare the data in Google Sheets
Work through the **Data-prep checklist** artifact. The two rules that prevent most problems:
1. **One header row, one record per row, one type per column.**
2. **Long, not wide** — a `Month` column, not twelve month columns.
Use an AI assistant on a **50-row sample** (not your whole sensitive dataset) with the **Find data-quality problems** prompt to get exact cleaning formulas, e.g. `=DATEVALUE()`, `=TRIM()`, `=IFERROR(VALUE(...))`. Paste the fixed values back.
Note: the Sheets connector **includes hidden and filtered cells by default** — delete junk rows rather than hiding them.
### 3. Write the dashboard spec before opening the tool
Fill in the **Dashboard spec** template: audience, the decision it supports, at most six metrics with plain-English definitions, default date range, filters, layout and acceptance numbers.
This replaces the most valuable thing a Tableau specialist brought — agreed metric definitions. Get the person who reads the dashboard to sign off on the metric definitions now, not after building.
### 4. Build in Data Studio (formerly Looker Studio)
1. Open Data Studio (formerly Looker Studio) → **Blank report** → **Google Sheets** connector → pick spreadsheet and tab, keep **Use first row as headers** on.
2. **Resource → Manage data sources → Edit** and add the calculated fields from the **Calculated-field cookbook** (e.g. `Is won = CASE WHEN Stage = "Won" THEN 1 ELSE 0 END`, `Win rate = SUM(Is won) / SUM(Is closed)`).
3. Build row by row from the spec: scorecards with **comparison date range**, a time series, a bar chart breakdown, a table with conditional formatting.
4. Add **Date range** and **Drop-down list** controls for the filters in the spec.
5. **Theme and layout**: set your brand colours once in the theme so every page matches.
6. Data credentials: *Owner's credentials* lets viewers see data without access to the sheet — decide deliberately.
If you add or rename columns in the sheet later, **refresh fields** in the data source.
### 5. Share and schedule email delivery
- **Share** with named people or a Google Group (avoid 'anyone with the link' for business data).
- **Schedule delivery** (Share menu → *Schedule delivery*): the report is emailed as a **PDF** with a link; choose pages and recipients (up to 50 addresses), and a repeat frequency. Without Pro, the most frequent option is **daily** and each report can have **one schedule**.
- Quotas: individual accounts can send 200 scheduled emails/day and 800/month; Google Workspace 500/day and 3,000/month, per Google's docs. Scheduled PDFs use US number/date formats.
**Microsoft 365 alternative:** Excel PivotTables and charts cover simple needs. **Power BI Desktop** is a free download, but sharing reports requires Power BI **Pro** ($14/user/month paid yearly) or Premium Per User; Pro is included in Microsoft 365 E5 / Office 365 E5.
### 6. Use AI for analysis — and check its arithmetic
Export a chart's table (**⋮ → Export → CSV/Google Sheets**) and use the **Explain a change in a metric** prompt. AI assistants are good at spotting patterns and drafting the commentary for a monthly report, but they can mis-add or misread columns. Require the assistant to show its working table, and check two numbers against the dashboard before sending anything.
Then run both systems for one reporting cycle and compare the acceptance numbers from the spec before cancelling Tableau seats.
## Prompts
### Find data-quality problems
Get exact cleaning formulas from a small sample before building the dashboard.
```text
Here are the header row and a 50-row sample from my Google Sheets tab "{{tab_name}}" (CSV):
{{sample_csv}}
One row should represent one {{row_grain}}. Identify:
1. Columns with mixed types or text where a number/date is expected.
2. Inconsistent category spellings (list the variants you see).
3. Rows that look like subtotals, blanks or duplicates.
4. Whether the table is 'wide' and should be reshaped long.
For each problem, give the exact Google Sheets formula for a helper column that fixes it (assume data starts in row 2). Don't guess about rows you haven't seen; tell me what to check in the full sheet.
```
### Write a calculated field
Get correct Data Studio / Looker Studio formula syntax for a metric definition.
```text
Write a calculated field for Google Data Studio (formerly Looker Studio). My data source fields (name: type) are:
{{field_list}}
Metric I want, in words: {{metric_definition}}
Give: (1) the formula, (2) whether it must be created in the data source or the chart, (3) the field type/format to set, (4) one way to sanity-check the result against the source sheet. Use only functions that exist in Data Studio; if what I want needs a blend or can't be done, say so. If my previous attempt failed, here is the formula and error: {{previous_error}}
```
### Explain a change in a metric
Draft monthly commentary from exported dashboard data, with visible working.
```text
I'm the {{role}} at a {{business_type}}. Below is a table exported from our dashboard (CSV). {{metric}} changed from {{previous_value}} in {{previous_period}} to {{current_value}} in {{current_period}}.
{{exported_csv}}
1. Show a working table that reproduces both values from the data. If you can't reproduce them, stop and tell me why.
2. Break the change down by {{breakdown_dimension}}: which segments drove it (absolute and % contribution).
3. Note anything that looks like a data problem rather than a business change.
4. Write a 4-sentence summary for the owners in plain English, no jargon, no speculation beyond the data.
```
## Templates and scripts
### Data-prep checklist for Google Sheets sources (checklist)
```
DATA-PREP CHECKLIST — do this in Google Sheets before connecting Looker Studio / Data Studio
Shape
[ ] One table per tab, starting at A1, ONE header row (Data Studio uses the first row as field names)
[ ] One row = one event/record (one order, one deal, one ticket) — no subtotal rows, no blank spacer rows, no merged cells
[ ] Long, not wide: a "Month" column + a "Value" column, NOT one column per month
[ ] Every column has a single data type all the way down (no "N/A" text in a number column — leave blank)
[ ] Stable, unique ID column (Order ID, Deal ID) for COUNT_DISTINCT and joins (blends)
Types and formats
[ ] Dates are real dates (right-aligned in Sheets), one format, no text like "Q3"
[ ] Currency columns are plain numbers; currency code in its own column if you have several
[ ] Categories spelled consistently (use data-validation dropdowns at the source; =UNIQUE(C2:C) to spot variants)
[ ] Percentages stored as numbers (0.25), not text ("25%")
Hygiene
[ ] Raw data tabs are append-only; calculations live in Data Studio calculated fields or a separate "model" tab
[ ] Hidden/filtered rows: Data Studio INCLUDES hidden and filtered cells by default — delete junk rows instead of hiding them
[ ] Freeze the header row and protect it (Data → Protect sheets and ranges) so nobody renames a column
(renaming breaks fields; after any column change, Resource → Manage data sources → Edit → Refresh fields)
[ ] Store the sheet in a normal Drive folder (the connector docs say shared/Team Drive files aren't supported)
[ ] Volume check: if a tab is approaching hundreds of thousands of rows or reports feel slow, move the data to BigQuery
AI help (paste a 50-row sample, never the full sensitive dataset)
[ ] Ask the assistant to list type problems, inconsistent categories and outliers in the sample
[ ] Ask for the exact Sheets formulas to fix them in a helper column, then paste values
```
### Dashboard spec template (template)
```
DASHBOARD SPEC — fill this in before building anything (one page per dashboard)
1. Purpose
Audience: ______ (e.g. owners + 2 account managers)
Decision it supports: ______ (e.g. "which clients need attention this week")
Review cadence: ______ (e.g. Monday 9:00, emailed PDF)
2. Data sources
| Source (sheet/tab) | Grain (one row = …) | Refresh (manual/form/import) | Owner | Rows today |
|--------------------|---------------------|------------------------------|-------|-----------|
3. Metrics (max 6 on page 1)
| Metric | Definition in words | Data Studio formula | Target / good-bad | Format |
| Revenue | Sum of invoice amount, excl. credit notes | SUM(Amount) with filter Type = Invoice | ≥ 40k/mo | Currency, 0 dp |
| Win rate | Won deals ÷ closed deals | SUM(CASE WHEN Stage = "Won" THEN 1 ELSE 0 END) / SUM(CASE WHEN Stage IN ("Won","Lost") THEN 1 ELSE 0 END) | ≥ 30% | Percent |
| Avg deal size | Won value ÷ won deals | SUM(Won value) / SUM(Is won) | | Currency |
4. Dimensions & filters
Date field: ______ Default range: ______ (e.g. last 12 months, compare to previous period)
Filter controls: ______ (e.g. Owner, Client segment)
Breakdowns: ______ (e.g. by month, by service line)
5. Layout (top → bottom)
Row 1: scorecards (metric + comparison)
Row 2: trend line (metric by month)
Row 3: breakdown bar chart + table with conditional formatting
Page 2+: detail tables for drill-down
6. Access & delivery
Viewers: ______ Editors: ______ Data credentials: owner's / viewer's
Scheduled email: recipients ______, frequency ______, pages ______
7. Acceptance test
Three numbers checked against the source sheet by hand: ______ / ______ / ______
```
### Calculated-field cookbook (template)
```
CALCULATED-FIELD COOKBOOK (Data Studio, formerly Looker Studio) — add via Resource → Manage data sources → Edit → Add a field
Field names below assume headers: Date, Amount, Stage, Client, Owner, Type, Deal ID.
Flag won deals (number, so it can be summed)
Is won = CASE WHEN Stage = "Won" THEN 1 ELSE 0 END
Closed deals
Is closed = CASE WHEN Stage IN ("Won", "Lost") THEN 1 ELSE 0 END
Win rate (aggregate field — set type to Percent)
Win rate = SUM(Is won) / SUM(Is closed)
Won value
Won value = CASE WHEN Stage = "Won" THEN Amount ELSE 0 END
Deal count (unique)
Deals = COUNT_DISTINCT(Deal ID)
Revenue excluding credit notes
Net revenue = CASE WHEN Type = "Credit note" THEN -Amount ELSE Amount END
Simple bucketing
Deal size band = CASE WHEN Amount >= 10000 THEN "10k+" WHEN Amount >= 2500 THEN "2.5k–10k" ELSE "<2.5k" END
Cleaning inconsistent text
Client clean = TRIM(UPPER(Client))
Age in days
Days open = DATE_DIFF(TODAY(), Date)
Tips
- Monthly trend: change the Date field's type to "Year Month" in the chart, rather than a formula.
- Put row-level CASE fields in the data source; ratios like Win rate must aggregate (SUM(...)/SUM(...)), never average a per-row ratio.
- If a formula errors, paste the error and your field list into the "Write a calculated field" prompt.
```
## Limitations
- No row-level security in the standard tier when using owner's credentials — every viewer of a report sees all the data it shows.
- Governance is light: content belongs to individual users unless you pay for Data Studio Pro (organisation-owned content, team workspaces).
- Google Sheets is not a database; large or fast-growing data makes reports slow and should move to BigQuery or another warehouse.
- Fewer advanced analytics and visual options than Tableau (no equivalent of LOD expressions; limited custom visuals).
- Scheduled delivery without Pro: at most daily, one schedule per report, PDF in US number/date formats, email quotas per account.
- AI-generated analysis can contain arithmetic or interpretation errors; it needs checking before it's shared.
## Risks
- **security** (medium): Reports using owner's credentials expose the underlying data to anyone the report is shared with, even if they can't open the sheet. Share with named people/groups only.
- **functionality_loss** (medium): Losing row-level security, certified data sources and advanced calculations can matter for multi-team or client-facing reporting.
- **reliability** (medium): Renamed or retyped columns in the source sheet break fields silently until someone refreshes the data source. Protect header rows.
- **collaboration** (low): If the report owner leaves, ownership must be transferred; Data Studio Pro's organisation ownership avoids this.
- **sensitive_data** (low): Pasting full customer or financial datasets into an AI assistant may conflict with your data policies; use samples or aggregated exports and a business plan where possible.
## Verification checklist (run before cancelling)
- [ ] For every migrated dashboard, three acceptance numbers from the spec match the Tableau version (and the source sheet) for the same date range.
- [ ] Changing a value in the source sheet appears in the report after refresh, and adding a new row for today shows up in the current period.
- [ ] A test viewer without access to the sheet can see exactly what you intend (and nothing more) using the chosen data-credential setting.
- [ ] The scheduled email arrives on time with the right pages as a PDF for at least two cycles, and recipients can open the link.
- [ ] Renaming a test column breaks a test field as expected, and your documented fix (refresh fields) restores it — so you know the recovery path.
- [ ] Every person who views a Tableau dashboard today has confirmed the replacement meets their need before seats are cancelled.
## Savings methodology
Savings = Tableau licences you can cancel (Creator, and any Explorer/Viewer seats only used for these dashboards) × price per month − incremental cost (normally $0 for Data Studio on Google Sheets; Data Studio Pro or Power BI Pro if you need them). Tableau is typically billed annually, so savings start at renewal. Build time is not counted in dollars.
Example (illustrative): A 25-person services firm with 2 Tableau Creator seats used to publish 4 recurring dashboards from Google Sheets, moving to Data Studio. $150/mo → $0/mo. Assumptions: ILLUSTRATIVE: 2 Creator seats at $75/user/month billed annually, as reported by third-party pricing guides. Tableau's own pricing pages returned HTTP 403 to our fetch today, so this price is not verified — use your contract. No Explorer/Viewer seats are included; viewers move to free Data Studio sharing. Standard (free) Data Studio is sufficient; no Data Studio Pro. Savings realised at the next Tableau renewal.
## Sources
- Data Studio — Schedule automatic report delivery: https://docs.cloud.google.com/looker/docs/studio/schedule-automatic-report-delivery (accessed 2026-10-13)
- Data Studio — Connect to Google Sheets: https://docs.cloud.google.com/looker/docs/studio/connect-to-google-sheets (accessed 2026-10-13)
- About Data Studio Pro: https://docs.cloud.google.com/looker/docs/studio/about-looker-studio-pro (accessed 2026-10-13)
- Power BI pricing: https://www.microsoft.com/en-us/power-platform/products/power-bi/pricing (accessed 2026-10-13)
- Tableau pricing: https://www.tableau.com/pricing/teams-orgs (accessed 2026-10-13)
# Drop Grammarly when you already pay for ChatGPT, Claude, Gemini or Copilot
> If you already pay for an AI assistant, prompts handle rewrites, tone and careful proofreading, and built-in checkers (Google Docs, Microsoft Editor, Apple Writing Tools) cover everyday spelling and grammar. What you genuinely lose is Grammarly's real-time underlines everywhere you type, plus plagiarism checks, AI detection and team style guides on paid plans.
- Outcome: Write clean, on-tone emails and documents without paying for a separate writing-assistant subscription.
- Replaces: Grammarly (full)
- Uses: ChatGPT (optional) — Proofreading, rewriting and tone prompts in a saved Project.; Claude (optional) — Proofreading, rewriting and tone prompts in a saved Project.; Google Gemini (optional) — Same prompts in a Gem, plus Gemini in Gmail/Docs on eligible Workspace plans.; Microsoft 365 Copilot (optional) — Same prompts inside Word and Outlook for Microsoft 365 users with Copilot.; Google Workspace (optional) — Google Docs' built-in spelling and grammar suggestions.; Microsoft 365 (optional) — Microsoft Editor in Word and Outlook (advanced refinements with a Microsoft 365 subscription).
- Extra monthly cost: $0 — $0 extra: this uses an AI assistant you already pay for plus spell/grammar checkers built into Google Docs, Microsoft 365/Edge and Apple devices with Apple Intelligence.
- Difficulty: easy; skill: none; setup: 30–45 minutes (style guide, saved Project, snippet/shortcut)
- Evidence: editorial; illustrative example: false; last reviewed 2026-10-13
- Canonical: https://onelesstool.com/workflows/drop-grammarly-with-existing-ai
## Good fit for
- Individuals and small teams paying for Grammarly Pro on top of an AI assistant subscription
- People who mostly use Grammarly for occasional rewrites, tone changes and a final proofread
- Writers who prefer to see a list of changes and decide, rather than accept underlines one by one
- Teams that write mainly in Google Docs, Word or Outlook, where built-in checkers already exist
## Not a fit for
- People who depend on real-time suggestions in every text box (CRM, support desk, Slack, browser forms) — copy-paste to an AI is slower
- Teams that need an enforced shared style guide or brand tones across many members, with admin controls
- Anyone who needs plagiarism checks or AI-text detection (both included in Grammarly Pro per its plans page)
- Non-native writers who learn from inline explanations as they type, or users who rely on Grammarly's accessibility benefits
## Before
Grammarly runs as a browser extension, desktop app and inside Office/Google Docs, underlining issues as you type everywhere and offering one-click fixes, tone suggestions, AI rewrites, and on Pro, plagiarism and AI detection plus a style guide and brand tone.
## After
Spelling and grammar are caught by the checker built into the app you're in (Google Docs, Word/Outlook's Editor, Edge, or Apple Writing Tools). For anything that matters — client emails, proposals, posts — you paste the text into a pinned 'Proofread' Project in ChatGPT/Claude/Gemini/Copilot that holds your house style, and get a list of every change with a reason, then the corrected text. A text-replacement snippet or Quick Action makes it a few keystrokes.
## Steps
### 1. Be clear about what you'll lose
Grammarly's plans page today lists (Free → Pro at **$12/month** → Enterprise):
- **Real-time suggestions everywhere you type** — browser extension (Chrome, Safari, Firefox, Edge), desktop apps (Windows, Mac), Office, Google Docs, mobile.
- **Plagiarism detection** and an **AI detector** — Pro and Enterprise only.
- **Style guide** and **brand tones** — 1 each on Pro, unlimited on Enterprise.
- **AI prompts** — 100/month Free, 2,000/member/month Pro.
(Grammarly is now part of Superhuman, per its site.) If plagiarism checks, enforced team style or underlines in every web form are essential to you, keep Grammarly — or drop to Grammarly **Free** for basic underlines and use your AI assistant for the rest.
### 2. Turn on the checkers you already have
- **Google Docs:** red underlines = spelling, blue = grammar; press **Tab** to accept. Run **Tools → Spelling and grammar** before sending. Grammar suggestions support English, Spanish, French, German, Portuguese and Italian.
- **Microsoft Word / Outlook:** **Microsoft Editor** (Home tab in Word for the web and Word for Microsoft 365 on Windows; Outlook on the web/Outlook.com). Basic spelling and grammar is free with a Microsoft account; clarity, conciseness and formality refinements need Microsoft 365.
- **Browsers:** Microsoft Edge has built-in spelling/grammar in text boxes; the **Microsoft Editor extension** works in Chrome and Edge.
- **Apple devices with Apple Intelligence:** select text → Control-click → **Writing Tools** → *Proofread* or *Rewrite* (Friendly, Professional, Concise). Works in most apps and websites, subject to language and region availability.
### 3. Write a one-page house style guide
Copy the **House style guide** artifact and fill in the brackets: US or UK spelling, Oxford comma, date format, product names, banned words, tone presets.
If you don't have one, paste 5–10 pieces of writing you're proud of into the **Build a style guide from examples** prompt and edit what it returns. Keep it **under one page** — models follow short, concrete rules more consistently.
This replaces Grammarly's style guide feature for an individual or a small team (share the doc), though nothing *enforces* it.
### 4. Create a pinned 'Proofread' workspace
In whichever assistant you pay for, create a **Project** (Claude or ChatGPT), a **Gem** (Gemini) or a **notebook/saved prompt** (Copilot) called **Proofread**. Paste the style guide plus the **Proofread with a change list** prompt as its instructions.
The key design choice: the output is a **numbered list of changes** (`original → corrected (reason)`) *before* the corrected text. You review changes instead of trusting a silent rewrite — the main way AI 'proofreading' goes wrong is quietly changing meaning, numbers or names.
For tone, use the **Rewrite for tone** prompt with one of your presets.
### 5. Make it a few keystrokes
Follow the **Keyboard-shortcut workflow** artifact:
1. A **text replacement** (macOS: System Settings → Keyboard → Text Replacements) so typing `;pf` expands into the proofreading instruction.
2. **Copy → switch to the pinned Proofread project → paste → Enter → copy the result back.** About 20–30 seconds.
3. Optional macOS **Quick Action** built in the Shortcuts app that wraps selected text in the prompt, copies it and opens your AI app, bound to a keyboard shortcut.
Use built-in underlines for everyday typing and the AI pass for anything external or important.
### 6. Test for two weeks before cancelling
Keep Grammarly on but ignore its suggestions for two weeks. On 10 real pieces of writing, run the AI proofread first, then look at what Grammarly would still flag. If Grammarly consistently catches real errors your new routine misses (not just style preferences), keep it or drop to Free. Otherwise cancel at the end of the billing period.
## Prompts
### Proofread with a change list
Careful proofreading that shows every change so nothing is altered silently.
```text
Proofread the text below as a careful copy editor.
Style: {{style_guide}}
Audience: {{audience}}
English variety: {{english_variety}}
Rules:
- Fix only spelling, grammar, punctuation, clear typos, and violations of the style guide.
- Do NOT change meaning, facts, numbers, names, links, quotes or formatting. Don't 'improve' wording that is already correct.
- If something might be an error but you're not sure (a name, a figure, a technical term), don't change it — list it under "Check".
Output exactly:
1. **Changes** — a numbered list: "original" → "corrected" (reason, max 8 words). Write "No changes needed" if none.
2. **Check** — anything ambiguous for me to decide.
3. **Corrected text** — in one block, ready to paste.
Text:
{{text}}
```
### Rewrite for tone
Replace Grammarly's tone suggestions with an explicit tone rewrite.
```text
Rewrite the text below in the {{tone_preset}} tone from my style guide, for {{audience}}.
Style guide:
{{style_guide}}
Constraints: keep every fact, number, date, name and commitment exactly; keep it within {{max_words}} words; keep any links. Give two versions (A: closest to the original wording, B: more rewritten), then one line on what you changed in each.
Text:
{{text}}
```
### Build a style guide from examples
Draft a one-page house style guide from writing you already like.
```text
Here are {{number_of_samples}} examples of writing from {{company_or_person}} that represent the voice we want:
{{writing_samples}}
Draft a one-page house style guide using ONLY patterns you can see in these samples. Sections: Language & spelling, Voice (5 bullet rules), Terms (always/never), Don'ts, three Tone presets (SUPPORT, SALES, INTERNAL) with one example sentence each. Where the samples are inconsistent, show both options and ask me to choose. Keep it under 350 words.
```
## Templates and scripts
### House style guide template (template)
```
HOUSE STYLE GUIDE — paste into a Claude Project / ChatGPT Project / Gemini Gem / Copilot notebook as standing instructions.
Keep it under one page; the AI follows short, concrete rules better than long essays.
Language & spelling
- Variety: [US English | UK English]. Spell-check against it; flag the other variety's spellings.
- Oxford comma: [yes | no]. Numbers: words for one–nine, digits for 10+; always digits with units (5 GB, 3 days).
- Dates: [13 October 2026 | October 13, 2026]. Times: [9:00 | 9am]. Currency: $1,200 (no ".00" unless cents matter).
Voice
- Plain, direct, friendly. Short sentences (aim < 20 words). Active voice.
- We say "you" to the reader and "we" for the company. No "utilize", "leverage", "synergy", "best-in-class".
- Headlines and buttons: [Sentence case | Title Case].
Terms (always / never)
- [Product name] — always capitalised like this; never "[wrong variant]".
- [customer | client] — use "[chosen]" only.
- [sign up] (verb) vs [sign-up] (noun).
Don'ts
- No exclamation marks in customer emails. No emojis in [contracts, invoices, support replies].
- Never promise dates, refunds or legal outcomes in support replies.
Tone presets (ask for one by name)
- SUPPORT: warm, apologise once, give the next step and a timeframe.
- SALES: confident, specific benefit, one question at the end.
- INTERNAL: brief, bullet points, decision first.
Editing rules for the AI
- Preserve meaning, facts, names, numbers, links and formatting. Never add claims.
- When proofreading, change only what's wrong or violates this guide; list every change.
```
### Keyboard-shortcut workflow (checklist)
```
KEYBOARD-SHORTCUT WORKFLOW — get "select text → fixed text" down to a few keystrokes
1. One saved place for the instructions (all platforms)
Create a Claude Project, ChatGPT Project, Gemini Gem or Copilot notebook called "Proofread" and paste the
house style guide + the proofreading prompt as its instructions. Pin it. Each check is then just: paste text → Enter.
2. Snippet expansion for the prompt (no extra software)
macOS: System Settings → Keyboard → Text Replacements → "+"
Replace: ;pf With: Proofread the text below using my house style. List every change as
"original → corrected (reason)", then give the corrected text in one block. Change nothing else.
Windows/other: use your existing text-expander, or keep the prompt as the Project instructions above.
3. Copy → ask → paste back (any app, any OS)
Select text → Cmd/Ctrl+C → switch to the Proofread project (Cmd/Ctrl+Tab or the AI app's own global shortcut,
if your app offers one — check its settings) → Cmd/Ctrl+V → Enter → copy the corrected block → switch back →
Cmd/Ctrl+V.
4. Built-in, no AI subscription needed
- Apple devices with Apple Intelligence: select text → Control-click → Writing Tools → Proofread / Rewrite
(Friendly, Professional, Concise) — works in most apps and websites.
- Microsoft Edge: built-in spelling/grammar in text boxes; Microsoft Editor extension for Chrome/Edge
(basic checks free with a Microsoft account; advanced refinements with Microsoft 365).
- Google Docs: Tab accepts a suggestion; Tools → Spelling and grammar for a full pass.
- Word: Editor pane on the Home tab (Word for the web / Microsoft 365 on Windows).
5. Optional macOS Quick Action (copies text + prompt, opens your AI app)
Shortcuts app → New Shortcut → Details: "Use as Quick Action", receive Text from Services/Quick Actions →
actions: Text ("Proofread using my house style…\n\n[Shortcut Input]") → Copy to Clipboard → Open App (your
AI app). Assign a key in the shortcut's details (Add Keyboard Shortcut). Then: select text → shortcut → Cmd+V → Enter.
```
## Limitations
- No real-time underlines in every app and web form from your AI assistant; you must copy text into it (built-in checkers cover only their own apps).
- No plagiarism checker or AI-text detector (Grammarly Pro includes both).
- Style guides aren't enforced across a team; each person must use the shared Project/instructions.
- AI assistants occasionally 'over-edit' — changing correct wording or, rarely, a fact — which is why the prompt requires a change list.
- Apple Writing Tools need Apple Intelligence on a supported device, language and region; Google Docs grammar covers six languages; Microsoft Editor's advanced refinements need Microsoft 365.
- Usage limits of your AI plan apply; heavy proofreading days can hit them.
## Risks
- **functionality_loss** (medium): Losing inline suggestions everywhere and plagiarism/AI detection can lead to more small errors in quick messages and no originality check on published content.
- **sensitive_data** (medium): Pasting contracts, HR or customer messages into an AI assistant sends them to that provider. Use a business plan whose data terms you've checked, or the on-device/built-in checkers for sensitive text. (Grammarly also processes what you type, so this is a change of processor, not a new category of risk.)
- **reliability** (low): A silent AI rewrite can change meaning. The change-list format and a quick read of the diff before sending mitigates this.
- **collaboration** (low): Team-wide consistency depends on people using the shared style guide; there are no admin controls or analytics.
## Verification checklist (run before cancelling)
- [ ] On 10 real pieces of your writing, the Proofread prompt caught every genuine error Grammarly flagged (style preferences excluded) and changed no facts, numbers or names.
- [ ] The prompt reliably outputs a numbered change list before the corrected text in your chosen assistant (test 5 times).
- [ ] Built-in checking is confirmed working where you write most: Google Docs suggestions on, Microsoft Editor visible in Word/Outlook, or Writing Tools available on your Apple device.
- [ ] The `;pf` snippet (or Quick Action/pinned Project) gets you from selected text to corrected text in under 30 seconds.
- [ ] You've confirmed nobody on the team needs Grammarly's plagiarism checker, AI detector or enforced team style guide — or you've kept seats only for those people.
- [ ] You've noted Grammarly's renewal date and cancel before it, keeping Grammarly Free if you still want basic underlines.
## Savings methodology
Savings = Grammarly paid seats × price per seat per month − incremental cost ($0, because the AI assistant and built-in checkers are already paid for or free). Dropping to Grammarly Free instead of cancelling keeps basic underlines at $0. If your Grammarly plan is billed annually, savings start at renewal.
Example: A freelance consultant paying for Grammarly Pro and ChatGPT Plus cancels Grammarly Pro and moves proofreading into a ChatGPT Project plus Google Docs/Word built-in checks. $12/mo → $0/mo. Assumptions: Grammarly Pro listed at $12/month on grammarly.com/plans on 2026-10-13 (the page did not state whether this figure requires annual billing; check your invoice). The ChatGPT subscription is already paid for other work, so it adds nothing. No need for plagiarism detection or an AI detector. Optionally keeps Grammarly Free ($0) for basic inline suggestions.
## Sources
- Grammarly plans: https://www.grammarly.com/plans (accessed 2026-10-13)
- Grammarly homepage: https://www.grammarly.com/ (accessed 2026-10-13)
- Google Docs — Check spelling and grammar: https://support.google.com/docs/answer/57859 (accessed 2026-10-13)
- Microsoft Editor: https://support.microsoft.com/en-us/office/microsoft-editor-checks-grammar-and-more-in-documents-mail-and-the-web-91ecbe1b-d021-4e9e-a82e-abc4cd7163d7 (accessed 2026-10-13)
- Apple — Use Writing Tools on Mac: https://support.apple.com/guide/mac-help/use-writing-tools-mchldcd6c260/mac (accessed 2026-10-13)
# Extract invoice data with AI into Google Sheets, with validation and human approval
> For low invoice volumes: use Gemini in Google Workspace or ChatGPT file upload with a strict extraction prompt (no-code), or an n8n flow from Gmail to an LLM to Sheets (automated). Either way, totals and duplicates are checked by rules, and a human approves every invoice before payment.
- Outcome: Get vendor, invoice number, dates, line items and totals from PDF invoices into a spreadsheet log, accurately enough to approve and pay — without a dedicated AP-automation subscription.
- Replaces: Zapier (task_specific)
- Uses: Google Workspace — Gmail (incoming invoices), Drive (PDF archive), Sheets (invoice log, validation formulas, approval column).; Google Gemini (optional) — Path A: Gemini in Sheets/Drive side panel on eligible Workspace plans, or the Gemini app, to read invoice PDFs.; ChatGPT (optional) — Path A alternative: upload PDFs and run the extraction prompt.; Claude (optional) — Path A alternative: upload PDFs and run the extraction prompt.; n8n (optional) — Path B: Gmail trigger → PDF text → Information Extractor (LLM, JSON schema) → validation → Sheets.
- Extra monthly cost: $5 — Path A (no-code, using an AI assistant or Gemini plan you already pay for) adds $0. Path B adds LLM API usage on top of an n8n instance you already run. $5/month is a conservative ILLUSTRATIVE allowance for ~100 invoices — we did not verify current per-token API prices today; check your provider's pricing page and the token count of a typical invoice.
- Difficulty: moderate; skill: basic; setup: Path A: 1–2 hours. Path B: 1 day including the parallel-run test.
- Evidence: editorial; illustrative example: true; last reviewed 2026-10-13
- Canonical: https://onelesstool.com/workflows/invoice-processing-with-ai
## Good fit for
- Small businesses receiving tens to roughly a hundred supplier invoices a month
- Bookkeepers who key invoices into a spreadsheet or accounting tool by hand today
- Teams already on Google Workspace with Gmail as the invoice inbox
- Anyone using a general-purpose automation tool plus a parser add-on just for invoices
## Not a fit for
- Hundreds or thousands of invoices a month, multi-entity AP, or three-way PO matching — dedicated AP automation is built for this
- Businesses that need audit-ready approval workflows, segregation of duties or e-invoicing compliance (e.g. mandated structured e-invoice formats) — a sheet doesn't provide these
- Organisations whose data policies don't allow financial documents to be sent to an external LLM provider
- Anyone hoping to remove human review — extraction errors must be caught before payment
## Before
Invoices arrive by email. Someone opens each PDF and types vendor, number, dates and amounts into a spreadsheet or accounting system — or pays for an AP-capture tool or a parser add-on chained into an automation platform to do it.
## After
Path A: once or twice a week, drag 5–10 invoice PDFs into ChatGPT, Claude or Gemini with a saved extraction prompt; paste the JSON/TSV into the Invoice log where formulas flag line-sum, total and duplicate problems. Path B: an n8n workflow watches a Gmail label, extracts PDF text, asks an LLM for schema-valid JSON, validates totals and duplicates in a Code node, appends to the same sheet as 'Awaiting approval', and emails the approver. In both paths nothing gets paid until a person has compared the row with the PDF and marked it Approved.
## Steps
### 1. Set up the Invoice log and a Gmail label
1. Create a Google Sheet **Invoice log** with the columns listed in the *Validation rules* artifact (A–P). Add the **O2** (normalised key) and **P2** (flags) formulas and fill down.
2. Add data validation on **K (Status)**: `Awaiting approval, Approved, Rejected, Blocked – duplicate, Paid`.
3. Conditional formatting: `=$P2<>""` → red fill.
4. In Gmail, create a filter that applies the label **AP/Inbox** to mail from your suppliers or sent to your invoices@ address. Save PDFs to a Drive folder **AP/2026** so the log can link to originals (column N).
### 2. Path A (no-code): extract with your AI assistant
Use whichever you already pay for:
- **ChatGPT or Claude:** start a Project (so the instructions persist), paste the *Invoice JSON schema* and the **Extract invoice to JSON** prompt as project instructions, then upload **5–10 PDFs per message**.
- **Gemini in Google Sheets** (on eligible Workspace editions — Business Starter does not include Gemini in Sheets per Google's pricing page): open the side panel in the Invoice log, reference the Drive PDFs and ask for a table using the same field list. Check that it read the right files.
Ask for the result as **JSON and as TSV**; paste the TSV into the log. The formulas then flag any line-sum, total or duplicate issues.
Scanned or photographed invoices: the assistant may misread digits. Mark them `HUMAN_CHECK` and compare every number.
### 3. Path B (automated): build the n8n workflow
Nodes, in order:
1. **Gmail Trigger** — poll every 15–60 min, filter by label `AP/Inbox`, unread only; enable downloading attachments.
2. **Filter** — keep only items with a PDF attachment.
3. **Extract From File** → *Extract From PDF* on the attachment's binary field. (Text-based PDFs only; n8n's docs don't mention OCR, so route scanned PDFs to a model that accepts images/PDFs directly, or to manual entry.)
4. **Information Extractor** with *Schema Type → Define using JSON Schema*, paste the schema artifact, connect your chat model (OpenAI, Anthropic, Gemini). Put the extraction rules from the prompt in the system message.
5. **Google Sheets → Get rows** from the Invoice log, then a **Code** node ("Run Once for All Items") that builds an `existingKeys` array — or simply rely on the sheet's DUPLICATE formula and keep this step simple.
6. **Code** node *Validate invoice* (artifact) — adds `flags`, `line_sum`, `norm_key`, `status`.
7. **Google Drive → Upload** the PDF to `AP/2026`; **Google Sheets → Append row** with the link and status `Awaiting approval` or `Blocked – duplicate`.
8. **Gmail → Send** the approver a summary with the flags and the sheet link.
9. Attach an **Error Workflow** so failures alert you instead of silently dropping invoices.
### 4. Validate every invoice with rules, not vibes
LLMs are good at reading invoices and bad at noticing their own mistakes. The *Validation rules* artifact catches the errors that cost money:
- **Line items sum to subtotal**, and **subtotal − discount + shipping + tax = total** (±0.01).
- **Duplicate invoice number** from the same vendor after normalising (`INV-00123` = `inv 123`) → blocked.
- **Near-duplicates** (same vendor and amount within 7 days, different number) → flagged; double-billing often looks like this.
- **Dates** in the future or more than a year old → flagged.
- **Bank details present on a new vendor or changed from last time** → verify by phone using a number you already have. Invoice fraud usually arrives as a legitimate-looking invoice with new bank details.
Anything flagged gets a human check against the PDF; a clean row still needs approval.
### 5. Human approval before any payment
Set a simple rule and write it at the top of the sheet: **nobody pays from an unapproved row.**
- The approver opens the PDF link (column N), compares vendor, number, total and due date, resolves flags with a note, then sets **Status = Approved** with their name and date.
- Payment is made in your bank or accounting software by someone other than the approver if you have two people (basic segregation of duties).
- After payment, set **Status = Paid**. Once a month, reconcile Paid rows against bank statements.
Use **Data → Protect sheets and ranges** so only approvers can edit columns K–M.
### 6. Parallel-run for one month, then decide
For one month, keep your current process and run the new one alongside it. Track per invoice: fields wrong, flags raised, minutes spent. Move to the new process only if **zero errors reached the 'Approved' state** and the time saved is real. Re-check the extraction prompt whenever a new supplier's layout causes repeated `HUMAN_CHECK` flags — add a one-line hint per problem supplier to the prompt.
## Prompts
### Extract invoice to JSON
Turn one or more invoice PDFs into schema-valid JSON without inventing values.
```text
You are an accounts-payable data-entry assistant. Extract data from the attached document(s) for {{company_name}}.
Return ONLY JSON that validates against this schema (one object per document; if several documents are attached, return a JSON array in the order given):
{{json_schema}}
Rules:
1. Copy values exactly as printed. Do not calculate, infer or 'fix' anything. If a value is not printed, use null (or 0 for tax_total only when the document clearly shows no tax).
2. Dates → YYYY-MM-DD. If the date format is ambiguous (e.g. 03/04/2026), assume {{date_convention}} and add the field to uncertain_fields.
3. Numbers → plain decimals without currency symbols or thousands separators.
4. invoice_number: keep prefixes, dashes and leading zeros exactly.
5. If it is not an invoice (statement, quote, receipt, marketing email), set document_type accordingly and still fill what you can.
6. Set bank_details_present to true if bank account / IBAN / routing details appear anywhere.
7. confidence = low if the scan is blurry, handwritten, cut off or totals don't appear.
No commentary outside the JSON.
```
### Convert extracted JSON to sheet rows
Produce paste-ready TSV in the Invoice log's column order (Path A).
```text
Convert this extracted invoice JSON into TSV rows for my Invoice log. Columns, in order: Received ({{received_date}}), Vendor, Invoice no, Invoice date, Due date, Currency, Subtotal, Tax, Total, Line sum (sum of line_items.amount, rounded to 2 decimals), Status (always "Awaiting approval"), Approver (blank), Approved on (blank), File link ({{file_link_placeholder}}).
{{extracted_json}}
Output only one TSV code block with no header row. Do not change any extracted value; if a field is null, leave the cell empty. After the code block, list any invoice where Line sum ≠ Subtotal or Subtotal + Tax ≠ Total.
```
### Second-look check on a flagged invoice
Re-read a flagged invoice field by field before a human decides.
```text
This invoice was flagged {{flags}} after extraction. Re-read the attached PDF carefully and compare it against the extracted JSON below, field by field.
{{extracted_json}}
Return a table: field | extracted value | value printed on the document (quote it exactly) | match (yes/no). Then say which flag is explained by an extraction error and which reflects a real problem on the invoice itself (e.g. the vendor's own arithmetic is wrong, or it's a duplicate). Do not recommend paying or not paying; just report what the document says.
```
## Templates and scripts
### Invoice JSON schema (schema)
```json
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "ExtractedInvoice",
"type": "object",
"additionalProperties": false,
"required": ["document_type", "vendor_name", "invoice_number", "invoice_date", "currency",
"line_items", "subtotal", "tax_total", "total", "confidence", "uncertain_fields"],
"properties": {
"document_type": { "enum": ["invoice", "credit_note", "receipt", "statement", "quote", "not_an_invoice"] },
"vendor_name": { "type": "string", "description": "Legal name as printed on the document" },
"vendor_tax_id": { "type": ["string", "null"], "description": "VAT/GST/EIN etc. exactly as printed, else null" },
"vendor_address": { "type": ["string", "null"] },
"bill_to_name": { "type": ["string", "null"] },
"invoice_number": { "type": "string", "description": "Exactly as printed, including prefixes and leading zeros" },
"po_number": { "type": ["string", "null"] },
"invoice_date": { "type": "string", "format": "date", "description": "YYYY-MM-DD" },
"due_date": { "type": ["string", "null"], "format": "date" },
"payment_terms": { "type": ["string", "null"], "description": "e.g. 'Net 30' as printed" },
"currency": { "type": "string", "pattern": "^[A-Z]{3}$", "description": "ISO 4217, e.g. USD" },
"line_items": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": ["description", "quantity", "unit_price", "amount"],
"properties": {
"description": { "type": "string" },
"quantity": { "type": ["number", "null"] },
"unit_price": { "type": ["number", "null"] },
"amount": { "type": "number", "description": "Line total before tax, as printed" },
"tax_rate": { "type": ["number", "null"], "description": "Percent, e.g. 20 for 20%" }
}
}
},
"subtotal": { "type": "number", "description": "Before tax, after line-level discounts" },
"discount_total": { "type": ["number", "null"], "description": "Document-level discount as a positive number" },
"shipping_total": { "type": ["number", "null"] },
"tax_total": { "type": "number", "description": "0 if no tax shown" },
"total": { "type": "number", "description": "Amount due as printed" },
"amount_paid": { "type": ["number", "null"] },
"bank_details_present": { "type": "boolean", "description": "true if the document shows bank/payment account details" },
"confidence": { "enum": ["high", "medium", "low"] },
"uncertain_fields": { "type": "array", "items": { "type": "string" },
"description": "Names of fields that were hard to read, inferred or missing" }
}
}
Conventions: numbers are plain decimals (1234.5, not "1,234.50"); credit notes use positive numbers with
document_type "credit_note"; never compute a value that isn't printed — put the field in uncertain_fields instead.
```
### Validation rules + Google Sheets formulas (checklist)
```
VALIDATION RULES — apply to every extracted invoice before it can be approved
Tolerance: 0.01 per amount (0.02 if more than 10 line items, to allow per-line rounding).
R1 Line sum | SUM(line_items.amount) = subtotal → else "LINE_SUM_MISMATCH"
R2 Total | subtotal − discount_total + shipping_total + tax_total = total → else "TOTAL_MISMATCH"
R3 Tax sanity | if line tax_rate present: tax_total ≈ Σ(amount × rate/100) → else "TAX_CHECK" (warning)
R4 Duplicate | same normalised vendor + same normalised invoice_number already in the log
| (normalise: upper-case, keep only letters/digits, drop zeros that lead a number) → "DUPLICATE" (block)
R5 Near-duplicate | same vendor + same total + invoice_date within 7 days, different number → "POSSIBLE_DUPLICATE"
R6 Dates | invoice_date not in the future and not > 365 days old; due_date ≥ invoice_date → "DATE_CHECK"
R7 Required | vendor_name, invoice_number, invoice_date, total present → else "MISSING_FIELD"
R8 Doc type | document_type = "invoice" (credit notes routed separately) → else "NOT_INVOICE"
R9 Confidence | confidence = "low" or uncertain_fields not empty → "HUMAN_CHECK"
R10 Bank details | bank_details_present = true AND vendor is new, or bank details differ from the vendor master
| → "VERIFY_BANK_DETAILS_BY_PHONE" (classic invoice-fraud pattern: call a known number, never the one on the invoice)
Google Sheets versions (Invoice log tab; columns: A Received, B Vendor, C Invoice no, D Invoice date,
E Due date, F Currency, G Subtotal, H Tax, I Total, J Line sum, K Status, L Approver, M Approved on, N File link,
O Norm key, P Flags):
O2 =UPPER(REGEXREPLACE(B2,"[^A-Za-z0-9]",""))&"|"®EXREPLACE(UPPER(REGEXREPLACE(C2,"[^A-Za-z0-9]","")),"(^|[A-Z])0+([0-9])","$1$2")
P2 =TEXTJOIN(", ",TRUE,
IF(ABS(J2-G2)>0.01,"LINE_SUM_MISMATCH",""),
IF(ABS(G2+H2-I2)>0.01,"TOTAL_MISMATCH",""),
IF(COUNTIF($O$2:$O,O2)>1,"DUPLICATE",""),
IF(D2>TODAY(),"DATE_CHECK",""))
(Adjust P2's TOTAL check if you track discount/shipping columns.)
Conditional formatting on A2:P: custom formula =$P2<>"" → red fill.
APPROVAL RULE: Status may only change to "Approved" when P is empty (or each flag is resolved with a note),
and the approver has opened the original PDF. Payment happens in your bank/accounting system, never from this sheet.
```
### n8n Code node: validate invoice (script)
```javascript
// n8n Code node — "Validate invoice" (mode: Run Once for Each Item)
// Input: the Information Extractor's structured result (n8n puts it under `output`; we also accept a top-level object)
// plus `existingKeys` (array of normalised "VENDOR|INVOICENO" keys) merged in from a Google Sheets lookup step.
const inv = $json.output ?? $json;
const existingKeys = $json.existingKeys ?? [];
const flags = [];
const tol = (inv.line_items?.length ?? 0) > 10 ? 0.02 : 0.01;
const num = (v) => (typeof v === 'number' && isFinite(v) ? v : 0);
const close = (a, b) => Math.abs(a - b) <= tol + 1e-9;
for (const f of ['vendor_name', 'invoice_number', 'invoice_date', 'total']) {
if (inv[f] === null || inv[f] === undefined || inv[f] === '') flags.push(`MISSING_FIELD:${f}`);
}
if (inv.document_type !== 'invoice') flags.push(`NOT_INVOICE:${inv.document_type}`);
const lineSum = (inv.line_items ?? []).reduce((s, l) => s + num(l.amount), 0);
if ((inv.line_items ?? []).length && !close(lineSum, num(inv.subtotal))) flags.push('LINE_SUM_MISMATCH');
const expectedTotal = num(inv.subtotal) - num(inv.discount_total) + num(inv.shipping_total) + num(inv.tax_total);
if (!close(expectedTotal, num(inv.total))) flags.push('TOTAL_MISMATCH');
const today = new Date(); today.setHours(0, 0, 0, 0);
const invDate = new Date(inv.invoice_date);
if (isNaN(invDate) || invDate > today || (today - invDate) / 86400000 > 365) flags.push('DATE_CHECK');
if (inv.due_date && new Date(inv.due_date) < invDate) flags.push('DATE_CHECK:due_before_invoice');
const norm = (s) => String(s ?? '').toUpperCase().replace(/[^A-Z0-9]/g, '');
const key = `${norm(inv.vendor_name)}|${norm(inv.invoice_number).replace(/(^|[A-Z])0+(?=\d)/g, '$1')}`; // INV-00123 -> INV123
if (existingKeys.includes(key)) flags.push('DUPLICATE');
if (inv.confidence === 'low' || (inv.uncertain_fields ?? []).length) flags.push('HUMAN_CHECK');
if (inv.bank_details_present) flags.push('VERIFY_BANK_DETAILS_BY_PHONE_IF_NEW_OR_CHANGED');
return {
json: {
...inv,
line_sum: Math.round(lineSum * 100) / 100,
norm_key: key,
flags: flags.join(', '),
status: flags.includes('DUPLICATE') ? 'Blocked – duplicate' : 'Awaiting approval',
},
};
```
## Limitations
- Extraction errors happen, especially on scans, photos, handwriting, multi-page tables and unusual layouts. Human review before payment is mandatory.
- n8n's Extract From File node reads text from PDFs; its docs don't mention OCR, so scanned invoices need a vision-capable model or manual entry.
- No three-way matching against purchase orders and goods receipts, no approval chains by amount, no vendor master management.
- Doesn't post bills into accounting software by itself; that needs another integration step or manual entry.
- Path A is still manual (upload, paste); it saves typing, not the whole process.
- Gemini features in Sheets/Drive depend on your Google Workspace edition or Google AI plan.
## Risks
- **sensitive_data** (high): Invoices contain bank details, amounts and personal data. OpenAI states it does not train on API, ChatGPT Business or Enterprise data by default; Anthropic states it does not train on commercial-product (Team, Enterprise, API) inputs by default. Consumer plans can differ — check your plan's data settings and your contracts before uploading supplier invoices.
- **reliability** (high): A misread digit or a hallucinated total can lead to an over- or under-payment. Rule-based validation catches arithmetic and duplicates, not a wrong-but-consistent number — the human check against the PDF is the control.
- **security** (medium): Automating the inbox can speed up invoice fraud (fake invoices, changed bank details) if people trust the pipeline. Keep the bank-details verification rule and never pay from a link or number on the invoice itself.
- **compliance** (medium): Tax rules may require retaining original invoices and, in some countries, structured e-invoices. Keep the original PDFs in Drive and check local requirements; the extracted sheet is not a substitute for the original.
- **functionality_loss** (medium): Compared with dedicated AP tools you lose supplier portals, automatic accounting sync, approval routing and audit trails.
## Verification checklist (run before cancelling)
- [ ] On a test set of 30 past invoices (including at least 5 scans and 5 multi-page invoices), every field matches the PDF on at least 28, and every error was caught by a flag or by the human check.
- [ ] Feeding the same invoice twice produces DUPLICATE and the second copy is blocked; 'INV-00123' and 'inv 123' from the same vendor are treated as the same number.
- [ ] An invoice with a deliberately wrong total (edit a test PDF) is flagged TOTAL_MISMATCH.
- [ ] A credit note and a supplier statement are recognised as such and not logged as invoices to pay.
- [ ] Path B: the n8n workflow processed every test email in the AP/Inbox label exactly once over 5 days, and the Error Workflow alerted on a deliberately broken run.
- [ ] Only approvers can edit the Status/Approver columns, and no payment in the parallel month was made from a row without Status = Approved.
- [ ] You have confirmed in writing which AI plan/API is used and that its data terms are acceptable for supplier financial data.
## Savings methodology
Savings = what you pay today for invoice capture (an AP-capture subscription or a parser add-on plus the automation tasks it consumes) − incremental cost of the new path (Path A: $0 with an AI plan you already have; Path B: LLM API usage). Time saved on data entry is real but not counted in dollars. Human review time remains in both cases.
Example (illustrative): A small agency processing ~60 supplier invoices a month with a paid invoice-capture add-on, switching to Path B on an n8n instance it already runs. $30/mo → $5/mo. Assumptions: ILLUSTRATIVE: $30/month for the current invoice-capture tool is an assumed figure, not a verified vendor price — use your own invoice. ILLUSTRATIVE: $5/month is a conservative allowance for LLM API usage at ~60 invoices; actual cost depends on model and pages per invoice and was not verified against a price list today. n8n and Google Workspace are already paid for; no new subscriptions. Human review (~1 minute per invoice) continues in both setups.
## Sources
- n8n docs — Information Extractor node: https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.information-extractor/ (accessed 2026-10-13)
- n8n docs — Extract From File: https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.extractfromfile/ (accessed 2026-10-13)
- n8n docs — Gmail Trigger: https://docs.n8n.io/integrations/builtin/trigger-nodes/n8n-nodes-base.gmailtrigger/ (accessed 2026-10-13)
- Gemini in Google Sheets: https://support.google.com/docs/answer/14218565 (accessed 2026-10-13)
- Google Workspace pricing / plan comparison: https://workspace.google.com/pricing (accessed 2026-10-13)
- OpenAI — Business data privacy: https://openai.com/business-data/ (accessed 2026-10-13)
- Anthropic — Is my data used for model training?: https://privacy.claude.com/en/articles/7996868-is-my-data-used-for-model-training (accessed 2026-10-13)
# Stop paying for Otter: use the transcription and AI notes already in Meet, Teams or Zoom
> Many business plans already include meeting transcripts and AI notes: Google Meet transcripts and 'Take notes for me' on eligible Workspace editions, Teams transcription (with AI notes via Teams Premium or Microsoft 365 Copilot), and Zoom's built-in meeting summaries on eligible paid plans. Check what you have, fill gaps with a transcript-to-action-items prompt, and handle recording consent properly.
- Outcome: Get a transcript, a summary and a clear list of action items from every meeting without a separate note-taker subscription.
- Replaces: Otter.ai (full)
- Uses: Google Workspace (optional) — Google Meet transcripts (Business Standard and up, among others) and Gemini 'Take notes for me' on eligible editions.; Microsoft 365 (optional) — Teams live transcription and Recap (availability depends on licence and admin policy).; Microsoft 365 Copilot (optional) — AI-generated notes, tasks and Q&A over Teams meetings (intelligent recap is part of the Copilot licence; also in Teams Premium).; Claude (optional) — Turn any transcript file into decisions and action items with the prompts below.; ChatGPT (optional) — Alternative for transcript-to-action-items.; Google Gemini (optional) — Alternative for transcript-to-action-items, already inside Google Docs on eligible plans.
- Extra monthly cost: $0 — $0 if your meeting platform plan already includes transcription/AI notes (see the eligibility matrix) and you already pay for an AI assistant for the gaps. If your plan doesn't include AI notes (e.g. Google Workspace Business Starter, Teams without Premium or Copilot), upgrading may cost more than Otter — do the comparison before cancelling.
- Difficulty: easy; skill: none; setup: 30–60 minutes (check plan eligibility, admin settings, invite template)
- Evidence: editorial; illustrative example: false; last reviewed 2026-10-13
- Canonical: https://onelesstool.com/workflows/meeting-notes-with-built-in-ai
## Good fit for
- Teams that meet mostly on one platform (Meet, Teams or Zoom) and already pay for an eligible business plan
- People using Otter mainly for summaries and action items of internal meetings
- Organisations that prefer meeting data to stay inside their existing Google or Microsoft tenant
## Not a fit for
- People who meet across many platforms or join other companies' meetings and need one bot that works everywhere
- Workflows built on Otter-specific features: shared searchable conversation library across all meetings, CRM sync, in-person recording from a phone app, importing audio files at volume
- Teams on plans without built-in AI notes (e.g. Google Workspace Business Starter, Microsoft 365 without Teams Premium or Copilot) where upgrading costs more than the note-taker
- Meetings where recording or transcription isn't permitted or consent can't be obtained
## Before
An Otter seat per person joins meetings (via calendar integration or a bot), records and transcribes them, writes a summary and action items, and keeps a searchable library of conversations.
## After
The meeting platform does the transcription natively: Meet saves a transcript Doc and Gemini notes to the organizer's Drive; Teams shows the transcript (and AI notes with Premium/Copilot) in Recap; Zoom produces a meeting summary on eligible paid plans. For anything the platform doesn't summarise well, the transcript file goes through a saved 'transcript → action items' prompt in your existing AI assistant. Consent wording is in every invite.
## Steps
### 1. Check exactly what your plan includes
Use the **Eligibility matrix** artifact, then confirm in your own account — vendors change these often.
- **Google:** start a test meeting as organizer. If the meeting tools offer **Transcripts** and **Take notes for me**, you have them. Transcripts are listed for Business Standard and above (not Business Starter). 'Take notes for me' supports 8 spoken languages, one per meeting.
- **Microsoft:** in a Teams meeting, open **More** and look for the **Record and transcribe** options. If it's missing, your admin's meeting policy or licence doesn't allow it — **check your plan with IT**. AI notes and tasks in Recap need **Teams Premium** or a **Microsoft 365 Copilot** licence.
- **Zoom:** in settings, look for **meeting summary** and **transcription** options. Zoom says these (formerly 'AI Companion') remain included with **eligible paid plans** — **check your plan**. Free Basic accounts get a small monthly allowance.
If none applies, compare the cost of upgrading against Otter before going further.
### 2. Turn the features on (admin + user)
- **Google Workspace admin:** make sure Meet transcripts and Gemini features are enabled for the right organisational units. Users then click **Take notes for me** (or set it to start automatically in the meeting options) and choose who receives notes under **Send notes to**.
- **Microsoft 365 / Teams admin:** in the Teams admin center meeting policy, allow transcription (and recording if you want it). For Copilot, organizers choose **During and after the meeting** so Copilot can use the transcript later.
- **Zoom admin:** enable meeting summaries and transcription at account or group level, and decide who summaries are sent to.
Test with a colleague: run a 5-minute meeting and confirm the transcript/notes land where you expect (Drive, OneDrive/Recap, Zoom summary email).
### 3. Put consent in the workflow, not in someone's memory
Work through the **Consent checklist** artifact. The short version:
- US federal law is one-party consent, but **several states require all-party consent** (the Digital Media Law Project lists California, Florida, Washington, Pennsylvania, Maryland and others). With mixed locations, get everyone's consent.
- In the EU/UK, transcripts are personal data under GDPR: tell people why, who sees it and how long you keep it.
- Add a consent line to your **default calendar invite**, say it out loud at the start of external calls, and **don't transcribe** HR, health, legal or performance conversations by default.
All three platforms show participants that transcription is running; Google also lets admins require explicit participant consent before transcription starts.
### 4. Fill the gaps with a saved prompt
Built-in notes are generic. For client calls and project meetings, download the transcript (Meet: the transcript Doc; Teams: Recap → Transcript → Download .docx; Zoom: the transcript file) and run the **Transcript → decisions and action items** prompt in Claude, ChatGPT or Gemini.
Save the prompt as a Claude/ChatGPT Project instruction or a Gemini Gem so it's one paste per meeting. The prompt forces **owners and due dates**, flags **unclear** commitments instead of inventing them, and quotes the transcript line for each action so you can verify it.
### 5. Replace Otter's library with a simple filing rule
Otter's searchable library is the hardest thing to replace. A good-enough version:
- Meet and Teams already file transcripts in the organizer's Drive/OneDrive and link them to the calendar event — search there.
- Paste each approved action-item summary into one running doc per client/project (e.g. `Client – Meeting log`), newest first. That doc becomes the searchable history.
- Before cancelling Otter, **export** the conversations you need to keep (check Otter's export options for your plan) and store them in that folder with the same retention rule.
### 6. Run both for two weeks, then cancel
For two weeks, let Otter and the built-in feature both run on the same internal meetings (with consent). Compare action items side by side. Cancel when the built-in notes plus the prompt catch every action item Otter caught on at least 5 meetings, and your exports are done.
## Prompts
### Transcript → decisions and action items
Turn a raw transcript into a verified action list with owners and dates.
```text
Below is the transcript of a {{meeting_type}} held on {{meeting_date}}. Attendees: {{attendees}}. Our team: {{our_team}}.
{{transcript}}
Produce:
1. **Decisions made** — one line each, with the transcript quote that shows the decision.
2. **Action items** — table: Action | Owner | Due date | Quote from transcript. Use only owners and dates actually stated. If an owner or date is missing or ambiguous, write "UNCLEAR" — do not guess.
3. **Open questions / parked items**.
4. **Risks or concerns raised** by anyone outside our team.
5. A follow-up email to {{recipient}} (max 150 words) summarising decisions and actions.
Transcripts contain recognition errors: if a name, number or product term looks wrong, flag it in a final "Check these" list rather than correcting it silently. Do not include anything said after someone asked to go off the record.
```
### Compare built-in notes with a transcript
Check what the platform's AI notes missed during the parallel run.
```text
Here are the AI-generated notes from {{platform}} and the full transcript of the same meeting.
AI notes:
{{platform_notes}}
Transcript:
{{transcript}}
List: (1) action items or decisions in the transcript that the notes missed, (2) statements in the notes not supported by the transcript, (3) items attributed to the wrong person. Quote the transcript for each. End with a one-line verdict: are these notes reliable enough to send without edits?
```
### Client meeting log entry
Create a consistent entry for a running per-client meeting log (replacing Otter's library).
```text
Create a meeting-log entry for {{client_name}} from these approved notes:
{{approved_notes}}
Format exactly:
### {{meeting_date}} – {{meeting_title}}
**Attendees:** …
**Decisions:** bullet list
**Actions:** - [ ] Action — Owner — Due
**Next meeting:** date or "not set"
**Tags:** up to 5 keywords for search (products, projects, topics)
Use only information in the notes.
```
## Templates and scripts
### Eligibility matrix: what Meet, Teams and Zoom include (checklist)
```
WHICH BUILT-IN FEATURE DO YOU ALREADY HAVE? (checked 2026-10-13 — vendors change this often; confirm in your admin console)
GOOGLE MEET (Google Workspace)
Transcripts (verbatim, saved as a Google Doc in the organizer's Drive "Google Meet" folder, linked to the Calendar event)
Editions listed by Google: Business Standard, Business Plus, Enterprise Starter, Enterprise Standard, Enterprise Plus,
Teaching and Learning Upgrade, Education Plus, Workspace Individual.
→ NOT listed: Business Starter.
"Take notes for me" (Gemini AI summary + next steps, saved as a Doc in the organizer's Drive and attached to the event)
Requires an eligible Workspace edition or Google AI plan; the ORGANIZER's edition must include it.
Google's plan comparison shows Gemini in Meet in Business Standard and Plus, not in Business Starter.
Spoken languages: English, French, German, Italian, Japanese, Korean, Portuguese, Spanish — one language per meeting.
Who gets notes: host setting "Send notes to" (all invited guests incl. external / internal invitees / hosts only).
MICROSOFT TEAMS (Microsoft 365)
Live transcription: participants are notified; transcript appears in the calendar event and the meeting chat's
Recap tab, downloadable as .docx/.vtt; stored in the organizer's OneDrive. Availability depends on your license
AND your admin's meeting policy → CHECK YOUR PLAN / ask IT if the Transcribe button is missing.
Intelligent recap with AI-generated notes and tasks: a Teams Premium feature (per Microsoft's Teams Premium
licensing page) and also part of the Microsoft 365 Copilot license (per Microsoft's Copilot-in-Teams support page).
Copilot in Teams meetings: transcription must be on for Copilot to work during and after the meeting
(organizer setting "During and after the meeting").
ZOOM WORKPLACE
Meeting summaries and transcription (formerly branded "AI Companion"): Zoom's June 2026 blog says these remain
"included with eligible paid plans" and are now simply named by what they do. → CHECK YOUR PLAN for eligibility.
Free Basic accounts: limited AI meeting summaries (Zoom's page lists 3 hosted meetings/month) and 40-minute meetings.
ZoomMate (agentic assistant, custom summary templates at scale, workflows) is a separate paid product.
NEITHER? Record with the platform's own recording (with consent), download the transcript/captions file, and use the
"Transcript → action items" prompt in Claude/ChatGPT/Gemini. That covers summaries, not live note-taking.
```
### Recording & transcription consent checklist (checklist)
```
RECORDING & TRANSCRIPTION CONSENT CHECKLIST (general information, not legal advice)
Know the rule that applies
[ ] US federal law (18 U.S.C. 2511(2)(d)) is ONE-party consent, but several states require ALL parties to consent —
the Digital Media Law Project lists California, Connecticut, Florida, Illinois, Maryland, Massachusetts (bans
secret recording), Montana, New Hampshire, Pennsylvania and Washington. With participants in several states,
follow the strictest rule: get everyone's consent.
[ ] EU/UK: recordings and transcripts are personal data under GDPR/UK GDPR — you need a lawful basis, a clear notice
(purpose, retention, who sees it) and must honour access/erasure requests. Employee monitoring rules may apply.
[ ] Other countries: check local law; when unsure, get explicit consent from everyone.
Before the meeting
[ ] Calendar invite says: "This meeting will be transcribed and AI-summarised for note-taking. Tell the organizer if
you'd prefer not." — include it in your default invite template
[ ] External meetings: ask at the start, out loud, and note the answer in the agenda doc
[ ] Sensitive topics (HR, health, legal, M&A, performance reviews): DON'T transcribe by default
During
[ ] Platform indicators are on (Meet/Teams/Zoom all show participants that transcription/notes are running)
[ ] If anyone objects, stop transcription and take manual notes
After
[ ] Restrict who receives auto-generated notes (Meet: "Send notes to"; Teams: transcript download policy)
[ ] Review AI notes before forwarding — they can misattribute statements
[ ] Retention: set a deletion rule (e.g. delete raw transcripts after 90 days; keep the approved action-item summary)
[ ] Pasting transcripts into a separate AI assistant? Use a business plan whose data terms you've checked, and
remove anything you wouldn't put in an email to that vendor
```
## Limitations
- Each platform only covers its own meetings; a dedicated note-taker works across Zoom, Meet and Teams and in-person recordings.
- Plan eligibility varies and changes: Google Workspace Business Starter lacks transcripts; Teams AI notes need Teams Premium or Microsoft 365 Copilot; Zoom features depend on an eligible paid plan.
- Google 'Take notes for me' handles one spoken language per meeting and a fixed list of languages.
- No cross-meeting searchable library like Otter's; you rely on Drive/OneDrive search and your own meeting logs.
- Transcription errors with names, jargon and accents carry into summaries; AI notes can misattribute statements.
- Notes usually land with the organizer; when you're a guest in someone else's meeting you may get nothing unless they share.
## Risks
- **compliance** (high): Recording or transcribing without the consent required by law (all-party consent in several US states; GDPR transparency in the EU/UK) can be unlawful. Put consent wording in invites, ask at the start of external calls and stop if anyone objects.
- **sensitive_data** (medium): Transcripts capture everything said, including confidential and personal information, and may be emailed to all invitees (including external guests) depending on settings. Restrict 'Send notes to' and set retention rules.
- **functionality_loss** (medium): Losing a cross-platform note-taker, CRM integration and a searchable conversation library.
- **data_portability** (low): Export the Otter conversations you need before cancelling; after cancellation, access may be limited.
## Verification checklist (run before cancelling)
- [ ] In a test meeting on your actual plan, the transcript (and AI notes, if expected) were generated and saved where you expected within 30 minutes of the meeting ending.
- [ ] On at least 5 real meetings run in parallel with Otter, the built-in notes plus the action-items prompt captured every action item Otter captured.
- [ ] Notes/transcripts reached only the intended recipients (test with an external guest invite to confirm external sharing behaviour).
- [ ] Your default calendar invite contains consent wording, and the team knows to stop transcription if someone objects.
- [ ] A retention/deletion rule for raw transcripts is set (admin policy or a calendar reminder) and documented.
- [ ] All Otter conversations you must keep have been exported and filed before the subscription ends.
## Savings methodology
Savings = Otter seats × price per seat per month − any upgrade needed to unlock built-in features (often $0 if you're already on an eligible plan). If you'd have to upgrade every user's meeting-platform plan or buy Teams Premium/Copilot just for notes, include that cost — it can exceed Otter's price.
Example: A 3-person consultancy on Google Workspace Business Standard paying for Otter Pro on monthly billing, switching to Meet transcripts and 'Take notes for me'. $50.97/mo → $0/mo. Assumptions: Otter Pro at $16.99 per user/month on monthly billing ($8.33/user/month billed annually), per otter.ai/pricing on 2026-10-13: 3 × $16.99 = $50.97. Business Standard includes Meet transcripts (Google's transcript help page) and Gemini in Meet (Google Workspace plan comparison) — no upgrade needed. They already pay for an AI assistant used for the action-items prompt. If they were on annual Otter billing the saving would be 3 × $8.33 = $24.99/month.
## Sources
- Google Meet — Use transcripts: https://support.google.com/meet/answer/12849897 (accessed 2026-10-13)
- Google Meet — Take notes for me: https://support.google.com/meet/answer/14754931 (accessed 2026-10-13)
- Google Workspace plan comparison: https://workspace.google.com/pricing (accessed 2026-10-13)
- Microsoft — Live transcription in Teams meetings: https://support.microsoft.com/en-us/office/view-live-transcription-in-microsoft-teams-meetings-dc1a8f23-2e20-4684-885e-2152e06a4a8b (accessed 2026-10-13)
- Microsoft Learn — Teams Premium licensing: https://learn.microsoft.com/en-us/microsoftteams/teams-add-on-licensing/licensing-enhance-teams (accessed 2026-10-13)
- Microsoft — Copilot in Teams: https://support.microsoft.com/en-us/copilot-teams (accessed 2026-10-13)
- Zoom blog — Meet ZoomMate (June 24, 2026): https://www.zoom.com/en/blog/zoom-ai-companion-zoommate/ (accessed 2026-10-13)
- Zoom — ZoomMate product page: https://www.zoom.com/en/products/ai-assistant/ (accessed 2026-10-13)
- Otter.ai pricing: https://otter.ai/pricing (accessed 2026-10-13)
- Digital Media Law Project — Recording phone calls and conversations: https://www.dmlp.org/legal-guide/recording-phone-calls-and-conversations (accessed 2026-10-13)
# Research ~500 target accounts a month with an AI assistant and Google Sheets
> Replace the account-research columns you'd build in Clay with batched, cited web research in Claude or ChatGPT, a strict JSON output schema, a scoring rubric and a 10% hallucination spot-check. It does not replace verified contact data — you still need Apollo, ZoomInfo or similar for emails and phones.
- Outcome: Each month, turn a list of ~500 target companies into a qualified, cited, de-duplicated account list with a fit score and a personalisation angle for the best ones.
- Replaces: Clay (partial)
- Uses: Claude (optional) — Web search / Research mode with citations to research each batch and return JSON.; ChatGPT (optional) — Alternative: web search or deep research with citations to research each batch.; Google Workspace — Google Sheets as the master account list, de-dup formulas and QA log.; Apollo.io (optional) — Verified business emails/phones for Tier A accounts only. Any licensed contact-data provider works (ZoomInfo, etc.).
- Extra monthly cost: $0 — $0 extra if you already pay for Claude or ChatGPT with web search and already have a contact-data source. Usage limits on research features vary by plan, so heavy months may hit caps. Contact data is NOT included: if Clay was also your email-finding tool, budget for a contact-data provider separately.
- Difficulty: moderate; skill: basic; setup: 2–3 hours (rubric, prompt tuning on 2 test batches, sheet setup)
- Evidence: editorial; illustrative example: true; last reviewed 2026-10-13
- Canonical: https://onelesstool.com/workflows/prospect-research-with-ai-assistant
## Good fit for
- Founders, SDRs and small sales teams researching tens to a few hundred accounts per week
- Account-based outreach where a cited 'why now' matters more than list size
- Teams that used Clay mainly for AI research and scoring columns, not for waterfall contact enrichment
- Anyone who can spend a few hours a week on batched research and spot-checks
## Not a fit for
- Teams that need verified emails, mobile numbers or firmographics at scale — that's a contact-data product, not an AI assistant
- Thousands of accounts per month or fully automated enrichment on a trigger — manual batching doesn't scale; consider an API pipeline or keep Clay
- Workflows that depend on scraping LinkedIn or other sites whose terms forbid automated collection
- Anyone not willing to spot-check sources — unchecked AI research will contain fabricated or misattributed facts
## Before
A Clay workbook imports a company list, runs enrichment and AI research columns per row (company summary, recent news, hiring signals, a scoring formula, an AI-written first line) and pushes results to a CRM or sequencer. It's fast and automated but billed in credits/actions, and the bill grows with every column and re-run.
## After
A Google Sheet holds the master list. Each working session you paste 10–25 new, de-duplicated companies into a saved research prompt in Claude or ChatGPT with web search on. The assistant returns strict JSON (one object per company, every claim with a source URL), which you paste into the sheet. Formulas flag duplicates and score totals; you open the sources for 10% of rows (and every Tier A) before trusting the batch. Only Tier A accounts go to Apollo/ZoomInfo for verified contacts.
## Steps
### 1. Write your rubric before you research anything
Copy the **Qualification rubric** artifact and replace the bracketed descriptions with your real ICP: core industries, employee sweet spot, the signals that actually predicted past wins.
Test it on **10 past customers and 10 lost deals**. If the rubric doesn't rank most past customers above the losses, fix the rubric now — no prompt will rescue a vague ICP.
Keep `reachability` partly human: warm paths come from *your* CRM and network, not from the AI.
### 2. Set up the master sheet
Create a Google Sheet with tabs **Input**, **Accounts**, **Manual**, **QA**.
- **Input:** `Company name | Domain | Normalised domain | Already researched?` with the formulas from the *De-duplication and QA* artifact.
- **Accounts:** one column per field in the JSON schema, plus `Batch ID`, `Researched on`, `QA result`, `Owner`, `Status`.
- Use **Data → Data validation** dropdowns for `tier` and `Status` (`New / Checked / Contacted / Disqualified`).
To paste JSON into columns, ask the assistant to also output the batch as **TSV** in a second code block (the batch prompt below does this), then paste into the first empty row of Accounts.
### 3. Run research in batches of 10–25
In Claude (turn on **web search**, or use **Research** on Pro/Max/Team/Enterprise) or ChatGPT (web search or **deep research**), paste the **Batch account research** prompt with 10–25 companies.
Why small batches:
- Quality drops and the model starts skipping or merging companies in long lists.
- Research modes consume plan limits faster; Anthropic notes Research uses the same limits as normal chats but can use them up faster.
- A bad batch of 20 is cheap to re-run; a bad batch of 200 isn't.
**Throughput reality:** 500 accounts ≈ 25 batches of 20. At 15–30 minutes per batch including QA, budget **8–20 hours a month**. Save the prompt in a Claude Project or ChatGPT Project/custom GPT so every batch uses identical instructions.
### 4. Validate structure, de-duplicate, then spot-check sources
Follow the *De-duplication and QA* artifact for every batch:
1. **Structure:** row count in = out; `fit_total` = sum of scores; every row has ≥1 source; no emails/phones.
2. **Identity:** if `resolved_domain` ≠ input domain, the model may have researched a namesake — move to **Manual**.
3. **Spot-check 10%** (minimum 3 rows, plus *every* Tier A): open each source URL and confirm the claim is on the page and the date matches. Log PASS/FAIL in **QA**.
4. If more than 1 in 10 fails, re-run the batch through the **Verify claims** prompt or redo it — don't fix rows by hand and trust the rest.
The rule *“no URL, no claim”* is what makes this usable: an uncited signal is capped at 1 point by the rubric.
### 5. Get contact data the compliant way — only for Tier A
An AI assistant **does not provide verified contact data**. Emails it 'finds' are often guessed patterns. For Tier A accounts only:
- Look up the buyer in **Apollo, ZoomInfo or another licensed provider**, or use contact details the company publishes for business enquiries.
- **Do not scrape LinkedIn.** LinkedIn's User Agreement (section 8.2) prohibits scraping or copying profiles and using bots or unauthorised automated methods. Read profiles manually if you must; don't automate it.
- **GDPR (EU/UK contacts):** document your lawful basis (usually legitimate interests) and give the Article 14 notice — who you are, why you have their data, where it came from, their rights — **at first contact** at the latest.
- **CAN-SPAM (US):** applies to B2B email too. Accurate headers and subject, a postal address, a clear opt-out honoured within 10 business days. Other countries (e.g. Canada's CASL) can be stricter — check where your recipients are.
### 6. Write openers from cited signals and close the loop
Use the **Personalisation from cited signals** prompt on Tier A rows only. It must quote the signal and URL it used, so you can check it in seconds.
After a month, compare reply and meeting rates by tier. If Tier B converts like Tier A, your rubric is too strict; if Tier A doesn't convert, re-weight `need_signal` and `timing`. Then decide what to cancel: if you only used Clay's research columns, downgrade it; if you also relied on its contact waterfall, keep or replace that part with a contact-data subscription.
## Prompts
### Batch account research (strict JSON)
Research 10–25 companies with citations and score them against your rubric.
```text
You are a B2B research analyst. Use web search. Research each company below for a seller of {{our_offer}} whose ideal customer is: {{icp_description}}.
Companies (name, domain):
{{company_list}}
Scoring rubric (score each 0–3):
{{rubric}}
Rules:
1. Every factual claim must come from a page you actually opened. Put its URL in source_url / sources. If you cannot find a source, write "unknown" and add the gap to `unknowns`. Never guess employee counts, funding or dates.
2. Prefer the company's own site, press releases, job boards and reputable news from the last 12 months. Today is {{today}}; ignore signals older than 18 months.
3. If a name is ambiguous, research the company at the given domain; set match_confidence accordingly. If you can't confirm it's the same company, use "low" or "not_found" and don't score it.
4. Do NOT output personal email addresses, phone numbers or home locations. Do not use LinkedIn content obtained by scraping.
5. reachability: score only 2 (buyer role publicly identifiable) or 1 (unclear); I'll add warm paths myself.
6. fit_total must equal the sum of fit_scores. Tier: A 11–15 with need_signal ≥2; B 7–10; C 3–6; otherwise disqualified with a reason.
Output exactly two code blocks and nothing else:
(a) a JSON array that validates against this schema:
{{json_schema}}
(b) the same rows as TSV with a header row, columns in schema order, signals flattened as "type: claim (date) URL" joined by " | ".
Return one object per input company, in input order, even if not found.
```
### Verify claims (second pass)
Have the assistant re-check a batch whose spot-check failed, claim by claim.
```text
Act as a fact-checker. For each row in the JSON below, open every source_url and check whether the page explicitly supports the claim, for the right company and date.
{{batch_json}}
Return a table with columns: input_name | claim | source_url | verdict (SUPPORTED / NOT FOUND ON PAGE / WRONG COMPANY / WRONG DATE / PAGE UNAVAILABLE) | corrected claim with new URL, or "remove".
Then return the corrected JSON array with unsupported claims removed, fit_scores lowered where a removed claim was the basis (cap uncited criteria at 1), fit_total and tier recomputed. Do not add new claims without a URL.
```
### Personalisation from cited signals
Draft a first line for Tier A accounts that a human can verify in seconds.
```text
Write a first line for a cold email from {{sender_name}} at {{our_company}} to the {{buyer_role}} at {{company_name}}.
Use ONLY these cited signals:
{{signals_with_urls}}
Our relevant proof point: {{proof_point}}
Rules: max 30 words; reference exactly one signal factually (no flattery, no 'I noticed', no invented details); no claims about the person. Give 3 options, and under each write the signal and URL it relies on.
```
## Templates and scripts
### JSON output schema for a research batch (schema)
```json
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "AccountResearchBatch",
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": ["input_name", "input_domain", "resolved_domain", "match_confidence",
"what_they_do", "industry", "hq_country", "employee_range",
"signals", "fit_scores", "fit_total", "tier", "personalization_hook",
"unknowns", "sources"],
"properties": {
"input_name": { "type": "string", "description": "Exactly as given in the input list" },
"input_domain": { "type": "string" },
"resolved_domain": { "type": "string", "description": "Domain of the company actually researched. Empty if not found." },
"match_confidence": { "enum": ["high", "medium", "low", "not_found"] },
"what_they_do": { "type": "string", "maxLength": 300, "description": "One or two plain sentences" },
"industry": { "type": "string" },
"hq_country": { "type": "string", "description": "ISO country name or 'unknown'" },
"employee_range": { "enum": ["1-10", "11-50", "51-200", "201-500", "501-1000", "1001-5000", "5000+", "unknown"] },
"signals": {
"type": "array", "maxItems": 5,
"items": {
"type": "object", "additionalProperties": false,
"required": ["type", "claim", "date", "source_url"],
"properties": {
"type": { "enum": ["hiring", "funding", "leadership_change", "product_launch", "expansion", "tech_stack", "partnership", "other"] },
"claim": { "type": "string", "maxLength": 200 },
"date": { "type": "string", "description": "YYYY-MM or YYYY-MM-DD; 'unknown' if not stated" },
"source_url": { "type": "string", "format": "uri" }
}
}
},
"fit_scores": {
"type": "object", "additionalProperties": false,
"required": ["icp_industry", "size", "need_signal", "timing", "reachability"],
"properties": {
"icp_industry": { "type": "integer", "minimum": 0, "maximum": 3 },
"size": { "type": "integer", "minimum": 0, "maximum": 3 },
"need_signal": { "type": "integer", "minimum": 0, "maximum": 3 },
"timing": { "type": "integer", "minimum": 0, "maximum": 3 },
"reachability": { "type": "integer", "minimum": 0, "maximum": 3 }
}
},
"fit_total": { "type": "integer", "minimum": 0, "maximum": 15 },
"tier": { "enum": ["A", "B", "C", "disqualified"] },
"disqualify_reason": { "type": "string" },
"personalization_hook": { "type": "string", "maxLength": 240, "description": "Must reference one of the cited signals" },
"unknowns": { "type": "array", "items": { "type": "string" } },
"sources": { "type": "array", "minItems": 1, "items": { "type": "string", "format": "uri" } }
}
}
}
NOTE: this schema intentionally has NO fields for personal email addresses or phone numbers.
Verified contact data comes from a contact-data provider, not from an AI assistant.
```
### Qualification rubric (0–15) (template)
```
QUALIFICATION RUBRIC — edit the descriptions to match YOUR ideal customer profile (ICP).
Score each criterion 0–3. Total 0–15. The AI proposes scores; a human confirms Tier A.
1. icp_industry
3 = core target industry ([your core industries])
2 = adjacent industry we have won before
1 = plausible but no references
0 = outside our market → disqualified
2. size (employees, from the company's own site or a cited source)
3 = inside our sweet spot (e.g. 51–500)
2 = just outside (e.g. 20–50 or 501–1,000)
1 = far outside but has a relevant division
0 = unknown after research (do NOT guess)
3. need_signal (evidence they have the problem we solve)
3 = explicit, dated, cited signal in the last 6 months (job post for the role we replace, public complaint, initiative announced)
2 = indirect signal (growth, new market, tech stack that implies the need)
1 = generic fit only
0 = signal suggests they've already solved it (e.g. announced a competitor)
4. timing
3 = trigger event in the last 90 days (funding, new leader in the buyer role, expansion)
2 = trigger event 3–12 months ago
1 = none found
0 = known freeze (layoffs, acquisition pending) — note it
5. reachability
3 = we have a warm path (customer, investor, partner in common) — fill from YOUR records, not the AI
2 = clear buyer role exists and is publicly identifiable
1 = buyer role unclear
0 = no way in found
TIERS
A = 11–15 and need_signal ≥ 2 → human review, then contact-data lookup, then personal outreach
B = 7–10 → nurture list / lighter-touch sequence
C = 3–6 → park; re-check in 6 months
disqualified = icp_industry 0, or a hard exclusion (existing customer, competitor, sanctioned country, under legal minimum size)
RULE: any score based on a claim without a source URL is capped at 1.
```
### De-duplication and QA checklist with Sheets formulas (checklist)
```
DE-DUPLICATION AND QA — run on every batch before it enters the master sheet
A. De-duplicate (Google Sheets, master tab "Accounts")
1. Normalise the domain in a helper column (assume raw domain/URL in column B):
=LOWER(REGEXREPLACE(REGEXREPLACE(TRIM(B2),"^(https?://)?(www\.)?",""),"[/?#].*$",""))
2. Flag duplicates against everything already researched:
=IF(COUNTIF($C$2:$C, C2)>1, "DUPLICATE", "")
3. Before each run, remove input rows whose normalised domain already exists in Accounts
(=ISNUMBER(MATCH(C2, Accounts!C:C, 0)) on the input tab). This avoids paying for the same research twice.
4. Also check resolved_domain vs input_domain: if they differ, the AI may have researched a
different company with a similar name → set status "CHECK MATCH".
B. Structural checks (instant, every row)
[ ] JSON parsed without edits (if not, re-run the batch; do not hand-fix silently)
[ ] Row count out = row count in
[ ] fit_total equals the sum of fit_scores
[ ] Every signal has a source_url; every row has ≥1 source
[ ] No email addresses or phone numbers anywhere in the output (search for "@" and digit runs) — delete if present
[ ] match_confidence "low"/"not_found" rows are moved to a Manual tab, not scored
C. Hallucination spot-check (10% of rows, minimum 3 per batch, ALWAYS include every Tier A)
For each sampled row, open every source URL and confirm:
[ ] The page loads and is about this company (not a namesake)
[ ] The claim is actually stated on the page (not inferred)
[ ] The date matches
Record result in a "QA" column: PASS / FAIL + note.
If >1 of 10 sampled rows FAIL → re-run the whole batch with the verification prompt; don't trust the rest.
D. Compliance gate before any outreach
[ ] Contact details came from a licensed provider or the person's own published business contact page — not scraped from LinkedIn
[ ] EU/UK contacts: lawful basis (usually legitimate interests) documented; GDPR Art. 14 notice given at first contact
[ ] US commercial email: CAN-SPAM basics in the template (accurate From/subject, postal address, working opt-out honoured within 10 business days)
[ ] Suppression list (unsubscribes, existing customers, competitors) applied
```
## Limitations
- No verified contact data: AI assistants don't maintain a B2B contact database. Emails they produce are often guessed patterns; use a licensed contact-data provider.
- Manual batching: 10–25 companies per run. 500 accounts a month is 25–50 runs and roughly 8–20 hours of human time, versus near-zero in an automated Clay table.
- Research quality depends on what's public. Private companies, small firms and non-English markets return many 'unknown' fields.
- AI research makes mistakes: namesake companies, outdated news presented as current and claims not actually on the cited page. The 10% spot-check reduces but doesn't eliminate this.
- Research features have plan-based usage limits that can change; a heavy month can hit them.
- No native CRM/sequencer push — results move by copy/paste or CSV import.
## Risks
- **reliability** (high): Hallucinated or misattributed facts can end up in outreach and damage credibility. Mitigation: no URL, no claim; spot-check 10% plus every Tier A; re-run failing batches.
- **compliance** (high): Outreach to people still triggers GDPR (EU/UK: lawful basis, Article 14 notice by first contact) and CAN-SPAM (US: applies to B2B; FTC lists penalties of up to $53,088 per violating email). Using the AI doesn't change who is the data controller — you are.
- **compliance** (medium): Scraping LinkedIn (directly or by asking an agent to) breaches LinkedIn's User Agreement section 8.2 and can get accounts restricted. Keep research to public web pages and licensed data.
- **sensitive_data** (low): Company lists and ICP notes are commercially sensitive. Use a business/team plan or check your consumer plan's training settings before pasting customer or pipeline data.
- **functionality_loss** (medium): You lose Clay's automation: scheduled refreshes, enrichment waterfalls across providers and pushes to CRM/sequencers.
## Verification checklist (run before cancelling)
- [ ] The rubric ranks at least 7 of 10 known past customers above at least 7 of 10 known lost/unfit deals in a back-test.
- [ ] Two full test batches (≥40 companies) came back as valid JSON with one row per input, in order, with no emails or phone numbers.
- [ ] Spot-check of those batches: at least 90% of sampled claims are SUPPORTED when you open the source URL; every Tier A row passed a full source check.
- [ ] Side-by-side on 25 accounts: the AI's tiering agrees with your existing Clay scoring (or a human's judgement) on at least 20.
- [ ] The de-dup formula catches a deliberately re-pasted batch (all rows flagged DUPLICATE) and normalises 'https://www.example.com/about' to 'example.com'.
- [ ] Contact data for Tier A accounts is coming from a licensed provider or published business contacts, and your outreach template includes the CAN-SPAM elements and (for EU/UK) an Article 14 notice.
- [ ] You timed a real month's workload (or a week × 4) and the hours are acceptable versus what you pay for Clay.
## Savings methodology
Savings = Clay subscription you can drop or downgrade − any extra spend (normally $0 if you already pay for Claude/ChatGPT with web search). Contact-data costs are excluded on both sides: if Clay was also your email finder, you need a contact-data subscription either way, so subtract that from the savings. Labour is the hidden cost: at 15–30 minutes per 10–25 companies, 500 accounts is roughly 8–20 hours a month — price your time before deciding.
Example (illustrative): A two-person outbound team that used a Clay Launch plan mainly for research and scoring columns on ~500 accounts a month. $167/mo → $0/mo. Assumptions: ILLUSTRATIVE: Clay's pricing page on 2026-10-13 showed $167/month as the Launch headline price but also lower 'starts at' prices and different figures in its FAQ, so we treat $167 as an example, not a verified price. Use your own invoice. They already pay for Claude or ChatGPT with web search; no new subscription. Contact data comes from an Apollo/ZoomInfo seat they already have; that cost is unchanged and excluded. 8–20 hours a month of research and QA time is not converted to dollars.
## Sources
- Clay pricing: https://www.clay.com/pricing (accessed 2026-10-13)
- Using Research on Claude: https://support.claude.com/en/articles/11088861-using-research-on-claude (accessed 2026-10-13)
- LinkedIn User Agreement: https://www.linkedin.com/legal/user-agreement (accessed 2026-10-13)
- FTC CAN-SPAM Act compliance guide: https://www.ftc.gov/business-guidance/resources/can-spam-act-compliance-guide-business (accessed 2026-10-13)
- GDPR Article 14: https://gdpr-info.eu/art-14-gdpr/ (accessed 2026-10-13)
- ChatGPT deep research FAQ: https://help.openai.com/en/articles/10500283-deep-research-faq (accessed 2026-10-13)
# Design a print-ready restaurant menu with AI instead of Canva
> Keep your menu as a simple list, have Claude or ChatGPT turn it into a clean, printable HTML menu (Letter or A4), and save it as a PDF from your browser. Includes a Google Docs route for owners who don't want to touch code, plus the allergen and print-shop caveats that matter.
- Outcome: I want a good-looking, up-to-date menu I can print in-house or send to a print shop, without paying for Canva Pro.
- Replaces: Canva (task_specific)
- Uses: Claude — Clean up the menu list, write short dish descriptions and fill the HTML menu template; it can show the result as a live preview.; ChatGPT (optional) — Alternative to Claude for the same prompts.; Google Workspace (optional) — No-code route: a Google Docs menu template exported to PDF; Google Sheets as the master price list.
- Extra monthly cost: $0 — Uses an AI assistant you already have (free tiers work for occasional menu updates), a web browser's built-in Save as PDF, and optionally Google Docs. Printing costs are the same as before.
- Difficulty: easy; skill: basic; setup: 1–2 hours for the first menu
- Evidence: editorial; illustrative example: true; last reviewed 2026-10-13
- Canonical: https://onelesstool.com/workflows/restaurant-menus-with-ai
## Good fit for
- Independent restaurants, cafés and food trucks that pay for Canva Pro mostly to update menus
- Menus that change often (seasonal dishes, price updates) where retyping in a design tool is the main cost
- Owners who want one master list of dishes, prices and allergens that every menu is generated from
## Not a fit for
- Menus with heavy illustration, photo collages or custom die-cut shapes
- Large-run professional print jobs that need CMYK files, bleed and crop marks (use a designer or the print shop's own template)
- Businesses that also use Canva Pro for social posts, signage and video — cancelling Canva would remove those too
- Anyone not willing to proofread every price and allergen marker personally before printing
## Before
Open the menu design in Canva Pro, find each changed dish, retype prices and descriptions in separate text boxes, nudge alignment, re-export a PDF for the printer and a PNG for the website, and repeat for the A4 and Letter versions or the takeaway menu.
## After
Update one master list (a Google Sheet or a text note) of dishes, prices and dietary tags. Paste it into Claude with the fill prompt and the HTML template; open the result in Chrome, check it on screen, and Print > Save as PDF. Non-technical owners do the same in a Google Docs template and download a PDF.
## Steps
### 1. Make one master list of dishes, prices and dietary tags
Put every menu item in a single list — a Google Sheet works well — with columns: **section, dish name, description, price, dietary tags (V, VG, GF, N…), allergens confirmed by kitchen (yes/no), last checked date**.
This list is the source of truth. The design is regenerated from it, so prices never drift between the printed menu, the website and delivery apps.
**Allergen and dietary information is your legal responsibility, not the AI's.** Fill the allergen columns from recipes and supplier specs with your head chef. Labelling rules differ by country and city; check what your local food authority requires.
### 2. Clean up names and write short descriptions
Paste the list into Claude or ChatGPT with the **Menu clean-up prompt**. It standardises capitalisation, trims descriptions to one line and flags inconsistencies (duplicate dishes, prices without decimals in one section but not another).
Tell it **not** to add or remove ingredients. Review its suggested descriptions against the recipe: a model may make up a garnish that changes an allergen.
### 3. Generate the printable HTML menu
Use the **Fill the menu template prompt** with the template below. Choose `letter` (US) or `A4` in the `@page` line.
Ask Claude to show it as a preview (an artifact) or save the HTML to a file and open it in Chrome. On screen, the page shows a white sheet with the printable margins so you can see whether everything fits on one page.
If something overflows: ask the AI to shorten descriptions, reduce the base `font-size` from `10.5pt` to `10pt`, or move a section to a second page block.
### 4. Save as PDF and print a test copy
In Chrome: **Print > Destination: Save as PDF > Margins: Default > More settings: tick "Background graphics" > Save.**
Print one copy on your normal printer at **100% / Actual size** (not "Fit to page"). Check prices, spelling and the dietary legend on paper, where errors are easier to spot.
**Print-shop caveat:** browser PDFs are RGB, with no **bleed** or **crop marks**. Designs with colour running to the paper edge will show a thin white line after trimming. Either keep a white margin (the template does), or ask the print shop whether they can add bleed or work from your PDF.
### 5. No-code route: Google Docs menu
If you'd rather not handle HTML:
1. In Google Docs, **File > Page setup** and choose Letter or A4 with 0.5 in margins.
2. Ask the AI for the **Google Docs menu layout prompt** output, then right-click > **Paste from Markdown** (turn on Markdown in Tools > Preferences first) or paste plain text.
3. Use a 2-column table with hidden borders for "dish — price" alignment, a heading style per section, and one accent colour.
4. **File > Download > PDF.**
It looks plainer than the HTML version, but anyone on staff can update it.
### 6. Run the final proof pass and publish
Run the **Proofreading and allergen cross-check prompt** with your master list and the final menu text. It returns a mismatch table (price differs, tag missing, dish missing).
The AI can only compare the two lists. It cannot know whether a dish actually contains nuts. Fix every mismatch at the source list, regenerate, and keep the PDF with a date in the filename (e.g. `menu-2026-10-13.pdf`) so you know which version is on the tables.
## Prompts
### Menu clean-up prompt
Standardise the master list and write short descriptions without inventing ingredients.
```text
Here is the menu for {{restaurant_name}}, a {{cuisine_style}} restaurant. Each line is: section | dish | ingredients or notes | price | dietary tags.
{{raw_menu_list}}
Tasks:
1. Standardise dish names to Title Case and keep them under 5 words where possible.
2. Write a description of at most {{max_description_words}} words per dish using ONLY the ingredients I listed. Do not add garnishes, sauces or ingredients.
3. Format prices as {{price_format}} (e.g. "14" or "14.00"), consistently.
4. Keep my dietary tags exactly as given. Do not add or remove tags.
5. After the cleaned list, add a "Check these" list: duplicates, missing prices, dishes with no tags where the name suggests meat/dairy/nuts, and anything ambiguous.
Return the cleaned list in the same pipe-separated format.
```
### Fill the menu template prompt
Turn the cleaned list into a complete printable HTML menu using the template.
```text
Below is an HTML menu template and my cleaned menu list. Produce one complete HTML file:
- Keep the template's CSS and structure. Replace the sample sections and items with mine, in my section order.
- Restaurant name: {{restaurant_name}}. Menu title: {{menu_title}}. Service times: {{service_times}}.
- Paper size: {{paper_size}} (set the @page line accordingly and remove the other).
- Accent colour: {{accent_color}}.
- Footer allergen statement: "{{allergen_statement}}". Contact line: "{{address_phone_website}}".
- Only include dietary tags that appear in my list, and make the legend match the tags used.
- It must fit on {{page_count}} page(s). If it won't, tell me which descriptions to shorten rather than shrinking text below 9pt.
Template:
{{html_template}}
Menu list:
{{clean_menu_list}}
```
### Google Docs menu layout prompt
Produce Markdown that pastes cleanly into Google Docs for the no-code route.
```text
Format this menu for Google Docs. Output Markdown only:
- "# {{restaurant_name}}" then one italic line: "{{menu_title}} · {{service_times}}".
- "## Section" headings.
- For each dish, a two-column Markdown table row: "**Dish name** (tags) – description" | "price".
- A final line with the dietary legend and this statement: "{{allergen_statement}}".
Menu list:
{{clean_menu_list}}
```
### Proofreading and allergen cross-check prompt
Catch mismatches between the master list and the final menu before printing.
```text
Compare the MASTER LIST with the FINAL MENU TEXT. Report every difference in a table with columns: dish | field (name, price, tags, description, missing) | master value | menu value.
Also list spelling mistakes and inconsistent price formats. Do not judge whether tags are correct for the ingredients; only compare the two texts.
MASTER LIST:
{{master_list}}
FINAL MENU TEXT:
{{final_menu_text}}
```
## Templates and scripts
### Printable HTML menu template (Letter or A4, two columns, text dietary markers) (template)
```html
{{restaurant_name}} – Menu
Served with house salad. Ask about today's market fish.
Roast Half Chicken GF24
Salsa verde, crushed potatoes, charred lemon
Wild Mushroom Risotto V · GF21
Aged parmesan, thyme, brown butter
Steak Frites32
8 oz bavette, peppercorn sauce, fries
Sides
Fries VG6
Greens, Garlic & Chilli VG · GF7
Desserts
Olive Oil Cake V9
Citrus, crème fraîche
Dark Chocolate Pot V · GF10
Sea salt, hazelnut praline N
```
## Limitations
- Browser PDFs are RGB with no bleed or crop marks; full-bleed colour and professional offset printing need a designer or the print shop's help.
- Less visual freedom than a drag-and-drop editor: photos, illustrations and unusual layouts need more prompting or CSS knowledge.
- Fonts are limited to what is installed on your computer unless you add web fonts yourself.
- The AI can rewrite or invent ingredients in descriptions; every description has to be checked against the recipe.
- The Google Docs route looks plainer and has limited layout control.
## Risks
- **compliance** (high): Wrong allergen or dietary markers can harm guests and breach food labelling rules. Tags must come from the kitchen's recipes and be checked by a person; never let the AI assign them.
- **reliability** (medium): Price typos on a printed menu can be costly. Always run the cross-check prompt and a paper proof.
- **functionality_loss** (low): Cancelling Canva Pro also removes Pro features you may use for signage or social posts.
- **data_portability** (low): Existing Canva menu designs can't be edited outside Canva; download final PDFs and image assets before cancelling.
## Verification checklist (run before cancelling)
- [ ] Your current menu, rebuilt with the template, fits on the intended number of pages at 100% scale with text no smaller than 9pt.
- [ ] A paper test print at Actual size has correct margins, no clipped text and readable prices from arm's length.
- [ ] The cross-check prompt reports zero mismatches between the master list and the final menu.
- [ ] Your head chef or kitchen lead has signed off every dietary tag and the allergen statement.
- [ ] If you use a print shop, they have confirmed they can print your browser PDF (or told you what they need for bleed).
- [ ] A price change takes you under 20 minutes from editing the master list to a new PDF.
- [ ] Any Canva menu files and images you still need are downloaded before cancelling.
## Savings methodology
Savings = your current Canva Pro cost attributable to menus − incremental cost of this workflow ($0 when using an AI assistant and Google Docs you already have). If menus are the only reason you pay for Canva Pro, the full subscription is saved; otherwise the saving is $0 until your other Canva uses are covered. Printing costs, setup time and staff time are not monetised.
Example (illustrative): A café owner pays for Canva Pro monthly and uses it only to update a one-page menu every few weeks; they already have a free Claude account and a Google account. $15/mo → $0/mo. Assumptions: Illustrative: $15/month is a round placeholder for a Canva Pro subscription. canva.com blocked automated access on 2026-10-13, so the current price was not verified. Menus are the only reason the café pays for Canva Pro. Free tiers of Claude or ChatGPT are enough for a few menu updates a month.
## Sources
- Google Docs Help: Use Markdown in Docs: https://support.google.com/docs/answer/12014036 (accessed 2026-10-13)
- Canva pricing: https://www.canva.com/pricing/ (accessed 2026-10-13)
# Run a small-business CRM in Google Sheets with AI-written Apps Script
> For a 1–5 person services business: a structured Google Sheet plus a short Apps Script (written and debugged with Claude or ChatGPT) gives you a pipeline, follow-up reminders and a daily email digest without a paid CRM seat. Try HubSpot's free CRM first if you don't want to maintain anything.
- Outcome: Track leads and deals, never miss a follow-up, and see the pipeline at a glance — without paying per seat for a CRM.
- Replaces: Pipedrive (full), HubSpot Sales Hub (full), Salesforce Sales Cloud (partial)
- Uses: Google Workspace — Google Sheets holds the data; Apps Script adds the timestamps, follow-up view and digest; MailApp sends the email. A free Gmail account also works, with lower email quotas.; Claude (optional) — Writes, adapts and debugs the Apps Script and formulas for your exact columns.; ChatGPT (optional) — Alternative to Claude for writing and debugging the script.
- Extra monthly cost: $0 — Google Sheets and Apps Script are included with Google Workspace and with free Google accounts. Using an AI assistant you already pay for adds nothing. The real cost is your time: about half a day to set up and ~15 minutes a month of upkeep.
- Difficulty: moderate; skill: basic; setup: 3–5 hours (sheet design, script install, one week of parallel use)
- Evidence: editorial; illustrative example: true; last reviewed 2026-10-13
- Canonical: https://onelesstool.com/workflows/small-business-crm-in-google-sheets
## Good fit for
- Agencies, consultants, studios, trades and other services firms with 1–5 people selling
- Fewer than a few thousand open contacts and a few dozen open deals at a time
- Teams already living in Google Workspace who want follow-up discipline more than automation
- Founders who outgrew a to-do list but find a CRM's per-seat price hard to justify
## Not a fit for
- More than ~5 people selling at once — concurrent edits, ownership rules and permissions get messy in a shared sheet
- Teams that rely on automatic email/calendar sync, open/click tracking or sales sequences — a sheet has none of these
- Anyone who needs forecasting, weighted pipeline by rep, quotas or multi-currency reporting out of the box
- Regulated businesses that need a tamper-evident audit trail, field-level permissions or data-retention controls (a sheet's version history is not a compliance audit log)
- People who will not maintain a script — if nobody owns it, start with HubSpot's free CRM instead
## Before
Each person pays for a CRM seat (HubSpot Starter, Pipedrive or a light Salesforce edition). Deals live in a pipeline board; the CRM reminds you of follow-ups and logs email automatically. In practice a small team uses maybe 20% of it: a list of deals, a stage, a next step and a reminder.
## After
One shared Google Sheet with Deals, Companies, Activities and Lists tabs, dropdown validation for stages and owners, and a 150-line Apps Script. Changing a deal's stage stamps the time and writes to a Stage log. Overdue rows turn red, due-today rows amber, a 'Follow-ups due' tab lists everything that needs action, and every morning each owner gets an email of their overdue follow-ups. An AI assistant writes any changes to the script or formulas when you need them.
## Steps
### 1. Decide whether you should build this at all
Before building, check two cheaper options:
- **HubSpot's free CRM** is free with no expiry and covers **up to 2 users and 1,000 contacts** (per HubSpot's product page), including deal pipelines and email tracking. If you're two people with under 1,000 contacts, it's the no-maintenance choice.
- **Your current CRM's export.** Export deals and contacts to CSV now (every major CRM supports it). You need this file either way.
Build the sheet if you're 3–5 people, you've hit the free tier's limits, or you want something you fully control.
### 2. Create the sheet structure
Create a new Google Sheet called **CRM** and add the tabs from the *Sheet schema* artifact: **Deals**, **Companies**, **Activities**, **Lists**.
1. Type the Deals headers **exactly** as listed (the script finds columns by header name, so order doesn't matter but spelling does).
2. Fill **Lists** with your stages, lead sources and team emails. Keep `Won` and `Lost` spelled exactly.
3. Add data validation (**Data → Data validation**):
- `Deals!F2:F` → *Dropdown (from a range)* `Lists!A2:A`, *Reject the input*
- `Deals!E2:E` → dropdown from `Lists!C2:C`
- `Deals!I2:I` → *Is valid date*
- `Deals!D2:D` → *Text is valid email*
4. **View → Freeze → 1 row** on every tab, and turn on a filter (**Data → Create a filter**) on Deals.
### 3. Import your existing data
Open your CRM export in a separate tab, then map it into Deals:
- Paste each column under the matching header. Use `=PROPER(TRIM(B2))` style helpers to clean names, then *Paste special → Values only*.
- Make sure **Stage** values match the Lists tab exactly. Find mismatches with `=FILTER(F2:F, ISNA(MATCH(F2:F, Lists!A2:A, 0)), F2:F<>"")`.
- Convert follow-up dates to real dates (they should right-align). If they're text, use `=DATEVALUE()` or ask your AI assistant for a formula that handles your export's format.
- Leave **Stage changed at** and **Created at** blank — the script fills them from now on. If you want history, paste the old CRM's stage-change dates there once.
Keep the raw export in a hidden tab called `_import` for 90 days in case you need to check something.
### 4. Install the Apps Script
1. **Extensions → Apps Script**, delete the placeholder, paste the *Apps Script* artifact, and **Save**.
2. **Project Settings** (gear icon) → set the **time zone** to yours. The digest runs at `DIGEST_HOUR` in that zone.
3. Reload the spreadsheet. A **CRM** menu appears.
4. Run **CRM → Set up (run once)** and approve the permissions Google asks for (Sheets, sending email as you, running triggers).
5. Test: change a deal's Stage. Within a second or two **Stage changed at** fills in and a row appears in **Stage log**.
6. Run **CRM → Send follow-up digest now** with one overdue test deal assigned to yourself.
Why two kinds of trigger: `onEdit` is a *simple trigger*, so it runs without authorisation but **cannot send email**, is limited to 30 seconds and **does not fire for edits made by scripts or the API**. The digest uses an *installable* time-driven trigger, which can send mail.
### 5. Adapt it with an AI assistant instead of hand-coding
When you want a change (an extra column, a weekly pipeline summary, a different stage list), paste the whole script plus your header row into Claude or ChatGPT with the **Modify the CRM script** prompt. Rules that keep this safe:
- Always give the assistant your **exact header row** — most bugs are mismatched column names.
- Ask for the **complete file** back, not a fragment, and keep the previous version — the simplest habit is pasting the old script into a dated Google Doc before replacing it.
- Test on a **copy** of the spreadsheet (**File → Make a copy** copies the script too) before changing the live one.
- If you get an error, paste the exact message from **Executions** (left sidebar in the Apps Script editor) using the **Debug an Apps Script error** prompt.
### 6. Run both systems in parallel for one week, then cancel
Keep the old CRM read-only for a week while the team works only in the sheet. Every day, check the digest against what the old CRM would have reminded you about. When the verification checklist passes, export a final full backup from the old CRM, store it in Drive, then downgrade or cancel. Put a monthly 10-minute calendar reminder to archive Won/Lost deals older than 12 months to an `Archive` tab so the sheet stays fast.
## Prompts
### Modify the CRM script
Safely change the Apps Script for a new column, rule or report.
```text
You are an experienced Google Apps Script developer. Below is my CRM spreadsheet's current Apps Script and the exact header row of my {{sheet_name}} tab.
Header row (tab-separated, exact spelling):
{{header_row}}
Current script:
```javascript
{{current_script}}
```
Change request: {{change_request}}
Rules:
- Return the COMPLETE updated script in one code block, not a diff.
- Find columns by header name, never by hard-coded column number.
- Keep onEdit as a simple trigger: no MailApp, GmailApp or other services that need authorisation inside it.
- Stay within Apps Script quotas (6 minutes per execution; MailApp recipient limits) and read/write ranges in bulk where possible.
- After the code, list: (1) what changed, (2) any new permission Google will ask for, (3) a 3-step manual test I can run on a copy of the sheet.
```
### Debug an Apps Script error
Turn an error from the Executions log into a fix.
```text
My Google Apps Script for a Sheets CRM fails. Explain the cause in plain English, then give the corrected function(s).
Function that failed: {{function_name}}
Trigger type: {{trigger_type}}
Exact error message and line from Executions:
{{error_message}}
Header row of the tab it reads:
{{header_row}}
Relevant code:
```javascript
{{code_snippet}}
```
If the cause is a permissions, quota or simple-trigger restriction rather than a code bug, say so and tell me what to change in the setup instead.
```
### Weekly pipeline review from a CSV export
Get a short pipeline review without a CRM reporting module.
```text
Here is this week's export of my Deals tab as CSV (columns include Stage, Value, Owner, Next follow-up, Stage changed at, Created at):
{{deals_csv}}
Today is {{today}}. Our stages in order are: {{stage_order}}.
Produce:
1. Open pipeline value and deal count by stage (table).
2. Deals with no Next follow-up date, or a follow-up more than 7 days overdue (table: Company, Owner, days overdue).
3. Deals that have sat in the same stage for more than {{stale_days}} days, using Stage changed at.
4. Won and Lost this week, with lost reasons.
5. Three specific actions for the team, each naming a deal.
Use only the data provided. If a value is missing or ambiguous, say so instead of guessing.
```
## Templates and scripts
### Sheet schema (tabs, columns, validation) (schema)
```
SPREADSHEET: "CRM" (one Google Sheets file, shared with the team as Editors)
TAB 1 — Deals (one row per opportunity; row 1 = headers, exact names matter for the script)
| Col | Header | Type / validation |
|-----|-------------------|------------------------------------------------------------------------|
| A | Deal ID | Text. Formula in A2 (optional): =IF(B2="","","D-"&TEXT(ROW()-1,"0000")) |
| B | Company | Text. Data validation: dropdown from a range = Companies!A2:A |
| C | Contact name | Text |
| D | Contact email | Text. Data validation: "Text is valid email" |
| E | Owner | Email of the teammate who owns the deal. Dropdown from Lists!C2:C |
| F | Stage | Dropdown from Lists!A2:A (reject invalid input) |
| G | Value | Number, format Currency. Validation: number >= 0 |
| H | Next step | Text — a verb phrase: "Send revised quote", "Call re: start date" |
| I | Next follow-up | Date. Validation: "is valid date" |
| J | Stage changed at | Date-time. Filled by the script — do not type here |
| K | Created at | Date-time. Filled by the script on first stage selection |
| L | Source | Dropdown from Lists!B2:B |
| M | Lost reason | Text (fill when Stage = Lost) |
| N | Notes | Text — short; long history goes in the Activities tab |
TAB 2 — Companies
| A Company | B Website | C Industry | D City | E Size (employees) | F Notes |
TAB 3 — Activities (append-only log; use a Google Form or type directly)
| A Date | B Deal ID | C Type (Call / Email / Meeting / Note) | D Summary | E Logged by |
Tip: =FILTER(Activities!A:E, Activities!B:B = A2) in a side panel shows a deal's history.
TAB 4 — Lists (single source for dropdowns)
| A Stage | B Source | C Owner |
|------------------|-----------------|----------------------|
| Lead | Referral | you@yourfirm.com |
| Qualified | Website form | colleague@yourfirm.com |
| Proposal sent | Event | |
| Negotiation | Outbound | |
| Won | Existing client | |
| Lost | | |
Keep "Won" and "Lost" spelled exactly like this — the script treats them as closed.
TAB 5 — Follow-ups due (created by the script; formula-driven, do not edit by hand)
TAB 6 — Stage log (created by the script; one row per stage change)
PROTECTION: Data > Protect sheets and ranges → protect "Follow-ups due", "Stage log" and
Deals!J:K with "Show a warning when editing this range" so nobody overwrites them by accident.
```
### Apps Script: stage timestamps, follow-ups view, daily digest (script)
```javascript
/**
* Small-business CRM helpers for Google Sheets.
* Install: Extensions > Apps Script > paste this file > Save.
* Reload the spreadsheet, then run CRM > "Set up (run once)" and approve the permissions.
*
* Adds:
* 1. onEdit timestamp: when Stage changes, writes "Stage changed at" (and "Created at" if blank)
* and appends a row to the "Stage log" tab.
* 2. A "Follow-ups due" tab (live FILTER formula) plus red/amber highlighting on Deals.
* 3. A daily email digest of overdue / due-today follow-ups, one email per Owner, via MailApp.
*/
const CONFIG = {
DEALS_SHEET: 'Deals',
DUE_SHEET: 'Follow-ups due',
LOG_SHEET: 'Stage log',
CLOSED_STAGES: ['Won', 'Lost'],
DIGEST_HOUR: 7, // hour of day in the script time zone (Project Settings)
FALLBACK_EMAIL: '', // gets deals with an empty Owner; blank = the person who ran setup
};
const COL = {
ID: 'Deal ID', COMPANY: 'Company', CONTACT: 'Contact name', EMAIL: 'Contact email',
OWNER: 'Owner', STAGE: 'Stage', VALUE: 'Value', NEXT_STEP: 'Next step',
FOLLOW_UP: 'Next follow-up', STAGE_CHANGED: 'Stage changed at', CREATED: 'Created at',
};
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('CRM')
.addItem('Set up (run once)', 'setup')
.addItem('Rebuild follow-ups view', 'buildFollowUpsView')
.addItem('Send follow-up digest now', 'sendFollowUpDigest')
.addToUi();
}
/** Maps header text -> 1-based column number. Throws if a required header is missing. */
function headerMap_(sheet) {
const headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
const map = {};
headers.forEach(function (h, i) { if (h !== '') map[String(h).trim()] = i + 1; });
Object.keys(COL).forEach(function (k) {
if (!map[COL[k]]) throw new Error('Missing column "' + COL[k] + '" on tab ' + sheet.getName());
});
return map;
}
function colLetter_(n) {
let s = '';
while (n > 0) { const m = (n - 1) % 26; s = String.fromCharCode(65 + m) + s; n = Math.floor((n - 1) / 26); }
return s;
}
/* ---------- 1. Stage-change timestamps (simple trigger) ---------- */
function onEdit(e) {
if (!e || !e.range) return;
const sheet = e.range.getSheet();
if (sheet.getName() !== CONFIG.DEALS_SHEET || e.range.getLastRow() < 2) return;
let cols;
try { cols = headerMap_(sheet); } catch (err) { e.source.toast(err.message, 'CRM script'); return; }
const stageCol = cols[COL.STAGE];
if (stageCol < e.range.getColumn() || stageCol > e.range.getLastColumn()) return;
const now = new Date();
const singleCell = e.range.getNumRows() === 1 && e.range.getNumColumns() === 1;
const editor = (e.user && e.user.getEmail && e.user.getEmail()) || '';
const log = e.source.getSheetByName(CONFIG.LOG_SHEET);
const firstRow = Math.max(2, e.range.getRow());
for (let r = firstRow; r <= e.range.getLastRow(); r++) {
const stage = sheet.getRange(r, stageCol).getValue();
sheet.getRange(r, cols[COL.STAGE_CHANGED]).setValue(now);
const created = sheet.getRange(r, cols[COL.CREATED]);
if (created.getValue() === '') created.setValue(now);
if (log) {
log.appendRow([
now,
sheet.getRange(r, cols[COL.ID]).getValue(),
sheet.getRange(r, cols[COL.COMPANY]).getValue(),
singleCell ? (e.oldValue || '') : '(bulk edit)',
stage,
editor,
]);
}
}
}
/* ---------- 2. Follow-ups view + highlighting ---------- */
function buildFollowUpsView() {
const ss = SpreadsheetApp.getActive();
const deals = ss.getSheetByName(CONFIG.DEALS_SHEET);
const cols = headerMap_(deals);
const lastCol = colLetter_(deals.getLastColumn());
const f = colLetter_(cols[COL.FOLLOW_UP]);
const s = colLetter_(cols[COL.STAGE]);
const src = "'" + CONFIG.DEALS_SHEET + "'!";
const conditions = [src + f + '2:' + f + '<>""', src + f + '2:' + f + '<=TODAY()']
.concat(CONFIG.CLOSED_STAGES.map(function (st) { return src + s + '2:' + s + '<>"' + st + '"'; }));
const formula = '=IFERROR(SORT(FILTER(' + src + 'A2:' + lastCol + ', ' + conditions.join(', ') +
'), ' + cols[COL.FOLLOW_UP] + ', TRUE), "Nothing due. Nice.")';
const due = ss.getSheetByName(CONFIG.DUE_SHEET) || ss.insertSheet(CONFIG.DUE_SHEET);
due.clear();
const headers = deals.getRange(1, 1, 1, deals.getLastColumn()).getValues();
due.getRange(1, 1, 1, headers[0].length).setValues(headers).setFontWeight('bold');
due.getRange('A2').setFormula(formula);
due.setFrozenRows(1);
}
function addHighlighting_() {
const deals = SpreadsheetApp.getActive().getSheetByName(CONFIG.DEALS_SHEET);
const cols = headerMap_(deals);
const f = '$' + colLetter_(cols[COL.FOLLOW_UP]) + '2';
const s = '$' + colLetter_(cols[COL.STAGE]) + '2';
const open = CONFIG.CLOSED_STAGES.map(function (st) { return s + '<>"' + st + '"'; }).join(',');
const overdue = '=AND(' + f + '<>"",' + f + '"",' + f + '=TODAY(),' + open + ')';
const range = deals.getRange(2, 1, deals.getMaxRows() - 1, deals.getLastColumn());
const rules = deals.getConditionalFormatRules().filter(function (r) {
const c = r.getBooleanCondition();
const v = c && c.getCriteriaValues()[0];
return v !== overdue && v !== today; // drop our old copies so re-running setup doesn't duplicate
});
rules.push(SpreadsheetApp.newConditionalFormatRule().whenFormulaSatisfied(overdue)
.setBackground('#f4c7c3').setRanges([range]).build());
rules.push(SpreadsheetApp.newConditionalFormatRule().whenFormulaSatisfied(today)
.setBackground('#fce8b2').setRanges([range]).build());
deals.setConditionalFormatRules(rules);
}
/* ---------- 3. Daily digest (installable time-driven trigger) ---------- */
function sendFollowUpDigest() {
const ss = SpreadsheetApp.getActive();
const deals = ss.getSheetByName(CONFIG.DEALS_SHEET);
const cols = headerMap_(deals);
const values = deals.getDataRange().getValues();
const fallback = CONFIG.FALLBACK_EMAIL || Session.getEffectiveUser().getEmail();
const startOfToday = new Date(); startOfToday.setHours(0, 0, 0, 0);
const startOfTomorrow = new Date(startOfToday.getTime() + 86400000);
const byOwner = {};
for (let i = 1; i < values.length; i++) {
const row = values[i];
const due = row[cols[COL.FOLLOW_UP] - 1];
const stage = String(row[cols[COL.STAGE] - 1]);
if (!(due instanceof Date) || CONFIG.CLOSED_STAGES.indexOf(stage) !== -1) continue;
if (due.getTime() >= startOfTomorrow.getTime()) continue;
const dueDay = new Date(due); dueDay.setHours(0, 0, 0, 0);
const owner = String(row[cols[COL.OWNER] - 1] || fallback).trim();
(byOwner[owner] = byOwner[owner] || []).push({
company: row[cols[COL.COMPANY] - 1], contact: row[cols[COL.CONTACT] - 1],
stage: stage, next: row[cols[COL.NEXT_STEP] - 1], value: row[cols[COL.VALUE] - 1],
daysLate: Math.round((startOfToday - dueDay) / 86400000), row: i + 1,
});
}
const url = ss.getUrl() + '#gid=' + deals.getSheetId();
const tz = ss.getSpreadsheetTimeZone();
Object.keys(byOwner).forEach(function (owner) {
if (MailApp.getRemainingDailyQuota() < 1) { console.warn('MailApp daily quota used up'); return; }
const items = byOwner[owner].sort(function (a, b) { return b.daysLate - a.daysLate; });
const rowsHtml = items.map(function (d) {
return '
';
const text = items.map(function (d) {
return '- ' + d.company + ' (' + d.stage + '): ' + d.next + ' [' + (d.daysLate === 0 ? 'today' : d.daysLate + 'd late') + ']';
}).join('\n') + '\n\n' + url;
MailApp.sendEmail({ to: owner, subject: 'CRM: ' + items.length + ' follow-up(s) due', body: text, htmlBody: html });
});
}
function esc_(v) {
return String(v === null || v === undefined ? '' : v)
.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"');
}
/* ---------- One-time setup ---------- */
function setup() {
const ss = SpreadsheetApp.getActive();
if (!ss.getSheetByName(CONFIG.LOG_SHEET)) {
ss.insertSheet(CONFIG.LOG_SHEET)
.appendRow(['Changed at', 'Deal ID', 'Company', 'From stage', 'To stage', 'Changed by']);
}
buildFollowUpsView();
addHighlighting_();
ScriptApp.getProjectTriggers().forEach(function (t) {
if (t.getHandlerFunction() === 'sendFollowUpDigest') ScriptApp.deleteTrigger(t);
});
ScriptApp.newTrigger('sendFollowUpDigest').timeBased().everyDays(1).atHour(CONFIG.DIGEST_HOUR).create();
ss.toast('CRM set up: follow-ups view, highlighting and daily digest at ~' + CONFIG.DIGEST_HOUR + ':00.', 'CRM', 8);
}
```
## Limitations
- No email or calendar sync: emails and meetings are not logged automatically; people must add a line to Activities or the Notes column.
- No sequences, open/click tracking or meeting-booking links — those need a CRM or a separate tool.
- Simple onEdit triggers do not fire for changes made by scripts, the Sheets API, Zapier-style integrations or form submissions, so those rows get no stage timestamp.
- Shared-sheet permissions are all-or-nothing per tab/range: anyone with edit access can see and change every deal.
- MailApp limits: 100 email recipients/day on a free Google account and 1,500/day on Google Workspace; triggers share a daily runtime quota (90 min consumer, 6 h Workspace).
- Reporting is whatever you build: pivot tables, charts or a Looker Studio dashboard — there's no forecasting engine.
- The digest's date logic uses the script's time zone; teammates in other time zones receive it at that zone's hour.
## Risks
- **functionality_loss** (medium): You lose automatic activity capture, mobile CRM apps, email tracking and built-in reports. Follow-up discipline depends on people updating the sheet.
- **reliability** (medium): If someone renames a header, the script stops (it shows a toast and the Executions log records the error). The digest silently stops if the trigger owner leaves the company or their account is suspended — reinstall the trigger from a shared admin account.
- **security** (medium): Customer contact details sit in a spreadsheet that can be shared or downloaded with a click. Restrict sharing to named people, disable 'Viewers and commenters can download, print and copy', and never share by link.
- **compliance** (low): Sheets version history is not a tamper-proof audit log, and deletion/retention requests (e.g. GDPR erasure) must be handled manually across tabs, the Stage log and version history.
- **migration_complexity** (low): Importing from a CRM is mostly copy-paste, but activity history and attachments rarely export cleanly. Keep the final CRM export archived.
## Verification checklist (run before cancelling)
- [ ] All open deals from the old CRM are in Deals: row count matches the old CRM's open-deal count, and total open Value matches within rounding.
- [ ] Changing a Stage in the sheet fills 'Stage changed at' within a few seconds and appends a row to 'Stage log' showing the old and new stage.
- [ ] A test deal with yesterday's follow-up date turns red, one dated today turns amber, and both appear on the 'Follow-ups due' tab; a Won deal with an old date does not appear.
- [ ] 'CRM → Send follow-up digest now' delivers an email to each owner listing only their overdue/due-today deals, with a working link to the sheet.
- [ ] The time-driven trigger shows in Apps Script → Triggers, and the digest arrived unprompted on at least 3 consecutive mornings.
- [ ] Every teammate has logged at least one deal and one activity without help, and nobody needed the old CRM during a full week of parallel running.
- [ ] A complete CSV export of the old CRM (contacts, companies, deals, notes) is saved in a restricted Drive folder before cancelling.
## Savings methodology
Savings = (CRM price per seat per month × number of paid seats) − incremental cost of the replacement. The replacement's incremental cost is $0 because Sheets, Apps Script and MailApp come with Google accounts you already have, and an AI assistant you already pay for. We do not count setup time (≈half a day) or maintenance (≈15 min/month) as dollars; if your time is billable, subtract it. If your current plan is billed annually, savings only start at renewal unless the vendor refunds unused time.
Example (illustrative): A 3-person design studio on a paid CRM plan moves its pipeline to Google Sheets. $120/mo → $0/mo. Assumptions: ILLUSTRATIVE: 3 paid CRM seats at an assumed $40 per seat per month. We could not verify current Pipedrive or HubSpot paid-plan prices on the vendors' own pages today (Pipedrive's pricing page blocked automated access; HubSpot's pricing page did not show prices) — use the amount on your own invoice. The studio already pays for Google Workspace and an AI assistant, so nothing new is bought. HubSpot's free CRM (up to 2 users, 1,000 contacts — verified on HubSpot's product page) would also cost $0 but doesn't fit 3 users.
## Sources
- HubSpot free CRM product page: https://www.hubspot.com/products/crm (accessed 2026-10-13)
- Apps Script simple triggers — restrictions: https://developers.google.com/apps-script/guides/triggers (accessed 2026-10-13)
- Apps Script quotas: https://developers.google.com/apps-script/guides/services/quotas (accessed 2026-10-13)
- Pipedrive pricing: https://www.pipedrive.com/en/pricing (accessed 2026-10-13)
- HubSpot Sales Hub pricing: https://www.hubspot.com/pricing/sales (accessed 2026-10-13)
# Downgrade Canva Pro to Canva Free and use AI for images and copy
> Keep using Canva — just the free plan — for layouts and exports, and move image generation and caption writing to ChatGPT or Gemini that you already have. This guide lists what you lose from Pro, a workaround for each, a two-week test to see whether you really need Pro, and when Pro is still worth paying for.
- Outcome: I want to keep making social media graphics without paying for Canva Pro.
- Replaces: Canva (partial)
- Uses: Canva — Canva Free for layouts, your saved master designs, text and export.; ChatGPT — Generate images and backgrounds instead of premium stock; draft captions and headline variants.; Google Gemini (optional) — Alternative image generator and editor; its free tier lists image creation and editing.; Google Workspace (optional) — A Google Doc for the brand sheet and a Google Sheet for the content calendar and the Pro-feature tracker.
- Extra monthly cost: $0 — Canva Free costs nothing. Assumes you already pay for ChatGPT or use Gemini's free tier, and already have a Google account for the brand sheet and calendar.
- Difficulty: easy; skill: basic; setup: 2–3 hours to build the brand sheet and master templates, plus a 2-week trial
- Evidence: editorial; illustrative example: true; last reviewed 2026-10-13
- Canonical: https://onelesstool.com/workflows/social-graphics-with-canva-free-and-ai
## Good fit for
- Solo founders, freelancers and small shops posting a few graphics a week
- People who mostly reuse their own layouts and rarely need premium stock
- Anyone who already pays for ChatGPT or Gemini and uses Canva Pro mainly for AI images and stock
## Not a fit for
- Teams that share brand kits, folders and approvals in Canva
- Accounts posting daily in many sizes where one-click resizing saves hours a week
- Workflows that depend on Canva's built-in scheduler to publish to several channels
- Brands whose look relies on premium Canva fonts, templates or stock that would need a licence elsewhere
## Before
Pay for Canva Pro; pick premium templates and stock, apply colours and fonts from the Brand Kit, remove backgrounds in one click, resize each design to every platform, and schedule posts from Canva's content planner.
## After
Use Canva Free with your own saved master designs for each size. A brand sheet doc holds colours, fonts and the AI style block. ChatGPT or Gemini generates images and caption drafts. Backgrounds are removed with your computer or phone's photo app, and posts are scheduled in each platform's own scheduler.
## Steps
### 1. Track which Pro features you actually use (2 weeks, before downgrading)
While still on Pro, log every time you use a Pro feature in the **Pro-feature tracker** (CSV below): which feature, for what, and whether a workaround would do.
The usual Pro-only items, as presented on Canva's plan pages (our automated check of canva.com was blocked, so **confirm against the crown icons in your own account**):
- **Brand Kit** beyond the basic free allowance (more kits, fonts and logos)
- **Background Remover** for unlimited or regular use
- **Resize / Magic Switch** (one-click copying a design into other sizes)
- **Premium templates, photos, graphics and fonts**
- **Content Planner** scheduling to social platforms (Canva's help centre lists Pro, Business, Education and Nonprofit accounts)
- Larger AI usage allowance, more storage, transparent PNG downloads
If a feature appears more than a few times a week, plan its replacement carefully or keep Pro.
### 2. Rebuild your brand kit as a brand sheet and master designs
Copy colours (hex codes), fonts and logo files into the **Brand sheet** template below (a Google Doc works).
Then, still on Pro, create one **master design per format** you post (square, portrait, story, landscape). Use only free fonts and elements in them so they survive the downgrade. Put them in a Canva folder called `00 Masters`.
Each new post starts by **making a copy of the right master**. This replaces most of what the Brand Kit and Resize did for you.
### 3. Replace premium stock with generated images
Paste the **AI style block** from your brand sheet into ChatGPT or Gemini, then use the **On-brand image prompt**. Ask for the aspect ratio you need (1:1, 4:5, 9:16 or 16:9) and **no text in the image**. Upload the result into Canva Free and add text there.
For product photos, keep using real photos. Generated product images can misrepresent what you sell.
### 4. Replace background removal and resizing
**Background removal:** use the subject-lift or background removal built into your phone or computer's photo app (recent macOS and iOS can copy a photo's subject with the background removed), or ask ChatGPT or Gemini to edit the image. Check edges at full size.
**Resize:** copy the master for the new size, then copy and paste elements across from the original design and adjust. With good masters this takes a few minutes per size. If you need 5+ sizes of every post, this is where Pro earns its price.
### 5. Write captions and plan posts with AI
Use the **Caption pack prompt** to turn one idea into captions for each platform, with your voice notes from the brand sheet. Keep the weekly plan in a Google Sheet (date, platform, design link, caption, status).
**Scheduling without Canva:** most platforms have their own scheduler (for example Meta Business Suite for Facebook and Instagram, and LinkedIn's post scheduling). Download the PNG from Canva Free and schedule it there.
### 6. Downgrade and run on Free for two weeks
Before downgrading, **download** any designs that use premium elements as PNG or PDF. Premium elements you used may become unavailable or watermarked after a downgrade (check Canva's help centre for how downgrades are handled), so finished files are your safe copy.
Downgrade at your **renewal date** (annual plans usually don't refund mid-term — check your billing page). Keep logging in the tracker. If after two weeks the minutes lost each week cost more than Pro, upgrade again; nothing is lost by trying.
## Prompts
### On-brand image prompt
Generate a background or scene image to replace premium stock.
```text
{{ai_style_block}}
Create one image for a {{platform}} post about {{post_topic}}.
Aspect ratio: {{aspect_ratio}}. Main subject: {{main_subject}}. Mood: {{mood}}.
Keep the {{text_side}} third plain and uncluttered for a headline I'll add later.
No text, letters, logos, watermarks or people's faces unless I ask.
```
### Caption pack prompt
Turn one post idea into platform-specific captions in your voice.
```text
Brand: {{brand_name}}. Voice: {{voice_adjectives}}. Never: {{voice_never}}.
Post idea: {{post_idea}}. Call to action: {{call_to_action}}.
Write: 1) an on-image headline of max 8 words (3 options); 2) an Instagram caption (max 120 words, 3–5 hashtags from: {{hashtags}}); 3) a LinkedIn version (max 80 words, no hashtags in the body); 4) an X/Threads version under 260 characters.
Don't invent facts, prices or dates I haven't given.
```
### Weekly content plan prompt
Plan a week of posts that reuse your master templates.
```text
I post {{posts_per_week}} times a week on {{platforms}} for {{brand_name}} ({{business_description}}).
This week's priorities: {{weekly_priorities}}.
My master templates are: {{master_template_list}}.
Make a table: day | platform | post idea | which master template | image needed (generated / own photo / none) | headline draft. Reuse templates rather than asking for new layouts.
```
## Templates and scripts
### Brand sheet template (replaces the paid Brand Kit) (template)
```markdown
# Brand sheet – {{brand_name}}
_Replaces the paid Brand Kit. Keep this doc pinned; paste the "AI style block" into ChatGPT/Gemini._
## Colours (hex)
| Role | Hex | Use for |
|---|---|---|
| Primary | {{primary_hex}} | Backgrounds, big shapes |
| Accent | {{accent_hex}} | Buttons, highlights, 1 word per graphic |
| Dark text | {{dark_hex}} | Body text |
| Light | {{light_hex}} | Text on dark backgrounds |
## Type
- Headline font: {{headline_font}} (available free in Canva? yes/no)
- Body font: {{body_font}}
- Rule: max 2 fonts, max 12 words of text per graphic.
## Logo files
- Full colour PNG (transparent): link
- White version PNG: link
- Square avatar: link
## Master templates (in Canva Free, folder "00 Masters")
| Format | Size (px) | Canva design link | Notes |
|---|---|---|---|
| Instagram/Facebook square | 1080 x 1080 | link | Logo bottom-left |
| Portrait feed post | 1080 x 1350 | link | Text in top 2/3 |
| Story / Reel cover | 1080 x 1920 | link | Keep top and bottom ~250 px clear of UI |
| LinkedIn / X landscape | 1200 x 675 | link | |
_Check each platform's current recommended sizes before relying on this table._
## Photo style
- Light: {{photo_light}} · Subjects: {{photo_subjects}} · Avoid: {{photo_avoid}}
## AI style block (paste before any image request)
Brand: {{brand_name}}. Visual style: {{visual_style}}. Colours: {{primary_hex}}, {{accent_hex}}.
No text, logos or watermarks in the image. Leave clear space on the {{text_side}} for a headline.
## Voice (for captions)
- We sound: {{voice_adjectives}}
- We never: {{voice_never}}
- Hashtag set: {{hashtags}}
```
### Pro-feature tracker (CSV) for the two-week test (checklist)
```csv
pro_feature_hit,date,design,what_you_needed,workaround_used,minutes_lost,would_pay_for_this(y/n)
"Background remover",2026-10-14,"Promo post #12","Cut out product photo","macOS Photos subject lift",4,n
"Resize",2026-10-15,"Launch post","Square -> story","Duplicated master story template, pasted elements",9,n
"Premium element",,,,,,
"Brand Kit",,,,,,
"Content Planner",,,,,,
```
## Limitations
- No one-click resize: each extra size means copying a master and moving elements by hand.
- No full Brand Kit: colours, fonts and logos live in a separate doc instead of the editor's side panel.
- Premium templates, stock, fonts and elements become unavailable; designs using them need free replacements.
- No Canva Content Planner scheduling; you schedule in each platform's own tools.
- Generated images vary in quality and style; getting a consistent look takes a saved style block and re-rolls.
- We could not load canva.com to confirm the exact Free vs Pro feature split today; check your own account before downgrading.
## Risks
- **functionality_loss** (medium): Pro-only elements in existing designs may become unavailable or watermarked after downgrading. Export finished designs first.
- **ip_licensing** (medium): Premium Canva assets are licensed through your Pro plan; check Canva's licence terms for reusing previously exported designs. For AI images, avoid prompting for trademarks or real people.
- **collaboration** (medium): If others edit your designs, they lose shared Pro features too. Teams may need a Canva team plan instead.
- **reliability** (low): More manual steps (resize, background removal) mean more room for inconsistent sizes and stray elements.
## Verification checklist (run before cancelling)
- [ ] Your two-week tracker shows each Pro feature used fewer than ~3 times a week, or with a workaround you're happy with.
- [ ] Master designs exist for every format you post, built only from free fonts and elements (no crown icons).
- [ ] You produced a full week of posts with generated images and Free-plan layouts without hitting a blocker.
- [ ] Background removal with your OS photo app or AI editor gives clean edges at full size on 3 of your typical photos.
- [ ] You have scheduled at least one post in each platform's native scheduler.
- [ ] All designs containing premium elements are exported as PNG/PDF before the downgrade.
- [ ] You've checked the renewal date and refund terms on your Canva billing page.
## Savings methodology
Savings = Canva Pro price you pay today − $0 (Canva Free) − any incremental AI cost ($0 if you already pay for ChatGPT or use Gemini's free tier). If you'd need to start a new AI subscription just for this, subtract it. Extra minutes for manual resizing and background removal are not monetised; the two-week tracker helps you judge whether they cancel out the saving.
Example (illustrative): A freelance consultant on Canva Pro who posts 4 graphics a week to LinkedIn and Instagram and already pays for ChatGPT. $15/mo → $0/mo. Assumptions: Illustrative: $15/month is a round placeholder for Canva Pro. canva.com blocked automated access on 2026-10-13, and third-party trackers reported price changes in 2026, so check your own billing page. ChatGPT is already paid for other work and not counted. The consultant uses 2 sizes per post, so manual resizing adds roughly 10–20 minutes a week (not monetised).
## Sources
- Canva pricing: https://www.canva.com/pricing/ (accessed 2026-10-13)
- Canva Help: Content Planner: https://www.canva.com/help/content-planner/ (accessed 2026-10-13)
- Canva: Background Remover: https://www.canva.com/features/background-remover/ (accessed 2026-10-13)
- Google Gemini subscriptions: https://gemini.google/subscriptions/ (accessed 2026-10-13)
# Make YouTube thumbnails with ChatGPT instead of Canva
> Generate on-brand thumbnail backgrounds with ChatGPT image generation, then add your real face and exact headline text with a free HTML template or the OneLessTool in-browser composer. Covers prompts, text-rendering fixes, export at YouTube's sizes and an A/B test before you cancel.
- Outcome: I want eye-catching, consistent YouTube thumbnails every week without paying for Canva Pro.
- Replaces: Canva (task_specific)
- Uses: ChatGPT — Generate thumbnail backgrounds, props and concept variations from a saved series-style prompt; brainstorm 2–4 word headline text.; Google Gemini (optional) — Alternative image generator. Gemini's free tier lists image creation and editing, so it also works if you don't pay for ChatGPT.; Claude (optional) — Alternative for the layout side: ask it to adapt the HTML template (new layouts, colours, fonts). It is better at layout code than at photographic images.
- Extra monthly cost: $0 — Assumes you already pay for (or use the free tier of) ChatGPT or Gemini. The HTML template and the OneLessTool composer are free and run in your browser. Image-generation limits vary by plan; heavy users on free tiers may hit daily caps.
- Difficulty: easy; skill: basic; setup: 60–90 minutes once (series style prompt, template colours, face cutouts)
- Evidence: editorial; illustrative example: true; last reviewed 2026-10-13
- Canonical: https://onelesstool.com/workflows/youtube-thumbnails-with-chatgpt
## Good fit for
- Solo creators who pay for Canva Pro mainly or only for thumbnails — for them this can replace the whole subscription
- Channels with a repeatable series look (same layout, colours, face position each week)
- Creators who already pay for ChatGPT Plus or use Gemini and want one less design subscription
## Not a fit for
- Teams where several editors share Canva brand kits, folders and approval comments
- Creators who also rely on Canva for social posts, video editing, presentations or printed material (cancelling would remove those too — see the Canva Free downgrade workflow instead)
- Thumbnails that need pixel-precise photo compositing of many cutouts; use a real photo editor for that
- Anyone uncomfortable with AI-generated imagery on their channel or with disclosure questions it may raise
## Before
Open Canva Pro, duplicate last week's thumbnail, swap the background with a stock photo or Canva AI image, remove the background from a new face photo with Canva's background remover, retype the headline using the brand kit font, then download a PNG and upload it to YouTube Studio.
## After
Paste a saved series-style prompt plus a short per-video prompt into ChatGPT to get a text-free background, drop it with a transparent face cutout and the exact headline into a reusable HTML template (or the OneLessTool composer), capture a 2560x1440 PNG from Chrome, check legibility at 168x94, and upload. Canva is no longer needed for this job.
## Steps
### 1. Record your baseline before changing anything
In **YouTube Studio > Analytics > Content**, note the **impressions click-through rate (CTR)** and views for your last 8–10 videos. Save the numbers in a sheet with the thumbnail file for each video.
Also list what you actually do in Canva for thumbnails: background removal, brand fonts, stock photos, templates. Each item needs a replacement in the steps below. If you use Canva for **other** jobs too, this workflow only replaces the thumbnail part.
### 2. Write a series style prompt once and save it
Use the **Series style prompt** below to describe your look in words: palette (hex codes), lighting, mood, recurring props, and **which side stays empty for text and your face**. Save it where you can reuse it every week:
- ChatGPT: a **Project** with the style text in its instructions, or a pinned note you paste in.
- Gemini or Claude: a saved prompt or a doc.
The key rule: **ask for backgrounds with no text at all.** Image models still misspell words, and you need exact control over the headline.
### 3. Generate the background for each video
Paste the series style plus the **Per-video background prompt**. Ask for a **16:9 landscape** image. Generate 2–3 options and pick the one with the clearest single focal point.
- If the model adds stray letters or logos, use the **Text-artefact fix prompt**.
- Keep the empty side genuinely empty. Busy areas behind text are the main cause of unreadable thumbnails.
- Save the image at the largest size offered. YouTube's help page recommends large thumbnails (it lists 3840x2160 for videos) and a minimum width of 640px.
### 4. Make a real face cutout (don't let AI redraw your face)
Take a well-lit photo with the expression you want. Remove the background with a tool you already have, for example the subject-lift feature built into recent macOS and iOS Photos, or your phone's gallery app. Save it as a **transparent PNG**.
You *can* ask ChatGPT or Gemini to cut out or "enhance" your face, but generated edits can subtly change your features. Viewers notice. Use a real photo for your face and AI only for the scene.
Build a small library of 6–10 cutouts (surprised, pointing, thinking, laughing) so most weeks need no new photo.
### 5. Compose the thumbnail with exact text
Two options, both free:
1. **OneLessTool thumbnail composer** on this workflow page: drop in the background and face PNG, type the headline, pick the accent colour and export. Everything runs in your browser.
2. **The HTML template below**: save it as `thumbnail.html`, replace the `{{placeholders}}` (image paths can be local files next to the HTML, e.g. `bg.png`), and open it in Chrome. The page shows live previews at 168x94, 320x180 and 480x270 under the main canvas.
Keep the headline to **2–4 words**. Use the **Headline options prompt** to get choices that add to the video title rather than repeat it. Keep the bottom-right corner clear: YouTube overlays the video length there (the template marks this area in red).
### 6. Export at the right size and check the file
In Chrome with the template open (add `?export` to the URL to hide guides):
1. Open DevTools and toggle the **device toolbar**.
2. Set the size to **1280 x 720** and the **device pixel ratio to 2** (gives 2560x1440) or **3** (gives 3840x2160).
3. In the Elements panel, right-click `
` and choose **Capture node screenshot**.
Then check the file:
- Width at least **1280px**. YouTube's A/B test tool downscales *all* variants to 854x480 if any variant is below 1280x720.
- **Under 2 MB** if you upload from the YouTube mobile app (desktop allows up to 50 MB). On a Mac, `sips -s format jpeg -s formatOptions 85 thumb.png --out thumb.jpg` converts a large PNG to a smaller JPG.
- JPG or PNG format.
Custom thumbnails require a **verified** YouTube account.
### 7. Test against your Canva thumbnails before cancelling
For the next 4–6 uploads, use YouTube Studio's **A/B testing (Test & compare)** on desktop: upload your new thumbnail alongside a Canva-made version (up to 3 variants). YouTube picks the winner by **watch time**, not CTR, so also compare CTR against the baseline from step 1.
Cancel Canva Pro only when the new thumbnails win or tie on most tests and your time per thumbnail is acceptable. Download anything you need from Canva before the subscription ends (see checklist).
## Prompts
### Series style prompt (save and reuse)
Define a consistent visual identity for every thumbnail background in your series.
```text
You are generating background images for YouTube thumbnails for a channel about {{channel_niche}}.
Apply this series style to every image I ask for in this conversation:
- Format: 16:9 landscape, photographic, high contrast, sharp focus on one subject.
- Palette: dominant {{primary_color_hex}}, accent {{accent_color_hex}}, deep shadows. Avoid muddy mid-tones.
- Mood and lighting: {{mood}}; strong rim light on the main subject.
- Recurring elements: {{recurring_elements}}.
- Composition: put the main subject on the {{subject_side}} third. Keep the {{empty_side}} 40% of the frame simple and darker, with no objects, so I can add a headline and a person there later.
- Never include any text, letters, numbers, logos, watermarks or UI elements.
- No people unless I ask. Never generate a face meant to be me.
Reply "Style saved" and wait for my first video brief.
```
### Per-video background prompt
Generate one background per video using the saved series style.
```text
New video brief, same series style as before.
Video topic: {{video_topic}}
The single visual idea: {{key_object_or_scene}}
Emotion the viewer should feel at a glance: {{emotion}}
Leave the {{headline_side}} side empty and darker for text.
Make 1 image. Then suggest 2 alternative scene ideas in one line each, so I can ask for them if this one doesn't work.
```
### Text-artefact fix prompt
Remove stray or misspelled text from a generated image, or fix text when you decide to keep it in the image.
```text
Edit the last image. Keep the composition, subject, lighting and colours exactly the same.
Remove every letter, number, sign, logo and watermark, including any on {{object_with_text}}. Replace those areas with plain matching texture.
If I give exact text below, render it instead, spelled exactly, in capitals, in a heavy {{font_style}} style, positioned {{text_position}}, and nothing else:
Exact text (may be blank): "{{exact_text}}"
After editing, list any characters you were unsure about.
```
### Headline options prompt
Get short thumbnail text that complements, not repeats, the video title.
```text
Video title: {{video_title}}
What happens in the video / the hook: {{video_hook}}
Audience: {{audience}}
Write 10 thumbnail headline options of 2–4 words each. Rules: do not repeat words from the title; create curiosity or state a concrete result; no clickbait claims the video doesn't deliver; avoid words longer than 9 letters. Mark your top 3 and explain each in one short line.
```
### Small-size critique prompt
Get a second opinion on legibility and focus before uploading (attach the exported image).
```text
I've attached a YouTube thumbnail. Imagine it shown at about 168x94 pixels next to {{competitor_count}} other thumbnails in the {{channel_niche}} niche.
Answer briefly: 1) Can the headline "{{headline_text}}" be read at that size? 2) What is the first thing the eye lands on? 3) Is anything important in the bottom-right corner, where YouTube shows the video length? 4) Two specific changes that would most improve it.
```
## Templates and scripts
### HTML/CSS thumbnail template (1280x720 layout with live small-size previews) (template)
```html
Thumbnail – {{headline_line_1}}
{{headline_line_1}}{{headline_line_2}}
{{badge_text}}
168 x 94 (small/mobile check)320 x 180480 x 270
```
## Limitations
- Image models still misspell text and add stray letters; exact headlines need to be added separately (template or composer).
- No Canva-style drag-and-drop editing of the generated image; changes mean re-prompting or editing the template.
- Generated images vary between runs, so a strict series look takes a saved style prompt and some re-rolls.
- Background removal for your face depends on another free tool (OS photo apps); results on hair and glasses can be rough.
- Image-generation limits depend on your ChatGPT or Gemini plan and can change; free tiers may cap daily images.
- No shared brand kit, folders or approvals for a team.
## Risks
- **ip_licensing** (medium): Don't prompt for copyrighted characters, logos or a real person's likeness. Check the image tool's terms on commercial use of outputs; YouTube thumbnails must also follow Community Guidelines.
- **functionality_loss** (low): Cancelling Canva Pro removes Pro features for every other design you make there, not just thumbnails.
- **data_portability** (low): Old Canva thumbnails stay editable only inside Canva. Download final PNGs of past thumbnails you may want to rework before cancelling.
- **reliability** (low): Thumbnail quality may drop for a few weeks while you learn the prompts; the A/B test step guards against this.
## Verification checklist (run before cancelling)
- [ ] You have produced at least 3 thumbnails end-to-end with this workflow, each in under 30 minutes.
- [ ] Each exported file is at least 1280px wide (ideally 2560 or 3840), 16:9, JPG or PNG, and under 2 MB if you upload from mobile.
- [ ] At the 168x94 preview in the template, someone else can read the headline and name the subject within 2 seconds.
- [ ] Nothing important sits in the bottom-right corner covered by the video-length badge.
- [ ] Your face cutout is a real photo, with clean edges on hair and shoulders at full size.
- [ ] YouTube Studio A/B tests on 4–6 videos show the new thumbnails winning or tying against Canva versions, and CTR is not below your recorded baseline.
- [ ] Any Canva designs or assets you still need are downloaded before the subscription ends.
## Savings methodology
Savings = what you currently pay for Canva Pro (or your share of a Canva plan) − incremental cost of this workflow ($0 if you already have ChatGPT or use Gemini's free tier). Count the full Canva price only if thumbnails are the only reason you pay; if you use Canva Pro for other work, the saving is $0 until those jobs are replaced too. One-time setup (about 1–1.5 hours) and any extra minutes per thumbnail are not monetised.
Example (illustrative): Solo creator posting one video a week, paying for Canva Pro monthly only for thumbnails, already paying for ChatGPT for scripting. $15/mo → $0/mo. Assumptions: Illustrative: the $15/month Canva Pro figure is a round placeholder. canva.com blocked automated access on 2026-10-13, so we could not verify the current US price; check your own billing page. ChatGPT is already paid for other work, so its cost is not counted. Thumbnails are the only reason the creator pays for Canva Pro.
## Sources
- YouTube Help: Add video thumbnails: https://support.google.com/youtube/answer/72431 (accessed 2026-10-13)
- YouTube Help: A/B test titles & thumbnails: https://support.google.com/youtube/answer/13861714 (accessed 2026-10-13)
- Google Gemini subscriptions: https://gemini.google/subscriptions/ (accessed 2026-10-13)
- Canva pricing: https://www.canva.com/pricing/ (accessed 2026-10-13)
# Move simple and medium Zaps to n8n (self-hosted or n8n Cloud)
> Inventory your Zaps, stand up n8n Community Edition on a small VPS with Docker Compose (or use n8n Cloud), migrate lowest-risk Zaps first, parallel-run each one, and only then cancel. You trade a per-task bill for owning uptime, patching and backups.
- Outcome: Keep the same app-to-app automations running while dropping or downgrading the Zapier subscription.
- Replaces: Zapier (full)
- Uses: n8n — The automation engine: self-hosted Community Edition (free under the Sustainable Use License for internal use) or a paid n8n Cloud plan.; Claude (optional) — Translates Zap logic into n8n expressions and Code-node JavaScript, and helps read error messages.; ChatGPT (optional) — Alternative to Claude for expression/Code-node help.; Google Workspace (optional) — Hosts the Zap inventory spreadsheet (any spreadsheet works).
- Extra monthly cost: $14.4 — Self-hosted: a DigitalOcean Basic Droplet with 2 GiB RAM is $12/month and weekly backups add 20% ($2.40), per DigitalOcean's pricing page today — $14.40/month. A 1 GiB droplet is $6 but leaves little headroom (our judgement, not an n8n requirement). Any comparable VPS works. A domain name and your own time are extra. n8n Cloud instead: Starter was listed at €20/month billed annually on n8n's pricing page (shown in euros to us; 2,500 executions/month) — no server to run, but it's a subscription.
- Difficulty: advanced; skill: technical; setup: 1 day for the server and first wave; 2–4 weeks elapsed for all waves including parallel runs
- Evidence: editorial; illustrative example: false; last reviewed 2026-10-13
- Canonical: https://onelesstool.com/workflows/zapier-to-n8n
## Good fit for
- Teams paying for Zapier Pro/Team mainly because of task volume or multi-step Zaps
- Someone on the team comfortable with Linux, Docker, DNS and reading logs
- Automations between mainstream apps that have native n8n nodes or simple REST APIs
- Organisations that want automation data to stay on infrastructure they control
## Not a fit for
- No one technical to own updates, security patches, backups and 2 a.m. failures — stay on Zapier or use n8n Cloud
- Mission-critical automations (billing, customer-facing messages, compliance) without monitoring and alerting in place
- Zaps built on Zapier-only features (Zapier Tables, Interfaces, Chatbots) or niche apps with no n8n node and no usable API
- Offering automation to your own customers (letting clients build or edit workflows) — not allowed under n8n's Sustainable Use License without a commercial agreement
## Before
Zaps run on Zapier's cloud. Pricing is per task; multi-step Zaps need a paid plan (Free allows only two-step Zaps and 100 tasks/month). Zapier handles hosting, OAuth app registrations, retries and uptime. You pay more as volume grows.
## After
n8n runs in Docker on a small VPS behind Traefik with automatic HTTPS, or on n8n Cloud. Each Zap is rebuilt as an n8n workflow, parallel-run against the original, then switched over. An Error Workflow alerts you on failures, nightly exports plus volume snapshots back everything up, and Zapier is downgraded to Free (for any leftovers) or cancelled after 30 quiet days.
## Steps
### 1. Inventory every Zap and assign migration waves
Fill the **Zap inventory** artifact: one row per Zap, including disabled ones you might need.
- Pull **tasks used in the last 30 days** from Zapier's task history so you know real volume.
- Mark anything using **Zapier Tables, Interfaces, Chatbots, Email Parser** or apps with no n8n node — these need redesign, not migration.
- Assign **waves** (1 = internal, low-impact, ≤3 steps → 4 = needs redesign).
If most of your task volume sits in wave 4, stop here: the migration may cost more than it saves.
### 2. Choose hosting and check the license
**Self-hosted Community Edition** is free under n8n's **Sustainable Use License** when only you or people in your organisation build workflows. Running your own business on it, building automations for clients on your instance (clients can't edit them) and charging for setup/consulting are allowed. **Not allowed:** hosting n8n as a service where clients build workflows, white-labelling, or using license-key enterprise features without a license. Read n8n's license FAQ if you're an agency.
**n8n Cloud** removes server work; its pricing page listed Starter at €20/month billed annually with 2,500 executions (prices shown in euros to us — check yours). Note that n8n counts *executions* (one per workflow run) rather than Zapier's per-action *tasks*, so compare volumes carefully.
For self-hosting, a 2 GiB RAM VPS is a comfortable start for a few dozen low-volume workflows (our judgement).
### 3. Deploy n8n with Docker Compose
On a fresh Ubuntu VPS with Docker installed:
1. Create an **A record** `n8n.yourdomain.com` → server IP.
2. Firewall: allow 22 (ideally only from your IP), 80 and 443; nothing else.
3. Save the **docker-compose.yml** artifact and its `.env` block. Generate the key with `openssl rand -hex 32` and store it in your password manager — **lose it and every stored credential is unreadable**.
4. `mkdir -p local-files backups && docker compose up -d`, then open `https://n8n.yourdomain.com` and **create the owner account immediately**. Since n8n 1.0 there are no `N8N_BASIC_AUTH_*` variables; the owner login *is* the protection.
5. Turn on **2FA** for the owner (**Settings → Personal → Enable 2FA**), and turn on your VPS provider's backups.
Check `N8N_WEBHOOK_URL` vs `WEBHOOK_URL` against your pinned version (the docs say `N8N_WEBHOOK_URL` needs 2.30.0+); if webhook URLs in the editor show `localhost`, you used the wrong one.
### 4. Set up credentials, backups and failure alerts before migrating anything
- **Credentials:** for Google, Microsoft, Slack and similar OAuth apps on self-hosted n8n, you usually register your own OAuth app in that vendor's developer console and paste in the redirect URL n8n shows. Budget time for Google's consent-screen setup. API-key apps (Stripe, Typeform, Airtable) are quicker.
- **Error Workflow:** build one workflow that starts with an **Error Trigger** and sends email/Slack with the workflow name and execution URL. Select it under each workflow's **Settings → Error workflow**.
- **Backups:** nightly cron on the host:
- `docker compose exec -u node n8n n8n export:workflow --backup --output=/backups/workflows/`
- `docker compose exec -u node n8n n8n export:credentials --backup --output=/backups/credentials/` (still encrypted — restore needs the same `N8N_ENCRYPTION_KEY`)
- copy `./backups` off the server (e.g. `rclone` to cloud storage) and keep the `.env` in your password manager.
- **Test a restore** onto a scratch server once. A backup you haven't restored is a hope, not a backup.
### 5. Rebuild Zaps wave by wave
For each Zap, screenshot every step, then rebuild in n8n. Rough mapping:
| Zapier | n8n |
|---|---|
| Trigger app | App trigger node, **Webhook** node, or **Schedule Trigger** + poll |
| Filter | **If** / **Filter** node |
| Paths | **Switch** node |
| Formatter | **Edit Fields (Set)** with expressions, or **Code** node |
| Delay | **Wait** node |
| Looping | items flow through nodes automatically; **Loop Over Items** for batches |
| Webhooks by Zapier | **Webhook** / **HTTP Request** nodes |
Paste the Zap's step list into the **Translate a Zap into an n8n workflow plan** prompt to get a node-by-node plan and expressions. Expressions use `{{ $json.field }}` syntax — the most common bug is referencing data from the wrong node.
### 6. Parallel-run, switch over, then downgrade Zapier
Follow the **Cutover checklist** for every Zap: at least **7 days or 20 executions** side by side, matching counts between Zapier task history and n8n's Executions list, and a field-level diff on 5 runs (time zones and date formats are the usual culprits).
For actions that must not happen twice (payments, customer emails), never run both live — replay recent payloads into n8n with the last step disabled.
Switch by activating the n8n workflow and turning the Zap off in the same minute; re-point any third-party webhooks. Keep turned-off Zaps for 30 days. Then move leftovers to **Zapier Free** if they fit (two-step, ≤100 tasks/month) or cancel.
## Prompts
### Translate a Zap into an n8n workflow plan
Get a node-by-node rebuild plan with expressions from a Zap description.
```text
I'm migrating a Zapier Zap to n8n (version {{n8n_version}}, self-hosted). Here is the Zap, step by step, including field mappings, filters and formatter settings:
{{zap_steps}}
Sample trigger payload (JSON, sensitive values redacted):
{{sample_payload}}
Give me:
1. A numbered list of n8n nodes (exact node names as they appear in n8n), with the settings to choose in each.
2. Every expression I need, in n8n syntax (e.g. {{ $json.email }} or {{ $('Node Name').item.json.field }}), mapped to the original Zap field.
3. Anything in this Zap with no direct n8n equivalent and how to handle it (HTTP Request node, Code node, or redesign).
4. Time zone, date-format and empty-field pitfalls specific to this Zap.
5. A test plan: which 3 sample inputs prove the n8n version matches the Zap.
If you're unsure whether a node or option exists in this n8n version, say so rather than inventing it.
```
### Write an n8n Code node
Replace Zapier Formatter/Code steps with a tested Code node.
```text
Write JavaScript for an n8n Code node in mode "{{code_mode}}" ("Run Once for All Items" or "Run Once for Each Item").
Input items look like this (JSON):
{{input_example}}
Output items must look like this:
{{output_example}}
Transformation rules:
{{rules}}
Requirements: use $input.all() or $input.item as appropriate for the mode; return items in n8n's [{ json: {...} }] shape; no external npm packages; handle missing fields without throwing; add short comments. Then give two edge-case inputs and the expected outputs so I can test it.
```
### Diagnose a failed n8n execution
Turn an n8n error into a fix during parallel running.
```text
An n8n workflow failed during a parallel run against the original Zap.
Node that failed: {{node_name}} ({{node_type}})
Error message: {{error_message}}
Input data to that node (redacted): {{node_input}}
What the Zapier version produced for the same trigger: {{zapier_output}}
Explain the most likely cause in plain English, give the exact fix (setting, expression or credential change), and tell me how to confirm it's fixed without triggering real side-effects (emails, payments, CRM writes).
```
## Templates and scripts
### docker-compose.yml + .env for n8n behind Traefik (HTTPS) (config)
```yaml
# docker-compose.yml — n8n Community Edition behind Traefik (automatic HTTPS)
# Adapted from n8n's "Docker Compose" server-setup guide (docs.n8n.io, checked 2026-10-13).
# Changes from the docs example: pinned image tag, explicit N8N_ENCRYPTION_KEY,
# Traefik dashboard NOT exposed (the docs example sets --api.insecure=true).
#
# Login: n8n has NO basic-auth env vars any more — N8N_BASIC_AUTH_* were removed in n8n 1.0.
# Access is protected by n8n's own user management: the first visitor creates the OWNER account.
# So create the owner account immediately after first start (or firewall port 443 to your IP until you have).
services:
traefik:
image: "traefik:${TRAEFIK_VERSION}"
restart: always
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
- "--certificatesresolvers.mytlschallenge.acme.email=${SSL_EMAIL}"
- "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- traefik_data:/letsencrypt
- /var/run/docker.sock:/var/run/docker.sock:ro
n8n:
image: "n8nio/n8n:${N8N_VERSION}" # pin a version; upgrade deliberately after reading release notes
restart: always
ports:
- "127.0.0.1:5678:5678" # only reachable through Traefik, not directly from the internet
labels:
- traefik.enable=true
- traefik.http.routers.n8n.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`)
- traefik.http.routers.n8n.tls=true
- traefik.http.routers.n8n.entrypoints=web,websecure
- traefik.http.routers.n8n.tls.certresolver=mytlschallenge
- traefik.http.middlewares.n8n.headers.SSLRedirect=true
- traefik.http.middlewares.n8n.headers.STSSeconds=315360000
- traefik.http.middlewares.n8n.headers.browserXSSFilter=true
- traefik.http.middlewares.n8n.headers.contentTypeNosniff=true
- traefik.http.middlewares.n8n.headers.forceSTSHeader=true
- traefik.http.middlewares.n8n.headers.SSLHost=${DOMAIN_NAME}
- traefik.http.middlewares.n8n.headers.STSIncludeSubdomains=true
- traefik.http.middlewares.n8n.headers.STSPreload=true
- traefik.http.routers.n8n.middlewares=n8n@docker
environment:
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY} # encrypts stored credentials; back this up separately
- N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
- N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}
- N8N_PORT=5678
- N8N_PROTOCOL=https
- NODE_ENV=production
- N8N_WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/ # n8n >= 2.30.0
# - WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/ # use this name instead on n8n < 2.30.0
- GENERIC_TIMEZONE=${GENERIC_TIMEZONE} # used by Schedule Trigger
- TZ=${GENERIC_TIMEZONE}
- N8N_RESTRICT_FILE_ACCESS_TO=/files
volumes:
- n8n_data:/home/node/.n8n # SQLite database, encryption key, settings — THIS is what you back up
- ./local-files:/files # create this folder yourself before first start
- ./backups:/backups # target for `n8n export:*` backup commands
volumes:
n8n_data:
traefik_data:
# ---------------------------------------------------------------------------
# .env (same folder; chmod 600 .env; never commit it)
# ---------------------------------------------------------------------------
# DOMAIN_NAME=example.com
# SUBDOMAIN=n8n # → https://n8n.example.com (create an A record to the server IP)
# GENERIC_TIMEZONE=America/New_York
# SSL_EMAIL=you@example.com # Let's Encrypt contact
# N8N_VERSION=
# TRAEFIK_VERSION=
# N8N_ENCRYPTION_KEY=