(function(){const posthogKey = "phc\_oMfVwfGjzwkE5n7cCaDf25rTm7WaYn8rH4FnvsVq57Zb"; const posthogHost = "https://i.buildy.so"; const forceAnalytics = false; const analyticsHosts = \["buildy.so","www.buildy.so","usecharming.com","www.usecharming.com"\]; const analyticsIdCookie = "charming\_marketing\_identity\_seen"; const legacyAnalyticsIdCookie = "buildy\_marketing\_identity\_seen"; const analyticsIdCookieMaxAgeSeconds = 31536000; !function(t,e){var o,n,p,r;e.\_\_SV||(window.posthog && window.posthog.\_\_loaded)||(window.posthog=e,e.\_i=\[\],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t\[o\[0\]\],e=o\[1\]),t\[e\]=function(){t.push(\[e\].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api\_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")\[0\]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e\[a\]=\[\]:a="posthog",u.people=u.people||\[\],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="init os ds Ie us vs ss ls capture calculateEventProperties register register\_once register\_for\_session unregister unregister\_for\_session ws getFeatureFlag getFeatureFlagPayload getFeatureFlagResult isFeatureEnabled reloadFeatureFlags updateFlags updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures on onFeatureFlags onSurveysLoaded onSessionId getSurveys getActiveMatchingSurveys renderSurvey displaySurvey cancelPendingSurvey canRenderSurvey canRenderSurveyAsync identify setPersonProperties group resetGroups setPersonPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags resetGroupPropertiesForFlags reset get\_distinct\_id getGroups get\_session\_id get\_session\_replay\_url alias set\_config startSessionRecording stopSessionRecording sessionRecordingStarted captureException startExceptionAutocapture stopExceptionAutocapture loadToolbar get\_property getSessionProperty bs ps createPersonProfile setInternalOrTestUser ys es $s opt\_in\_capturing opt\_out\_capturing has\_opted\_in\_capturing has\_opted\_out\_capturing get\_explicit\_consent\_status is\_capturing clear\_opt\_in\_out\_capturing cs debug M gs getPageViewId captureTraceFeedback captureTraceMetric Qr".split(" "),n=0;n<o.length;n++)g(u,o\[n\]);e.\_i.push(\[i,s,a\])},e.\_\_SV=1)}(document,window.posthog||\[\]); var h = window.location.hostname; if (forceAnalytics || analyticsHosts.indexOf(h) !== -1) { const hashParams = new URLSearchParams(window.location.hash.substring(1)); const productDistinctId = hashParams.get('distinct\_id'); const productSessionId = hashParams.get('session\_id'); const productBootstrap = productDistinctId && productSessionId ? { distinctID: productDistinctId, sessionID: productSessionId } : null; let markerDistinctId = null; if (!productBootstrap) { const markerIdPattern = /^\[0-9a-f\]{8}-\[0-9a-f\]{4}-\[0-9a-f\]{4}-\[0-9a-f\]{4}-\[0-9a-f\]{12}$/i; var markerUsedLegacy = false; for (const markerName of \[analyticsIdCookie, legacyAnalyticsIdCookie\]) { const markerPrefix = markerName + '='; const markerCookie = document.cookie .split(';') .map(function (part) { return part.trim(); }) .find(function (part) { return part.startsWith(markerPrefix); }); if (!markerCookie) continue; try { const value = decodeURIComponent(markerCookie.slice(markerPrefix.length)); if (markerIdPattern.test(value)) { markerDistinctId = value; markerUsedLegacy = markerName === legacyAnalyticsIdCookie; break; } } catch {} } } const bootstrap = productBootstrap ?? (markerDistinctId ? { distinctID: markerDistinctId } : null); posthog.init(posthogKey, { api\_host: posthogHost, defaults: '2026-01-30', ...(bootstrap ? { bootstrap } : {}), loaded: function (ph) { const distinctId = ph.get\_distinct\_id(); if (typeof distinctId !== 'string') return; if (markerUsedLegacy) { ph.capture('legacy\_state\_key\_observed', { key: legacyAnalyticsIdCookie }); } try { localStorage.setItem(analyticsIdCookie, distinctId); localStorage.removeItem(legacyAnalyticsIdCookie); } catch {} document.cookie = analyticsIdCookie + '=' + encodeURIComponent(distinctId) + '; Path=/; Max-Age=' + analyticsIdCookieMaxAgeSeconds + '; SameSite=Lax' + (window.location.protocol === 'https:' ? '; Secure' : ''); document.cookie = legacyAnalyticsIdCookie + '=; Path=/; Max-Age=0; SameSite=Lax' + (window.location.protocol === 'https:' ? '; Secure' : ''); }, }); } })();(function(){const ga4Id = "G-XG5Q0M59CD"; const forceAnalytics = false; const analyticsHosts = \["buildy.so","www.buildy.so","usecharming.com","www.usecharming.com"\]; var h = window.location.hostname; if (forceAnalytics || analyticsHosts.indexOf(h) !== -1) { window.dataLayer = window.dataLayer || \[\]; function gtag() { window.dataLayer.push(arguments); } window.gtag = gtag; gtag('consent', 'default', { ad\_storage: 'denied', ad\_user\_data: 'denied', ad\_personalization: 'denied', analytics\_storage: 'granted', }); gtag('js', new Date()); gtag('config', ga4Id); var s = document.createElement('script'); s.async = true; s.src = 'https://www.googletagmanager.com/gtag/js?id=' + ga4Id; document.head.appendChild(s); } })(); (function () { function setThemeColorMetas(theme) { var light = document.querySelector('meta\[data-theme-color="light"\]'); var dark = document.querySelector('meta\[data-theme-color="dark"\]'); if (light) light.setAttribute('media', theme === 'light' ? 'all' : 'not all'); if (dark) dark.setAttribute('media', theme === 'dark' ? 'all' : 'not all'); } try { var stored = localStorage.getItem('charming-theme'); if (stored === 'dark' || stored === 'light') { document.documentElement.setAttribute('data-theme', stored); setThemeColorMetas(stored); } } catch (\_err) { // Storage can be unavailable (private mode, disabled) — fall back to // the media query, same as a first-time visitor. } })(); Custom quote calculator built with AI | Charming(() => { // Keep this fallback aligned with copyValueToClipboard in ./clipboard.ts. // This script runs before modules load, so it cannot import the shared helper. async function copy(value) { try { if (navigator.clipboard) { await navigator.clipboard.writeText(value); return true; } } catch { // Fall through to the textarea path for browsers that block the async API. } let fallback; try { fallback = document.createElement('textarea'); fallback.value = value; fallback.setAttribute('readonly', ''); fallback.style.position = 'fixed'; fallback.style.top = '-9999px'; document.body.appendChild(fallback); fallback.select(); return document.execCommand('copy'); } catch { return false; } finally { fallback?.remove(); } } const resetTimers = new WeakMap(); function setVisible(element, visible) { element?.classList.replace( visible ? 'opacity-0' : 'opacity-100', visible ? 'opacity-100' : 'opacity-0', ); } function resetFeedback(button, island) { const action = button.querySelector('\[data-copy-action-label\]'); const confirmed = button.querySelector('\[data-copy-confirmed-label\]'); const confirmation = island.querySelector('\[data-copy-confirmation\]'); const liveRegion = island.querySelector('\[data-copy-live-region\]'); setVisible(action, true); setVisible(confirmed, false); setVisible(confirmation, false); confirmation?.classList.replace('translate-y-0', 'translate-y-1'); if (confirmation) { confirmation.textContent = button.dataset.copySuccessMessage ?? ''; if (confirmation.dataset.copyConfirmation === 'false') { confirmation.parentElement?.classList.replace('mt-2.5', 'mt-0'); confirmation.parentElement?.classList.replace('grid-rows-\[1fr\]', 'grid-rows-\[0fr\]'); } } if (liveRegion) liveRegion.textContent = ''; resetTimers.delete(button); } function showFeedback(button, island, copied) { const action = button.querySelector('\[data-copy-action-label\]'); const confirmed = button.querySelector('\[data-copy-confirmed-label\]'); const confirmation = island.querySelector('\[data-copy-confirmation\]'); const liveRegion = island.querySelector('\[data-copy-live-region\]'); const message = copied ? (button.dataset.copySuccessMessage ?? '') : (button.dataset.copyBlockedMessage ?? ''); setVisible(action, !copied); setVisible(confirmed, copied); if (confirmation) { confirmation.textContent = message; const buttonOnlySuccess = copied && confirmation.dataset.copyConfirmation === 'false'; setVisible(confirmation, !buttonOnlySuccess); confirmation.classList.replace( buttonOnlySuccess ? 'translate-y-0' : 'translate-y-1', buttonOnlySuccess ? 'translate-y-1' : 'translate-y-0', ); if (!copied && confirmation.dataset.copyConfirmation === 'false') { confirmation.parentElement?.classList.replace('mt-0', 'mt-2.5'); confirmation.parentElement?.classList.replace('grid-rows-\[0fr\]', 'grid-rows-\[1fr\]'); } } if (liveRegion) liveRegion.textContent = message; const priorTimer = resetTimers.get(button); if (priorTimer) clearTimeout(priorTimer); resetTimers.set( button, setTimeout(() => resetFeedback(button, island), 10000), ); } document.addEventListener( 'click', async (event) => { const target = event.target instanceof Element ? event.target : null; const button = target?.closest('button\[data-copy-value\]'); const island = button?.closest('astro-island\[ssr\]'); if (!button || !island) return; showFeedback(button, island, await copy(button.dataset.copyValue ?? '')); }, true, ); })(); {"@context":"https://schema.org","@graph":\[{"@type":"WebPage","@id":"https://usecharming.com/apps/pricing-calculator#webpage","url":"https://usecharming.com/apps/pricing-calculator","name":"Custom quote calculator built with AI | Charming","description":"Build a custom quote calculator for services. Let clients choose a package, scope, timeline, and add-ons, then see a live estimate with clear assumptions.","isPartOf":{"@id":"https://usecharming.com/#website"},"about":{"@id":"https://usecharming.com/#software"},"primaryImageOfPage":"https://usecharming.com/og-image-pricing-calculator.png","speakable":{"@type":"SpeakableSpecification","cssSelector":\["h1","\[data-speakable\]"\]}},{"@type":"BreadcrumbList","@id":"https://usecharming.com/apps/pricing-calculator#breadcrumb","itemListElement":\[{"@type":"ListItem","position":1,"name":"Charming","item":"https://usecharming.com/"},{"@type":"ListItem","position":2,"name":"App ideas","item":"https://usecharming.com/personal-app-ideas"},{"@type":"ListItem","position":3,"name":"Quote calculator","item":"https://usecharming.com/apps/pricing-calculator"}\]},{"@type":"FAQPage","@id":"https://usecharming.com/apps/pricing-calculator#faq","mainEntity":\[{"@type":"Question","name":"What can a custom quote calculator include?","acceptedAnswer":{"@type":"Answer","text":"Include the choices that shape your price, such as service package, project scope, timeline, team size, add-ons, and assumptions. The app can update a working estimate as those choices change."}},{"@type":"Question","name":"Who is this useful for?","acceptedAnswer":{"@type":"Answer","text":"A quote calculator works well for consultants, agencies, studios, and service firms with a repeatable offer whose price changes with a few clear inputs."}},{"@type":"Question","name":"How should we present the result?","acceptedAnswer":{"@type":"Answer","text":"Show the result as a working estimate or a final quote, based on your process. Keep the assumptions and scope beside the total."}},{"@type":"Question","name":"Can clients use the calculator themselves?","acceptedAnswer":{"@type":"Answer","text":"Yes. Share the app link so a client can try the choices in a browser. You can keep changing the calculator through your AI as your services and pricing rules change."}}\]}\]}.custom-app-header\[data-astro-cid-lezcerkg\]{border-bottom:1px solid var(--demo-line);background:var(--demo-panel);justify-content:space-between;align-items:center;gap:12px;padding:14px 16px;display:flex}.app-identity\[data-astro-cid-lezcerkg\]{align-items:center;gap:9px;min-width:0;font-size:12px;display:inline-flex}.app-mark\[data-astro-cid-lezcerkg\]{background:var(--app-accent);width:25px;height:25px;color:var(--app-accent-ink);border-radius:7px;flex:none;place-items:center;font-size:10px;font-weight:800;display:grid}.app-identity\[data-astro-cid-lezcerkg\] strong\[data-astro-cid-lezcerkg\]{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.header-detail\[data-astro-cid-lezcerkg\]{color:var(--demo-ink-muted);flex:none;align-items:center;font-size:8px;display:flex}.header-detail\[data-astro-cid-lezcerkg\]:empty{display:none} .custom-app-shell\[data-astro-cid-2dntfsgd\]{border:1px solid var(--border-card);border-radius:var(--radius-card);background:var(--wsb-mock-surface);width:100%;box-shadow:var(--shadow-card);overflow:hidden} .demo-stage\[data-astro-cid-kddhf3eu\]{--demo-ink:var(--color-ink);--demo-ink-soft:var(--color-ink-light);--demo-ink-muted:var(--color-ink-lighter);--demo-line:var(--color-rule);--demo-line-strong:var(--color-rule-strong);--demo-surface:var(--wsb-mock-surface);--demo-canvas:var(--color-paper);--demo-panel:var(--color-card);--demo-muted:var(--color-muted);--demo-font-ui:var(--wsb-font-sans);--demo-font-display:var(--wsb-font-serif);width:100%;color:var(--demo-ink);font-family:var(--demo-font-ui)}.demo-stage\[data-astro-cid-kddhf3eu\],.demo-stage\[data-astro-cid-kddhf3eu\] \[data-astro-cid-kddhf3eu\]{box-sizing:border-box} 

[![Charming](/charming-lockup.svg)![Charming](/charming-lockup-dark.svg)](/)

[Ideas](/#apps)[Pricing](/#pricing)[For Work](/work)[Blog](/blog)[Docs](/docs)

[Sign up](https://charm.ing/auth/signup)

[Ideas](/#apps)[Pricing](/#pricing)[For Work](/work)[Blog](/blog)[Docs](/docs)

var e=document.querySelector(\`\[data-nav-menu\]\`);e&&(e.querySelectorAll(\`a\`).forEach(t=>{t.addEventListener(\`click\`,()=>{e.open=!1})}),document.addEventListener(\`pointerdown\`,t=>{e.open&&!e.contains(t.target)&&(e.open=!1)}),document.addEventListener(\`keydown\`,t=>{t.key===\`Escape\`&&e.open&&(e.open=!1,e.querySelector(\`summary\`)?.focus())}));

# Turn scope into a clear estimate.

Build a custom quote calculator for your services. Let clients choose a package, scope, timeline, and add-ons, then see the estimate update.

astro-island,astro-slot,astro-static-slot{display:contents}(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).load=e;window.dispatchEvent(new Event("astro:load"));})();(()=>{var g=Object.defineProperty;var w=(a,s,c)=>s in a?g(a,s,{enumerable:!0,configurable:!0,writable:!0,value:c}):a\[s\]=c;var l=(a,s,c)=>w(a,typeof s!="symbol"?s+"":s,c);var E=new Set(\["\_\_proto\_\_","constructor","prototype"\]);{let a={0:t=>y(t),1:t=>c(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(c(t)),5:t=>new Set(c(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t),11:t=>Number.POSITIVE\_INFINITY\*t},s=t=>{let\[p,e\]=t;return p in a?a\[p\](e):void 0},c=t=>t.map(s),y=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map((\[p,e\])=>\[p,s(e)\]));class f extends HTMLElement{constructor(){super(...arguments);l(this,"Component");l(this,"hydrator");l(this,"hydrate",async()=>{var b;if(!this.hydrator||!this.isConnected)return;let e=(b=this.parentElement)==null?void 0:b.closest("astro-island\[ssr\]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let r=this.querySelectorAll("astro-slot"),n={},d=this.querySelectorAll("template\[data-astro-template\]");for(let o of d){let i=o.closest(this.tagName);i!=null&&i.isSameNode(this)&&(n\[o.getAttribute("data-astro-template")||"default"\]=o.innerHTML,o.remove())}for(let o of r){let i=o.closest(this.tagName);i!=null&&i.isSameNode(this)&&(n\[o.getAttribute("name")||"default"\]=o.innerHTML)}let u;try{u=this.hasAttribute("props")?y(JSON.parse(this.getAttribute("props"))):{}}catch(o){let i=this.getAttribute("component-url")||"<unknown>",v=this.getAttribute("component-export");throw v&&(i+=\` (export ${v})\`),console.error(\`\[hydrate\] Error parsing props for component ${i}\`,this.getAttribute("props"),o),o}let h;await this.hydrator(this)(this.Component,u,n,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});l(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute("await-children")||document.readyState==="interactive"||document.readyState==="complete")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener("DOMContentLoaded",e),r.disconnect(),this.childrenConnectedCallback()},r=new MutationObserver(()=>{var n;((n=this.lastChild)==null?void 0:n.nodeType)===Node.COMMENT\_NODE&&this.lastChild.nodeValue==="astro:end"&&(this.lastChild.remove(),e())});r.observe(this,{childList:!0}),document.addEventListener("DOMContentLoaded",e)}}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}getRetryImportUrl(e){let r=new URL(e,document.baseURI);return r.searchParams.set("astro-retry",Date.now().toString()),r.toString()}async importWithRetry(e){try{return await import(e)}catch(r){return await new Promise(n=>setTimeout(n,1e3)),import(this.getRetryImportUrl(e))}}handleHydrationError(e){let r=this.getAttribute("component-url"),n=new CustomEvent("astro:hydration-error",{cancelable:!0,bubbles:!0,composed:!0,detail:{error:e,componentUrl:r}});this.dispatchEvent(n)&&console.error(\`\[astro-island\] Error hydrating ${r}\`,e)}async start(){let e=JSON.parse(this.getAttribute("opts")),r=this.getAttribute("client");if(Astro\[r\]===void 0){window.addEventListener(\`astro:${r}\`,()=>this.start(),{once:!0});return}try{await Astro\[r\](async()=>{let n=this.getAttribute("renderer-url");try{let\[d,{default:u}\]=await Promise.all(\[this.importWithRetry(this.getAttribute("component-url")),n?this.importWithRetry(n):Promise.resolve({default:()=>()=>{}})\]),h=this.getAttribute("component-export")||"default";if(h.includes(".")){this.Component=d;for(let m of h.split(".")){if(E.has(m)||!this.Component||typeof this.Component!="object"&&typeof this.Component!="function"||!Object.hasOwn(this.Component,m))throw new Error(\`Invalid component export path: ${h}\`);this.Component=this.Component\[m\]}}else{if(E.has(h))throw new Error(\`Invalid component export path: ${h}\`);this.Component=d\[h\]}return this.hydrator=u,this.hydrate}catch(d){return this.handleHydrationError(d),()=>{}}},e,this)}catch(n){this.handleHydrationError(n)}}attributeChangedCallback(){this.hydrate()}}l(f,"observedAttributes",\["props"\]),customElements.get("astro-island")||customElements.define("astro-island",f)}})();

[Create an app](https://charm.ing/auth/signup)

![](/logos/openclaw.svg)![](/logos/codex.svg)![](/logos/claude-code.png)![](/logos/cursor.svg)Copy promptCopied!

Copied! Now paste it into your favorite AI agent!

Q**Project quote**Northstar launchEstimate updates as options change

1**Package**2**Scope**3**Options**

Service package

**Focused**Core project

**Partner**Project + rollout

**Extended**Full program

Scope

**4 workstreams**−    +

Timeline

**6 weeks**Change

Add-ons

_✓_**Team workshop**+$2,400

**On-site day**+$1,800

Working estimate**$18,600**Based on the options shown

Partner package

$14,400

Scope

$1,800

Team workshop

$2,400

Assumptions

One weekly review. Client supplies research files. Travel is not included.

Save these options

## Show what changes the price.

Give each choice a clear place. Keep the total and the assumptions in view.

Core

Plus

Full

### Service package

Let clients start with the level of help they need.

Workstreams**4   −   +**

Team size**8   −   +**

Markets**2   −   +**

### Scope

Turn the work that changes the price into clear choices.

2 weeks**6 weeks**10 weeks

### Timeline

Show how pace or duration changes the estimate.

_✓_Workshop

On-site day

Support

### Add-ons

Keep useful extras separate from the base package.

WORKING ESTIMATE**$18,600**Updates with each choice

### Live estimate

Update the total as the client changes an option.

ASSUMPTIONS

One weekly review  
Client supplies files  
Travel not included

### Assumptions

Put the limits and inputs next to the number.

## Fit the calculator to the service.

Use the inputs your clients already ask about. Give them a faster way to compare the choices.

[See more client apps for consultants](/work/consultants)

### Consulting scope

01

Price a project by workstream, team size, and timeline.

Working estimate**$18,600**4 workstreams · 6 weeks

### Agency package

02

Let a client compare packages and choose useful add-ons.

Working estimate**$7,400**Growth package · 2 add-ons

### Service plan

03

Make recurring scope and options easier to compare.

Working estimate**$3,200**Monthly · Standard support

## Your pricing logic, in an app.

Your AI can turn the way you price work into a calculator clients can use. When the offer changes, ask it to change the app.

01

### Start with your offer

Use your packages, inputs, and rules.

02

### Share the choices

Let clients explore the options in a browser.

03

### Change it later

Ask your AI to update the calculator.

## Turn your pricing rules into a calculator clients can use.

(()=>{var a=(s,i,o)=>{let r=async()=>{await(await s())()},t=typeof i.value=="object"?i.value:void 0,c={rootMargin:t==null?void 0:t.rootMargin},n=new IntersectionObserver(e=>{for(let l of e)if(l.isIntersecting){n.disconnect(),r();break}},c);for(let e of o.children)n.observe(e)};(self.Astro||(self.Astro={})).visible=a;window.dispatchEvent(new Event("astro:visible"));})();

[Create an app](https://charm.ing/auth/signup)

![](/logos/openclaw.svg)![](/logos/codex.svg)![](/logos/claude-code.png)![](/logos/cursor.svg)Copy promptCopied!

Copied! Now paste it into your favorite AI agent!

## Quote calculator questions

What can a custom quote calculator include?+

Include the choices that shape your price, such as service package, project scope, timeline, team size, add-ons, and assumptions. The app can update a working estimate as those choices change.

Who is this useful for?+

A quote calculator works well for consultants, agencies, studios, and service firms with a repeatable offer whose price changes with a few clear inputs.

How should we present the result?+

Show the result as a working estimate or a final quote, based on your process. Keep the assumptions and scope beside the total.

Can clients use the calculator themselves?+

Yes. Share the app link so a client can try the choices in a browser. You can keep changing the calculator through your AI as your services and pricing rules change.

[](/)

Software that’s finally yours.

[Up and running](https://status.usecharming.com "System status. Opens status.usecharming.com")

## Explore

*   [Ideas](/#apps)
*   [How it works](/how-it-works)
*   [Pricing](/#pricing)
*   [For Work](/work)
*   [Blog](/blog)

## For work

*   [Finance](/work/finance)
*   [Internal tools](/work/internal-tools)
*   [Recruiting](/work/recruiting)
*   [Consultants](/work/consultants)
*   [Marketing](/work/marketing)

## Works with

*   [ChatGPT](https://chatgpt.com/plugins/plugin_asdk_app_6a56c533cd7c8191b9a16cb7973a65e6)
*   [Claude](https://charm.ing/docs/clients/claude)
*   [Microsoft 365 Copilot](https://charm.ing/docs/clients/microsoft-365-copilot)
*   [Cursor](https://charm.ing/docs/clients/cursor)
*   [All setup guides](/works-with)

## Learn

*   [Docs](/docs)
*   [Guides](/guides)
*   [Contact](/contact-us)
*   [llms.txt](/llms.txt)
*   [Email us](mailto:support@usecharming.com)

Explore+

*   [Ideas](/#apps)
*   [How it works](/how-it-works)
*   [Pricing](/#pricing)
*   [For Work](/work)
*   [Blog](/blog)

For work+

*   [Finance](/work/finance)
*   [Internal tools](/work/internal-tools)
*   [Recruiting](/work/recruiting)
*   [Consultants](/work/consultants)
*   [Marketing](/work/marketing)

App ideas+

*   [Job application tracker](/apps/job-application-tracker)
*   [Project status](/apps/project-status-tracker)
*   [Meeting actions](/apps/meeting-action-tracker)
*   [Vendor review](/apps/vendor-review)
*   [Product launch](/apps/product-launch-tracker)
*   [Review and approval](/apps/review-approval)
*   [Quote calculator](/apps/pricing-calculator)

Works with+

*   [ChatGPT](https://chatgpt.com/plugins/plugin_asdk_app_6a56c533cd7c8191b9a16cb7973a65e6)
*   [Claude](https://charm.ing/docs/clients/claude)
*   [Microsoft 365 Copilot](https://charm.ing/docs/clients/microsoft-365-copilot)
*   [Cursor](https://charm.ing/docs/clients/cursor)
*   [All setup guides](/works-with)

Learn+

*   [Docs](/docs)
*   [Guides](/guides)
*   [Contact](/contact-us)
*   [llms.txt](/llms.txt)
*   [Email us](mailto:support@usecharming.com)

## App ideas

[Job application tracker](/apps/job-application-tracker)[Project status](/apps/project-status-tracker)[Meeting actions](/apps/meeting-action-tracker)[Vendor review](/apps/vendor-review)[Product launch](/apps/product-launch-tracker)[Review and approval](/apps/review-approval)[Quote calculator](/apps/pricing-calculator)

© 2026 Charming

[Privacy](/privacy)[Terms](/terms)[Fair use](/fair-use)[Subprocessors](/subprocessors)

charm.ing

var e=document.documentElement,t=window.matchMedia(\`(prefers-color-scheme: dark)\`),n=()=>{let n=e.getAttribute(\`data-theme\`);return n===\`light\`||n===\`dark\`?n:t.matches?\`dark\`:\`light\`},r=document.querySelector(\`\[data-theme-toggle\]\`),i=()=>{if(!r)return;let e=n()===\`dark\`?\`light\`:\`dark\`;r.setAttribute(\`aria-label\`,\`Switch to ${e} theme\`)};i();var a=e=>{let t=document.querySelector(\`meta\[data-theme-color="light"\]\`),n=document.querySelector(\`meta\[data-theme-color="dark"\]\`);t?.setAttribute(\`media\`,e===\`light\`?\`all\`:\`not all\`),n?.setAttribute(\`media\`,e===\`dark\`?\`all\`:\`not all\`)};r?.addEventListener(\`click\`,()=>{let t=n()===\`dark\`?\`light\`:\`dark\`;e.setAttribute(\`data-theme\`,t),a(t);try{localStorage.setItem(\`charming-theme\`,t)}catch{}i()}),t.addEventListener(\`change\`,()=>{e.hasAttribute(\`data-theme\`)||i()});