Family Values Journey
An interactive book a family lives, not just reads
A year-long journey where the whole family lives one value each month: notice it, understand it, apply it, and keep it going. Parents and children take part together, each with their own role and signature.
- Client
- Soadaa Family Development Association
- Content
- Written by Mohammed Kulaib
- Front end
- Framework-free JavaScript, installable PWA
- Server
- Node.js and MongoDB, with a local file fallback
- Works
- Offline, syncing when the connection returns
- My role
- The whole app, solo
01The values map
The journey starts with the self, then the family, then society. The first value is open now; the rest open one by one.
02How a family lives a value
Every value goes through five stages, and the app tracks each activity. The number under each stage is its activity count for Responsibility.
03What the family does
- A story that unfoldsThe value’s story reveals part by part, for the family to read together.
- A drawing padChildren draw inside the app, and the drawing is saved with the family’s progress.
- Belief-correction cardsA card flips to show the right idea against the mistaken one.
- Games and timersA “Where is responsibility?” quiz, a patience challenge, and a focus timer.
- The family charterEach member signs the charter and the monthly pledge by name.
- Certificate and medalA thank-you certificate and an end-of-month medal, ready to print.
04Three engineering decisions
Save on the device first
Every activity saves to the device at once, then syncs to the server in the background. When the page closes, the last copy goes out with sendBeacon so nothing is lost. If the database is down, the server falls back to a local file.
function save() {
clearTimeout(saveT);
saveT = setTimeout(function () {
localStorage.setItem(KEY, JSON.stringify(S));
}, 150);
syncCloud();
}
window.addEventListener('beforeunload', function () {
navigator.sendBeacon('/api/sync', blob);
});No week opens before the last one
The four weekly tasks unlock in order, so a family can’t skip to the end. Each week shows as done, current or locked.
var unlocked = (i === 0) ||
!!(S.r.weekly[i - 1] && S.r.weekly[i - 1].done);A full app without a framework
Instead of React, each part of the page is registered by name and re-renders on its own. A child types in a field and the page updates around them without losing their place. The result is light enough for modest phones.
/* re-render one part of a page without losing focus */
function block(id, fn) {
BLOCKS[id] = fn;
return '<div data-block="' + id + '">' + fn() + '</div>';
}05Being built now
06Thanks
Content written by Mohammed Kulaib for Soadaa Family Development Association, supported by the Associations Support Fund and Al-Jomaih Charitable Foundation.