Skip to content

Instantly share code, notes, and snippets.

@Braunson
Created April 10, 2025 22:56
Show Gist options
  • Save Braunson/d0c54f8ac89b90ed1187503c6d0cc3cb to your computer and use it in GitHub Desktop.
Save Braunson/d0c54f8ac89b90ed1187503c6d0cc3cb to your computer and use it in GitHub Desktop.
Pizza Dough calculator build with Tailwind CSS & Alpine.js. Initially inspired + based on https://doughguy.co
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pizza Dough Calculator</title>
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<!-- Print-only styles -->
<style type="text/css" media="print">
.print-hide, .print-hide * {
display: none !important;
}
.timer-section {
display: none !important;
}
body {
font-family: Arial, sans-serif;
background: white;
}
button, .text-sm.bg-blue-100 {
display: none !important;
}
@page {
margin: 1cm;
}
.recipe-content {
page-break-inside: avoid;
}
</style>
</head>
<body class="bg-gray-100 font-sans">
<div class="container mx-auto py-8 px-4 max-w-4xl" x-data="doughCalculator()">
<h1 class="text-3xl font-bold text-center mb-8 text-red-700">Pizza Dough Calculator</h1>
<!-- Controls -->
<div class="flex flex-wrap justify-between items-center mb-6 print-hide">
<!-- Print Button -->
<button @click="printRecipe()" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded mb-2 sm:mb-0 flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 17h2a2 2 0 002-2v-4a2 2 0 00-2-2H5a2 2 0 00-2 2v4a2 2 0 002 2h2m2 4h6a2 2 0 002-2v-4a2 2 0 00-2-2H9a2 2 0 00-2 2v4a2 2 0 002 2zm8-12V5a2 2 0 00-2-2H9a2 2 0 00-2 2v4h10z" />
</svg>
Print Recipe
</button>
<!-- Show Active Timers -->
<button @click="showActiveTimers = !showActiveTimers" class="bg-gray-600 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded mb-2 sm:mb-0 flex items-center">
Show/Hide Timers
</button>
<!-- Save Configuration -->
<div class="flex flex-col sm:flex-row gap-2">
<input x-model="saveConfigName" placeholder="Configuration Name" class="border rounded px-3 py-2 w-full sm:w-48">
<button @click="saveConfiguration()" class="bg-green-600 hover:bg-green-700 text-white font-bold py-2 px-4 rounded flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4" />
</svg>
Save Config
</button>
</div>
</div>
<!-- Saved Configurations -->
<div class="mb-6 print-hide" x-show="savedConfigs.length > 0">
<div class="bg-white rounded-lg shadow p-4">
<h3 class="font-semibold text-lg mb-2">Saved Configurations</h3>
<div class="flex flex-wrap gap-2">
<template x-for="(config, index) in savedConfigs" :key="index">
<div class="flex items-center">
<button @click="loadConfiguration(config)" class="bg-gray-200 hover:bg-gray-300 text-gray-800 py-1 px-3 rounded-l">
<span x-text="config.name"></span>
</button>
<button @click="deleteConfiguration(index)" class="bg-red-200 hover:bg-red-300 text-red-800 py-1 px-2 rounded-r">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</template>
</div>
</div>
</div>
`
<!-- Main Calculator Card -->
<div class="bg-white rounded-lg shadow-lg p-6 mb-8">
<!-- Basic Settings -->
<div class="grid md:grid-cols-2 gap-6 mb-6 print-hide">
<div>
<h2 class="text-xl font-semibold mb-4 text-red-600">Basic Settings</h2>
<!-- Pizza Size -->
<div class="mb-4">
<label class="block text-gray-700 mb-2">Pizza Size: <span x-text="pizzaSize"></span> <span x-text="units.length"></span></label>
<input type="range" x-model.number="pizzaSize" min="10" max="20" step="1" class="w-full h-2 bg-red-200 rounded-lg appearance-none cursor-pointer">
</div>
<!-- Number of Pizzas -->
<div class="mb-4">
<label class="block text-gray-700 mb-2">Number of Pizzas: <span x-text="pizzaQuantity"></span></label>
<input type="range" x-model.number="pizzaQuantity" min="1" max="10" step="1" class="w-full h-2 bg-red-200 rounded-lg appearance-none cursor-pointer">
</div>
<!-- Pizza Thickness -->
<div class="mb-4">
<label class="block text-gray-700 mb-2">Pizza Thickness:</label>
<select x-model.number="pizzaThickness" class="w-full p-2 border border-gray-300 rounded">
<option value="1.8">Thin (1.8)</option>
<option value="2.11">Regular (2.11)</option>
<option value="2.75">Thick (2.75)</option>
</select>
</div>
<!-- Temperature Conversion -->
<div class="mb-4 p-4 bg-gray-50 rounded-lg">
<h3 class="font-semibold text-md mb-2">Temperature Conversion</h3>
<div class="grid grid-cols-2 gap-3">
<div>
<label class="block text-gray-700 text-sm">Fahrenheit</label>
<input type="number" x-model.number="fahrenheit" @input="celsiusFromF()" class="w-full p-2 border border-gray-300 rounded">
</div>
<div>
<label class="block text-gray-700 text-sm">Celsius</label>
<input type="number" x-model.number="celsius" @input="fahrenheitFromC()" class="w-full p-2 border border-gray-300 rounded">
</div>
</div>
</div>
</div>
<div>
<h2 class="text-xl font-semibold mb-4 text-red-600">Advanced Settings</h2>
<!-- Unit Toggle -->
<div class="mb-4">
<label class="block text-gray-700 mb-2">Measurement Units:</label>
<div class="flex space-x-4">
<label class="inline-flex items-center">
<input type="radio" x-model="unitSystem" value="metric" class="form-radio text-red-600">
<span class="ml-2">Metric (g, ml)</span>
</label>
<label class="inline-flex items-center">
<input type="radio" x-model="unitSystem" value="imperial" class="form-radio text-red-600">
<span class="ml-2">Imperial (oz, cups)</span>
</label>
</div>
</div>
<!-- Hydration Percentage -->
<div class="mb-4">
<label class="block text-gray-700 mb-2">Hydration: <span x-text="hydrationPercentage"></span>%</label>
<input type="range" x-model.number="hydrationPercentage" min="55" max="75" step="1" class="w-full h-2 bg-red-200 rounded-lg appearance-none cursor-pointer">
</div>
<!-- Preferment Option -->
<div class="mb-4">
<label class="block text-gray-700 mb-2">Dough Method:</label>
<select x-model="doughMethod" class="w-full p-2 border border-gray-300 rounded">
<option value="direct">Direct Method</option>
<option value="preferment">Preferment (Biga/Poolish)</option>
<option value="sourdough">Sourdough</option>
</select>
</div>
<!-- Preferment Percentage (only visible when preferment is selected) -->
<div class="mb-4" x-show="doughMethod === 'preferment'">
<label class="block text-gray-700 mb-2">Preferment Percentage: <span x-text="prefermentPercentage"></span>%</label>
<input type="range" x-model.number="prefermentPercentage" min="20" max="60" step="5" class="w-full h-2 bg-red-200 rounded-lg appearance-none cursor-pointer">
</div>
<!-- Sourdough Starter Percentage (only visible when sourdough is selected) -->
<div class="mb-4" x-show="doughMethod === 'sourdough'">
<label class="block text-gray-700 mb-2">Starter Percentage: <span x-text="starterPercentage"></span>%</label>
<input type="range" x-model.number="starterPercentage" min="10" max="30" step="5" class="w-full h-2 bg-red-200 rounded-lg appearance-none cursor-pointer">
<p class="text-sm text-gray-500 mt-1">Assumes 100% hydration starter</p>
</div>
</div>
</div>
<!-- Results -->
<div class="mt-8 border-t pt-6 recipe-content">
<h2 class="text-xl font-semibold mb-4 text-center text-red-600">Recipe Results</h2>
<!-- Ingredient Table -->
<div class="overflow-x-auto">
<table class="w-full border-collapse">
<thead>
<tr class="bg-red-100">
<th class="p-2 text-left border">Ingredient</th>
<th class="p-2 text-right border">Amount</th>
<template x-if="doughMethod === 'preferment'">
<th class="p-2 text-right border">For Preferment</th>
</template>
<template x-if="doughMethod === 'sourdough'">
<th class="p-2 text-right border">For Levain</th>
</template>
<th class="p-2 text-right border">For Main Dough</th>
</tr>
</thead>
<tbody>
<!-- Flour -->
<tr class="border-b hover:bg-gray-50">
<td class="p-2 border">Flour</td>
<td class="p-2 text-right border">
<span x-text="formatMeasurement(ingredients.flour.total)"></span>
</td>
<template x-if="doughMethod === 'preferment'">
<td class="p-2 text-right border">
<span x-text="formatMeasurement(ingredients.flour.preferment)"></span>
</td>
</template>
<template x-if="doughMethod === 'sourdough'">
<td class="p-2 text-right border">
<span x-text="formatMeasurement(ingredients.flour.preferment)"></span>
</td>
</template>
<td class="p-2 text-right border">
<span x-text="formatMeasurement(ingredients.flour.main)"></span>
</td>
</tr>
<!-- Water -->
<tr class="border-b hover:bg-gray-50">
<td class="p-2 border">Water</td>
<td class="p-2 text-right border">
<span x-text="formatMeasurement(ingredients.water.total, 'liquid')"></span>
</td>
<template x-if="doughMethod === 'preferment'">
<td class="p-2 text-right border">
<span x-text="formatMeasurement(ingredients.water.preferment, 'liquid')"></span>
</td>
</template>
<template x-if="doughMethod === 'sourdough'">
<td class="p-2 text-right border">
<span x-text="formatMeasurement(ingredients.water.preferment, 'liquid')"></span>
</td>
</template>
<td class="p-2 text-right border">
<span x-text="formatMeasurement(ingredients.water.main, 'liquid')"></span>
</td>
</tr>
<!-- Sourdough Starter (only for sourdough method) -->
<template x-if="doughMethod === 'sourdough'">
<tr class="border-b hover:bg-gray-50">
<td class="p-2 border">Sourdough Starter (100% hydration)</td>
<td class="p-2 text-right border">
<span x-text="formatMeasurement(ingredients.starter.total)"></span>
</td>
<td class="p-2 text-right border">
<span x-text="formatMeasurement(ingredients.starter.total)"></span>
</td>
<td class="p-2 text-right border">0</td>
</tr>
</template>
<!-- Yeast (not for sourdough) -->
<template x-if="doughMethod !== 'sourdough'">
<tr class="border-b hover:bg-gray-50">
<td class="p-2 border">Yeast (instant dry)</td>
<td class="p-2 text-right border">
<span x-text="formatMeasurement(ingredients.yeast.total, 'yeast')"></span>
</td>
<template x-if="doughMethod === 'preferment'">
<td class="p-2 text-right border">
<span x-text="formatMeasurement(ingredients.yeast.preferment, 'yeast')"></span>
</td>
</template>
<td class="p-2 text-right border">
<span x-text="formatMeasurement(ingredients.yeast.main, 'yeast')"></span>
</td>
</tr>
</template>
<!-- Salt -->
<tr class="border-b hover:bg-gray-50">
<td class="p-2 border">Salt</td>
<td class="p-2 text-right border">
<span x-text="formatMeasurement(ingredients.salt.total)"></span>
</td>
<template x-if="doughMethod === 'preferment' || doughMethod === 'sourdough'">
<td class="p-2 text-right border">0</td>
</template>
<td class="p-2 text-right border">
<span x-text="formatMeasurement(ingredients.salt.main)"></span>
</td>
</tr>
<!-- Sugar -->
<tr class="border-b hover:bg-gray-50">
<td class="p-2 border">Sugar</td>
<td class="p-2 text-right border">
<span x-text="formatMeasurement(ingredients.sugar.total)"></span>
</td>
<template x-if="doughMethod === 'preferment' || doughMethod === 'sourdough'">
<td class="p-2 text-right border">0</td>
</template>
<td class="p-2 text-right border">
<span x-text="formatMeasurement(ingredients.sugar.main)"></span>
</td>
</tr>
<!-- Olive Oil -->
<tr class="border-b hover:bg-gray-50">
<td class="p-2 border">Olive Oil</td>
<td class="p-2 text-right border">
<span x-text="formatMeasurement(ingredients.oliveOil.total, 'liquid')"></span>
</td>
<template x-if="doughMethod === 'preferment' || doughMethod === 'sourdough'">
<td class="p-2 text-right border">0</td>
</template>
<td class="p-2 text-right border">
<span x-text="formatMeasurement(ingredients.oliveOil.main, 'liquid')"></span>
</td>
</tr>
<!-- Total Dough Weight -->
<tr class="border-b hover:bg-gray-50 font-bold bg-gray-100">
<td class="p-2 border">Total Dough Weight</td>
<td class="p-2 text-right border">
<span x-text="formatMeasurement(totalDoughWeight)"></span>
</td>
<template x-if="doughMethod === 'preferment' || doughMethod === 'sourdough'">
<td class="p-2 text-right border">
<span x-text="formatMeasurement(prefermentTotalWeight)"></span>
</td>
</template>
<td class="p-2 text-right border">
<span x-text="formatMeasurement(mainDoughWeight)"></span>
</td>
</tr>
<!-- Dough Ball Weight -->
<tr class="border-b hover:bg-gray-50 font-bold">
<td class="p-2 border">Dough Ball Weight (each)</td>
<td class="p-2 text-right border" colspan="3">
<span x-text="formatMeasurement(doughBallWeight)"></span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- The Active Timers section at the top still provides a consolidated view -->
<div class="mb-6 print-hide" x-show="activeTimers.length > 0 && showActiveTimers">
<div class="bg-white rounded-lg shadow p-4">
<h3 class="font-semibold text-lg mb-2">Active Timers</h3>
<div class="space-y-2">
<template x-for="timer in activeTimers" :key="timer.id">
<div class="bg-yellow-100 border-l-4 border-yellow-500 p-3 rounded"
:class="{
'bg-yellow-100 border-yellow-500': timer.running && timer.remaining > 0,
'bg-gray-100 border-gray-500': !timer.running && timer.remaining > 0,
'bg-green-100 border-green-500': timer.remaining <= 0
}">
<div class="flex justify-between items-center">
<div>
<h4 class="font-bold" x-text="timer.name"></h4>
<p class="text-2xl font-mono" x-text="formatTime(timer.remaining)"></p>
</div>
<div class="flex gap-2">
<button
@click="toggleTimerById(timer.id)"
class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-1 px-3 rounded"
:class="timer.running ? 'bg-yellow-600 hover:bg-yellow-700' : 'bg-blue-600 hover:bg-blue-700'">
<span x-text="timer.running ? 'Pause' : 'Resume'"></span>
</button>
<button
@click="resetTimerById(timer.id)"
class="bg-green-600 hover:bg-green-700 text-white font-bold py-1 px-3 rounded">
Reset
</button>
<button
@click="removeTimerById(timer.id)"
class="bg-red-600 hover:bg-red-700 text-white font-bold py-1 px-3 rounded">
Remove
</button>
</div>
</div>
</div>
</template>
</div>
</div>
</div>
<!-- Instructions Card -->
<div class="bg-white rounded-lg shadow-lg p-6 recipe-content">
<h2 class="text-xl font-semibold mb-4 text-red-600">Dough Making Instructions</h2>
<!-- Direct Method Instructions -->
<template x-if="doughMethod === 'direct'">
<ol class="list-decimal pl-6 space-y-2">
<li>
<div class="flex justify-between items-center">
<span>Cool water to &lt;60°F (15°C).</span>
<div class="timer-section" x-html="timerButton('Cool water', 5)"></div>
</div>
</li>
<li>
<div class="flex justify-between items-center">
<span>Mix the water and yeast.</span>
<div class="timer-section" x-html="timerButton('Mix water & yeast', 1)"></div>
</div>
</li>
<li>
<div class="flex justify-between items-center">
<span>Add flour and olive oil and mix for 2 minutes.</span>
<div class="timer-section" x-html="timerButton('Initial mix', 2)"></div>
</div>
</li>
<li>Keep mixing on low, then add sugar and salt.</li>
<li>
<div class="flex justify-between items-center">
<span>Mix for 10 more minutes.</span>
<div class="timer-section" x-html="timerButton('Final mix', 10)"></div>
</div>
</li>
<li>
<div class="flex justify-between items-center">
<span>Cover the dough with plastic wrap and rest for 20 minutes.</span>
<div class="timer-section" x-html="timerButton('Dough rest', 20)"></div>
</div>
</li>
<li>Divide the dough into <span x-text="pizzaQuantity"></span> portions of <span x-text="formatMeasurement(doughBallWeight)"></span> each.</li>
<li>Shape into balls, sealing the seam.</li>
<li>Put the dough in a lightly oiled container.</li>
<li>
<div class="flex justify-between items-center">
<span>Cover tightly and refrigerate for 2-4 days. 3 days is ideal.</span>
</div>
</li>
<li>
<div class="flex justify-between items-center">
<span>Let the dough come to room temperature before using (about 2 hours).</span>
<div class="timer-section" x-html="timerButton('Room temp rest', 120, '2 hours')"></div>
</div>
</li>
</ol>
</template>
<!-- Preferment Method Instructions -->
<template x-if="doughMethod === 'preferment'">
<div>
<h3 class="font-semibold text-lg mb-2">Day 1: Make the Preferment</h3>
<ol class="list-decimal pl-6 space-y-2 mb-4">
<li>Mix <span x-text="formatMeasurement(ingredients.flour.preferment)"></span> flour with <span x-text="formatMeasurement(ingredients.water.preferment, 'liquid')"></span> water and <span x-text="formatMeasurement(ingredients.yeast.preferment, 'yeast')"></span> yeast.</li>
<li>
<div class="flex justify-between items-center">
<span>Cover and let ferment at room temperature for 12-16 hours.</span>
<div class="flex items-center timer-section">
<button @click="startTimer('Preferment fermentation', 14*60)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded">
Set Timer (14 hrs)
</button>
</div>
</div>
</li>
</ol>
<h3 class="font-semibold text-lg mb-2">Day 2: Make the Final Dough</h3>
<ol class="list-decimal pl-6 space-y-2">
<li>Add the preferment to <span x-text="formatMeasurement(ingredients.water.main, 'liquid')"></span> cool water.</li>
<li>
<div class="flex justify-between items-center">
<span>Add <span x-text="formatMeasurement(ingredients.flour.main)"></span> flour and <span x-text="formatMeasurement(ingredients.oliveOil.main, 'liquid')"></span> olive oil and mix for 2 minutes.</span>
<div class="flex items-center timer-section">
<button @click="startTimer('Initial mix', 2)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded">
Set Timer (2 min)
</button>
</div>
</div>
</li>
<li>
<div class="flex justify-between items-center">
<span>Add <span x-text="formatMeasurement(ingredients.salt.main)"></span> salt and <span x-text="formatMeasurement(ingredients.sugar.main)"></span> sugar and mix for 8-10 more minutes.</span>
<div class="flex items-center timer-section">
<button @click="startTimer('Final mix', 9)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded">
Set Timer (9 min)
</button>
</div>
</div>
</li>
<li>
<div class="flex justify-between items-center">
<span>Cover the dough and let rest for 30 minutes.</span>
<div class="flex items-center timer-section">
<button @click="startTimer('Dough rest', 30)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded">
Set Timer (30 min)
</button>
</div>
</div>
</li>
<li>
<div class="flex justify-between items-center">
<span>Perform 3-4 sets of stretch and folds at 30-minute intervals.</span>
<div class="flex items-center timer-section">
<button @click="startTimer('Stretch and fold', 30)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded">
Set Timer (30 min)
</button>
</div>
</div>
</li>
<li>
<div class="flex justify-between items-center">
<span>After the final fold, let the dough bulk ferment for 1-2 hours at room temperature.</span>
<div class="flex items-center timer-section">
<button @click="startTimer('Bulk fermentation', 90)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded">
Set Timer (90 min)
</button>
</div>
</div>
</li>
<li>Divide the dough into <span x-text="pizzaQuantity"></span> portions of <span x-text="formatMeasurement(doughBallWeight)"></span> each.</li>
<li>Shape into balls, sealing the seam.</li>
<li>Put the dough in a lightly oiled container.</li>
<li>
<div class="flex justify-between items-center">
<span>Cover tightly and refrigerate for 24-48 hours.</span>
<div class="flex items-center timer-section">
<button @click="startTimer('Refrigeration', 36*60)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded">
Set Timer (36 hrs)
</button>
</div>
</div>
</li>
<li>
<div class="flex justify-between items-center">
<span>Let the dough come to room temperature before using (about 2-3 hours).</span>
<div class="flex items-center timer-section">
<button @click="startTimer('Room temp rest', 150)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded">
Set Timer (2.5 hrs)
</button>
</div>
</div>
</li>
</ol>
</div>
</template>
<!-- Sourdough Method Instructions -->
<template x-if="doughMethod === 'sourdough'">
<div>
<h3 class="font-semibold text-lg mb-2">Day 1: Make the Levain</h3>
<ol class="list-decimal pl-6 space-y-2 mb-4">
<li>Mix <span x-text="formatMeasurement(ingredients.starter.total)"></span> sourdough starter with <span x-text="formatMeasurement(ingredients.flour.preferment)"></span> flour and <span x-text="formatMeasurement(ingredients.water.preferment, 'liquid')"></span> water.</li>
<li>
<div class="flex justify-between items-center">
<span>Cover and let ferment at room temperature for 8-12 hours.</span>
<div class="flex items-center timer-section">
<button @click="startTimer('Levain fermentation', 10*60)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded">
Set Timer (10 hrs)
</button>
</div>
</div>
</li>
</ol>
<h3 class="font-semibold text-lg mb-2">Day 2: Make the Final Dough</h3>
<ol class="list-decimal pl-6 space-y-2">
<li>Add the levain to <span x-text="formatMeasurement(ingredients.water.main, 'liquid')"></span> cool water.</li>
<li>
<div class="flex justify-between items-center">
<span>Add <span x-text="formatMeasurement(ingredients.flour.main)"></span> flour and <span x-text="formatMeasurement(ingredients.oliveOil.main, 'liquid')"></span> olive oil and mix for 2 minutes.</span>
<div class="flex items-center timer-section">
<button @click="startTimer('Initial mix', 2)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded">
Set Timer (2 min)
</button>
</div>
</div>
</li>
<li>
<div class="flex justify-between items-center">
<span>Add <span x-text="formatMeasurement(ingredients.salt.main)"></span> salt and <span x-text="formatMeasurement(ingredients.sugar.main)"></span> sugar and mix for 2 more minutes.</span>
<div class="flex items-center timer-section">
<button @click="startTimer('Final mix', 2)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded">
Set Timer (2 min)
</button>
</div>
</div>
</li>
<li>
<div class="flex justify-between items-center">
<span>Cover the dough and let rest for 30 minutes.</span>
<div class="flex items-center timer-section">
<button @click="startTimer('Dough rest', 30)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded">
Set Timer (30 min)
</button>
</div>
</div>
</li>
<li>
<div class="flex justify-between items-center">
<span>Perform 4-6 sets of stretch and folds at 30-minute intervals.</span>
<div class="flex items-center timer-section">
<button @click="startTimer('Stretch and fold', 30)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded">
Set Timer (30 min)
</button>
</div>
</div>
</li>
<li>
<div class="flex justify-between items-center">
<span>After the final fold, let the dough bulk ferment for 2-4 hours at room temperature.</span>
<div class="flex items-center timer-section">
<button @click="startTimer('Bulk fermentation', 3*60)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded">
Set Timer (3 hrs)
</button>
</div>
</div>
</li>
<li>Divide the dough into <span x-text="pizzaQuantity"></span> portions of <span x-text="formatMeasurement(doughBallWeight)"></span> each.</li>
<li>Shape into balls, sealing the seam.</li>
<li>Put the dough in a lightly oiled container.</li>
<li>
<div class="flex justify-between items-center">
<span>Cover tightly and refrigerate for 24-72 hours.</span>
<div class="flex items-center timer-section">
<button @click="startTimer('Refrigeration', 48*60)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded">
Set Timer (48 hrs)
</button>
</div>
</div>
</li>
<li>
<div class="flex justify-between items-center">
<span>Let the dough come to room temperature before using (about 3-4 hours).</span>
<div class="flex items-center timer-section">
<button @click="startTimer('Room temp rest', 3.5*60)" class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded">
Set Timer (3.5 hrs)
</button>
</div>
</div>
</li>
</ol>
</div>
</template>
</div>
<!-- Attribution Footer -->
<div class="mt-8 text-center text-gray-600 text-sm recipe-content">
<p>Initially inspired by and based on the <a href="https://doughguy.co" class="text-blue-600 hover:underline">DoughGuy calculator</a></p>
</div>
</div>
<script>
function doughCalculator() {
return {
// Basic settings
pizzaSize: 16,
pizzaQuantity: 6,
pizzaThickness: 2.11,
// Advanced settings
unitSystem: 'metric',
hydrationPercentage: 62,
doughMethod: 'direct',
prefermentPercentage: 30,
starterPercentage: 20,
// Temperature conversion
fahrenheit: 60,
celsius: 15.6,
// Local storage config
savedConfigs: [],
saveConfigName: '',
// Timer settings (multiple timers)
activeTimers: [],
showActiveTimers: false,
// Unit conversions
units: {
weight: 'g',
liquid: 'ml',
length: 'inches'
},
timerButton(name, minutes, timeFormat = null) {
return `
<div x-data="{ localTimer: null }" :id="'timer-container-' + Date.now() + Math.floor(Math.random() * 1000)">
<!-- Timer button -->
<button
@click="localTimer = startTimerForStep('${name}', ${minutes}, $el.parentNode)"
x-show="!localTimer || !timerExists(localTimer)"
class="text-sm bg-blue-100 hover:bg-blue-200 text-blue-800 py-1 px-2 rounded">
Set Timer (${timeFormat ? timeFormat : minutes + ' mins'})
</button>
<!-- Timer display -->
<div
x-show="localTimer && timerExists(localTimer)"
class="flex items-center space-x-1 py-1 px-2 rounded"
:class="{
'bg-yellow-100 text-yellow-800': localTimer && getTimer(localTimer).running && getTimer(localTimer).remaining > 0,
'bg-gray-100 text-gray-800': localTimer && !getTimer(localTimer).running && getTimer(localTimer).remaining > 0,
'bg-green-100 text-green-800': localTimer && getTimer(localTimer).remaining <= 0
}">
<span class="font-mono" x-text="localTimer && timerExists(localTimer) ? formatTime(getTimer(localTimer).remaining) : ''"></span>
<div class="flex space-x-1">
<button
@click="toggleTimerById(localTimer)"
class="text-xs p-1 rounded"
:class="localTimer && getTimer(localTimer).running ? 'bg-yellow-200 hover:bg-yellow-300' : 'bg-blue-200 hover:bg-blue-300'">
<span x-text="localTimer && getTimer(localTimer).running ? 'Pause' : 'Resume'"></span>
</button>
<button
@click="resetTimerById(localTimer)"
class="text-xs p-1 bg-green-200 hover:bg-green-300 rounded">
Reset
</button>
<button
@click="removeTimerById(localTimer)"
class="text-xs p-1 bg-red-200 hover:bg-red-300 rounded">
</button>
</div>
</div>
</div>
`;
},
// Initialize
init() {
this.loadSavedConfigs();
// Set up a timer checking interval that runs every second
setInterval(() => {
this.activeTimers.forEach((timer, index) => {
if (timer.running) {
timer.remaining--;
// If timer reaches zero
if (timer.remaining <= 0) {
timer.running = false;
// Play sound or notification
if (Notification.permission === 'granted') {
new Notification('Timer Complete', {
body: `Your ${timer.name} timer is complete!`,
//icon: '/favicon.ico'
});
}
try {
var snd = new Audio("data:audio/mp4;base64,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8VkVWN7//////ww4XW//hdaDYNC63//DDYNg7///8DDFwNIPC6wGOHgwcAMOxWRVKkxBTUUzLjEwMKqquMOly6gYAIXDoyTRg25i45Zso5un81SLA2ncI1tMgwKIcxMB4BC+NBoLAOwOgLUtch9coEAFOGjjxf5MsFALJEZVCC7Rf0LACBQsMNQUVRhhaLqS+kqV6meFekgMu7A9Jbwz/+rReadtUtNVrVa1aZmkyS1sU3liiXgtolKS+orHKYJoHyiCnDaf7O3//QJI2RWgSRSRSX/3E9KRqkiktX2E+I552Z+ZmcaMr0/v77VtW25uZubm5Ww5EYmtQ5ububS9L0vtLpEEETy9O/v74nhBR9VVVXtVVVZummi+llhkvPulQRBImCpjU0GmWsb1//PkZPAb+djUAHWs1rcUAbAE5ha9XhjUzmZyOc2s5qQ5GbTubgSIwFgoCRUBM3ibCC6UdhoQHCKs6clnIVUHOjNNS00ZhQNAQpOiXEm3ii9i3fvZY5Y1o7Du///1uOKBSCfvX7NqzWq0s1HVHkFo/Ur4MPk2iStf/8kEPx0B0KhyZL1dX///8xMPQD0fmJgxLVTIPSyQ3H1ryk0JruSbE+oHo/RSZWwnJNiYmHsZdeNpGXbI2kKea6YmWPZdXX/////82STK6//5QAfF6BOdPyTYmPVDycfV1VoE6qquGJVVTEFNRTMuMTAwqqqqqqqqCLRu+Q0BoUhFlkICqULALjhvh0jeLqXYdoyhZxbCaDGG6ZyLTBdRZg2RTR8EvPBLpUyiCjCFmHeWw40qqosFiTx+opcrpEncZpUGAdaacpp1CW4kI7SoN9OKdSKdQLaqQ1TNrcnTeKEexUHOjHcXD5hUymX1wxvG940qlDT+Uq6XKKO02DDO9QNLjGiwoMkl9b/9bQpcZxnGaU3X6jK0/jdO1IKdghtS5XCnZ3TM9ZlCX4kJAiNF/QhziSsSRTC8xvH7x+socX03Uwp2Bval9cJ9ncX0uKq4vonwsxAy+IepEmiEPRhwluO1SP5DlFeC//PkZPAl/hyUBmMPAiLUOVgEYU180hsjsLeciLOw5zaH8IUJ6Rou52GaQIaIkA7DLQLNq8yuOU3T2XbA1sR+l2Kk2TkUbhDgP3SqTylXm+RhP4upRKlavunxJHoTyocK3bVszA2+6urZaShxFQ1DmYK3H6f3TMz9WmWWL0/vrZqGh2fRFqiodmMqOzlMJKR2f/1RFRdP/oqaoqEdjFMIiQWNIPZymERISEyHRUUhHbMUSERpDt2MZUWqKMQ7P7FRfRV/0//6p+UkCiQI+LZzLvKfycCihR6Fw8bk07OxpwHVTEFNRTMuMTAwVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV");
audio.play();
} catch (e) {
console.log('Audio play failed', e);
}
}
}
});
}, 1000);
},
// Calculate all ingredients
get ingredients() {
// Base calculations for 16" pizza, 6 pizzas, regular thickness (2.11)
const basePizzaSize = 16;
const baseFlourAmount = 1509.797685;
const baseQuantity = 6;
const baseThickness = 2.11;
// Calculate scaling factors
const sizeScaleFactor = Math.pow(this.pizzaSize / basePizzaSize, 2);
const quantityScaleFactor = this.pizzaQuantity / baseQuantity;
const thicknessScaleFactor = this.pizzaThickness / baseThickness;
// Calculate total flour amount
const flourAmount = baseFlourAmount * sizeScaleFactor * quantityScaleFactor * thicknessScaleFactor;
// Calculate ingredients based on baker's percentages
const water = flourAmount * (this.hydrationPercentage / 100);
const yeast = flourAmount * 0.004; // 0.4% yeast
const salt = flourAmount * 0.025; // 2.5% salt
const sugar = flourAmount * 0.025; // 2.5% sugar
const oliveOil = flourAmount * 0.033; // 3.3% olive oil
let flourPreferment = 0;
let waterPreferment = 0;
let yeastPreferment = 0;
let starter = 0;
// Calculate preferment amounts if using preferment method
if (this.doughMethod === 'preferment') {
flourPreferment = flourAmount * (this.prefermentPercentage / 100);
waterPreferment = flourPreferment * 1; // 100% hydration preferment
yeastPreferment = flourPreferment * 0.001; // 0.1% yeast in preferment
}
// Calculate sourdough starter and levain if using sourdough method
if (this.doughMethod === 'sourdough') {
starter = flourAmount * (this.starterPercentage / 100);
flourPreferment = starter / 2; // Assuming 100% hydration starter
waterPreferment = starter / 2;
}
// Calculate main dough amounts
const flourMain = flourAmount - flourPreferment;
const waterMain = water - waterPreferment;
const yeastMain = this.doughMethod === 'preferment' ? (yeast - yeastPreferment) : yeast;
return {
flour: {
total: Math.round(flourAmount),
preferment: Math.round(flourPreferment),
main: Math.round(flourMain)
},
water: {
total: Math.round(water),
preferment: Math.round(waterPreferment),
main: Math.round(waterMain)
},
yeast: {
total: yeast,
preferment: yeastPreferment,
main: this.doughMethod === 'sourdough' ? 0 : yeast - yeastPreferment
},
salt: {
total: Math.round(salt),
main: Math.round(salt)
},
sugar: {
total: Math.round(sugar),
main: Math.round(sugar)
},
oliveOil: {
total: Math.round(oliveOil),
main: Math.round(oliveOil)
},
starter: {
total: Math.round(starter)
}
};
},
// Calculate total dough weight
get totalDoughWeight() {
return this.ingredients.flour.total +
this.ingredients.water.total +
(this.doughMethod === 'sourdough' ? 0 : this.ingredients.yeast.total) +
this.ingredients.salt.total +
this.ingredients.sugar.total +
this.ingredients.oliveOil.total;
},
// Calculate preferment weight
get prefermentTotalWeight() {
if (this.doughMethod === 'preferment') {
return this.ingredients.flour.preferment +
this.ingredients.water.preferment +
this.ingredients.yeast.preferment;
} else if (this.doughMethod === 'sourdough') {
return this.ingredients.starter.total +
this.ingredients.flour.preferment +
this.ingredients.water.preferment;
}
return 0;
},
// Calculate main dough weight
get mainDoughWeight() {
return this.totalDoughWeight - (this.prefermentTotalWeight || 0);
},
// Calculate dough ball weight
get doughBallWeight() {
return Math.round(this.totalDoughWeight / this.pizzaQuantity);
},
// Format measurements based on unit system
formatMeasurement(value, type = 'weight') {
if (value === 0) return '0';
if (this.unitSystem === 'metric') {
if (type === 'yeast') {
return value.toFixed(1) + ' g';
} else {
return Math.round(value) + (type === 'liquid' ? ' ml' : ' g');
}
} else {
// Imperial conversions
if (type === 'yeast') {
const tsp = value / 3; // Approximately 3g per tsp of instant yeast
return tsp.toFixed(2) + ' tsp';
} else if (type === 'liquid') {
const flOz = value / 29.574; // ml to fl oz
if (flOz < 0.25) {
return (flOz * 2).toFixed(1) + ' tsp';
} else if (flOz < 2) {
return (flOz * 2).toFixed(1) + ' tbsp';
} else {
const cups = flOz / 8;
return cups.toFixed(2) + ' cups';
}
} else {
const oz = value / 28.35; // g to oz
return oz.toFixed(2) + ' oz';
}
}
},
// Temperature conversion functions
celsiusFromF() {
this.celsius = parseFloat(((this.fahrenheit - 32) * 5/9).toFixed(1));
},
fahrenheitFromC() {
this.fahrenheit = parseFloat((this.celsius * 9/5 + 32).toFixed(1));
},
// Multiple Timer functions
startTimer(name, minutes) {
// Request notification permission if needed
if (Notification.permission !== 'granted' && Notification.permission !== 'denied') {
Notification.requestPermission();
}
// Add a new timer to the activeTimers array
this.activeTimers.push({
name: name,
originalTime: minutes * 60, // Store original time for reset
remaining: minutes * 60, // In seconds
running: true,
id: Date.now() // Unique ID for the timer
});
},
// New timer functions for integrated timers
startTimerForStep(name, minutes, containerEl) {
// Request notification permission if needed
if (Notification.permission !== 'granted' && Notification.permission !== 'denied') {
Notification.requestPermission();
}
// Generate a unique ID for this timer
const timerId = Date.now();
// Track the container that started this timer
const containerId = containerEl ? containerEl.id : null;
// Add a new timer to the activeTimers array
this.activeTimers.push({
id: timerId,
name: name,
originalTime: minutes * 60, // Store original time for reset
remaining: minutes * 60, // In seconds
running: true,
containerId: containerId // Store the container ID
});
return timerId;
},
timerExists(id) {
if (!id) return false;
return this.activeTimers.some(timer => timer.id === id);
},
// Get a timer by ID
getTimer(id) {
if (!id) return { running: false, remaining: 0 };
return this.activeTimers.find(timer => timer.id === id) || { running: false, remaining: 0 };
},
// Toggle timer by ID
toggleTimerById(id) {
const timerIndex = this.activeTimers.findIndex(timer => timer.id === id);
if (timerIndex >= 0) {
this.activeTimers[timerIndex].running = !this.activeTimers[timerIndex].running;
}
},
// Reset timer by ID
resetTimerById(id) {
const timerIndex = this.activeTimers.findIndex(timer => timer.id === id);
if (timerIndex >= 0) {
this.activeTimers[timerIndex].remaining = this.activeTimers[timerIndex].originalTime;
this.activeTimers[timerIndex].running = true;
}
},
// Remove timer by ID
removeTimerById(id) {
// Skip if no ID provided
if (!id) return;
// Remove from activeTimers array
const timerIndex = this.activeTimers.findIndex(t => t.id === id);
if (timerIndex >= 0) {
this.activeTimers.splice(timerIndex, 1);
}
// Find all containers that might reference this timer and reset them
// This is a more thorough approach than tracking a single container
document.querySelectorAll('[id^="timer-container-"]').forEach(container => {
if (container.__x && container.__x.$data.localTimer === id) {
container.__x.$data.localTimer = null;
}
});
},
// Function to properly clear a timer from both the list and the local reference
clearTimerAndLocal(id) {
this.removeTimerById(id);
},
// Original timer functions for compatibility with the timers view at the top
startTimer(name, minutes) {
return this.startTimerForStep(name, minutes, null);
},
formatTime(seconds) {
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const secs = seconds % 60;
let formattedTime = '';
if (hours > 0) {
formattedTime += `${hours}:`;
formattedTime += `${minutes.toString().padStart(2, '0')}:`;
} else {
formattedTime += `${minutes}:`;
}
formattedTime += secs.toString().padStart(2, '0');
return formattedTime;
},
// Print only the recipe parts and hide the form
printRecipe() {
window.print();
},
// Save current configuration to local storage
saveConfiguration() {
if (!this.saveConfigName.trim()) {
alert('Please enter a name for your configuration.');
return;
}
const config = {
name: this.saveConfigName,
settings: {
pizzaSize: this.pizzaSize,
pizzaQuantity: this.pizzaQuantity,
pizzaThickness: this.pizzaThickness,
unitSystem: this.unitSystem,
hydrationPercentage: this.hydrationPercentage,
doughMethod: this.doughMethod,
prefermentPercentage: this.prefermentPercentage,
starterPercentage: this.starterPercentage
}
};
this.savedConfigs.push(config);
this.saveSavedConfigs();
this.saveConfigName = '';
},
// Load configuration from saved configs
loadConfiguration(config) {
const settings = config.settings;
this.pizzaSize = settings.pizzaSize;
this.pizzaQuantity = settings.pizzaQuantity;
this.pizzaThickness = settings.pizzaThickness;
this.unitSystem = settings.unitSystem;
this.hydrationPercentage = settings.hydrationPercentage;
this.doughMethod = settings.doughMethod;
this.prefermentPercentage = settings.prefermentPercentage;
this.starterPercentage = settings.starterPercentage;
},
// Delete a saved configuration
deleteConfiguration(index) {
if (confirm('Are you sure you want to delete this configuration?')) {
this.savedConfigs.splice(index, 1);
this.saveSavedConfigs();
}
},
// Save configs to local storage
saveSavedConfigs() {
localStorage.setItem('pizzaCalculatorConfigs', JSON.stringify(this.savedConfigs));
},
// Load configs from local storage
loadSavedConfigs() {
const savedConfigs = localStorage.getItem('pizzaCalculatorConfigs');
if (savedConfigs) {
this.savedConfigs = JSON.parse(savedConfigs);
}
}
};
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment