{
 "generated": "2026-10-08",
 "source": "/api/public/kb",
 "categories": [
  {
   "id": "a602a917-92e7-496c-9e6c-e0a6a9fa4da9",
   "slug": "getting-started",
   "title": "Getting started",
   "description": "What Dashbread is, installing it, and everything free Core does on its own."
  },
  {
   "id": "9cfcc2e5-779e-4061-a250-7ac5853be6cc",
   "slug": "pro",
   "title": "Dashbread Pro",
   "description": "The staff side of the app — members, plans, companies, messaging, email, and the design tools."
  },
  {
   "id": "fedde577-81c2-41c4-a5c6-6959d42fdf68",
   "slug": "pmas",
   "title": "Pro Module Add-ons",
   "description": "Modules inside Pro that switch on with their add-on — no extra plugin to install."
  },
  {
   "id": "0f4115a5-9f48-47a0-9c1c-f8bb62ed7e25",
   "slug": "shortcodes",
   "title": "Shortcodes",
   "description": "Put Dashbread on any page: sign-in forms, members-only content, plan cards, charts and tasks."
  },
  {
   "id": "28ba9a52-4793-4e50-aadd-6c6be5c7c4c4",
   "slug": "developers",
   "title": "Developers",
   "description": "Hooks, filters, islands and data sources for building your own plugin into the app."
  },
  {
   "id": "30ef656d-c943-4322-8da7-a3f5fd790014",
   "slug": "billing",
   "title": "Billing & licensing",
   "description": "Licenses, site limits, renewals, upgrades and refunds."
  }
 ],
 "articles": [
  {
   "slug": "communications",
   "title": "Communications",
   "excerpt": "One contact list for members and visitors, with lists, tags, segments, sign-up forms, double opt-in and a preference center. Broadcasts, reports and automations follow.",
   "category": "pmas",
   "category_id": "fedde577-81c2-41c4-a5c6-6959d42fdf68",
   "body": "<p><em>Coming soon.</em> Communications is in testing and will be available to buy once email sending is ready.</p>\n<h4>About</h4><p>Communications is email marketing that lives inside Dashbread. Every member of your site gets a contact record automatically, and visitors who sign up through a form get one too, so you keep one list instead of copying people between WordPress and a separate email tool. Each contact has lists, tags, custom fields, team notes, a consent record and an activity timeline that shows what they did on your site: forms sent, plans started or ended, tools used, companies joined.</p><p>This first release covers your audience: contacts, lists and tags, segments, sign-up forms, double opt-in, the preference center, and importing from CSV, Mailster or Groundhogg. The email editor, broadcasts, sending through your SMTP or email API (SparkPost, Emailit, Amazon SES, Mailgun, SendGrid, Postmark, Brevo), reports and automations arrive in the next updates.</p>\n<h4>Use cases</h4><ul><li>A newsletter list that grows from a popup on your blog and a checkbox on your registration form.</li><li>Tagging members by plan automatically (for example \"Plan: Gold\"), so you can reach everyone on a plan or everyone who left one.</li><li>A segment of members who haven't signed in for 30 days, or visitors who sent a particular form.</li><li>Moving off Mailster or Groundhogg without losing subscriber status, lists, tags or notes.</li></ul>\n<h4>How to use</h4><ol><li>Go to <strong>Dashbread › Communications › Settings</strong>. Fill in the sender name and email, your company name and postal address (they appear in the footer of every email), and choose whether members are added as contacts automatically.</li><li>Open <strong>Lists and tags</strong> and create your lists. Leave <strong>Double opt-in</strong> on for a list when people should confirm by email before they're subscribed.</li><li>Open <strong>Sign-up forms</strong> and create a form. Choose the lists, whether people pick lists themselves, and how it appears: inline with the shortcode shown on the form (for example <code>[dashbread_signup id=\"k3x9p2qa\"]</code>), or as a popup or slide-in shown after a delay, on scroll, or when someone is about to leave.</li><li>To add people from an Advanced Forms form, open the form's <strong>Actions</strong> tab and turn on <strong>Add to Communications</strong>. Choose the email field, the consent field and the lists and tags.</li><li>Use <strong>Contacts</strong> to search, filter and open a contact. Select several to add or remove tags and lists, change status or send confirmation emails in bulk.</li><li>Use <strong>Segments</strong> to save a group defined by conditions, for example \"status is subscribed and plan is Gold and last activity more than 30 days ago\".</li><li>Use <strong>Import &amp; export</strong> to bring in a CSV (you map the columns) or copy contacts straight from Mailster or Groundhogg if either is installed on the same site.</li></ol>\n<h4>Consent and unsubscribing</h4><p>Only contacts who are <strong>Subscribed</strong> will receive marketing email. Anyone who signs up through a form gets a confirmation email when the list requires it, and their consent is recorded with the time, the form, the wording they agreed to and their IP address. When you import or mark someone subscribed yourself, Dashbread asks you to confirm you have their permission. Every email carries a link to the preference center, where people choose their lists or unsubscribe from everything with one click. Members also find these choices under <strong>Profile › Email preferences</strong>.</p>\n<h4>For developers</h4><p>Actions: <code>dashbread_comms_contact_created</code>, <code>dashbread_comms_signup</code>, <code>dashbread_comms_unsubscribed</code>. Filter <code>dashbread_comms_segment_fields</code> adds segment conditions. Contacts are also a Data &amp; Graphs object, with sources for new contacts and unsubscribes. The WordPress personal data exporter and eraser include Communications data.</p>"
  },
  {
   "slug": "advanced-forms-steps-uploads",
   "title": "Multi-step forms, file uploads, repeaters and more (Advanced Forms)",
   "excerpt": "Split long forms into pages, collect files and line items, let people save and come back, sign them up, and send entries to other apps.",
   "category": "pmas",
   "category_id": "fedde577-81c2-41c4-a5c6-6959d42fdf68",
   "body": "<h4>About</h4><p>Advanced Forms can handle longer, richer forms: application forms over several pages, order forms with line items, requests with attachments. People can save their answers and finish later, and each entry can make a member account or go straight to another app.</p>\n<h4>Multi-step forms</h4><ul><li>Add a <strong>Page break</strong> field (under Layout) wherever a new page should start. Give each page a title if you like.</li><li>People move with <strong>Next</strong> and <strong>Back</strong>. Each page is checked before they go on, and pages whose questions are all hidden by conditional logic are skipped.</li><li>Under <strong>Settings › Pages</strong> choose the progress display (a bar, step names, or none) and the button text.</li></ul>\n<h4>File uploads</h4><ul><li>Add a <strong>File upload</strong> field. Choose how many files (up to 10), the largest size (up to 50 MB) and which kinds: images, documents, spreadsheets, ZIP, audio or video. Web pages, scripts and SVG images are never accepted.</li><li>Files upload as soon as they're picked. They're stored privately: only administrators can download them, from the entry or the links in the notification email.</li><li>Files nobody sends are removed after a day. Deleting an entry or form deletes its files.</li></ul>\n<h4>Repeaters</h4><ul><li>Add a <strong>Repeater</strong> for anything people list row by row: items, attendees, references. Pick its columns (text, paragraph, number, email, phone, date or dropdown), which are required, and the fewest and most rows.</li><li>Entries show the rows as a table; emails and exports put one row per line. In logic, a repeater compares as its number of rows.</li></ul>\n<h4>Save and continue later</h4><ul><li>Turn it on under <strong>Settings › Save and continue later</strong>. Visitors get a private link (they can email it to themselves); signed-in members' answers are saved as they type and come back when they return.</li><li>Saved answers are kept for the number of days you choose (30 by default), including uploaded files.</li></ul>\n<h4>Actions</h4><ul><li><strong>Create a member account</strong>: people who send the form get an account from its Email and Name fields, an email to set their password and, if you like, a plan. They can be signed in straight away. If the address already has an account, nobody is signed in — they're asked to sign in instead. For forms that take a payment, the account is made once they've paid.</li><li><strong>Webhooks</strong>: send each entry as JSON to up to five URLs (Zapier, Make, your own server). Requests are signed with a secret (<code>X-Dashbread-Signature</code>), failures are retried for about 15 hours, and a log shows every delivery with a Retry button. Use <strong>Send test</strong> to try a URL.</li></ul>\n<h4>Spam protection with Cloudflare Turnstile</h4><p>Add your free Turnstile keys under <strong>Forms › Spam protection</strong>, then switch it on in a form's Settings. The secret key is stored encrypted, and administrators aren't challenged.</p>\n<h4>Works with the rest of Pro</h4><ul><li><strong>Tasks</strong>: a checklist can be assigned when a member first sends a form.</li><li><strong>Offers</strong>: aim an offer at members who sent certain forms.</li><li><strong>Graphs</strong>: a Form entries source and object for charts.</li></ul>\n<h4>For developers</h4><p>Filter <code>dashbread_form_webhook_payload</code> changes the JSON; <code>dashbread_turnstile_verify</code> can replace the Turnstile check. Action <code>dashbread_form_registered</code> fires when a form makes an account.</p>"
  },
  {
   "slug": "form-payments",
   "title": "Take payments with a form (Advanced Forms)",
   "excerpt": "Charge when someone sends a form — event fees, deposits, paid applications — through your own Stripe account.",
   "category": "pmas",
   "category_id": "fedde577-81c2-41c4-a5c6-6959d42fdf68",
   "body": "<p>The Payment field is part of Advanced Forms. It uses Pro's Stripe connection (Dashbread › Payments).</p>\n<h4>About</h4><p>Add a <strong>Payment</strong> field to any form and people pay when they send it. They go to Stripe's secure checkout, then come straight back to your page to see your confirmation, the amount paid and a receipt link. Nothing is sent to you or them until the payment goes through.</p>\n<h4>Use cases</h4><ul><li>Event registration with Early bird and Regular tickets.</li><li>A deposit or booking fee on a request form.</li><li>A paid application, or a donation form where people choose the amount.</li></ul>\n<h4>Set it up</h4><ol><li>Connect Stripe under <strong>Dashbread › Payments</strong> (test keys first).</li><li>In a form, add <strong>Payment</strong> (under Advanced) and choose how much to charge:<ul><li><strong>Fixed</strong> — one amount.</li><li><strong>Options</strong> — a list of choices, each with its own price. People pick one.</li><li><strong>From a field</strong> — the amount in a Number or Calculation field (for example a donation or an order total), with an optional minimum.</li></ul></li><li>Optionally set the name shown on the receipt (it defaults to the form's name). Publish.</li></ol>\n<p>The form shows a live <strong>Total</strong>. A form can have one Payment field, and it won't publish until the amount is set up.</p>\n<h4>What happens</h4><ul><li>When someone sends the form, their entry is saved as <strong>Unpaid</strong> and they go to Stripe checkout. Members pay as their Stripe customer; visitors get their email filled in.</li><li>Once they pay, the entry moves to your inbox, notifications go out, and they see your confirmation with <em>Payment received</em> and a receipt link.</li><li>If they cancel, nothing is charged or sent; they see a note and can try again. Their entry stays under the <strong>Unpaid</strong> tab.</li><li>Form payments appear under <strong>Dashbread › Payments</strong> with a link to the entry. Refund them there; the entry shows the refund too.</li></ul>\n<h4>Merge tags</h4><p><code>%%PAYMENT_AMOUNT%%</code>, <code>%%PAYMENT_STATUS%%</code> and <code>%%PAYMENT_RECEIPT%%</code> work in confirmations and notifications.</p>\n<h4>For developers</h4><p>Filter <code>dashbread_form_checkout_params</code> to change the Checkout Session (tax, locale, custom fields). Action <code>dashbread_form_paid</code> fires once a form payment goes through.</p>"
  },
  {
   "slug": "tool-builder",
   "title": "Tool Builder: tools, access and results",
   "excerpt": "Turn any form into a tool — a calculator, quote, quiz or AI plan — with its own landing page, who-can-use-it rules (free, members, plans, lead magnet or paid), and a result page, PDF and email.",
   "category": "pmas",
   "category_id": "fedde577-81c2-41c4-a5c6-6959d42fdf68",
   "body": "<p>Tool Builder includes everything in Advanced Forms, plus <strong>calculations and lookup tables</strong> and <strong>AI results</strong>.</p>\n<h4>About</h4><p>A tool is a form that gives people something back: a price quote, a mortgage estimate, a quiz result, a savings plan written by AI. Tool Builder gives each tool a landing page, rules for who can use it, and a result people keep: a page of its own, a clean PDF and an email. Members find their tools under <strong>Tools</strong> in the app and everything they got back under <strong>My results</strong>.</p>\n<h4>Use cases</h4><ul><li>A quote calculator on your pricing page that emails the visitor a PDF quote.</li><li>A members-only mortgage or ROI calculator that saves each member's numbers.</li><li>A quiz lead magnet: visitors get their result by email, you get their address and their \"type\".</li><li>A paid assessment: people buy access once (or monthly) through your Stripe account.</li></ul>\n<h4>Make a tool</h4><ol><li>Open <strong>Dashbread › Tools</strong> and click <strong>New tool</strong>. Start from a starter (Savings coach with AI, Price quote calculator, Mortgage calculator, Quiz lead magnet) or a blank tool. Any existing form can become a tool too: open it and switch on the <strong>Tool</strong> tab.</li><li>On the <strong>Tool</strong> tab, write what it does, pick an icon and a category, and choose whether it's listed under Tools in the app.</li><li>Publish. The tool gets an app link (<code>/app/tools/your-tool</code>) and a shortcode for any page: <code>[dashbread_tool id=\"your-tool\"]</code>.</li></ol>\n<h4>Who can use it</h4><ul><li><strong>Anyone</strong> — visitors and members.</li><li><strong>Signed-in members</strong> — visitors are asked to sign in or create an account first.</li><li><strong>Members of certain plans</strong> — everyone else sees which plans include it, with buy buttons when the plan has a price.</li><li><strong>Lead magnet</strong> — anyone can use it and the result is emailed to them (the form needs an Email field).</li><li><strong>Paid</strong> — enter a price and choose one-time, monthly or yearly, then click <strong>Set price</strong>. Dashbread makes a plan for the tool (kept off your pricing table) and sells it through <strong>Plans billing</strong>. After checkout, buyers land back on the tool, unlocked.</li></ul>\n<h4>The result</h4><ol><li>Give the result a title, e.g. <code>%%FIRST_NAME%%'s savings plan</code>.</li><li>Write what it shows with merge tags: any answer (<code>%%TOTAL%%</code>), <code>%%NAME%%</code>, <code>%%DATE%%</code>, <code>%%ALL_FIELDS%%</code> (every answer in a table), and with AI, <code>%%AI_RESULT%%</code> and <code>%%ARCHETYPE%%</code>. Leave it empty to show the AI result (if any) and the answers. Click <strong>Preview</strong> to see it filled in with the latest entry.</li><li>Choose: keep a result page, offer a PDF, and email the result (with the PDF attached, sent once the AI has answered).</li></ol>\n<p>After someone sends the form, links to <strong>View your full result</strong> and <strong>Download PDF</strong> appear under the confirmation. Visitors' result pages use a private link; members' results live in the app. Notifications can use <code>%%RESULT_URL%%</code> and <code>%%RESULT_PDF_URL%%</code>.</p>\n<h4>Works with</h4><ul><li><strong>Offers</strong> — aim an offer at members who used a tool, or who got a certain archetype.</li><li><strong>Tasks</strong> — a checklist can start \"when a member first uses\" a tool.</li><li><strong>Data &amp; Graphs</strong> — Tool results, AI runs and My tool results sources.</li><li><strong>Dashboard</strong> — the <strong>Dashbread Tools</strong> widget shows each member's latest results and tools to try.</li><li>Members get a \"your result is ready\" notification.</li></ul>\n<h4>Good to know</h4><ul><li>Access is checked when the form shows and again when it's sent.</li><li>Deleting an entry also turns off its result links.</li><li>PDFs need the PHP dom and mbstring extensions (standard on most hosts).</li><li>If Tool Builder lapses, tool pages show nothing and forms keep working as plain forms; your tools and results are kept.</li></ul>\n<h4>For developers</h4><p>Filters: <code>dashbread_tool_result_html</code>, <code>dashbread_tool_pdf_template</code>, <code>dashbread_tool_pdf_paper</code>, <code>dashbread_form_tags</code>, <code>dashbread_form_response</code>. Actions: <code>dashbread_tool_used</code>, <code>dashbread_tool_result_ready</code>.</p>"
  },
  {
   "slug": "ai-results",
   "title": "AI results for forms (Tool Builder)",
   "excerpt": "Give each person a personalized result written by AI from their answers and your own data, using your own OpenAI or Anthropic key.",
   "category": "pmas",
   "category_id": "fedde577-81c2-41c4-a5c6-6959d42fdf68",
   "body": "<p>AI results are part of the Tool Builder add-on.</p>\n<h4>About</h4><p>Turn a form into an advisor. After someone sends the form, AI writes them a personalized result — a plan, a recommendation, a summary — from their answers and the information you give it. It shows under the confirmation message, can be emailed, and is saved with the entry. You bring your own OpenAI or Anthropic API key, so requests go straight from your site to the provider and you pay them only for what you use.</p>\n<h4>Use cases</h4><ul><li>A savings coach: budget and goals in, a step-by-step plan out, based on your own house rules.</li><li>A product finder that recommends from your price table and product pages.</li><li>A quiz that tags each person with an archetype (for example <em>big-saver</em> or <em>investor</em>) you can use to target offers.</li></ul>\n<h4>Set up the provider</h4><ol><li>Open <strong>Dashbread › AI › Provider &amp; limits</strong>, choose OpenAI or Anthropic and paste your API key. It is stored encrypted.</li><li>Click <strong>Check key</strong> to load the models your key can use, pick one, and save.</li><li>Set limits: runs per month for the whole site, per member per month, and per visitor per day. When a limit is reached the form still works; people just don't get an AI result.</li></ol>\n<h4>Add AI to a form</h4><ol><li>In the form builder open the <strong>AI</strong> tab and turn it on.</li><li>Write the prompt. <strong>Insert an answer</strong> adds tags like <code>%%BUDGET%%</code>; <code>%%ALL_FIELDS%%</code> adds every answer.</li><li>Add <strong>data sources</strong> and rank each as primary, secondary or tertiary: pasted text, a web address, a page on your site, a lookup table, or totals from this form's entries. Primary sources win when they disagree. Turn <strong>general knowledge</strong> off to keep the AI to your sources.</li><li>Choose whether to show the result on the page, its heading, and whether to tag an archetype (optionally from your own list).</li><li>Use <strong>Try it</strong> with sample answers to see the result and the exact prompt sent.</li></ol>\n<h4>Emailing the result</h4><p>Put <code>%%AI_RESULT%%</code> (and <code>%%ARCHETYPE%%</code> if you like) in a notification on the Notifications tab. That notification waits for the AI; the others go right away. If the AI can't answer, it still goes with a short fallback line.</p>\n<h4>Good to know</h4><ul><li>Results are cleaned to simple formatting — no scripts, styles or images.</li><li>Answers and sources are treated as information, never as instructions to the AI.</li><li><strong>Dashbread › AI › Usage</strong> logs every run with model, tokens, time and result; staff can open an entry and click <strong>Run again</strong>.</li><li>Members' archetypes are saved on their profile, per form.</li><li>Runs happen in the background; sites with WP-Cron turned off still work, because the page asks for the result.</li></ul>"
  },
  {
   "slug": "calculations-and-lookup-tables",
   "title": "Calculated fields and lookup tables (Tool Builder)",
   "excerpt": "Add live calculations to forms — prices, quotes, estimates — and look values up in tables of rates or tiers.",
   "category": "pmas",
   "category_id": "fedde577-81c2-41c4-a5c6-6959d42fdf68",
   "body": "<p>Calculated fields and lookup tables are part of the Tool Builder add-on. Tool Builder includes everything in Advanced Forms.</p>\n<h4>About</h4><p>Calculated fields turn a form into a calculator: a quote, an estimate, a loan payment, a price with tax. Results update as people type, show with the decimals and symbols you choose, and are worked out again on the server when the form is sent, so what's saved can't be tampered with. Lookup tables hold the numbers your calculations need — tax rates by ZIP code, price tiers by size, product lists — and a dropdown can take its options straight from one.</p>\n<h4>Use cases</h4><ul><li>A quote form: quantity × unit price, plus sales tax looked up by ZIP code, plus an install fee by square footage.</li><li>A mortgage calculator using <code>pmt()</code>.</li><li>A course price that changes with the options someone ticks, with a \"PO number\" field that only appears for orders over $1,000.</li></ul>\n<h4>Lookup tables</h4><ol><li>Open <strong>Dashbread › Lookup tables</strong> and click <strong>New table</strong>. Name it and set its columns (text or number).</li><li>Type rows into the grid, or <strong>Import CSV</strong>: <em>Replace</em> uses the file's header row as the columns; <em>Add rows</em> matches the headers to your columns.</li><li>The table's <strong>short name</strong> (for example <code>sales_tax</code>) is what formulas use. Tables hold up to 20,000 rows.</li></ol>\n<h4>Calculated fields</h4><ol><li>In a form, add a <strong>Calculation</strong> field (under Advanced).</li><li>Write the formula. Answers are <code>{field_key}</code>; use <code>+ - * /</code>, <code>^</code> for powers, <code>&amp;</code> to join text, and <code>= != &lt; &gt; and or not</code> to compare. <strong>Insert a field</strong>, <strong>Insert a function</strong> and <strong>Look up in a table</strong> write the pieces for you.</li><li>Choose the decimals, and text to show before or after the result (like <code>$</code> or <code>/mo</code>). <strong>Hide from the form</strong> keeps a step-in-the-middle result out of sight but still saves it.</li><li>Open <strong>Try it</strong>, type sample answers and click <strong>Calculate</strong> to check the result.</li></ol>\n<h4>Functions</h4><p><code>round(x, 2)</code>, <code>floor</code>, <code>ceil</code>, <code>abs</code>, <code>min</code>, <code>max</code>, <code>sum</code>, <code>avg</code>, <code>count</code>, <code>if(condition, then, otherwise)</code>, <code>and</code>, <code>or</code>, <code>not</code>, <code>blank</code>, <code>number</code>, <code>text(x, 2)</code>, <code>concat</code>, <code>len</code>, <code>pmt(rate, periods, amount)</code>, <code>lookup(\"table\", \"match column\", value, \"return column\")</code> and <code>range_lookup(\"table\", value, \"min column\", \"max column\", \"return column\")</code> (a blank min or max means \"no limit\").</p>\n<h4>Good to know</h4><ul><li>Blank answers count as 0. Dividing by zero, or looking up a table that doesn't exist, leaves the result blank.</li><li>A formula can only use fields above it. Conditional logic can test a calculation's result.</li><li>A form won't publish while a formula has a problem; the builder marks the field \"check formula\".</li><li>Small tables are sent with the form so results appear instantly; tables over 1,500 rows are calculated on the server as people type.</li><li>Entries, notifications (<code>%%TOTAL%%</code>) and CSV exports include calculation results.</li></ul>\n<h4>For developers</h4><p>The formula language lives in the shared forms engine (<code>Formula</code> and <code>Calculate</code>, in PHP and JavaScript, kept identical by a shared test file), so OrgFuse can offer the same calculations.</p>"
  },
  {
   "slug": "plans-billing",
   "title": "Plans billing with Stripe",
   "excerpt": "Sell your plans with Stripe: prices, free trials, hosted checkout, renewals and a billing page for members.",
   "category": "pro",
   "category_id": "9cfcc2e5-779e-4061-a250-7ac5853be6cc",
   "body": "<h4>About</h4><p>Plans billing lets members pay for a plan with Stripe. You give a plan one or more prices (one-time, or every so many days, weeks, months or years, with an optional free trial). Members pay on Stripe's secure checkout page, and their membership switches on, renews and ends by itself as Stripe collects. Members get a billing page for their card, invoices and cancellation, and you get a Payments screen with revenue, subscriptions and refunds. It's part of Dashbread Pro, no add-on needed.</p>\n<h4>Use cases</h4><ul><li>A $19/month Pro plan with a 7-day free trial and a $199/year option.</li><li>A one-time $49 pass that gives 30 days of access.</li><li>A pricing table on your public site that sends visitors to sign in, then straight to checkout.</li></ul>\n<h4>Set up Stripe</h4><ol><li>Open <strong>Dashbread › Payments › Stripe settings</strong>. Paste your test publishable and secret keys (from Stripe › Developers › API keys). A restricted key works too.</li><li>In Stripe › Developers › Webhooks, add an endpoint with the webhook URL shown on the screen, choose the events listed under it, and paste its signing secret into <strong>Webhook signing secret</strong>.</li><li>Click <strong>Test connection</strong>. You should see your Stripe account's name.</li><li>When you're ready to take real payments, add the live keys and a live webhook endpoint the same way, then switch <strong>Mode</strong> to Live. Test and live settings are kept side by side.</li></ol>\n<h4>Sell a plan</h4><ol><li>Open <strong>Dashbread › Plans</strong>, pick a plan and open the <strong>Pricing</strong> tab.</li><li>Click <strong>Add a price</strong>: the amount, how often to charge, and an optional free trial. Add as many prices as you like (monthly and yearly, say).</li><li>Members now see <strong>Subscribe</strong> or <strong>Buy</strong> buttons for the plan on <code>/app/membership</code>. To show plan cards on a public page, add <code>[dashbread_pricing]</code> (or <code>[dashbread_pricing plans=\"pro,team\" highlight=\"pro\"]</code>).</li></ol>\n<h4>How memberships follow payments</h4><ul><li>A new subscription (or trial) puts the member on the plan until the paid-up date, plus a few grace days (Payments settings).</li><li>Each renewal pushes that date out. If a renewal fails, the member keeps access while Stripe retries and is told to update their card.</li><li>If the subscription is cancelled, the member keeps access to the end of the period it was paid for. When it ends, the membership ends.</li><li>A one-time price uses the plan's duration (or keeps the member on the plan until you revoke it).</li><li>Each member gets one free trial per plan. A member can't take out two subscriptions to the same plan.</li><li>Memberships change only when Stripe confirms it through the webhook, never from the checkout page alone.</li></ul>\n<h4>Payments screen</h4><p><strong>Dashbread › Payments › Overview</strong> shows revenue for the last 30 days, running subscriptions and every payment. From there you can cancel a subscription at the period end (or end it now), resume one, open anything in Stripe, and refund a payment. A refund can also end the membership it paid for.</p>\n<h4>For members</h4><p><code>/app/membership</code> shows each plan with its trial end or renewal date, a <strong>Keep my subscription</strong> button if they've cancelled, a <strong>Manage billing</strong> button that opens Stripe's billing page (card, invoices, cancel), and their payment history with receipts.</p>\n<h4>For developers</h4><p>Filter <code>dashbread_checkout_params</code> adjusts the Stripe Checkout Session (tax, locale, custom fields). Memberships fire the usual <code>dashbread_membership_granted</code> and <code>dashbread_membership_revoked</code> actions, with source <code>stripe</code>. One Stripe account can serve several sites: each object carries the site address in its metadata, and events for other sites are ignored.</p>"
  },
  {
   "slug": "advanced-forms",
   "title": "Advanced Forms",
   "excerpt": "Build forms in wp-admin, show them on any page or inside the app, and work through entries in an inbox.",
   "category": "pmas",
   "category_id": "fedde577-81c2-41c4-a5c6-6959d42fdf68",
   "body": "<h4>About</h4><p>Advanced Forms lets you build forms in wp-admin and put them anywhere: on any page with a shortcode, or on their own page inside the member app. Forms have conditional logic, confirmation messages or redirects, email notifications, and an entries inbox with search and CSV export. Spam protection works without a captcha: a hidden honeypot, a minimum fill time and a per-visitor hourly limit. Signed-in members get their name and email filled in for them. With Dashbread Pro's Stripe connection, a <strong>Payment</strong> field can charge when the form is sent — event fees, deposits, paid applications (see <em>Take payments with a form</em>).</p><p>Longer forms can be split into pages, collect file uploads and repeating rows, let people save and finish later, create a member account, send each entry to other apps by webhook, and use Cloudflare Turnstile (see <em>Multi-step forms, file uploads, repeaters and more</em>).</p>\n<h4>Use cases</h4><ul><li>A contact or support form that asks for an order number only when the topic is Billing.</li><li>An RSVP, feedback survey or quote request that emails your team and thanks the person who sent it.</li><li>A members-only request form inside the app, with each entry linked to the member who sent it.</li></ul>\n<h4>How to use</h4><ol><li>Buy the add-on (or the All PMAs bundle, Lifetime, or Tool Builder, which includes it). Your license refreshes and <strong>Dashbread › Forms</strong> appears; there is nothing to install.</li><li>Click <strong>New form</strong> and pick a starter: blank, contact, support, quote, RSVP, feedback or signup.</li><li>On <strong>Fields</strong>, add fields from the left, drag to reorder, and click a field to change its label, options, width, default value and help text. Turn on <strong>Only show this field when…</strong> to add conditional logic.</li><li>On <strong>Confirmations</strong> and <strong>Notifications</strong>, set what the person sees after sending and who gets an email. Merge tags such as <code>%%EMAIL%%</code> and <code>%%ALL_FIELDS%%</code> fill in answers.</li><li>On <strong>Settings</strong>, choose who can fill it in (anyone or signed-in members), the submit button label, an entry limit and spam settings.</li><li>Publish. On <strong>Share</strong>, copy the shortcode (for example <code>[dashbread_form id=\"contact-us\"]</code>) or click <strong>Show inside the app</strong>.</li><li>Entries arrive under <strong>Entries</strong>: open one to read it (it's marked read), mark it spam, trash it, resend notifications or export everything to CSV.</li></ol>\n<h4>Good to know</h4><ul><li>Drafts are only visible to administrators; use <strong>Preview</strong> to try them.</li><li>A field's logic can only test fields above it. Answers to hidden fields are never stored.</li><li>Add <code>title=\"1\"</code> to the shortcode to show the form's name above it. Add <code>?key=value</code> to a page address to pre-fill a field that has <strong>Fill from the page address</strong> set.</li><li>If the license lapses, forms stop showing (no raw shortcodes appear) and your forms and entries stay in the database.</li></ul>\n<h4>For developers</h4><p>Filter <code>dashbread_form_validate</code> can refuse a submission with a <code>WP_Error</code>; action <code>dashbread_form_submitted</code> fires with the form, entry id, answers and member id; filter <code>dashbread_form_templates</code> adds or changes starters. Validation, logic and notifications come from the same shared forms engine OrgFuse uses.</p>"
  },
  {
   "slug": "graph-sources",
   "title": "Graph sources for developers",
   "excerpt": "Add a chart source or a whole table to Data & Graphs from your own plugin.",
   "category": "developers",
   "category_id": "28ba9a52-4793-4e50-aadd-6c6be5c7c4c4",
   "body": "<h4>About</h4><p>Data &amp; Graphs has two extension points. <code>dashbread_graph_sources</code> registers a ready-made source: a label, description, group (<code>site</code> or <code>me</code>), the capability needed to see it, the chart kinds it supports, and a <code>resolve( $days, $user_id )</code> callback returning labels and series. <code>dashbread_graph_objects</code> goes further and adds one of your plugin's database tables to the query builder, so site owners build their own charts from it.</p><p>An object describes its table (it must exist under the WordPress prefix), primary key, owner column (for \"each member's own\" sources), date column, an optional fixed WHERE, an optional meta table, and its properties with types — text, enum (with options), number, date, bool, user or lookup (a label from another table). Mark anything personal as <code>sensitive</code> and it is never offered. Unknown tables and columns are dropped, and every query is built and prepared by Dashbread.</p><h4>Use cases</h4><ul><li>A work-order plugin exposes its orders table so managers can chart \"Work orders by status\" and \"Completed per week\".</li><li>A plugin registers a fixed \"Invoices paid\" source with its own resolve callback.</li></ul><h4>How to use</h4><ol><li>Hook <code>dashbread_graph_objects</code> and add an entry keyed by your table name with <code>label</code>, <code>group</code>, <code>table</code>, <code>key</code>, <code>owner</code>, <code>date</code> and <code>properties</code>.</li><li>Give enum properties their <code>options</code>, and lookups their <code>[table, key, label]</code>.</li><li>Mark emails, phone numbers and similar as <code>'sensitive' =&gt; true</code>.</li><li>Open Dashbread › Graphs › New custom source — your object appears in the list.</li></ol>"
  },
  {
   "slug": "custom-graphs",
   "title": "Custom graph sources (query builder)",
   "excerpt": "Build your own chart source from users, posts, comments or Dashbread data — filters, grouping and sums, no SQL.",
   "category": "pmas",
   "category_id": "fedde577-81c2-41c4-a5c6-6959d42fdf68",
   "body": "<h4>About</h4><p>The query builder lets you turn your own data into a chart source without writing SQL. Pick an <strong>object</strong> — users, any post type, comments, or Dashbread's own data (notifications, messages, companies, memberships, email log, tasks) — then what to measure (a count, or the sum or average of a number), and the shape: <strong>over time</strong> by a date, or <strong>grouped by</strong> a property or one custom field. Add up to eight filters with operators that fit each field, and merge tags like <code>{current_user}</code>, <code>{today}</code> and <code>{days_ago:30}</code>.</p><p>Security comes first: only fields Dashbread knows about can be used, sensitive columns (emails, logins, phones, IP addresses) are never offered, secret-looking custom fields are blocked, and every query is built and escaped by Dashbread. A source can be site-wide (choose which capability may see it) or <em>each member's own</em>, which always limits it to the viewer's rows.</p><h4>Use cases</h4><ul><li>An admin charts \"Orders by status\" from a post type, filtered to the last 90 days.</li><li>A portal gives every member a donut of their own tasks by priority.</li></ul><h4>How to use</h4><ol><li>Open <strong>Dashbread › Graphs</strong> and click <strong>New custom source</strong>.</li><li>Name it, choose the object, the measure and the shape (over time or grouped).</li><li>Add filters; pick values from the list or type a merge tag.</li><li>Choose who sees it — site (and the capability required) or each member's own — and watch the live preview.</li><li>Click <strong>Create</strong>. The new source appears in the list; add it to the dashboard like any other.</li></ol>"
  },
  {
   "slug": "shortcodes",
   "title": "Shortcode reference",
   "excerpt": "Every Dashbread shortcode in one place — grouped by Core, Pro and add-on — with what each does and the options it takes.",
   "category": "shortcodes",
   "category_id": "0f4115a5-9f48-47a0-9c1c-f8bb62ed7e25",
   "body": "<h4>About</h4><p>Shortcodes are the <code>[bracketed]</code> tags you paste into a page or post (or a Shortcode block) to put a Dashbread feature on it — a sign-in form, members-only content, plan cards, a chart. They work on your theme's public pages and on hosted pages inside the app. This reference lists every tag Dashbread ships, grouped by whether it comes with free Core, with Pro, or with a specific add-on.</p><p>Inside wp-admin, <strong>Dashbread › Help</strong> shows this same list with a one-click <strong>Copy</strong> button beside every tag, and marks any tag your license doesn't include yet. Tags whose feature is switched off render nothing, so a page never shows raw brackets.</p><h4>Use cases</h4><ul><li>You're building a public \"Members\" page and need a sign-in form plus content only signed-in people should see.</li><li>You're adding a pricing section that shows plan cards to visitors and an upgrade prompt to members on the basic plan.</li></ul><h4>How to use</h4><ol><li>Find the tag you need below (or in Dashbread › Help, where you can search and copy).</li><li>Paste it into a page, post or Shortcode block. Tags with a closing tag wrap the content they control: <code>[dashbread_logged_in]</code>…<code>[/dashbread_logged_in]</code>.</li><li>Add any options shown beside it, e.g. <code>plan=\"gold\"</code> or <code>range=\"90\"</code>.</li><li>Publish and view the page signed in and signed out to check both sides.</li></ol><h4>Core (free)</h4><table><thead><tr><th>Shortcode</th><th>What it does</th><th>Options</th></tr></thead><tbody><tr><td><code>[dashbread_login]</code></td><td>The sign-in form on any page. Signed-in people see \"Open the app\" and \"Sign out\" instead.</td><td>redirect=\"profile\" (an app page or a same-site URL) · email_only=\"1\" · title=\"\"</td></tr><tr><td><code>[dashbread_app_link]</code></td><td>A button into the app for members; visitors see a Sign in button that returns them to the same place.</td><td>label=\"\" · label_out=\"\" · page=\"profile\" · button=\"0\" for a plain link</td></tr><tr><td><code>[dashbread_logged_in]</code> … <code>[/dashbread_logged_in]</code></td><td>Show the enclosed content only to signed-in people.</td><td>—</td></tr><tr><td><code>[dashbread_logged_out]</code> … <code>[/dashbread_logged_out]</code></td><td>Show the enclosed content only to signed-out visitors.</td><td>—</td></tr><tr><td><code>[dashbread_protect]</code> … <code>[/dashbread_protect]</code></td><td>Members-only gate: visitors get a sign-in prompt, and people outside the roles get a message, instead of the content.</td><td>roles=\"subscriber,editor\" · message=\"\"</td></tr><tr><td><code>[dashbread_role is=\"editor\"]</code> … <code>[/dashbread_role]</code></td><td>Show content only to these roles; everyone else sees nothing.</td><td>is=\"\" · not=\"\" (hide from roles instead)</td></tr><tr><td><code>[dashbread_show from=\"…\" until=\"…\"]</code> … <code>[/dashbread_show]</code></td><td>Show content inside a date window, in the site's time zone. Alias <code>[dashbread_expire]</code>.</td><td>from=\"2026-10-01\" · until=\"2026-12-31 17:00\" (a bare date runs to the end of that day)</td></tr><tr><td><code>[dashbread_user field=\"first_name\"]</code></td><td>The signed-in person's own details.</td><td>field=\"display_name|first_name|last_name|email|username\" · fallback=\"\"</td></tr></tbody></table><h4>Pro</h4><table><thead><tr><th>Shortcode</th><th>What it does</th><th>Options</th></tr></thead><tbody><tr><td><code>[dashbread_has_plan plan=\"gold\"]</code> … <code>[/dashbread_has_plan]</code></td><td>Content for members with an active membership on these plans.</td><td>plan=\"gold,silver\" (slugs or ids; empty = any plan)</td></tr><tr><td><code>[dashbread_no_plan plan=\"gold\"]</code> … <code>[/dashbread_no_plan]</code></td><td>Content for everyone without that plan, including visitors — upgrade prompts.</td><td>plan=\"\"</td></tr><tr><td><code>[dashbread_plans]</code></td><td>Plan cards with price, features and a Get button; members see \"Your plan\" on the one they have.</td><td>plans=\"gold,silver\" · columns=\"1–4\"</td></tr><tr><td><code>[dashbread_field key=\"company_size\"]</code></td><td>The signed-in member's own answer to a custom field.</td><td>key=\"\" · fallback=\"\"</td></tr><tr><td><code>[dashbread_company field=\"name\"]</code></td><td>The signed-in member's primary company.</td><td>field=\"name|city|state|website|phone|email\" · fallback=\"\"</td></tr></tbody></table><h4>Pro Module Add-ons</h4><p>These render app components, so place them on a hosted page. On a theme page, signed-in members get a link to open them in the app instead.</p><table><thead><tr><th>Shortcode</th><th>What it does</th><th>Options</th></tr></thead><tbody><tr><td><code>[dashbread_graph source=\"members_joined\"]</code></td><td>Data &amp; Graphs — a chart inside a hosted page.</td><td>kind=\"stat|line|bar|pie\" · range=\"7|30|90|365\" · ranges=\"1\" · title=\"\"</td></tr><tr><td><code>[dashbread_tasks]</code></td><td>Tasks — the member's open tasks with checkboxes, inside a hosted page.</td><td>limit=\"5\" · add=\"1\" · title=\"\"</td></tr></tbody></table>"
  },
  {
   "slug": "content-gating",
   "title": "Members-only content and upgrade prompts",
   "excerpt": "Recipes for showing the right thing to visitors, members, roles and plans — on any page.",
   "category": "shortcodes",
   "category_id": "0f4115a5-9f48-47a0-9c1c-f8bb62ed7e25",
   "body": "<h4>About</h4><p>Dashbread's conditional shortcodes decide who sees a piece of a page. <code>[dashbread_logged_in]</code> and <code>[dashbread_logged_out]</code> split signed-in people from visitors; <code>[dashbread_protect]</code> swaps content for a sign-in prompt (or a message for the wrong role); <code>[dashbread_role]</code> shows content only to certain roles; <code>[dashbread_show]</code> shows it inside a date window. With Pro, <code>[dashbread_has_plan]</code> and <code>[dashbread_no_plan]</code> do the same for memberships. They nest, so you can combine them.</p><p>For whole pages, it is usually simpler to host the page in the app and use its roles or a plan gate (see <em>Hosted pages</em> and <em>Plans &amp; memberships</em>). Use shortcodes when only part of a public page should change.</p><h4>Use cases</h4><ul><li>A public course page shows the syllabus to everyone, the lesson links to students, and a \"Get Pro\" card to everyone else.</li><li>A homepage banner advertises early-bird pricing until the end of the month and disappears on its own.</li></ul><h4>How to use</h4><ol><li><strong>Members-only section:</strong> <code>[dashbread_protect]</code>Your content<code>[/dashbread_protect]</code> — visitors get a Sign in button.</li><li><strong>Different content for visitors and members:</strong> <code>[dashbread_logged_out]</code>Join us…<code>[/dashbread_logged_out]</code> <code>[dashbread_logged_in]</code>Welcome back, <code>[dashbread_user field=\"first_name\"]</code>!<code>[/dashbread_logged_in]</code></li><li><strong>Upgrade prompt (Pro):</strong> <code>[dashbread_no_plan plan=\"pro\"]</code><code>[dashbread_plans plans=\"pro\"]</code><code>[/dashbread_no_plan]</code> and <code>[dashbread_has_plan plan=\"pro\"]</code>The Pro material…<code>[/dashbread_has_plan]</code></li><li><strong>Staff-only note:</strong> <code>[dashbread_role is=\"editor,administrator\"]</code>Internal link<code>[/dashbread_role]</code></li><li><strong>Time-limited banner:</strong> <code>[dashbread_show until=\"2026-10-31\"]</code>Early-bird pricing ends Oct 31<code>[/dashbread_show]</code></li></ol>"
  },
  {
   "slug": "profile",
   "title": "The member profile",
   "excerpt": "One /app/profile screen for details, password, notification preferences, appearance and account.",
   "category": "getting-started",
   "category_id": "a602a917-92e7-496c-9e6c-e0a6a9fa4da9",
   "body": "<h4>About</h4><p>Every member gets <code>/app/profile</code> with five tabs. <strong>Profile</strong> holds their name, display name, email and any extra fields; <strong>Password</strong> changes it with the current one; <strong>Notifications</strong> lets them mute notification types (Pro adds per-type email opt-outs); <strong>Appearance</strong> picks light, dark or system mode; <strong>Account</strong> shows their account details and sign-out.</p><p>Plugins can add fields to the Profile tab through the <code>dashbread_profile_fields</code> filter. With Pro, the Field builder adds your own fields — text, choices, dates, name and address blocks, file uploads — grouped into sections, targeted by role, and shown only when another answer matches.</p><h4>Use cases</h4><ul><li>A member updates their phone number and turns off notification types they don't care about.</li><li>A site asks members for their company size and region on the profile, then uses those answers to filter the Members screen (Pro).</li></ul><h4>How to use</h4><ol><li>Members open the avatar menu in the header and choose <strong>Profile</strong>, or go to <code>/app/profile</code>.</li><li>Changes save per tab; errors show inline on the field that needs attention.</li><li>Show a member's own details anywhere with <code>[dashbread_user field=\"first_name\"]</code> — or, with Pro, a custom answer with <code>[dashbread_field key=\"…\"]</code>.</li></ol>"
  },
  {
   "slug": "sidebar-and-menus",
   "title": "Sidebar and header menus",
   "excerpt": "Two WordPress menus shape the app's navigation — with icons, role visibility and live badges.",
   "category": "getting-started",
   "category_id": "a602a917-92e7-496c-9e6c-e0a6a9fa4da9",
   "body": "<h4>About</h4><p>The app has two menu locations: <strong>Dashbread Sidebar</strong> (the main navigation) and <strong>Dashbread Header</strong> (links in the account menu). Both are ordinary WordPress menus, so you build them under Appearance › Menus. Dashbread adds two fields to every menu item: an <strong>icon</strong> (any Lucide icon, chosen from a searchable picker) and <strong>Visible to roles</strong>. The menus are created for you on first activation and Dashbread remembers the assignment even if you switch themes.</p><p>Menu items that point at a hosted page link to its app address automatically, and hosted pages you haven't placed in the menu get a link of their own. Native app pages — Notifications, Profile, and Pro's Messages, Tasks, Company and Membership — appear in the sidebar with live count badges where it makes sense.</p><h4>Use cases</h4><ul><li>A site groups its hosted pages into \"Learn\", \"Account\" and \"Help\" sections with nested menu items.</li><li>Staff-only links (an internal handbook, a reports page) are marked visible to the Editor role so members never see them.</li></ul><h4>How to use</h4><ol><li>Go to <strong>Appearance › Menus</strong> and select <strong>Dashbread Sidebar</strong>.</li><li>Add pages, custom links or categories. Nest items to create sections.</li><li>Open each item and choose an <strong>Icon</strong> and, if needed, <strong>Visible to roles</strong>.</li><li>Save and reload <code>/app</code>. Use the <strong>Dashbread Header</strong> menu the same way for account-menu links.</li></ol><h4>How visibility combines</h4><ul><li>A menu item's roles can narrow who sees a hosted page; the page's own roles still apply on top.</li><li>A hosted page that is anywhere in the Dashbread Sidebar menu is never added again automatically — the menu decides.</li><li>A hosted page with an icon passes it to a menu item that has none.</li></ul>"
  },
  {
   "slug": "dashboard-widgets",
   "title": "The dashboard and widgets",
   "excerpt": "The app's home screen is a WordPress widget area rendered as cards that members can collapse and hide.",
   "category": "getting-started",
   "category_id": "a602a917-92e7-496c-9e6c-e0a6a9fa4da9",
   "body": "<h4>About</h4><p>The first screen members see at <code>/app</code> is the dashboard: the <em>Dashbread Dashboard</em> widget area, drawn as a grid of cards. Anything that is a WordPress widget or block works there — text, images, recent posts, a plugin's widget, and Dashbread's own (Pro adds <em>Dashbread Graph</em> and <em>Dashbread Tasks</em>). Widgets without a title get a header built from their first heading.</p><p>Every card has two tools in its header: collapse (the chevron) and hide (the ×). Each member's choices are saved to their own account, and a <strong>Show hidden widgets</strong> button brings hidden ones back. With Pro's Canvas, members can also drag cards into their own order and set each one to one, two or three columns wide.</p><h4>Use cases</h4><ul><li>A portal shows a welcome message, the latest announcements and quick links on everyone's home screen.</li><li>A busy member hides the widgets they never use and collapses the rest to headers.</li></ul><h4>How to use</h4><ol><li>Go to <strong>Appearance › Widgets</strong> and open the <strong>Dashbread Dashboard</strong> area.</li><li>Add widgets or blocks. Give each a title so it gets a proper card header.</li><li>Open <code>/app</code> to see the result; the order in the widget area is the default order.</li><li>Members collapse or hide cards from the card header; <strong>Show hidden widgets</strong> next to the page title restores them.</li><li>(Pro) Click <strong>Customize dashboard</strong> to drag, resize and set a site-wide default — see <em>Dashboard Canvas</em>.</li></ol>"
  },
  {
   "slug": "sign-in-and-registration",
   "title": "Sign-in, registration and password screens",
   "excerpt": "Login, register, lost-password and reset screens that match the app — WordPress still handles the credentials.",
   "category": "getting-started",
   "category_id": "a602a917-92e7-496c-9e6c-e0a6a9fa4da9",
   "body": "<h4>About</h4><p>Dashbread replaces the look of wp-login.php with its own screens at <code>/app/login</code>, <code>/app/register</code>, <code>/app/lost-password</code> and <code>/app/reset-password</code>. They use your logo, colors and preset, keep members on the page for errors and confirmations, and send people back to where they were going after signing in. Credentials still go through WordPress itself, so security plugins, two-factor plugins and password rules keep working.</p><p>Every \"Log in\", \"Register\" and \"Lost your password?\" link WordPress generates points at these screens, and password-reset emails open Dashbread's reset form. Registration follows WordPress's own <em>Anyone can register</em> setting. With Pro, the Field builder can add your own fields to the registration form, and the Customizer can change the layout (card, split or cover) and background.</p><h4>Use cases</h4><ul><li>A membership site lets people register from its pricing page and land straight in the app.</li><li>A company portal keeps registration closed and invites members by creating their accounts; they set a password from the reset email.</li></ul><h4>How to use</h4><ol><li>Under <strong>Dashbread › Settings</strong>, keep <strong>Use Dashbread's login, register, and password screens</strong> on (it is on by default).</li><li>To allow sign-ups, tick <strong>Settings › General › Anyone can register</strong> and choose the default role.</li><li>Put <code>[dashbread_login]</code> on any public page for an inline sign-in form, or <code>[dashbread_app_link]</code> for a button that says Sign in to visitors and Open the app to members.</li><li>Need the original WordPress login (for example to debug a plugin)? Add <code>?native=1</code> to <code>wp-login.php</code>.</li></ol>"
  },
  {
   "slug": "license",
   "title": "Connecting your Pro license",
   "excerpt": "Paste the key under Dashbread › License; Pro and your add-ons switch on and stay current.",
   "category": "pro",
   "category_id": "9cfcc2e5-779e-4061-a250-7ac5853be6cc",
   "body": "<h4>About</h4><p>The <strong>License</strong> screen connects this site to your dashbread.com account. When you connect a key, Dashbread checks it with dashbread.com, records this site as one of your activations, and receives the list of things the license grants: <code>pro</code>, and each add-on as <code>addon:&lt;name&gt;</code> (bundles and Lifetime grant all of them). Pro's screens and modules switch on from that list. The license is re-checked daily; if dashbread.com can't be reached, the last known list stays in place, so a network hiccup never switches anything off.</p><h4>Use cases</h4><ul><li>A site owner connects a new Pro key and the Members, Plans and Messages screens appear straight away.</li><li>An agency moves a license from a staging copy to the live site by disconnecting one and connecting the other.</li></ul><h4>How to use</h4><ol><li>Install and activate Dashbread Pro (Core must be active).</li><li>Open <strong>Dashbread › License</strong>, paste the key from your dashbread.com account and click <strong>Connect license</strong>.</li><li>Check the list of entitlements on the screen — Pro and each add-on you own show as active.</li><li>Bought something new? Click <strong>Check now</strong> (or <strong>Refresh prices</strong> on Pro &amp; Add-ons) instead of waiting for the daily check.</li><li>Moving sites: <strong>Disconnect</strong> here to free the activation, then connect on the other site. Local and development hosts (localhost, <code>.test</code>, <code>.local</code>, private IPs) don't use an activation.</li></ol>"
  },
  {
   "slug": "admin-screens",
   "title": "The Dashbread admin screens",
   "excerpt": "A tour of the Dashbread menu in wp-admin: Dashboard, Settings, Hosted pages, Notifications, Pro & Add-ons and Help.",
   "category": "getting-started",
   "category_id": "a602a917-92e7-496c-9e6c-e0a6a9fa4da9",
   "body": "<h4>About</h4><p>Everything Dashbread manages lives under one <strong>Dashbread</strong> menu in wp-admin, drawn as a single app-style screen with tabs. Core provides <strong>Dashboard</strong> (status, quick links, what's set up), <strong>Settings</strong>, <strong>Hosted pages</strong>, <strong>Notifications</strong> (stats and the broadcast composer), <strong>Pro &amp; Add-ons</strong> and <strong>Help</strong>. When Pro is active it adds its screens to the same menu — License, Members, Plans, Companies, Messages, Email, Fields, Customize, and the add-on screens such as Graphs and Tasks — and only the ones your license covers appear.</p><p><strong>Pro &amp; Add-ons</strong> shows the plans and add-ons with their prices, which plan you are on, and every add-on with its status (Active, Coming soon or Upgrade) and a link to its guide. The prices and this knowledge base ship with each Dashbread release; with Pro active, both come live from dashbread.com. <strong>Help</strong> brings this knowledge base into wp-admin with search, the shortcode reference with one-click copy, and — for Pro licenses — a contact form that opens a support ticket with your system details attached.</p><h4>Use cases</h4><ul><li>An administrator checks the Dashboard tab to confirm permalinks, the app route and the menus are in place.</li><li>A site owner compares plans on Pro &amp; Add-ons, clicks a guide to read how Tasks works, then upgrades.</li></ul><h4>How to use</h4><ol><li>Open the <strong>Dashbread</strong> menu in wp-admin. Tabs across the top switch screens without reloading.</li><li>Use <strong>Help</strong> to search guides, copy shortcodes, or contact support (Pro).</li><li>With Pro, use <strong>Pro &amp; Add-ons › Refresh prices</strong> if you just bought something and want the screen and your license to update right away.</li></ol>"
  },
  {
   "slug": "settings-and-branding",
   "title": "Settings and branding",
   "excerpt": "Logo, colors, preset, light or dark, the app route, and how members move between the site and the app.",
   "category": "getting-started",
   "category_id": "a602a917-92e7-496c-9e6c-e0a6a9fa4da9",
   "body": "<h4>About</h4><p><strong>Dashbread › Settings</strong> is where the free app gets its look and its rules. <em>Branding</em>: app name, logo (from the media library), primary color, footer text. <em>Look</em>: the Console or Comfort preset and the default light, dark or system mode. <em>Behavior</em>: the app route and the member switches — use Dashbread's login screens, land members in the app after login, hide the admin bar for members, send members who open wp-admin to the app, and redirect <code>/login</code> to the app.</p><p>Changes are held until you click <strong>Save</strong>; <strong>Discard</strong> puts the form back. Pro's Customizer goes much further — palettes, sidebar and header styles, fonts, corner shapes, login layouts and custom CSS, all with a live preview — and writes its primary color back here so free and Pro screens always agree.</p><h4>Use cases</h4><ul><li>A studio sets its logo and brand purple and chooses the Comfort preset for a softer member area.</li><li>A site switches the default to dark mode to match its product.</li></ul><h4>How to use</h4><ol><li>Open <strong>Dashbread › Settings</strong>.</li><li>Upload a logo and choose a primary color; the preview updates as you go.</li><li>Pick a preset and default mode, then set the behavior switches.</li><li>Click <strong>Save</strong> and open <code>/app</code> to check.</li></ol>"
  },
  {
   "slug": "upgrades-and-refunds",
   "title": "Upgrades, renewals and refunds",
   "excerpt": "Moving between plans, what renews when, Lifetime, and the 14-day refund window.",
   "category": "billing",
   "category_id": "30ef656d-c943-4322-8da7-a3f5fd790014",
   "body": "<h4>About</h4><p>Pro, add-ons and the All PMAs bundle are annual subscriptions that renew automatically until cancelled; cancelling stops the next renewal and the license stays active to the end of the paid year. <strong>Lifetime</strong> is a single payment for Pro on unlimited sites, every add-on released as of your purchase, any add-on released within three years of it, and updates for as long as Dashbread is maintained.</p><p>Any purchase — new, upgrade or renewal — can be refunded within 14 days of that charge, no questions asked. We chose 14 days because Core is free and uncapped, so you can try the real product before paying. A refunded license is deactivated.</p><h4>Use cases</h4><ul><li>A site on Pro 1-site upgrades to 5 sites when it takes on new clients.</li><li>A buyer who changes their mind in the first week gets a full refund by emailing support.</li></ul><h4>How to use</h4><ol><li>Manage subscriptions, cards and invoices from your dashbread.com account.</li><li>To upgrade, buy the higher plan from <strong>Dashbread › Pro &amp; Add-ons</strong>, then connect the license key shown in your dashbread.com account under <strong>Dashbread › License</strong> (if it is the same key, click <strong>Check now</strong>).</li><li>For a refund, email <a href=\"mailto:support@dashbread.com\">support@dashbread.com</a> within 14 days of the charge.</li><li>Full details are in the <a href=\"https://dashbread.com/terms\">Terms of Service</a>.</li></ol>"
  },
  {
   "slug": "islands",
   "title": "Islands: React components inside the shell",
   "excerpt": "Ship a React component that mounts in a hosted page, a widget or a shortcode, using the shell's own React.",
   "category": "developers",
   "category_id": "28ba9a52-4793-4e50-aadd-6c6be5c7c4c4",
   "body": "<h4>About</h4><p>The app shell is rendered by PHP, and interactive parts are <strong>islands</strong>: small React components mounted into placeholders. Core loads a runtime on app pages that exposes <code>window.Dashbread</code> with <code>React</code>, <code>register( name, Component )</code>, <code>mount()</code>, <code>api( path, opts )</code> (REST calls with the nonce), <code>Icon</code>, <code>ago()</code> and config, and fires a <code>dashbread:ready</code> event. Pro's Messages, Tasks and Graphs are built this way.</p><p>Your plugin prints a mount point with <code>\\Dashbread\\Shell\\Islands::render( 'my-island', $props )</code> and registers the component from a script that depends on the <code>dashbread-islands</code> handle. Build with esbuild (or similar) aliasing <code>react</code>, <code>react-dom</code> and the JSX runtime to <code>window.React</code>, so the page never loads a second copy of React.</p><h4>Use cases</h4><ul><li>A job-tracking plugin renders a live job board on its <code>/app/jobs</code> page.</li><li>A widget shows a member's account balance, refreshing through the plugin's own REST route.</li></ul><h4>How to use</h4><ol><li>In PHP, output <code>Islands::render( 'job-board', [ 'jobs' =&gt; $jobs ] )</code> from your page's render callback, a widget or a shortcode.</li><li>Enqueue your script on app requests with <code>array( 'dashbread-islands' )</code> as a dependency.</li><li>In JS: <code>window.Dashbread.register( 'job-board', ( { jobs } ) =&gt; … )</code>. Use <code>Dashbread.api( 'myplugin/v1/jobs' )</code> for REST calls.</li><li>Use the shell's CSS variables (<code>--sui-primary</code>, <code>--sui-card</code>, <code>--sui-border</code>…) so your component follows light, dark and the Customizer.</li></ol>"
  },
  {
   "slug": "member-messaging",
   "title": "Member Messaging",
   "excerpt": "Members message each other, one-to-one and in small groups, in the same inbox as Pro Messaging, with blocking, reporting and staff moderation.",
   "category": "pmas",
   "category_id": "fedde577-81c2-41c4-a5c6-6959d42fdf68",
   "body": "<h4>About</h4><p>Member Messaging lets members start conversations with each other, one-to-one or in small groups, from the same <strong>Messages</strong> inbox they use to talk to your team. It builds on Pro Messaging, so it needs Pro with messaging on. Member conversations are private: staff only see a message when someone reports it, unless you choose otherwise in the settings.</p><h4>Use cases</h4><ul><li>Members of a community or association contacting each other without sharing email addresses.</li><li>Colleagues at the same company coordinating inside your app.</li><li>Cohorts, study groups or project teams talking in a small group thread.</li></ul><h4>How to use</h4><ol><li>Buy the add-on (or the All PMAs bundle, or Lifetime) from <strong>Dashbread › Pro &amp; Add-ons</strong>. Your license refreshes and the module switches on; there is nothing to install.</li><li>Open <strong>Dashbread › Member messages › Settings</strong> and choose who members can message: any member, people in the same company (needs Companies), or only members with certain roles.</li><li>Set the limits: whether group conversations are allowed and how many people they can hold (3–25, including the sender), how many new conversations a member can start per day (replies are never limited), and whether members can turn off messages from other members.</li><li>In the app, members go to <strong>Messages › New message</strong>, pick <strong>A member</strong>, search by name, add one or more people and send. Starting a conversation with someone you already have a one-to-one with reopens that conversation.</li></ol><h4>What members can do</h4><ul><li><strong>Mute</strong> a conversation to stop notifications, or <strong>archive</strong> it to move it to the Archived tab. A new message brings it back.</li><li><strong>Leave</strong> a group conversation.</li><li><strong>Block</strong> someone from a one-to-one conversation. Neither person can message the other, the blocked person drops out of search, and their messages are hidden.</li><li><strong>Report</strong> a message as spam, harassment, inappropriate or other, with an optional note.</li><li>Use the gear icon in Messages to turn off messages from other members (if you allow it) and manage their blocked list.</li></ul><p>Search shows names, avatars and companies only, never email addresses. Members get an in-app notification and an email for new messages, unless they muted the conversation or turned that notification off.</p><h4>Moderation</h4><ul><li>Reports appear under <strong>Dashbread › Member messages › Reports</strong>, and staff get a notification for each one.</li><li>Open a report to see the message with the conversation around it, who reported it and any earlier reports on the same member.</li><li><strong>Resolve</strong> it, optionally removing the message (members see \"removed by a moderator\" and the sender is notified) and suspending the member from member messaging. Or <strong>Dismiss</strong> it.</li><li>Suspended members can still read their conversations and message your team. Lift a suspension from the <strong>Suspended</strong> tab.</li><li>To let staff read every member conversation, turn on <strong>Staff can read all member conversations</strong> in Settings. Staff can read those conversations but not reply unless they are a participant.</li></ul>"
  },
  {
   "slug": "offers",
   "title": "Offers",
   "excerpt": "Targeted promotions on the dashboard, in the header panel and on hosted pages, aimed by role, plan, join date or profile field, with dates and click tracking.",
   "category": "pmas",
   "category_id": "fedde577-81c2-41c4-a5c6-6959d42fdf68",
   "body": "<h4>About</h4><p>Offers lets you show promotions to your members inside the app: upgrades, events, partner deals, anything with a button. Each offer is aimed at the members it fits, can run between two dates, and counts how many members saw it, clicked it and hid it.</p><h4>Use cases</h4><ul><li>An upgrade offer shown only to members who aren't on your top plan yet.</li><li>An event invitation for members who joined in the last 30 days.</li><li>A partner discount with a promo code members can copy.</li><li>A seasonal sale that starts and stops on its own.</li></ul><h4>How to use</h4><ol><li>Buy the add-on (or the All PMAs bundle, or Lifetime) from <strong>Dashbread › Pro &amp; Add-ons</strong>. Your license refreshes and the module switches on; there is nothing to install.</li><li>Add the <strong>Dashbread Offers</strong> widget to the Dashbread Dashboard widget area (<strong>Appearance › Widgets</strong>). It hides itself when a member has nothing to see.</li><li>Open <strong>Dashbread › Offers</strong> and click <strong>New offer</strong>. Write a headline, and optionally a badge (like <em>20% off</em>), text, an image, a promo code, and a button with its link. The preview updates as you type.</li><li>Under <strong>Who sees it</strong>, aim the offer: by role, by plan (only members on these plans, or hide it from members who already have one), by how recently they joined, or by one profile field. The screen shows how many members fit right now.</li><li>Under <strong>When and where</strong>, set it to <strong>Active</strong>, choose optional start and end dates, and pick where it appears: the dashboard widget, the header panel, or both. Decide whether members can hide it, and give it a priority (higher shows first).</li></ol><h4>Where offers appear</h4><ul><li><strong>Dashboard:</strong> in the Dashbread Offers widget.</li><li><strong>Header panel:</strong> a gift icon appears in the panel when a member has an offer there.</li><li><strong>Hosted pages:</strong> <code>[dashbread_offers]</code> shows every live offer aimed at the member (optional <code>limit=\"3\"</code>, up to 6, and <code>title=\"\"</code>).</li></ul><h4>Results</h4><p>Open an offer to see its views, members reached, clicks, click rate and how many members hid it, with a 30-day chart. Numbers are counted once per member per day. The Data &amp; Graphs add-on also has <em>Offer views</em> and <em>Offer clicks</em> sources for dashboard charts. Use <strong>Duplicate</strong> to start a new offer from an old one; the copy starts as a draft.</p><h4>For developers</h4><p>Filter <code>dashbread_offer_matches</code> has the last word on who sees an offer. Actions: <code>dashbread_offer_saved</code>, <code>dashbread_offer_clicked</code>.</p>"
  },
  {
   "slug": "white-label",
   "title": "White Label",
   "excerpt": "Your own name, logo and help link across the app and wp-admin, with Dashbread's screens and plugin details hidden from other administrators.",
   "category": "pmas",
   "category_id": "fedde577-81c2-41c4-a5c6-6959d42fdf68",
   "body": "<h4>About</h4><p>White Label puts your brand where Dashbread would name itself. The admin menu, screen headers, window titles, widget and menu names, and the member app all use your product name, logo and menu icon, and the app footer credit can be hidden or replaced with your own. For everyone except you (the owner), Dashbread's own screens and plugin details disappear: other administrators see your name on the Plugins screen and your Help link in the menu. Switching it off, or a lapsed license, puts Dashbread's name straight back; nothing about your site or data changes.</p><h4>Use cases</h4><ul><li>An agency hands a client a finished member portal under the agency's own product name.</li><li>A business runs its member app as \"Acme Portal\" and doesn't want staff seeing third-party branding.</li><li>A developer keeps full control of licensing and updates while the client's administrators manage members, pages and offers.</li></ul><h4>How to use</h4><ol><li>Buy the add-on (or the All PMAs bundle, or Lifetime) from <strong>Dashbread › Pro &amp; Add-ons</strong>. Your license refreshes and the module switches on; there is nothing to install.</li><li>Open <strong>Dashbread › White label</strong>, switch on <strong>Use my brand instead of Dashbread</strong> and enter your product name. Add a header subtitle if you want one.</li><li>Choose a logo (square works best) and an admin menu icon: one of the built-in icons or your logo. The preview shows the menu entry, screen header and app footer as you go.</li><li>Under <strong>App footer credit</strong>, pick no credit, your own credit (text and an optional link), or keep \"Powered by Dashbread\".</li><li>Under <strong>Other administrators</strong>, decide what your team sees: hide Pro &amp; Add-ons, Help, License and White label from them; add your own Help link (label and address); rename the plugins with your author name and link, or hide them from the Plugins screen entirely.</li><li>Save. The page reloads with your brand applied.</li></ol><h4>Who is the owner?</h4><p>The administrator who first saves the screen becomes the owner. The owner keeps seeing Dashbread's own screens and the real plugin names, so licensing, updates and support stay in your hands. Another administrator can take over with <strong>Make me the owner</strong> only while the screens aren't hidden from them. If the owner's account is deleted or loses administrator access, every administrator counts as the owner again, so no one is ever locked out.</p><h4>If you get locked out</h4><p>Add <code>define( 'DASHBREAD_WHITE_LABEL_OFF', true );</code> to <code>wp-config.php</code>. Dashbread's name and screens come back for everyone without changing your settings; remove the line to restore your brand.</p><h4>For developers</h4><p>Core exposes the brand through filters any plugin can use: <code>dashbread_brand_name</code>, <code>dashbread_brand_logo</code>, <code>dashbread_brand_menu_icon</code>, <code>dashbread_brand_pro_pill</code>, <code>dashbread_brand_tagline</code> and <code>dashbread_powered_by</code>. Action <code>dashbread_white_label_saved</code> fires after the settings change.</p>"
  },
  {
   "slug": "licensing-entitlements",
   "title": "Licenses, entitlements and site limits",
   "excerpt": "How a license key turns into features, what a site limit means, and what happens at renewal.",
   "category": "billing",
   "category_id": "30ef656d-c943-4322-8da7-a3f5fd790014",
   "body": "<h4>About</h4><p>A Dashbread license is a key that grants <strong>entitlements</strong>: <code>pro</code>, and add-ons as <code>addon:&lt;name&gt;</code> (the All PMAs bundle and Lifetime grant every add-on). Pro reads that list from dashbread.com when you connect, refreshes it daily, and switches features on or off from it — there are no separate downloads for add-ons.</p><p>Pro licenses are sold by site count: one site, five sites or unlimited. Each site you connect uses an activation; disconnecting frees it. Local and development hosts (<code>localhost</code>, <code>.test</code>, <code>.local</code>, <code>.invalid</code>, private IP ranges) don't use one. If dashbread.com can't be reached, the last known entitlements stay in place.</p><h4>Use cases</h4><ul><li>An agency buys a 5-site license and connects it on five client sites, plus as many local copies as it likes.</li><li>A site adds the Tasks add-on mid-year; it switches on at the next daily check, or right away with Check now on the License screen.</li></ul><h4>How to use</h4><ol><li>Connect the key under <strong>Dashbread › License</strong>.</li><li>See what the license includes on that screen or on <strong>Pro &amp; Add-ons</strong>.</li><li>Free an activation by clicking <strong>Disconnect</strong> on the old site.</li><li>Renewal is automatic each year. If a license lapses, the plugin keeps working but updates, support and add-ons stop until it is renewed.</li></ol>"
  },
  {
   "slug": "social-login",
   "title": "Social Login & 2FA",
   "excerpt": "Sign in with Google, Microsoft or Apple, and two-step verification (authenticator app, email codes, backup codes) you can require by role.",
   "category": "pmas",
   "category_id": "fedde577-81c2-41c4-a5c6-6959d42fdf68",
   "body": "<h4>About</h4><p>Social Login &amp; 2FA adds <strong>Continue with Google</strong>, <strong>Microsoft</strong> and <strong>Apple</strong> buttons to the Dashbread sign-in and sign-up screens, and two-step verification for your members: codes from an authenticator app or by email, one-time backup codes, and remembered devices. You can require two-step for any role.</p><h4>Use cases</h4><ul><li>Let members sign in with an account they already have instead of another password.</li><li>Protect staff and administrator accounts with a second step.</li><li>Require two-step for clients whose data you hold.</li></ul><h4>How to use</h4><ol><li>Buy the add-on (or the All PMAs bundle, or Lifetime) from <strong>Dashbread › Pro &amp; Add-ons</strong>. Your license refreshes and the module switches on; there is nothing to install.</li><li>Open <strong>Dashbread › Sign-in &amp; security › Sign-in providers</strong>. For each provider, click <strong>Setup</strong>, follow the steps, and copy the redirect address shown into the provider's settings.<ul><li><strong>Google:</strong> Google Cloud console › APIs &amp; Services › Credentials › OAuth client ID (Web application). Paste the Client ID and Client secret.</li><li><strong>Microsoft:</strong> Microsoft Entra admin center › App registrations. Add a Web redirect URI, create a client secret, and paste its Value with the Application (client) ID. Choose which accounts can sign in.</li><li><strong>Apple:</strong> Apple Developer › a Services ID with Sign in with Apple, and a key (.p8). Paste the Services ID, Team ID, Key ID and the whole .p8 file. Apple needs HTTPS.</li></ul></li><li>Switch the provider on and save. The buttons appear on the sign-in and sign-up screens right away.</li><li>Under <strong>New members</strong>, choose what happens when someone signs in with a provider but has no account: create one if registration is open, always create one, or existing members only.</li><li>Under <strong>Two-step verification</strong>, choose the methods members can use, the roles that must use two-step, and how many days a device can be remembered (0 turns that off).</li></ol><h4>What members see</h4><ul><li>Members manage everything under <strong>Profile › Password &amp; security</strong> in the app: connect or disconnect Google, Microsoft or Apple; set up an authenticator app by scanning a QR code; turn on email codes; get new backup codes; forget remembered devices.</li><li>Everyone who turns on two-step gets ten one-time backup codes. Changes like removing a method need a current code.</li><li>With two-step on, signing in needs the password (or a connected account) and then a code. If the role requires two-step, a member without it sets it up during that sign-in.</li><li>Members get an email when two-step is turned on or off, when it's reset, and when a sign-in provider is connected.</li></ul><h4>How accounts are matched</h4><ul><li>A Google or Apple sign-in joins an existing account with the same verified email, except administrator accounts, which connect from their profile.</li><li>Microsoft doesn't confirm email addresses, so members connect Microsoft from their profile while signed in.</li><li>A member who signed up with a provider has no password. They can add one with <em>Forgot password?</em>, and they can't disconnect their only way to sign in.</li></ul><h4>Helping a locked-out member</h4><p>Open <strong>Dashbread › Sign-in &amp; security › Members</strong>, search for the member and click <strong>Reset two-step</strong>. They can sign in with their password and set it up again. The same screen can disconnect a provider.</p><h4>For developers</h4><p>Filters and actions: <code>dashbread_sso_allow</code>, <code>dashbread_sso_endpoints</code>, <code>dashbread_sso_linked</code>, <code>dashbread_sso_unlinked</code>, <code>dashbread_sso_registered</code>, <code>dashbread_2fa_method_added</code>, <code>dashbread_2fa_method_removed</code>, <code>dashbread_2fa_passed</code>, <code>dashbread_2fa_reset</code>. XML-RPC password sign-ins are refused for members with two-step; application passwords keep working.</p>"
  },
  {
   "slug": "installing-dashbread",
   "title": "Installing Dashbread Core and Pro",
   "excerpt": "Core from WordPress.org; Pro from your dashbread.com account, connected with a license key.",
   "category": "getting-started",
   "category_id": "a602a917-92e7-496c-9e6c-e0a6a9fa4da9",
   "body": "<h4>About</h4><p>Dashbread is two plugins. <strong>Dashbread</strong> (Core) is free and installs from WordPress.org like any plugin. <strong>Dashbread Pro</strong> is a separate plugin you download from your dashbread.com account; it requires Core and adds its features the moment a license is connected. Pro Module Add-ons are not separate downloads — they live inside Pro and switch on from your license.</p><h4>Use cases</h4><ul><li>A new site starts on Core, builds its app, and adds Pro later without changing anything already set up.</li><li>An agency installs Pro on a client site, connects the client's own license key, and the add-ons they bought appear on their own.</li></ul><h4>How to use</h4><ol><li>In wp-admin go to <strong>Plugins › Add New</strong>, search for <em>Dashbread</em>, then <strong>Install</strong> and <strong>Activate</strong>.</li><li>Make sure <strong>Settings › Permalinks</strong> is set to anything other than <em>Plain</em> (Post name is best). Dashbread shows a notice if it isn't — without pretty permalinks <code>/app</code> only works as a query URL.</li><li>Open <strong>Dashbread › Settings</strong> to confirm the app route (default <code>app</code>), add your logo and pick a primary color. Then visit <code>/app</code> while signed in.</li><li>For Pro: download <em>dashbread-pro.zip</em> from your dashbread.com account, then <strong>Plugins › Add New › Upload Plugin</strong> and activate it. Core must stay active.</li><li>Open <strong>Dashbread › License</strong>, paste your license key and click <strong>Connect license</strong>. Pro and any add-ons you own switch on immediately; updates arrive through the normal Plugins screen while the license is active.</li></ol><h4>Requirements</h4><ul><li>WordPress 6.5 or newer</li><li>PHP 8.1 or newer</li><li>Pretty permalinks (any setting except Plain)</li><li>Pro: Dashbread Core active, and an outbound HTTPS connection to dashbread.com for license checks and updates</li></ul>"
  },
  {
   "slug": "the-app-route",
   "title": "The /app route and the shell",
   "excerpt": "How Dashbread takes over one route for members, keeps visitors on your theme, and keeps members out of wp-admin.",
   "category": "getting-started",
   "category_id": "a602a917-92e7-496c-9e6c-e0a6a9fa4da9",
   "body": "<h4>About</h4><p>Dashbread registers one route — <code>/app</code> by default — and renders its own shell there: a sidebar, a header with the notifications bell, flyout and account menu, a dashboard on the home screen, and a page area. Everything outside that route is untouched, so your theme keeps running the public site. Theme stylesheets are kept out of the shell; styles from other plugins you host inside it stay, so their forms and tables still work.</p><p>Four switches under <strong>Dashbread › Settings</strong> decide how members move between the two: send WordPress login links to Dashbread's own sign-in screen, land members in the app after they sign in, hide the WordPress admin bar for members, and redirect members who open wp-admin back to the app. \"Members\" here means anyone without the <code>edit_posts</code> capability — editors and administrators keep normal WordPress behavior.</p><h4>Use cases</h4><ul><li>A membership site renames the route to <code>/portal</code> so member links read naturally.</li><li>A client portal turns on \"keep members out of wp-admin\" so customers who find <code>/wp-admin</code> end up back in their dashboard.</li></ul><h4>How to use</h4><ol><li>Open <strong>Dashbread › Settings</strong> and set the <strong>App route</strong> if you want something other than <code>app</code>. Links update everywhere, including the sidebar.</li><li>Choose the member behaviors: redirect login to Dashbread, land in the app after sign-in, hide the admin bar, keep members out of wp-admin, and send the old <code>/login</code> path to the app.</li><li>Visit the route while signed in. Signed-out visitors who open any <code>/app</code> link are sent to the sign-in screen and returned to that page after signing in.</li><li>Use <code>[dashbread_app_link]</code> on public pages to give members a button into the app — visitors see a Sign in button instead (see <em>Shortcode reference</em>).</li></ol><h4>Inside the shell</h4><ul><li><strong>Dashboard</strong> — the <em>Dashbread Dashboard</em> widget area, rendered as cards (see <em>The dashboard and widgets</em>).</li><li><strong>Sidebar</strong> — the <em>Dashbread Sidebar</em> menu plus hosted pages (see <em>Sidebar and header menus</em>).</li><li><strong>Header</strong> — notifications bell, flyout tabs (Pro adds Messages and Tasks), light/dark toggle and the account menu.</li><li><strong>Presets</strong> — Console (dense, dark sidebar) and Comfort (roomy, light), each with light and dark modes. Members can choose light, dark or system in Profile › Appearance.</li></ul>"
  },
  {
   "slug": "hosted-pages",
   "title": "Hosted pages: any page or plugin inside the app",
   "excerpt": "Tick \"Show in Dashbread app\" and a page renders inside the shell at /app/<slug> — with your plugins' content, not your theme.",
   "category": "getting-started",
   "category_id": "a602a917-92e7-496c-9e6c-e0a6a9fa4da9",
   "body": "<h4>About</h4><p>A hosted page is any WordPress page flagged <strong>Show in Dashbread app</strong>. It renders at <code>/app/&lt;slug&gt;</code> inside the shell, with Dashbread's reset applied so forms, tables and buttons from other plugins look native. WooCommerce My Account, a forms plugin, course lessons, a support desk — anything that renders on a page works, because the page is still a normal WordPress page with its shortcodes and blocks.</p><p>Each hosted page carries an icon, a sidebar position and an optional list of roles that may see it. Hosted pages that aren't already placed in the Dashbread Sidebar menu get a sidebar link automatically. With Pro, Plans can also put a page behind a membership: a member without the plan sees a locked card with the plan's offer instead of the page.</p><h4>Use cases</h4><ul><li>A shop hosts WooCommerce's My Account page so customers see orders and downloads inside the app.</li><li>A training company hosts a \"Resources\" page visible only to the <em>Student</em> role, with a Pro plan gate on the advanced material.</li></ul><h4>How to use</h4><ol><li>Edit the page and tick <strong>Show in Dashbread app</strong> in the Dashbread box — or open <strong>Dashbread › Hosted pages</strong>, search for the page and add it there.</li><li>Pick an icon (the picker searches the full Lucide set), a position, and optionally the roles that may see it. Leave roles empty for every signed-in member.</li><li>Open <code>/app/&lt;slug&gt;</code>. The page appears in the sidebar automatically unless you have placed it in the Dashbread Sidebar menu yourself.</li><li>To move or nest it, add it to <strong>Appearance › Menus › Dashbread Sidebar</strong> — once it is in the menu, the menu decides where it shows.</li><li>(Pro) To gate it behind a membership, tick the plan in the page's <strong>Dashbread plans</strong> box or on the plan's Pages tab.</li></ol><h4>Visibility rules</h4><ul><li>A page's own <em>Visible to roles</em> always applies — a sidebar menu item pointing at it can narrow who sees it, never widen it.</li><li>A role-hidden page returns \"Page not found\" to members without the role.</li><li>A plan-gated page (Pro) shows a locked card with the plan's description and a Get button to members without the plan. Administrators always see everything.</li></ul>"
  },
  {
   "slug": "notifications",
   "title": "In-app notifications",
   "excerpt": "The bell, the flyout, the notifications page, per-type muting, broadcasts — and what plugins can send.",
   "category": "getting-started",
   "category_id": "a602a917-92e7-496c-9e6c-e0a6a9fa4da9",
   "body": "<h4>About</h4><p>Core ships a notification center. New notifications light up the bell in the header with an unread count; the flyout shows the latest, and <code>/app/notifications</code> lists them all with <strong>All / Unread</strong> filters, <strong>Mark all read</strong> and Load more. Clicking a notification marks it read and opens its link.</p><p>Every notification has a type — system, broadcast, and whatever plugins or Pro modules register (messages, memberships, tasks). Members mute types they don't want in Profile › Notifications. Staff send announcements from <strong>Dashbread › Notifications</strong>, and with Pro's Email delivery the same notification can also go out by email.</p><h4>Use cases</h4><ul><li>An admin announces scheduled maintenance to every member, with a link to the details page.</li><li>A plugin notifies a member when their order ships, and the member sees it in the bell and by email.</li></ul><h4>How to use</h4><ol><li>Open <strong>Dashbread › Notifications</strong>, write a title and message, optionally add a link, choose everyone or specific roles, and send.</li><li>Members see the bell count update, open the flyout, or visit <code>/app/notifications</code> for the full list.</li><li>Developers send one with <code>dashbread_notify( $user_id, 'my_type', [ 'title' =&gt; '…', 'body' =&gt; '…', 'url' =&gt; '…' ] )</code> and register the type's label and icon on <code>dashbread_register</code>.</li></ol>"
  },
  {
   "slug": "core-vs-pro",
   "title": "Core vs Pro: what unlocks what",
   "excerpt": "A plain comparison of the free plugin, Pro, and the Pro Module Add-ons.",
   "category": "getting-started",
   "category_id": "a602a917-92e7-496c-9e6c-e0a6a9fa4da9",
   "body": "<h4>About</h4><p>Dashbread comes in three layers. <strong>Core</strong> is free and complete: the member app and everything a member touches. <strong>Pro</strong> adds the staff side and the design tools, and makes the Core surfaces richer without changing how you set them up. <strong>Pro Module Add-ons</strong> switch on extra modules inside Pro. You can run on Core indefinitely, add Pro when you need to manage members, and add only the modules that fit.</p><h4>Use cases</h4><ul><li>A small community runs entirely on Core: hosted pages, notifications and the profile are all it needs.</li><li>A client portal adds Pro for Members, Plans and Messaging, then the Tasks add-on for onboarding checklists.</li></ul><h4>How to use</h4><ol><li>Start on Core and build your app.</li><li>Open <strong>Dashbread › Pro &amp; Add-ons</strong> to see prices and what you already have.</li><li>Buy Pro (1 site, 5 sites or unlimited) or Lifetime at dashbread.com, install Pro and connect the key.</li><li>Add a module later from the same screen; it switches on when the license refreshes.</li></ol><h4>At a glance</h4><table><thead><tr><th></th><th>Core (free)</th><th>Pro</th><th>Add-ons</th></tr></thead><tbody><tr><td>App route, shell, presets, light/dark</td><td>✓</td><td>✓</td><td></td></tr><tr><td>Hosted pages, menus, dashboard widgets</td><td>✓</td><td>✓ + Canvas</td><td></td></tr><tr><td>Notifications (in-app)</td><td>✓</td><td>+ email delivery</td><td></td></tr><tr><td>Profile, sign-in screens</td><td>✓</td><td>+ Field builder, login layouts</td><td></td></tr><tr><td>Shortcodes</td><td>Core tags</td><td>+ plan, field, company tags</td><td>+ graph, tasks</td></tr><tr><td>Members, Plans, Companies, Messaging</td><td></td><td>✓</td><td></td></tr><tr><td>Customizer with live preview</td><td></td><td>✓</td><td></td></tr><tr><td>Data &amp; Graphs, Tasks</td><td></td><td></td><td>✓ per add-on</td></tr><tr><td>Support</td><td>WordPress.org forum</td><td>Direct, from the Help screen</td><td>Included with Pro</td></tr></tbody></table>"
  },
  {
   "slug": "members",
   "title": "Members screen",
   "excerpt": "Every member in one place: search, filter, roles, notes, plans, notify, message and export.",
   "category": "pro",
   "category_id": "9cfcc2e5-779e-4061-a250-7ac5853be6cc",
   "body": "<h4>About</h4><p><strong>Dashbread › Members</strong> is the staff view of everyone who can sign in. A stat row shows totals, new in the last 30 days, active in the last 30 days, never signed in, and bounced email addresses. The list searches by name, username or email and filters by role, company, activity (active in 30 days, inactive for 90, never signed in, bounced) and any custom field answer. Sort by name, date joined or last sign-in.</p><p>Click a member to open their panel. <strong>About</strong> shows their role (change it right there unless it is an administrator or you), company, activity and plans — add them to a plan or cancel one. <strong>Fields</strong> shows their custom-field answers by section. <strong>Staff notes</strong> are private to staff. <strong>Notify</strong> sends them an in-app notification. <strong>Message</strong> starts a conversation in Messages. <strong>Export CSV</strong> downloads the filtered list with one column per custom field.</p><h4>Use cases</h4><ul><li>Support finds a member by email, checks when they last signed in, and adds a private note about their account.</li><li>An admin filters to members who never signed in, exports them, and sends a reminder notification.</li></ul><h4>How to use</h4><ol><li>Open <strong>Dashbread › Members</strong>.</li><li>Search or filter the list; the URL remembers the open member, so you can share a link with a colleague.</li><li>Click a row to open the panel, then use the tabs: change a role, add a plan, write a note, notify or message.</li><li>Click <strong>Export CSV</strong> to download exactly the list you are looking at.</li><li>If a member's email bounced, use <strong>Allow again</strong> in their panel once they have fixed the address.</li></ol>"
  },
  {
   "slug": "plans",
   "title": "Plans & memberships",
   "excerpt": "Create plans, gate pages behind them, grant roles, set durations, and let members see their own membership.",
   "category": "pro",
   "category_id": "9cfcc2e5-779e-4061-a250-7ac5853be6cc",
   "body": "<h4>About</h4><p>A <strong>plan</strong> is a level of access: a name, description, an optional role to grant, a duration (or until cancelled), the hosted pages it unlocks, and an offer — a price label, a checkout link and a list of features. A <strong>membership</strong> is one member on one plan, with a start date, an end date, a status (active, expired or cancelled) and a note.</p><p>Pages tied to a plan are visible only to members on it. Everyone else sees a locked card with the plan's description and a <strong>Get</strong> button that goes to your checkout link. Memberships expire on their end date (a daily check removes the granted role and notifies the member), and every member sees their own plans and the others on offer at <code>/app/membership</code>. Plan shortcodes put the same logic on public pages.</p><h4>Use cases</h4><ul><li>A course site sells a \"Pro\" plan: buyers are added to it, get the <em>Student</em> role, and unlock the advanced lessons for a year.</li><li>A client portal gives each tier its own resource pages and shows upgrade cards on a public pricing page with <code>[dashbread_plans]</code>.</li></ul><h4>How to use</h4><ol><li>Open <strong>Dashbread › Plans</strong> and click <strong>New plan</strong>. Fill in <strong>Details</strong> — name, description, duration, and a role to grant if you want one.</li><li>On <strong>Pages</strong>, tick the hosted pages this plan unlocks (you can also do this from the page editor's <strong>Dashbread plans</strong> box).</li><li>On <strong>Offer</strong>, add a price label, your checkout URL and the features to list.</li><li>On <strong>Members</strong>, search for a person and add them with an optional end date and note. Change end dates inline; <strong>Cancel</strong>, <strong>Reactivate</strong> or <strong>Remove</strong> as needed.</li><li>Use <code>[dashbread_has_plan plan=\"pro\"]</code>, <code>[dashbread_no_plan plan=\"pro\"]</code> and <code>[dashbread_plans]</code> on any page to show content, upgrade prompts and pricing cards.</li></ol><h4>Good to know</h4><ul><li>A member keeps a granted role while any active plan grants it; cancelling one plan doesn't remove a role another still grants.</li><li>Archiving a plan removes its granted role from active members; restoring it puts the role back.</li><li>Deleting a plan cancels its memberships first.</li><li>Developers can add memberships from another system with the <code>dashbread_user_plan_ids</code> filter.</li></ul>"
  },
  {
   "slug": "companies",
   "title": "Companies",
   "excerpt": "Group members into companies with owners, admins and members; give every company its own page in the app.",
   "category": "pro",
   "category_id": "9cfcc2e5-779e-4061-a250-7ac5853be6cc",
   "body": "<h4>About</h4><p><strong>Companies</strong> lets you organize members by the organization they belong to. A company has contact details (email, phone, website, address), a logo, notes and a status. Members join with a role — <strong>owner</strong>, <strong>admin</strong> or <strong>member</strong> — plus a title and phone, and one company is marked as each member's primary.</p><p>Members see their company at <code>/app/company</code>: everyone sees the profile and the people; owners and admins can edit the profile themselves. Staff manage every company from <strong>Dashbread › Companies</strong>, and the Members screen can filter by company.</p><h4>Use cases</h4><ul><li>A B2B portal lets each customer company's owner keep its address and logo current without contacting you.</li><li>An association groups members by employer and filters the Members screen to one company before sending a notification.</li></ul><h4>How to use</h4><ol><li>Open <strong>Dashbread › Companies</strong> and click <strong>New company</strong>. Fill in the details and save.</li><li>In the <strong>People</strong> panel, search for a member and add them with a role; edit titles and roles inline.</li><li>Members open <strong>Company</strong> in the app sidebar; owners and admins can edit the details right there.</li><li>Archive a company to hide it without losing its history; delete removes it and its member links.</li><li>Show a member's company anywhere with <code>[dashbread_company field=\"name\"]</code>.</li></ol>"
  },
  {
   "slug": "messaging",
   "title": "Messaging",
   "excerpt": "Member ↔ staff conversations with an inbox in the app, internal notes, and email delivery.",
   "category": "pro",
   "category_id": "9cfcc2e5-779e-4061-a250-7ac5853be6cc",
   "body": "<h4>About</h4><p><strong>Messaging</strong> gives members a private line to your team. Members see <code>/app/messages</code>: a three-pane inbox with their conversations, the open thread, and a composer; a Messages icon in the header shows the unread count and a flyout of recent threads. Staff (administrators and editors by default) work from <strong>Dashbread › Messages</strong> with <em>Awaiting reply</em>, <em>Open</em>, <em>Unread</em> and <em>Closed</em> views and search.</p><p>Staff can reply or add an <strong>internal note</strong> that members never see and that never notifies anyone. Replies notify the other side in the app and — with Email delivery on — by email. Threads can be closed and reopened by either side.</p><h4>Use cases</h4><ul><li>A customer asks a billing question from the app; the next available staff member answers from wp-admin and the customer gets the reply in the bell and their inbox.</li><li>Staff leave an internal note on a thread so a colleague picking it up knows what has been tried.</li></ul><h4>How to use</h4><ol><li>Members open <strong>Messages</strong> in the sidebar and click <strong>New message</strong>.</li><li>Staff open <strong>Dashbread › Messages</strong>, pick a thread, and reply or switch to <strong>Internal note</strong>.</li><li>Start a conversation with a specific member from their panel on the Members screen (<strong>Message</strong> tab).</li><li>Close a thread when it is resolved; either side can reopen it by replying.</li></ol>"
  },
  {
   "slug": "email_delivery",
   "title": "Email delivery",
   "excerpt": "Send notifications and messages by email through SparkPost, Emailit or any SMTP server, with bounce handling.",
   "category": "pro",
   "category_id": "9cfcc2e5-779e-4061-a250-7ac5853be6cc",
   "body": "<h4>About</h4><p><strong>Email delivery</strong> makes Dashbread's notifications and messages reach members by email as well as in the app. Choose a provider — SparkPost, Emailit, any SMTP server, or WordPress's own mail — and Dashbread sends through it with your logo and colors in a clean template. The password is stored encrypted and never shown again.</p><p>You decide what goes out: which notification types are emailed, and whether message replies are. Members can opt out per type in their profile. Bounces and spam complaints reported by your provider's webhook stop further email to that address until staff allow it again, and a recent-sends log shows what went out and what failed.</p><h4>Use cases</h4><ul><li>A portal emails every new message reply so members don't have to check the app.</li><li>An admin sees that a member's address bounced, contacts them another way, and clicks Allow again once it is fixed.</li></ul><h4>How to use</h4><ol><li>Open <strong>Dashbread › Email</strong> and choose a provider card; the host, port and encryption fill in for SparkPost and Emailit.</li><li>Enter the username and API key or password, then the From name, From email and an optional Reply-to.</li><li>Pick which notification types to email and whether message replies are emailed.</li><li>Click <strong>Test connection</strong>, then <strong>Send test email</strong> to yourself.</li><li>For bounce handling, copy the webhook URL shown under <strong>Bounces</strong> into your provider's webhook settings.</li></ol>"
  },
  {
   "slug": "canvas",
   "title": "Dashboard Canvas",
   "excerpt": "Let members arrange, resize and hide dashboard widgets — and save a site-wide default.",
   "category": "pro",
   "category_id": "9cfcc2e5-779e-4061-a250-7ac5853be6cc",
   "body": "<h4>About</h4><p><strong>Canvas</strong> turns the app dashboard into a layout members can make their own. A <strong>Customize dashboard</strong> button puts it in edit mode: drag cards by their handle (touch works too), set each card to one, two or three columns wide, and hide the ones you don't need. Each member's layout is saved to their account.</p><p>Administrators can arrange the dashboard and click <strong>Save as site default</strong>, which becomes the starting layout for everyone who hasn't made their own. Members can always go back to it with <strong>Reset to default</strong>. New widgets you add later appear at the end of everyone's layout.</p><h4>Use cases</h4><ul><li>A manager moves their stats chart to the top at full width and hides the welcome card.</li><li>An admin designs a clean default layout for new members before launch.</li></ul><h4>How to use</h4><ol><li>Open <code>/app</code> and click <strong>Customize dashboard</strong>.</li><li>Drag cards into order, use the 1 / 2 / 3 picker for width, and hide cards with the ×.</li><li>Click <strong>Done</strong> to save your layout.</li><li>(Admins) Click <strong>Save as site default</strong> to make your layout everyone's starting point.</li></ol>"
  },
  {
   "slug": "field_builder",
   "title": "Field builder",
   "excerpt": "Custom profile and sign-up fields with sections, conditional visibility, roles, and name / address / file types.",
   "category": "pro",
   "category_id": "9cfcc2e5-779e-4061-a250-7ac5853be6cc",
   "body": "<h4>About</h4><p>The <strong>Field builder</strong> adds your own questions to the member profile and, if you choose, the registration form. Field types include text, textarea, email, phone, number, date, URL, dropdown, radio, checkboxes and a yes/no checkbox, plus Pro's <strong>name</strong> (prefix, first, middle, last, suffix — and it can fill WordPress's own name fields), <strong>address</strong> (street, city, state, ZIP, country) and <strong>file</strong> (image, PDF, document, with a size limit).</p><p>Group fields into sections, mark them required, make them full width, show them only to certain roles, and show a field only when another answer matches (\"Show only when Member type is Business\"). Answers are saved on the member and show on the Members screen, in the CSV export, and in filters.</p><h4>Use cases</h4><ul><li>A membership site asks for a mailing address and a headshot at sign-up.</li><li>A B2B portal asks \"Company size\" only when the member says they are a business, then filters Members by it.</li></ul><h4>How to use</h4><ol><li>Open <strong>Dashbread › Fields</strong> and choose <strong>Add field</strong>.</li><li>Set the label (the key is created from it and locked once saved), type, section, help text and placeholder.</li><li>For choices, enter one per line as <code>value | Label</code>. For name and address fields, choose which parts to show.</li><li>Choose where it shows (Profile, Sign-up or both), whether it is required, which roles see it, and any show-only-when rule.</li><li>Drag to reorder, click <strong>Save</strong>, then use the Profile and Sign-up preview links to check. Show a member's own answer on a page with <code>[dashbread_field key=\"…\"]</code>.</li></ol>"
  },
  {
   "slug": "customizer",
   "title": "Customizer",
   "excerpt": "Colors, sidebar and header styles, typography, shape, login layouts and custom CSS — with a live preview.",
   "category": "pro",
   "category_id": "9cfcc2e5-779e-4061-a250-7ac5853be6cc",
   "body": "<h4>About</h4><p>The <strong>Customizer</strong> is a design tool for the whole app with a live preview beside it. Start from one of five starters (Clean, Soft, Midnight, Forest, Ocean) or set things yourself: <strong>Colors</strong> (primary, accent, page), <strong>Sidebar &amp; header</strong> (auto, dark, light, brand or a custom sidebar color; card, page or brand header), <strong>Type</strong> (system font or Inter, DM Sans, Manrope, Plus Jakarta, Nunito, IBM Plex, Source Sans, or your own; size scale; heading style), <strong>Shape</strong> (corner radius from sharp to pill, density, card style, sidebar width), <strong>Login</strong> (card, split or cover layout; plain, brand, gradient or image background; headline and blurb) and <strong>CSS</strong>.</p><p>The preview switches between Dashboard, Profile and Login screens, light and dark, desktop and phone. Nothing reaches members until you save; Reset returns to Dashbread's defaults.</p><h4>Use cases</h4><ul><li>A studio matches the app to its brand fonts and a soft rounded style in ten minutes.</li><li>A company uses the split login layout with a headline and product image so the sign-in page feels like part of their site.</li></ul><h4>How to use</h4><ol><li>Open <strong>Dashbread › Customize</strong>.</li><li>Pick a starter on the <strong>Start</strong> tab, or go straight to Colors.</li><li>Adjust each tab and watch the preview; switch screens, modes and devices from the preview bar.</li><li>Click <strong>Save</strong> to publish, or <strong>Reset</strong> to go back to defaults.</li></ol>"
  },
  {
   "slug": "data-graphs",
   "title": "Data & Graphs",
   "excerpt": "Charts on the dashboard and in pages from your own data — stat tiles, lines, bars and donuts.",
   "category": "pmas",
   "category_id": "fedde577-81c2-41c4-a5c6-6959d42fdf68",
   "body": "<h4>About</h4><p><strong>Data &amp; Graphs</strong> puts charts in the app. Pick a data source, a chart (stat tile with change vs the previous period, line, bars or donut) and a range (7, 30, 90 days or a year), and add it to the dashboard or any hosted page. Every chart has hover tooltips, a Table view for exact numbers, and works in light and dark mode.</p><p>Built-in sources cover the site — members joined, members by role, posts published, notifications sent, messages sent, memberships by plan, tasks completed — and each member's own activity (\"My notifications\", \"My messages\", \"My completed tasks\"). Site charts are visible only to staff; \"My\" charts show every member their own numbers. Build your own sources with the query builder — see <em>Custom graph sources</em>.</p><h4>Use cases</h4><ul><li>An admin keeps \"Members joined\" and \"Messages sent\" charts at the top of their dashboard.</li><li>Every member sees a \"My completed tasks\" stat tile on their home screen.</li></ul><h4>How to use</h4><ol><li>Open <strong>Dashbread › Graphs</strong> and pick a source on the left.</li><li>Choose the chart and range; the preview updates as you go. Give it a title and choose whether members can switch the range.</li><li>Click <strong>Add to dashboard</strong>. It appears on <code>/app</code> for everyone allowed to see that source.</li><li>To place a chart inside a hosted page instead, use <code>[dashbread_graph source=\"members_joined\" kind=\"line\"]</code>.</li><li>Remove a chart from <strong>On the dashboard</strong>, or manage it under Appearance › Widgets like any widget.</li></ol>"
  },
  {
   "slug": "tasks",
   "title": "Tasks",
   "excerpt": "Tasks for members — assigned by staff or by themselves — with checklists, due dates, reminders and a dashboard widget.",
   "category": "pmas",
   "category_id": "fedde577-81c2-41c4-a5c6-6959d42fdf68",
   "body": "<h4>About</h4><p><strong>Tasks</strong> gives every member a to-do list in the app at <code>/app/tasks</code>, a Tasks icon in the header with their open count, and a <em>Dashbread Tasks</em> dashboard widget. Staff assign tasks with notes, a due date and a priority; members tick them off, add notes, and — if you allow it — add their own tasks. Overdue tasks are highlighted, and a daily reminder notifies members about tasks due today or overdue.</p><p><strong>Checklists</strong> are reusable task templates: a named list of items, each with its own due offset (\"+3 days\") and priority. Assign one to a member in one click, or set it to apply automatically when someone registers or when they are added to a plan — ideal for onboarding. A checklist never duplicates tasks that are still open.</p><h4>Use cases</h4><ul><li>New clients automatically get an onboarding checklist the moment their plan is granted.</li><li>A coach assigns a member a single task with a due date and gets notified when they finish it.</li></ul><h4>How to use</h4><ol><li>Open <strong>Dashbread › Tasks</strong>. On the <strong>Tasks</strong> tab click <strong>New task</strong>, pick a member, and fill in the title, notes, due date and priority — or choose a checklist to assign.</li><li>On the <strong>Checklists</strong> tab click <strong>New checklist</strong>, add items with due offsets and priorities, and choose a trigger (never, on registration, or when a plan is granted).</li><li>Members work their list at <code>/app/tasks</code>, from the header flyout, or from the dashboard widget.</li><li>Place a task list inside a hosted page with <code>[dashbread_tasks add=\"1\"]</code>.</li></ol>"
  },
  {
   "slug": "dashbread-basics",
   "title": "Dashbread Basics: a website for visitors, an app for members",
   "excerpt": "What Dashbread Core does on its own, what Pro adds, and what a Pro Module Add-on is.",
   "category": "getting-started",
   "category_id": "a602a917-92e7-496c-9e6c-e0a6a9fa4da9",
   "body": "<h4>About</h4><p>Dashbread turns a WordPress site into two things at once. Your public site keeps whatever theme it has. Signed-in members get something else: an app at <code>/app</code> with its own sidebar, header, dashboard, notifications and pages — and every page or plugin you put inside it looks like part of one product instead of a stack of WordPress screens. Members never see wp-admin again.</p><p><strong>Dashbread Core</strong> is free on WordPress.org and complete on its own: the <code>/app</code> route and shell, hosted pages (any page or plugin screen inside the app), the sidebar and header menus, a widget dashboard members can tidy, in-app notifications with a bell and a full page, a profile manager, sign-in / registration / password screens that match the app, and a set of shortcodes for your public pages. It has no usage caps and no expiry — it is not a trial.</p><p><strong>Dashbread Pro</strong> is one licensed plugin that adds the staff side: a Members screen, Plans &amp; memberships that gate pages, grant roles and sell with Stripe (prices, free trials, checkout, renewals and a member billing page), Companies, member ↔ staff Messaging, email delivery with bounce handling, the drag-and-drop dashboard Canvas, a Field builder for profile and sign-up fields, and a Customizer with live preview — plus direct support from the Help screen.</p><p><strong>Pro Module Add-ons (PMAs)</strong> are modules already shipped inside Pro that switch on with an add-on license: Data &amp; Graphs, Tasks, Member Messaging, Social Login &amp; 2FA, Offers, White Label, Advanced Forms (multi-step forms, file uploads, save and resume, webhooks, and a Payment field for fees and deposits) and Tool Builder (calculators, quotes, quizzes and AI results, which you can give away or sell). Buy one, or the All PMAs bundle, and it turns on when your license refreshes. Nothing extra to install.</p><h4>Use cases</h4><ul><li>A coaching business keeps its marketing site on its theme and gives paying clients an app with their courses, a support inbox and a task list.</li><li>An association runs member-only resources, a directory plugin and its forms inside <code>/app</code>, so members sign in once and never land in wp-admin.</li></ul><h4>How to use</h4><ol><li>Install and activate <strong>Dashbread</strong> (Core) — see <em>Installing Dashbread Core and Pro</em>.</li><li>Open <code>/app</code> while signed in. That is the member app; your public pages are unchanged.</li><li>Put content inside it: tick <strong>Show in Dashbread app</strong> on a page (see <em>Hosted pages</em>), add widgets to the <em>Dashbread Dashboard</em> widget area, and shape the sidebar under Appearance › Menus.</li><li>Brand it under <strong>Dashbread › Settings</strong> — logo, primary color, preset, light or dark.</li><li>When you need the staff tools, add Pro from <strong>Dashbread › Pro &amp; Add-ons</strong>; add a PMA from the same screen.</li></ol>"
  },
  {
   "slug": "hooks-and-filters",
   "title": "Hooks & filters reference",
   "excerpt": "The stable hooks plugins use to live inside the app — pages, menus, shell, admin screens, data and shortcodes.",
   "category": "developers",
   "category_id": "28ba9a52-4793-4e50-aadd-6c6be5c7c4c4",
   "body": "<h4>About</h4><p>Dashbread is built to host other plugins. Everything below is part of the public API and works with Core alone unless marked Pro. Hooks are prefixed <code>dashbread_</code>; register pages, header items and notification types on the <code>dashbread_register</code> action (it runs on <code>init</code>, so translations are safe).</p><h4>Use cases</h4><ul><li>An MFS plugin registers its own <code>/app/jobs</code> page with a sidebar badge and a header icon that opens a flyout tab.</li><li>A plugin adds its own table to the Data &amp; Graphs query builder so site owners can chart it.</li></ul><h4>How to use</h4><ol><li>Hook <code>dashbread_register</code> and call <code>$registry-&gt;register_page()</code>, <code>register_header_item()</code> and <code>register_notification_type()</code>.</li><li>Render React components with <code>\\Dashbread\\Shell\\Islands::render()</code> (see <em>Islands</em>).</li><li>Add an admin screen with <code>dashbread_admin_screens</code> and mount it with <code>window.DashbreadAdmin.registerScreen()</code>.</li><li>Notify members with <code>dashbread_notify()</code>.</li></ol><h4>Pages, menus and access</h4><ul><li><code>dashbread_register</code> (action, receives the Registry) — <code>register_page( $slug, [ title, icon, position, render ] )</code>, <code>register_header_item()</code>, <code>register_notification_type()</code>.</li><li><code>dashbread_hosted_visible( $visible, $post, $user )</code> — decide whether a hosted page shows for a member.</li><li><code>dashbread_route_fallback( $html, $route )</code> — render something instead of \"Page not found\".</li><li><code>dashbread_nav_badge( $badge, $item )</code> — a count on a sidebar item.</li></ul><h4>Shell and screens</h4><ul><li><code>dashbread_flyout_tabs</code> / <code>dashbread_flyout_panes</code> — add a flyout tab and its pane.</li><li><code>dashbread_widget_classes</code>, <code>dashbread_widget_tools</code>, <code>dashbread_dashboard_actions</code> — dashboard widget chrome.</li><li><code>dashbread_auth_messages</code>, <code>dashbread_auth_before</code>, <code>dashbread_auth_subtitle</code>, <code>dashbread_auth_body_class</code> — sign-in screens.</li><li><code>dashbread_admin_screens</code> — add a screen under the Dashbread menu.</li><li><code>dashbread_shortcode_reference</code> — add your plugin's shortcodes to the Help screen's reference (sections of <code>{key, label, note, items[{code, close, note, guide}]}</code>).</li></ul><h4>Data</h4><ul><li><code>dashbread_notify( $user_id, $type, $payload )</code>; <code>dashbread_notified</code> fires after each one.</li><li><code>dashbread_profile_fields</code>, <code>dashbread_profile_render_field</code>, <code>dashbread_profile_sanitize_field</code> — profile fields.</li><li>Pro: <code>dashbread_member_row</code>, <code>dashbread_member_detail</code>, <code>dashbread_user_plan_ids</code>, <code>dashbread_membership_granted</code> / <code>_revoked</code> / <code>_expired</code>, <code>dashbread_message_sent</code>, <code>dashbread_thread_started</code>, <code>dashbread_task_completed</code>, <code>dashbread_company_saved</code>, <code>dashbread_email_template</code>, <code>dashbread_email_html</code>.</li><li>Data &amp; Graphs: <code>dashbread_graph_sources</code> and <code>dashbread_graph_objects</code> — see <em>Graph sources for developers</em>.</li></ul><h4>Helpers</h4><ul><li><code>dashbread_user_has_plan( $user_id, $slug_or_id )</code> (Pro).</li><li><code>\\Dashbread\\Core\\Features::has( $feature )</code> — is a feature available on this site?</li></ul>"
  }
 ]
}
