Twelve - The Ultimate 12-Step Daily Harmony Planner
About this app
A premium, focused productivity app built around the power of 12. Manage your daily 12 tasks, track 12-month progress, and master 12-minute focus sprints.
Twelve - The Ultimate 12-Step Daily Harmony Planner 0/12 Twelve Wednesday, Oct 23, 2024 The Daily 12 Reset Day Tip: Don't try to do 50 things. Pick the 12 most important blocks and focus only on those today. 12-Minute Focus Sprint Put your phone away. Set a goal. Go. 12:00 Start 12m Sprint 12m Active 3m Rest 4x Cycles 12-Month Performance Days Active 0 Current Streak 0 Intensity Guide No activity 1-3 Tasks (Partial) 4-8 Tasks (Balanced) 9-12 Tasks (Peak Performance) Tasks Sprint History
Put this on your site
Source
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
<title>Twelve - The Ultimate 12-Step Daily Harmony Planner</title>
<meta name="description" content="A premium, focused productivity app built around the power of 12. Manage your daily 12 tasks, track 12-month progress, and master 12-minute focus sprints.">
<meta name="keywords" content="12, productivity, planner, daily tasks, time management, focus timer, goal tracker, harmony, efficiency">
<!-- Libraries -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" crossorigin="anonymous">
<script type="text/javascript">
try {
document.addEventListener("DOMContentLoaded", function() {
// --- App Logic ---
const app = {
tasks: JSON.parse(localStorage.getItem('twelve_tasks')) || Array(12).fill({ text: '', done: false }),
history: JSON.parse(localStorage.getItem('twelve_history')) || {},
timer: null,
timerSeconds: 12 * 60,
isTimerRunning: false,
init() {
this.renderTasks();
this.updateStats();
this.renderCalendar();
this.initTimer();
this.updateDateDisplay();
this.bindEvents();
this.displayQuote();
},
save() {
localStorage.setItem('twelve_tasks', JSON.stringify(this.tasks));
localStorage.setItem('twelve_history', JSON.stringify(this.history));
},
updateDateDisplay() {
const now = new Date();
const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
$('#current-date').text(now.toLocaleDateString(undefined, options));
},
renderTasks() {
const $list = $('#task-list');
$list.empty();
this.tasks.forEach((task, idx) => {
const checked = task.done ? 'checked' : '';
const taskHtml = `
<div class="task-item d-flex align-items-center mb-3 p-3 ${task.done ? 'completed' : ''}" data-index="${idx}">
<div class="task-number me-3">${idx + 1}</div>
<input type="text" class="form-control flex-grow-1 task-input" value="${task.text}" placeholder="Focus task ${idx + 1}..." ${task.done ? 'disabled' : ''}>
<div class="form-check ms-3">
<input class="form-check-input task-checkbox" type="checkbox" ${checked}>
</div>
</div>
`;
$list.append(taskHtml);
});
this.updateProgress();
},
updateProgress() {
const completed = this.tasks.filter(t => t.done && t.text.trim() !== '').length;
const total = this.tasks.filter(t => t.text.trim() !== '').length || 1;
const percentage = Math.round((completed / 12) * 100);
$('.progress-ring-circle').css('stroke-dashoffset', 283 - (283 * percentage / 100));
$('#progress-text').text(`${completed}/12`);
// Save daily progress to history
const today = new Date().toISOString().split('T')[0];
this.history[today] = percentage;
this.save();
},
bindEvents() {
const self = this;
// Task input changes
$(document).on('input', '.task-input', function() {
const idx = $(this).closest('.task-item').data('index');
self.tasks[idx].text = $(this).val();
self.save();
self.updateProgress();
});
// Task completion
$(document).on('change', '.task-checkbox', function() {
const idx = $(this).closest('.task-item').data('index');
self.tasks[idx].done = $(this).is(':checked');
self.renderTasks();
self.save();
});
// Reset Day
$('#btn-reset').on('click', function() {
if(confirm('Reset all 12 tasks for today?')) {
self.tasks = Array(12).fill({ text: '', done: false });
self.renderTasks();
self.save();
}
});
// Timer Buttons
$('#timer-toggle').on('click', () => this.toggleTimer());
$('#timer-reset').on('click', () => this.resetTimer());
// Tab switching
$('.nav-link').on('click', function(e) {
e.preventDefault();
$('.nav-link').removeClass('active');
$(this).addClass('active');
const target = $(this).data('target');
$('.app-screen').hide();
$(`#${target}`).show();
if(target === 'screen-stats') self.renderCalendar();
});
},
initTimer() {
this.updateTimerDisplay();
},
toggleTimer() {
if (this.isTimerRunning) {
clearInterval(this.timer);
$('#timer-toggle').html('<i class="fas fa-play"></i> Start 12m Sprint');
$('#timer-toggle').removeClass('btn-danger').addClass('btn-success');
} else {
this.timer = setInterval(() => {
this.timerSeconds--;
this.updateTimerDisplay();
if (this.timerSeconds <= 0) {
this.toggleTimer();
alert('12-minute sprint completed!');
this.resetTimer();
}
}, 1000);
$('#timer-toggle').html('<i class="fas fa-pause"></i> Pause Sprint');
$('#timer-toggle').removeClass('btn-success').addClass('btn-danger');
}
this.isTimerRunning = !this.isTimerRunning;
},
resetTimer() {
clearInterval(this.timer);
this.isTimerRunning = false;
this.timerSeconds = 12 * 60;
this.updateTimerDisplay();
$('#timer-toggle').html('<i class="fas fa-play"></i> Start 12m Sprint');
$('#timer-toggle').removeClass('btn-danger').addClass('btn-success');
},
updateTimerDisplay() {
const mins = Math.floor(this.timerSeconds / 60);
const secs = this.timerSeconds % 60;
$('#timer-display').text(`${mins}:${secs.toString().padStart(2, '0')}`);
const pct = ((12*60 - this.timerSeconds) / (12*60)) * 100;
$('#timer-progress').css('width', `${pct}%`);
},
renderCalendar() {
const $grid = $('#stats-grid');
$grid.empty();
const now = new Date();
// Generate last 12 months roughly (simplified)
for(let i = 0; i < 12; i++) {
const mDate = new Date(now.getFullYear(), now.getMonth() - (11 - i), 1);
const monthName = mDate.toLocaleString('default', { month: 'short' });
const monthYear = mDate.getFullYear();
$grid.append(`
<div class="month-card col-4 col-md-3 mb-3">
<div class="month-inner p-2 text-center border rounded shadow-sm bg-light">
<div class="small fw-bold">${monthName}</div>
<div class="tiny-text">${monthYear}</div>
<div class="dot-container d-flex flex-wrap justify-content-center mt-1">
${this.getDotsForMonth(mDate)}
</div>
</div>
</div>
`);
}
},
getDotsForMonth(date) {
// Dummy dots for visual representation of "History"
// In a real app, this iterates through actual logged days.
let dots = '';
const daysInMonth = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
for(let d = 1; d <= daysInMonth; d++) {
const dayStr = `${date.getFullYear()}-${(date.getMonth()+1).toString().padStart(2,'0')}-${d.toString().padStart(2,'0')}`;
const level = this.history[dayStr] || 0;
let color = '#eee';
if(level > 75) color = '#4caf50';
else if(level > 50) color = '#8bc34a';
else if(level > 25) color = '#cddc39';
else if(level > 0) color = '#ffeb3b';
dots += `<div class="stat-dot" style="background:${color}" title="${dayStr}"></div>`;
}
return dots;
},
updateStats() {
const keys = Object.keys(this.history);
$('#stat-days').text(keys.length);
const streak = this.calculateStreak();
$('#stat-streak').text(streak);
},
calculateStreak() {
let streak = 0;
const today = new Date();
for(let i = 0; i < 365; i++) {
const d = new Date();
d.setDate(today.getDate() - i);
const ds = d.toISOString().split('T')[0];
if(this.history[ds] && this.history[ds] > 0) streak++;
else if(i > 0) break;
}
return streak;
},
displayQuote() {
const quotes = [
"The number 12 represents completion and perfection.",
"Do not wait; the time will never be 'just right'.",
"The only way to do great work is to love what you do.",
"Success is the sum of small efforts, repeated daily.",
"Productivity is being able to do things that you were never able to do before.",
"Focus on being productive instead of busy.",
"The shorter the sprint, the higher the intensity.",
"Twelve tasks, one clear mind.",
"Your future is created by what you do today.",
"Start where you are. Use what you have. Do what you can.",
"A year from now you may wish you had started today.",
"12 minutes of pure focus can change your hour."
];
$('#daily-quote').text(quotes[Math.floor(Math.random() * quotes.length)]);
}
};
app.init();
});
} catch (error) {
throw error;
}
</script>
<style>
:root {
--primary: #6366f1;
--secondary: #a855f7;
--accent: #f59e0b;
--bg: #f8fafc;
--card-bg: #ffffff;
--text: #1e293b;
}
body {
background-color: var(--bg);
color: var(--text);
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
margin-bottom: 80px; /* Space for bottom nav */
}
#main-container {
max-width: 600px;
margin: 0 auto;
padding-top: 2rem;
}
.glass-header {
background: linear-gradient(135deg, var(--primary), var(--secondary));
color: white;
border-radius: 20px;
padding: 2rem;
margin-bottom: 2rem;
box-shadow: 0 10px 25px -5px rgba(99, 102, 241, 0.4);
text-align: center;
position: relative;
overflow: hidden;
}
.glass-header::after {
content: '12';
position: absolute;
font-size: 15rem;
bottom: -50px;
right: -20px;
opacity: 0.1;
font-weight: 900;
pointer-events: none;
}
.progress-ring-container {
position: relative;
width: 100px;
height: 100px;
margin: 0 auto 1rem;
}
.progress-ring {
transform: rotate(-90deg);
}
.progress-ring-circle-bg {
fill: none;
stroke: rgba(255,255,255,0.2);
stroke-width: 8;
}
.progress-ring-circle {
fill: none;
stroke: white;
stroke-width: 8;
stroke-linecap: round;
stroke-dasharray: 283;
stroke-dashoffset: 283;
transition: stroke-dashoffset 0.6s ease;
}
#progress-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-weight: bold;
font-size: 1.2rem;
}
.task-item {
background: var(--card-bg);
border-radius: 15px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
transition: all 0.2s ease;
border-left: 5px solid var(--primary);
}
.task-item:hover {
transform: translateY(-2px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
}
.task-item.completed {
border-left-color: #10b981;
opacity: 0.7;
}
.task-number {
width: 32px;
height: 32px;
background: #e2e8f0;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
color: var(--text);
flex-shrink: 0;
}
.task-input {
border: none;
background: transparent;
font-weight: 500;
padding-left: 0;
}
.task-input:focus {
box-shadow: none;
background: transparent;
}
.form-check-input:checked {
background-color: #10b981;
border-color: #10b981;
}
/* Bottom Nav */
.bottom-nav {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 70px;
background: white;
display: flex;
justify-content: space-around;
align-items: center;
box-shadow: 0 -4px 10px rgba(0,0,0,0.05);
z-index: 1000;
padding-bottom: env(safe-area-inset-bottom);
}
.nav-link {
color: #94a3b8;
text-align: center;
font-size: 0.8rem;
text-decoration: none;
transition: color 0.2s;
}
.nav-link.active {
color: var(--primary);
}
.nav-link i {
font-size: 1.4rem;
display: block;
margin-bottom: 2px;
}
/* Timer Screen */
#timer-display {
font-size: 5rem;
font-weight: 800;
font-variant-numeric: tabular-nums;
color: var(--primary);
margin: 2rem 0;
}
.timer-card {
background: white;
border-radius: 25px;
padding: 3rem 1rem;
text-align: center;
box-shadow: 0 10px 20px rgba(0,0,0,0.05);
}
.progress-bar-container {
height: 12px;
background: #e2e8f0;
border-radius: 6px;
overflow: hidden;
margin: 1rem 0 2rem;
}
#timer-progress {
height: 100%;
background: linear-gradient(90deg, var(--primary), var(--secondary));
width: 0%;
transition: width 1s linear;
}
/* Stats Screen */
.stat-dot {
width: 10px;
height: 10px;
margin: 2px;
border-radius: 2px;
background-color: #eee;
}
.tiny-text { font-size: 0.65rem; color: #64748b; }
.month-inner {
min-height: 100px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
#daily-quote {
font-style: italic;
font-size: 0.9rem;
opacity: 0.8;
margin-top: 0.5rem;
}
/* Animations */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.app-screen {
animation: fadeIn 0.3s ease forwards;
}
/* Responsive tweaks */
@media (max-width: 480px) {
#timer-display { font-size: 4rem; }
.glass-header { padding: 1.5rem 1rem; }
}
</style>
</head>
<body>
<div id="main-container">
<!-- Header Section -->
<header class="glass-header">
<div class="progress-ring-container">
<svg class="progress-ring" width="100" height="100">
<circle class="progress-ring-circle-bg" cx="50" cy="50" r="45"></circle>
<circle class="progress-ring-circle" cx="50" cy="50" r="45"></circle>
</svg>
<div id="progress-text">0/12</div>
</div>
<h2 class="fw-bold mb-0">Twelve</h2>
<div id="current-date" class="small mb-2">Wednesday, Oct 23, 2024</div>
<p id="daily-quote"></p>
</header>
<!-- Screen: Daily Tasks -->
<main id="screen-tasks" class="app-screen">
<div class="d-flex justify-content-between align-items-center mb-4">
<h4 class="mb-0 fw-bold">The Daily 12</h4>
<button id="btn-reset" class="btn btn-sm btn-outline-secondary rounded-pill">
<i class="fas fa-rotate"></i> Reset Day
</button>
</div>
<div id="task-list">
<!-- Tasks injected by JS -->
</div>
<div class="alert alert-info mt-4 rounded-4 small">
<i class="fas fa-lightbulb me-2"></i>
<strong>Tip:</strong> Don't try to do 50 things. Pick the 12 most important blocks and focus only on those today.
</div>
</main>
<!-- Screen: Focus Timer -->
<main id="screen-timer" class="app-screen" style="display:none;">
<h4 class="mb-4 fw-bold text-center">12-Minute Focus Sprint</h4>
<div class="timer-card">
<p class="text-muted">Put your phone away. Set a goal. Go.</p>
<div id="timer-display">12:00</div>
<div class="progress-bar-container">
<div id="timer-progress"></div>
</div>
<div class="d-flex justify-content-center gap-3">
<button id="timer-toggle" class="btn btn-lg btn-success rounded-pill px-4">
<i class="fas fa-play"></i> Start 12m Sprint
</button>
<button id="timer-reset" class="btn btn-lg btn-light rounded-pill border">
<i class="fas fa-undo"></i>
</button>
</div>
</div>
<div class="mt-4 row g-3 text-center">
<div class="col-4">
<div class="p-3 bg-white rounded-4 shadow-sm border">
<div class="h5 mb-0 fw-bold">12m</div>
<div class="tiny-text">Active</div>
</div>
</div>
<div class="col-4">
<div class="p-3 bg-white rounded-4 shadow-sm border">
<div class="h5 mb-0 fw-bold">3m</div>
<div class="tiny-text">Rest</div>
</div>
</div>
<div class="col-4">
<div class="p-3 bg-white rounded-4 shadow-sm border">
<div class="h5 mb-0 fw-bold">4x</div>
<div class="tiny-text">Cycles</div>
</div>
</div>
</div>
</main>
<!-- Screen: Statistics -->
<main id="screen-stats" class="app-screen" style="display:none;">
<h4 class="mb-4 fw-bold">12-Month Performance</h4>
<div class="row g-3 mb-4">
<div class="col-6">
<div class="bg-white p-3 rounded-4 shadow-sm text-center border">
<div class="text-muted small">Days Active</div>
<div id="stat-days" class="h2 fw-bold text-primary mb-0">0</div>
</div>
</div>
<div class="col-6">
<div class="bg-white p-3 rounded-4 shadow-sm text-center border">
<div class="text-muted small">Current Streak</div>
<div id="stat-streak" class="h2 fw-bold text-secondary mb-0">0</div>
</div>
</div>
</div>
<div id="stats-grid" class="row gx-2 gy-2">
<!-- Months generated by JS -->
</div>
<div class="mt-4 p-3 bg-white rounded-4 border">
<h6 class="fw-bold mb-3">Intensity Guide</h6>
<div class="d-flex align-items-center gap-2 mb-2">
<div class="stat-dot" style="background:#eee"></div> <span class="small">No activity</span>
</div>
<div class="d-flex align-items-center gap-2 mb-2">
<div class="stat-dot" style="background:#ffeb3b"></div> <span class="small">1-3 Tasks (Partial)</span>
</div>
<div class="d-flex align-items-center gap-2 mb-2">
<div class="stat-dot" style="background:#8bc34a"></div> <span class="small">4-8 Tasks (Balanced)</span>
</div>
<div class="d-flex align-items-center gap-2">
<div class="stat-dot" style="background:#4caf50"></div> <span class="small">9-12 Tasks (Peak Performance)</span>
</div>
</div>
</main>
</div>
<!-- Navigation -->
<nav class="bottom-nav">
<a href="#" class="nav-link active" data-target="screen-tasks">
<i class="fas fa-list-check"></i>
<span>Tasks</span>
</a>
<a href="#" class="nav-link" data-target="screen-timer">
<i class="fas fa-stopwatch"></i>
<span>Sprint</span>
</a>
<a href="#" class="nav-link" data-target="screen-stats">
<i class="fas fa-chart-line"></i>
<span>History</span>
</a>
</nav>
</body>
</html>
NEW APPS
These are apps made by the community!