Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion info/pricing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ With Kernel, you only pay for what you use and nothing more. You don't pay for i
| Browser type | Price ($/sec) |
| --- | --- |
| Headless | 0.0000166667 |
| Headful | 0.0001333336 |
| Headful (8GB) | 0.0001333336 |
| Headful (16GB) | 0.0002666672 |
| Headful + GPU acceleration | 0.0008000016 |

> Note: GPU acceleration is only available on headful, on-demand browsers. Standby mode is not supported for GPU-accelerated browsers.
Expand Down
35 changes: 30 additions & 5 deletions snippets/calculator.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const PricingCalculator = () => {

const [plan, setPlan] = useState(defaults.plan);
const [browserType, setBrowserType] = useState(defaults.browserType);
const [headful16, setHeadful16] = useState(false);
const [avgSessionLength, setAvgSessionLength] = useState(defaults.avgSessionLength);
const [numSessions, setNumSessions] = useState(defaults.numSessions);
const [flash, setFlash] = useState(false);
Expand All @@ -20,11 +21,12 @@ export const PricingCalculator = () => {
var url = new URL(window.location);
url.searchParams.set('plan', plan);
url.searchParams.set('browserType', browserType);
url.searchParams.set('headful16', headful16);
url.searchParams.set('duration', avgSessionLength);
url.searchParams.set('sessions', numSessions);
url.hash = 'pricing-calculator';
window.history.replaceState(null, '', url);
}, [plan, browserType, avgSessionLength, numSessions]);
}, [plan, browserType, headful16, avgSessionLength, numSessions]);

const handleBrowserTypeChange = (type) => {
hasInteracted.current = true;
Expand All @@ -34,6 +36,12 @@ export const PricingCalculator = () => {
}
};

const handleMemoryChange = (is16) => {
hasInteracted.current = true;
setHeadful16(is16);
setBrowserType('headful');
};

const handlePlanChange = (newPlan) => {
hasInteracted.current = true;
if (browserType === 'gpu' && newPlan !== 'startup') {
Expand All @@ -43,7 +51,7 @@ export const PricingCalculator = () => {
};

var price = planPrices[plan];
var multiplier = browserMultipliers[browserType];
var multiplier = browserType === 'headful' ? 8 * (headful16 ? 2 : 1) : browserMultipliers[browserType];
var usageCost = usagePrices * multiplier * numSessions * avgSessionLength;

var includedUsageCredits = 5;
Expand Down Expand Up @@ -77,11 +85,23 @@ export const PricingCalculator = () => {
paddingRight: '1.5rem',
};
const btnStyle = (active) => ({
padding: '0.25rem 0.5rem',
padding: '0.375rem 0.75rem',
borderRadius: '0.375rem',
border: '1px solid var(--btn-border)',
fontSize: '0.875rem',
whiteSpace: 'nowrap',
background: active ? 'var(--btn-selected-bg)' : undefined,
cursor: 'pointer',
display: 'inline-flex',
alignItems: 'center',
gap: '0.15rem',
});
const gbStyle = (active) => ({
padding: '0 0.3rem',
background: 'transparent',
fontSize: '0.875rem',
cursor: 'pointer',
color: active ? 'inherit' : 'rgba(128,128,128,0.55)',
});
return (
<Columns cols={2}>
Expand All @@ -102,14 +122,19 @@ export const PricingCalculator = () => {
<label style={labelStyle}>Number of sessions</label>
<input type="number" style={{...inputStyle}} value={numSessions} onChange={(e) => { hasInteracted.current = true; setNumSessions(parseInt(e.target.value)); }} />
</div>
<div style={rowStyle}>
<div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: '0.5rem' }}>
<button class="btn btn-primary dark:text-white" style={btnStyle(browserType === 'headless')} onClick={() => handleBrowserTypeChange('headless')}>Headless</button>
<button class="btn btn-primary dark:text-white" style={btnStyle(browserType === 'headful')} onClick={() => handleBrowserTypeChange('headful')}>Headful</button>
<button class="btn btn-primary dark:text-white" style={btnStyle(browserType === 'headful')} onClick={() => handleBrowserTypeChange('headful')}>
Headful
<span style={gbStyle(!headful16)} onClick={(e) => { e.stopPropagation(); handleMemoryChange(false); }}>8gb</span>
<span style={gbStyle(headful16)} onClick={(e) => { e.stopPropagation(); handleMemoryChange(true); }}>16gb</span>
</button>
<button class="btn btn-primary dark:text-white" style={btnStyle(browserType === 'gpu')} onClick={() => handleBrowserTypeChange('gpu')}>Headful + GPU</button>
</div>
<div style={rowStyle}>
<span style={{ width: '100%', fontSize: '0.8rem', fontStyle: 'italic' }}>
${(usagePrices * multiplier).toFixed(8)}/second
{browserType === 'headful' && <span style={{ marginLeft: '0.5rem' }}>({headful16 ? '16GB' : '8GB'})</span>}
{browserType === 'gpu' && <span style={{ marginLeft: '0.5rem' }}>(Startup tier required)</span>}
</span>
</div>
Expand Down
Loading