(function(){ if (window.__LM_ONCE__) return; window.__LM_ONCE__ = true; /* Rename the Home CTA + wire link to #writingroom; shorten Writing Room CTAs to "Start" */ function renameCTA(){ var nodes = Array.from(document.querySelectorAll('a, button')); nodes.forEach(function(n){ var text = (n.textContent || '').trim().toLowerCase(); // Home page primary CTA → "Start Your Story" + link to #writingroom if (n.closest('#home')) { if (text.includes('start')) { n.textContent = 'Start Your Story'; n.setAttribute('href', '#writingroom'); } } // Writing Room chapter CTAs → just "Start" if (n.closest('#writingroom')) { if (text.includes('start your story') || text.includes('begin') || text.includes('go') || text === 'start chapter 1' || text === 'start chapter') { n.textContent = 'Start'; } // ensure the button gets the consistent style n.classList.add('wr-btn'); } }); } /* Move “Chapter 1 — Where It All Began” into the Back/Next row (footer) */ function relocateChapterTitle(){ var s = document.querySelector('#ch1q2a'); if (!s) return; var h1 = s.querySelector('h1'); // "Chapter 1" var h2 = s.querySelector('h2'); // "Where It All Began" var title = (h1 ? h1.textContent.trim() : '') || ''; var sub = (h2 ? h2.textContent.trim() : '') || ''; if (!title && !sub) return; // Try to find the actual Back/Next row that holds both buttons var prev = document.getElementById('prevBtn'); var next = document.getElementById('nextBtn'); if (!prev || !next) return; // Climb to their shared container var row = prev; for (var i=0; i<6 && row; i++){ if (row.contains(next) && row.nodeType===1 && row.tagName!=='BUTTON') break; row = row.parentElement; } if (!row || !row.contains(next)) return; row.classList.add('lm-actions'); if (!row.querySelector('.lm-footer-title')) { var span = document.createElement('span'); span.className = 'lm-footer-title'; span.textContent = sub ? (title + ' — ' + sub) : title; row.appendChild(span); } // Hide the top headings so they don’t duplicate if (h1) h1.style.display = 'none'; if (h2) h2.style.display = 'none'; } /* DOM ready helper */ function ready(fn){ if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', fn, { once:true }); } else { fn(); } } ready(function(){ renameCTA(); relocateChapterTitle(); }); // Re-run after potential Carrd defers / anchor navigation window.addEventListener('load', function(){ setTimeout(function(){ renameCTA(); relocateChapterTitle(); }, 50); setTimeout(function(){ renameCTA(); relocateChapterTitle(); }, 400); }); })();
LifeMine Stories
Your life story — one chapter at a time.
How it works
◆Capture your life story in 7 chapters, each dedicated to a different era of your life.
◆Answer a set of questions designed specifically for each chapter.
◆Your responses will generate a "rough draft" in story form.
◆Review and edit the draft to fine tune your story.
◆Save your changes then lock and finalize the finished version.
◆Complete all 7 chapters for your full story, available in 3 formats:
—An online version for easy viewing and sharing (included)
—A printable PDF (included)
—An MP3 audiobook professionally narrated by AI (additional purchase)
This is a short preview. Your full chapter is already written.
Unlock Chapter to keep reading and start editing.
Click Edit My Story to make changes.
Click Lock & Finalize to publish your final version.
The final view will show options to Print and Share.
Loading your chapter…
Edit your chapter
(function(){ if (window.__LM_CORE_P13__) return; window.__LM_CORE_P13__ = true; var LM = window.__LM__ = window.__LM__ || {}; LM.v = 'PROD_P13'; /* ====== CONFIG ====== */ LM.R2_BASE = 'https://stories.lifeminestories.net'; LM.EDIT_TOKEN_URL = 'https://lifeminestories.com/#buy-edit-token'; /* ✅ DEV MODE: default owner view ON until Memberstack exists */ LM.DEV_OWNER_DEFAULT = true; /* ====== Query helpers ====== */ LM.qs = function(){ return new URLSearchParams(location.search || ''); }; LM.getUUID = function(){ return (LM.qs().get('uuid') || '').trim(); }; LM.getRecordId = function(){ return (LM.qs().get('record_id') || '').trim(); }; LM.isOwner = function(){ var ownerFlag = (LM.qs().get('owner') || '').trim(); if (ownerFlag === '1' || ownerFlag.toLowerCase() === 'y' || ownerFlag.toLowerCase() === 'yes') return true; if (!!LM.getRecordId()) return true; return !!LM.DEV_OWNER_DEFAULT; // dev fallback }; LM.getIntParam = function(name, fallback){ var v = (LM.qs().get(name) || '').trim(); var n = parseInt(v, 10); return Number.isFinite(n) ? n : fallback; }; /* ====== URL helpers ====== */ LM.buildURLWithParams = function(paramsObj, hash){ try{ var u = new URL(location.href); Object.keys(paramsObj || {}).forEach(function(k){ var v = paramsObj[k]; if (v === null || v === undefined || v === ''){ u.searchParams.delete(k); } else { u.searchParams.set(k, String(v)); } }); if (hash) u.hash = hash; return u.toString(); }catch(_){ return location.href; } }; /* ====== Share URL: ALWAYS clean/public ====== */ LM.cleanShareURL = function(){ var uuid = LM.getUUID(); if (!uuid) return location.href; return location.origin + '/?uuid=' + encodeURIComponent(uuid) + '#ch1-story'; }; /* ====== R2 helpers ====== */ LM.finalHTML = function(uuid){ return LM.R2_BASE + '/view_final/' + encodeURIComponent(uuid) + '.html'; }; LM.exists = async function(url){ try{ var h = await fetch(url + '?t=' + Date.now(), { method:'HEAD', cache:'no-store', mode:'cors' }); return !!(h && h.ok); }catch(_){ return false; } }; /* ====== Print/Share wiring ====== */ LM.wirePrintShare = function(){ var btnPrint = document.getElementById('btnPrint'); var btnShare = document.getElementById('btnShare'); if (btnPrint && !btnPrint.__lmBound){ btnPrint.__lmBound = true; btnPrint.onclick = function(e){ e.preventDefault(); try{ window.print(); }catch(_){} }; } if (btnShare && !btnShare.__lmBound){ btnShare.__lmBound = true; btnShare.onclick = async function(e){ e.preventDefault(); var url = LM.cleanShareURL(); try{ if (navigator.share){ await navigator.share({ title: document.title || 'LifeMine Stories', url: url }); return; } }catch(_){} try{ if (navigator.clipboard && navigator.clipboard.writeText){ await navigator.clipboard.writeText(url); alert('Link copied to clipboard.'); return; } }catch(_){} try{ prompt('Copy this link:', url); }catch(_){} }; } }; function start(){ LM.wirePrintShare(); } if (document.readyState === 'loading'){ document.addEventListener('DOMContentLoaded', start, { once:true }); } else { start(); } window.addEventListener('lm:chapter_loaded', function(){ start(); }); })();
(function(){ if (window.__LM_P2_P13__) return; window.__LM_P2_P13__ = true; var LM = window.__LM__ = window.__LM__ || {}; var LOCK_WEBHOOK = 'https://hook.us2.make.com/cswmcu27474joa1a84b5t8cm4raq7ic8'; function $id(id){ return document.getElementById(id); } /* ====== Byline ====== */ function getBylineAuthor(){ var by = $id('pvByline'); if (!by) return '—'; var t = (by.innerText || by.textContent || '').trim(); return t.replace(/^by\s+/i,'').trim() || '—'; } /* ====== Owner UI: Version badge ====== */ function ensureVersionBadge(){ if ($id('lmVerBadge')) return true; var byline = $id('pvByline'); var anchor = byline || $id('btnPrint') || $id('btnShare') || document.body; if (!anchor) return false; var badge = document.createElement('span'); badge.id = 'lmVerBadge'; badge.style.cssText = [ 'display:none', 'margin-left:10px', 'padding:5px 10px', 'border-radius:999px', 'background:rgba(255,255,255,.16)', 'border:1px solid rgba(255,255,255,.35)', 'backdrop-filter:saturate(120%) blur(3px)', 'font:600 12px Inter,system-ui', 'letter-spacing:.02em', 'vertical-align:middle' ].join(';'); if (byline) byline.appendChild(badge); else if (anchor && anchor.parentNode) anchor.parentNode.insertBefore(badge, anchor); else document.body.appendChild(badge); return true; } function updateVersionBadge(){ if (!ensureVersionBadge()) return; var badge = $id('lmVerBadge'); if (!badge) return; var uuid = LM.getUUID ? LM.getUUID() : ''; var fv = LM.getIntParam ? LM.getIntParam('finalized_version', 0) : 0; if (!uuid || !(LM.isOwner && LM.isOwner()) || fv < 1){ badge.style.display = 'none'; return; } badge.textContent = 'V' + fv; badge.style.display = 'inline-block'; } /* ====== Owner UI: Final-view Edit button ====== */ function ensureFinalEditButton(){ if ($id('btnReopen')) return true; var btnPrint = $id('btnPrint'); var btnShare = $id('btnShare'); var container = null; if (btnPrint && btnPrint.parentNode) container = btnPrint.parentNode; else if (btnShare && btnShare.parentNode) container = btnShare.parentNode; if (!container) return false; var a = document.createElement('a'); a.href = 'javascript:void(0)'; a.id = 'btnReopen'; a.textContent = 'Edit'; a.style.display = 'none'; if (btnPrint) container.insertBefore(a, btnPrint); else container.insertBefore(a, container.firstChild); return true; } function updateFinalEditButtonVisibility(){ if (!ensureFinalEditButton()) return; var btn = $id('btnReopen'); if (!btn) return; var fv = LM.getIntParam ? LM.getIntParam('finalized_version', 0) : 0; var show = (LM.isOwner && LM.isOwner()) && (fv >= 1); btn.style.display = show ? 'inline-flex' : 'none'; } function editsExhausted(){ var fv = LM.getIntParam ? LM.getIntParam('finalized_version', 0) : 0; var inc = LM.getIntParam ? LM.getIntParam('included_versions', 3) : 3; return fv >= inc; } function tokenGateMsg(){ var inc = LM.getIntParam ? LM.getIntParam('included_versions', 3) : 3; return 'You’ve used all ' + inc + ' included finalized versions for this chapter.\n\nAny additional changes will require the purchase of an edit token.'; } /* ====== No-change guard compares to last FINAL in R2 (V2+) ====== */ async function getPrevFinalPvContentHTML(finalUrl){ try{ var res = await fetch(finalUrl + '?t=' + Date.now(), { cache:'no-store', mode:'cors' }); if (!res || !res.ok) return null; var txt = await res.text(); var m = txt.match(/id=["']pvContent["'][^>]*>([\s\S]*?)<\/div>/i); return m ? (m[1] || '').trim() : null; }catch(_){ return null; } } function normalizeHTML(s){ return String(s || '') .replace(/]*lm:author[^>]*>/ig, '') .replace(/\s+/g,' ') .trim(); } /* ====== Your wording ====== */ function finalizeMessage(nextV, included){ var base = 'Your chapter purchase includes the ability to edit freely and then use "Lock & Finalize" up to ' + included + ' times.\n\n' + 'Each new "Lock & Finalize" replaces the previous version.\n\n'; if (nextV === 1) return base + 'You’re about to lock in version 1 of ' + included + ' for this chapter.\n\nContinue?'; if (nextV === 2) return base + 'You’re about to lock in version 2 of ' + included + ' for this chapter.\n\nContinue?'; if (nextV === 3) return base + 'You’re about to lock in version 3 of ' + included + ' for this chapter.\n\nAdditional changes after this will require the purchase of an edit token.\n\nContinue?'; return base + 'You’re about to lock in version ' + nextV + ' of ' + included + ' for this chapter.\n\nAdditional changes after this will require the purchase of an edit token.\n\nContinue?'; } /* ====== Wire FINAL Edit button ====== */ function wireFinalEditButton(){ if (!ensureFinalEditButton()) return; var btn = $id('btnReopen'); if (!btn || btn.__lmBound) return; btn.__lmBound = true; btn.onclick = function(e){ e.preventDefault(); if (!(LM.isOwner && LM.isOwner())) return; if (editsExhausted()){ alert(tokenGateMsg()); try{ var u = new URL(LM.EDIT_TOKEN_URL); var uuid = LM.getUUID(); if (uuid) u.searchParams.set('uuid', uuid); location.assign(u.toString()); }catch(_){} return; } var uuid = LM.getUUID ? LM.getUUID() : ''; if (!uuid) return; var fv = LM.getIntParam ? LM.getIntParam('finalized_version', 0) : 0; var inc = LM.getIntParam ? LM.getIntParam('included_versions', 3) : 3; var url = LM.buildURLWithParams({ uuid: uuid, owner: '1', finalized_version: fv || 0, included_versions: inc || 3, force: 'unlocked' }, '#ch1-story'); location.assign(url); }; } /* ====== Lock & Finalize ====== */ function wireLock(){ var btnLock = $id('btnLock'); if (!btnLock || btnLock.__lmBound) return; btnLock.__lmBound = true; btnLock.onclick = async function(e){ e.preventDefault(); var uuid = LM.getUUID ? LM.getUUID() : ''; if (!uuid){ alert('No chapter id found.'); return; } if (!(LM.isOwner && LM.isOwner())){ alert('This link is view-only. Use your owner link to edit and finalize.'); return; } var slot = $id('pvContent'); if (!slot){ alert('Missing story container.'); return; } var finalized = LM.getIntParam ? LM.getIntParam('finalized_version', 0) : 0; var included = LM.getIntParam ? LM.getIntParam('included_versions', 3) : 3; if (finalized >= included){ alert(tokenGateMsg()); try{ location.assign(LM.EDIT_TOKEN_URL); }catch(_){} return; } var nextV = finalized + 1; if (!confirm(finalizeMessage(nextV, included))) return; if (finalized >= 1){ var prevFinal = await getPrevFinalPvContentHTML(LM.finalHTML ? LM.finalHTML(uuid) : ''); if (prevFinal !== null){ var a = normalizeHTML(prevFinal); var b = normalizeHTML(slot.innerHTML); if (a === b){ alert('No changes detected since your last finalized version.'); return; } } } btnLock.disabled = true; var old = btnLock.textContent; btnLock.textContent = 'Finalizing…'; btnLock.style.opacity = '0.75'; try{ var authorNow = getBylineAuthor(); var safeAuthorForMeta = authorNow.replace(/"/g,'"'); var htmlWithMeta = '' + (slot.innerHTML || ''); await fetch(LOCK_WEBHOOK, { method:'POST', mode:'no-cors', headers:{ 'Content-Type':'text/plain;charset=UTF-8' }, body: JSON.stringify({ uuid: uuid, html: htmlWithMeta, author: authorNow }) }); var attempts = 0; while (attempts < 40){ if (LM.exists && LM.finalHTML && (await LM.exists(LM.finalHTML(uuid)))){ var newUrl = LM.buildURLWithParams({ uuid: uuid, owner: '1', finalized_version: nextV, included_versions: included || 3, force: '' }, '#ch1-story'); location.replace(newUrl); return; } await new Promise(function(r){ setTimeout(r, 2000); }); attempts++; } alert('Finalization sent, but the final file is not ready yet. Please refresh in a minute.'); }catch(err){ console.error(err); alert('We ran into a problem finalizing your chapter. Please try again.'); }finally{ btnLock.disabled = false; btnLock.textContent = old || 'Lock & Finalize'; btnLock.style.opacity = '1'; } }; } /* ====== Apply until DOM exists ====== */ function apply(){ updateVersionBadge(); updateFinalEditButtonVisibility(); wireFinalEditButton(); wireLock(); if (LM.wirePrintShare) LM.wirePrintShare(); } var tries = 0; (function tick(){ apply(); var ready = !!($id('btnPrint') || $id('btnShare') || $id('pvByline') || $id('btnLock')); tries++; if (!ready && tries < 100){ setTimeout(tick, 150); } })(); window.addEventListener('lm:chapter_loaded', function(){ apply(); }); try{ var mo = new MutationObserver(function(){ apply(); }); mo.observe(document.documentElement, { childList:true, subtree:true }); }catch(_){} })();
If you still see the preview, refresh once—unlock can take a few seconds.
(function(){ if (window.__LM_FINAL_READONLY_SCRUB__) return; window.__LM_FINAL_READONLY_SCRUB__ = true; // 1) Hide any “owner link” UI if it exists in the DOM (old widgets/buttons) function nukeOwnerUI(){ const sel = [ '#lmOwnerLink', // hypothetical id '.lm-owner-link', // hypothetical class '[data-owner-link]', // data attr '#btnOwner', // any stray button '.get-owner-link', // legacy label '.owner-chip' // any chip/badge ].join(','); document.querySelectorAll(sel).forEach(el => { try{ el.remove(); }catch(_){} }); } // 2) Strip ?k= from the current URL (don’t leak keys in address bar or shares) (function stripKParam(){ try{ const url = new URL(location.href); if (url.searchParams.has('k')) { url.searchParams.delete('k'); history.replaceState({}, '', url.toString()); } }catch(_){} })(); // 3) Wrap Share so we never include ?k= even if something re-adds it (function guardShare(){ const btnShare = document.getElementById('btnShare'); if (!btnShare) return; btnShare.onclick = async function(e){ e.preventDefault(); try{ const base = new URL(location.href); const clean = new URL(base.origin + base.pathname); // Preserve uuid only const qs = new URLSearchParams(location.search || ''); const uuid = (qs.get('uuid') || '').trim(); if (uuid) clean.searchParams.set('uuid', uuid); clean.hash = '#ch1-story'; const sharable = clean.toString(); const data = { title: document.title || 'LifeMine Chapter', text: 'Read my chapter', url: sharable }; if (navigator.share){ try { await navigator.share(data); return; } catch(_){} } await navigator.clipboard.writeText(sharable); alert('Link copied to clipboard.'); }catch(_){ prompt('Copy this link:', location.origin + location.pathname + location.search + '#ch1-story'); } }; })(); // 4) Force final copies to hide Edit/Lock (in case CSS is overridden elsewhere) function enforceFinalButtons(){ if (!document.body.classList.contains('lm-final')) return; ['btnEdit','btnLock'].forEach(id=>{ const el = document.getElementById(id); if (el){ el.style.display = 'none'; el.setAttribute('aria-hidden','true'); } }); } // 5) Neutralize any legacy “owner gate” toggles that might re-add edit function neutralizeLegacyGate(){ // remove accidental lm-owner class so nothing re-enables Edit in final document.body.classList.remove('lm-owner'); // noop any globals some old embeds might have installed ['LM_owner','LM_makeOwnerLink'].forEach(k=>{ try{ if (typeof window[k] !== 'undefined') window[k] = {}; }catch(_){} }); } function run(){ nukeOwnerUI(); neutralizeLegacyGate(); enforceFinalButtons(); } // Run now and after DOM changes for a short window (to catch late inserts) run(); const mo = new MutationObserver(()=>run()); mo.observe(document.documentElement, {childList:true, subtree:true}); setTimeout(()=>{ try{ mo.disconnect(); }catch(_){ } }, 8000); })();