Skip to content

About

๐ŸŒ™ Open-source sleep diary app for clinical research โ€” built with React Native & Expo. Morning & evening questionnaires, sleep metrics, data export (CSV/JSON), and push notifications.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

ย 

History

307 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐ŸŒ™ Sleep Diaries

An open-source, research-grade sleep diary app built with React Native and Expo. Available on iOS, Android, and the web. Designed to be easily tailored by researchers, clinicians, and developers for their own sleep studies and clinical needs.

Tests Version DOI Stable Expo React Native React PWA Platform License: MIT Last commit Issues PRs welcome

๐ŸŒ Web app: https://sleepdiaries.circadia-lab.uk

๐Ÿงฌ Adapting this for your own study? Use SleepDiaries Protocol instead โ€” a template repository that seeds a clean copy of a specific release with lab-specific config already stripped out.


๐Ÿ“– What is Sleep Diaries?

Sleep Diaries is a cross-platform app (iOS, Android, and web) that guides users through structured morning and evening questionnaires to track their sleep patterns over time. It is based on consensus sleep diary methodology used in clinical sleep research.

The app is intentionally simple and modular โ€” the question sets, input types, themes, and data storage can all be customised without touching the core navigation or UI logic.

It also includes a suite of validated one-time research questionnaires (ESS, ISI, MEQ, PSQI, and others), a scored final report unlocking after 14 diary days, and support for researcher-assigned participant codes โ€” making it suitable for deployment in structured sleep studies.


โœจ Features

  • ๐ŸŒ… Morning entry โ€” 13-question diary covering bedtime, sleep onset, night wakings, final awakening, sleep quality, and restedness
  • ๐ŸŒ™ Evening entry โ€” 5-question diary covering naps, caffeine, exercise, and medication
  • โฑ๏ธ Rich input types โ€” 24-hour time stepper, duration stepper, yes/no, 1โ€“5 rating scale, number counter, medication tracker, and free text
  • ๐Ÿ”€ Conditional questions โ€” follow-up questions appear automatically based on previous answers
  • ๐ŸŽจ Dual themes โ€” amber for morning entries, blue for evening entries
  • ๐Ÿ’พ Local persistence โ€” all entries saved to device storage via AsyncStorage
  • ๐Ÿ“‹ Past entries โ€” scrollable history grouped by date with expandable answer cards
  • ๐Ÿ“Š Final report โ€” auto-unlocks after 14 morning entries, computes sleep metrics with colour-coded reference bands
  • ๐Ÿ”ญ Sleep pattern actogram โ€” weekly chart of bedtime to out-of-bed time with night-waking markers and a sleep-midpoint trend line, so drifting schedules and missed days are visible at a glance
  • ๐ŸŽฏ Age-aware reference ranges โ€” optional age group (under 18, 18โ€“64, 65+) chosen at onboarding or in the Profile adjusts the green/amber/red bands for sleep duration, latency and WASO; stored on the device only
  • ๐Ÿ›Ÿ Data-safety reminders โ€” entries live on the device, so the Home tab nudges participants to install the PWA (web) and to export a backup; the browser is also asked to keep storage persistent
  • ๐Ÿ“ค Data export โ€” CSV and JSON export via native share sheet, including questionnaire results
  • ๐Ÿ–ผ๏ธ Share card โ€” share a branded sleep report image to social media from the final report screen, with the original home screen background; works on iOS, Android, and mobile web (PWA)
  • ๐Ÿ”” Push notifications โ€” daily 8am and 9pm reminders
  • โš™๏ธ Settings โ€” notifications toggle, text-to-speech, language, questionnaire credits, account management
  • ๐Ÿ‘ค Profile โ€” editable name and research code, summary stats, sleep metrics glossary, quick actions
  • ๐Ÿ“ˆ Entry tab stats โ€” streak, entry counts, days in study
  • ๐Ÿ“ฅ JSON import โ€” restore a backup or migrate between devices, with merge or replace (imports questionnaire results too)
  • ๐Ÿ“ฑ iOS & Android โ€” single codebase via React Native + Expo
  • ๐ŸŒ Web โ€” Progressive Web App (PWA) installable on any device
  • ๐Ÿ“ฒ Installable โ€” installs to home screen on iOS, Android, and desktop Chrome with full offline support
  • ๐ŸŒ Localisation โ€” English, Portuguese (Brazil) ๐Ÿ‡ง๐Ÿ‡ท and Swedish ๐Ÿ‡ธ๐Ÿ‡ช (UI and daily diary), locale detected automatically from device settings
  • ๐Ÿงฉ Fully coded UI โ€” entry cards, the completion screen, tab bar, nav buttons and backgrounds are drawn in code with no per-language artwork, so a new language only needs strings
  • ๐Ÿ“‹ Research questionnaires โ€” validated one-time instruments (ESS, ISI, DBAS-16, MEQ, PSQI, RU-SATED, STOP-BANG, MCTQ) accessible from the Profile, with results unlocking after 14 diary days
  • ๐Ÿ’Š My Medications โ€” save regular treatments to your profile; they auto-populate the morning and evening medication questions

๐Ÿ—‚๏ธ Project Structure

SleepDiaries/
โ”œโ”€โ”€ app/                        # expo-router file-based navigation
โ”‚   โ”œโ”€โ”€ _layout.jsx             # Root stack navigator + asset preloading + PWA splash
โ”‚   โ”œโ”€โ”€ index.jsx               # Onboarding / name entry screen (+ research code)
โ”‚   โ”œโ”€โ”€ questionnaire.jsx       # Step-by-step questionnaire (morning or evening)
โ”‚   โ”œโ”€โ”€ past-entries.jsx        # Scrollable entry history
โ”‚   โ”œโ”€โ”€ final-report.jsx        # Sleep metrics summary report
โ”‚   โ”œโ”€โ”€ export.jsx              # CSV / JSON export + JSON import
โ”‚   โ”œโ”€โ”€ EntryDatePrompt.jsx     # "Which night is this for?" prompt for entries made after midnight
โ”‚   โ”œโ”€โ”€ QuestionnaireScreen.jsx # Full-screen runner for one-time research questionnaires
โ”‚   โ”œโ”€โ”€ InstructionsModal.jsx   # Full-screen instructions slideshow (coded, no PNGs)
โ”‚   โ”œโ”€โ”€ ProfileModal.jsx        # Profile sheet (name, code, stats, glossary, questionnaires)
โ”‚   โ”œโ”€โ”€ QuestionnaireModal.jsx  # Step-by-step one-time research questionnaire modal
โ”‚   โ”œโ”€โ”€ MedicationsScreen.jsx           # Saved medication presets (accessible from Profile modal)
โ”‚   โ”œโ”€โ”€ SleepMetricsScreen.jsx          # Sleep metrics glossary (push screen from Profile modal)
โ”‚   โ”œโ”€โ”€ QuestionnairesScreen.jsx        # Questionnaires list (push screen from Profile modal)
โ”‚   โ”œโ”€โ”€ QuestionnaireCreditsScreen.jsx  # Questionnaire credits (push screen from Settings)
โ”‚   โ”œโ”€โ”€ ThresholdReferencesScreen.jsx   # References for the metric thresholds used in the final report
โ”‚   โ””โ”€โ”€ (tabs)/                         # Tab bar screens
โ”‚       โ”œโ”€โ”€ _layout.jsx         # Custom tab bar (Ionicons, no image assets)
โ”‚       โ”œโ”€โ”€ home.jsx            # Home screen
โ”‚       โ”œโ”€โ”€ entry.jsx           # Entry tab with sleep stats dashboard
โ”‚       โ””โ”€โ”€ settings.jsx        # Settings (includes questionnaire credits)
โ”œโ”€โ”€ components/
โ”‚   โ”œโ”€โ”€ ActogramChart.jsx       # Weekly sleep pattern chart for the final report (react-native-svg)
โ”‚   โ”œโ”€โ”€ AgeBandPicker.jsx       # Optional age group selector (onboarding + Profile)
โ”‚   โ”œโ”€โ”€ BottomCards.jsx         # Past Entries and Final Report shortcut cards
โ”‚   โ”œโ”€โ”€ DataSafetyBanner.jsx    # Install / back-up reminder on the Home tab
โ”‚   โ”œโ”€โ”€ EntryCardContent.jsx    # Morning / evening entry cards (all languages, no PNGs)
โ”‚   โ”œโ”€โ”€ EntryCompleteSplash.jsx # "Entry complete" screen shown after saving
โ”‚   โ”œโ”€โ”€ NavButtons.jsx          # Questionnaire Back / Next buttons
โ”‚   โ””โ”€โ”€ ScreenBackground.jsx    # Shared gradient/background wrapper used across screens
โ”œโ”€โ”€ data/
โ”‚   โ”œโ”€โ”€ questions.js            # โญ Daily diary question definitions โ€” start here to customise
โ”‚   โ”œโ”€โ”€ questions.pt-BR.js      # Portuguese (BR) translations of question text
โ”‚   โ”œโ”€โ”€ questions.sv.js         # Swedish translations of question text
โ”‚   โ”œโ”€โ”€ useQuestions.js         # Merges locale overrides at startup
โ”‚   โ””โ”€โ”€ questionnaires.js       # โญ One-time research questionnaire definitions (ESS, ISI, etc.)
โ”œโ”€โ”€ i18n/
โ”‚   โ”œโ”€โ”€ index.js                # Locale detector + t() helper (interpolation, plurals)
โ”‚   โ”œโ”€โ”€ en.js                   # English strings
โ”‚   โ”œโ”€โ”€ pt-BR.js                # Portuguese (Brazil) strings
โ”‚   โ””โ”€โ”€ sv.js                   # Swedish strings
โ”œโ”€โ”€ storage/
โ”‚   โ”œโ”€โ”€ storage.js              # AsyncStorage helpers + CSV/JSON export + import
โ”‚   โ”œโ”€โ”€ EntriesContext.jsx      # React Context โ€” shared entry cache consumed by all screens
โ”‚   โ””โ”€โ”€ notifications.js        # Push notification scheduling
โ”œโ”€โ”€ utils/
โ”‚   โ”œโ”€โ”€ alert.js                # Cross-platform Alert helper (web fallback)
โ”‚   โ”œโ”€โ”€ constants.js            # โญ Shared constants (e.g. MIN_ENTRIES_FOR_REPORT)
โ”‚   โ”œโ”€โ”€ dataSafety.js           # Persistent-storage request and install / back-up reminder rules
โ”‚   โ”œโ”€โ”€ dateEntry.js            # Entry-date logic for post-midnight entries and the evening gate
โ”‚   โ”œโ”€โ”€ metrics.js              # Final-report metrics (duration, efficiency, SOL, WASO, ...)
โ”‚   โ”œโ”€โ”€ referenceRanges.js      # โญ Age-banded reference ranges and colour logic for the final report
โ”‚   โ””โ”€โ”€ stats.js                # Shared stat helpers (computeStats)
โ”œโ”€โ”€ theme/
โ”‚   โ”œโ”€โ”€ colors.js               # โญ Central colour palette and morning/evening themes
โ”‚   โ”œโ”€โ”€ typography.js           # Font constants (Livvic, Afacad)
โ”‚   โ””โ”€โ”€ useInsets.js            # Cross-platform safe area hook
โ”œโ”€โ”€ web/
โ”‚   โ”œโ”€โ”€ manifest.json           # PWA manifest
โ”‚   โ”œโ”€โ”€ sw.js                   # Service worker (offline support)
โ”‚   โ”œโ”€โ”€ icons/                  # PWA icons (192px, 512px)
โ”‚   โ””โ”€โ”€ splashscreens/          # iPhone/iPad splash screens
โ”œโ”€โ”€ scripts/
โ”‚   โ”œโ”€โ”€ deploy.sh               # Web export + PWA injection + deploy prep (with release-branch guard)
โ”‚   โ”œโ”€โ”€ fix-paths.js            # Rewrites asset paths for sub-path (GitHub Pages) hosting
โ”‚   โ””โ”€โ”€ crop_taskbars.py        # Legacy utility to centre-crop taskbar image assets
โ”œโ”€โ”€ assets/
โ”‚   โ””โ”€โ”€ images/                 # Logo, social preview and splash icon; index.js maps them
โ”œโ”€โ”€ __tests__/                  # Jest tests (metrics, stats, storage, export, i18n and translation keys, questionnaires, Swedish, reference ranges, data safety)
โ”œโ”€โ”€ .github/workflows/
โ”‚   โ”œโ”€โ”€ test.yml                # Runs the Jest suite and a web build check on every push and pull request
โ”‚   โ””โ”€โ”€ release-pr.yml          # Opens a main โ†’ release PR pinned to a version tag
โ”œโ”€โ”€ metro.config.js             # Metro bundler config (SVG support)
โ”œโ”€โ”€ declarations.d.ts           # TypeScript declaration for SVG imports
โ”œโ”€โ”€ app.json                    # Expo configuration
โ””โ”€โ”€ package.json                # Dependencies

๐Ÿš€ Getting Started

Prerequisites

  • Node.js v18 or later
  • Expo CLI
  • Expo Go on your phone, or Xcode (iOS simulator) / Android Studio (Android emulator)

Installation

# Clone the repository
git clone https://github.com/circadia-bio/SleepDiaries.git
cd SleepDiaries

# Install dependencies
npm install

# Start the development server
npx expo start

Then press i for iOS simulator, a for Android emulator, or scan the QR code with Expo Go on your phone.

Running on web (development)

npx expo start --web

Deploying to the web

npm run deploy

This runs the deploy script which exports the web build, injects PWA tags, copies assets, and outputs everything to the docs/ folder.

Release workflow

Production is deployed from the release branch, not main. main is the integration branch: pull requests (new features, translations) merge there and get a Netlify branch-deploy preview, while release only moves when you cut a version, so unreleased work can never reach users by accident.

  1. Bump the version (app.json, package.json, CITATION.cff, CHANGELOG.md, README.md) on main, then tag it: git tag v1.2.0 && git push origin v1.2.0
  2. Run Actions โ†’ Open release PR with that tag. It opens a PR into release from a snapshot of the tag (release-candidate/v1.2.0), so anything merged to main afterwards is not included. It fails if the tag is not on main or does not match the version in package.json.
  3. Merge the PR. Netlify then deploys release to production.

scripts/deploy.sh includes a guard: locally it refuses to run unless you are on release with no uncommitted changes to tracked files (override with FORCE_DEPLOY=1); on Netlify it fails any production build that is not from release, while deploy previews and branch deploys are allowed.

The workflow needs Allow GitHub Actions to create and approve pull requests enabled under Settings โ†’ Actions โ†’ General (and at organisation level for org-owned repositories).

๐ŸŒ Live web app: https://sleepdiaries.circadia-lab.uk


๐ŸŒ Localisation

The app detects the device locale at startup using expo-localization and selects the appropriate language automatically. No in-app language switcher is required โ€” it just works.

Supported languages

Language Locale code Status
๐Ÿ‡ฌ๐Ÿ‡ง English en โœ… Complete
๐Ÿ‡ง๐Ÿ‡ท Portuguese (Brazil) pt-BR โœ… Complete
๐Ÿ‡ธ๐Ÿ‡ช Swedish sv, sv-SE, sv-FI UI and daily diary; research instruments remain in English

Swedish is selected automatically for Swedish device/browser locales, including Sweden and Finland. Restart the app after changing the device/browser language. Notification text, sharing controls, report labels, dates and decimal separators (e.g. "7,5" in Swedish and Portuguese) also follow the locale. If reminders were already enabled before changing language, switch reminders off and back on in Settings to reschedule their text in the new language.

The Swedish daily diary and instructions are an unvalidated app translation, not an authorized or clinically validated Swedish Consensus Sleep Diary version. Research instrument titles, instructions, questions, response options, scale anchors, credits and interpretations remain in their original English. A Swedish notice makes this explicit in the questionnaire list, both questionnaire views, and the final report. Scoring, stored answer values and CSV/JSON keys are unchanged.

The Swedish alcohol help retains the source diary's 355/150/45 ml serving sizes. It clarifies that these servings are not equivalent to UK alcohol units; no numeric thresholds or calculation logic have been changed.

All other locales fall back to English.

How it works

All UI strings are defined in i18n/en.js, i18n/pt-BR.js and i18n/sv.js. The i18n/index.js module resolves the correct bundle at startup and exports a t() helper used throughout the app:

import t from '../i18n';

t('login.cta')                          // "Let's go" / "Vamos lรก"
t('home.entriesNeeded', { count: 3 })   // "3 more entries needed" / "Faltam 3 registros"

The helper supports {{variable}} interpolation and automatic _one / _other pluralisation.

Question translations

Question text, rating labels, units, and placeholders are defined separately in data/questions.<locale>.js (questions.pt-BR.js, questions.sv.js) and merged over the base English definitions at startup by data/useQuestions.js. Only translatable fields are overridden โ€” IDs, types, defaults, and conditional logic remain in data/questions.js.

Adding a new language

  1. Create i18n/<locale>.js following the structure of en.js
  2. Create data/questions.<locale>.js for the question text
  3. Add the locale to the TRANSLATIONS map in i18n/index.js
  4. Register the question overrides in data/useQuestions.js
  5. Add the locale to the LANGUAGE_NAMES map in app/(tabs)/settings.jsx
  6. Add the strings for the entry cards and completion screen under appText (morningCard, eveningCard, entryPendingMorning, entryDoneMorning, entryLocked, entrySavedMorning, homepage, ...). No image assets are needed

No locale-specific artwork

Everything that used to be baked into PNGs is now rendered in code from the i18n strings: the morning/evening entry cards (components/EntryCardContent.jsx), the entry-complete screen (components/EntryCompleteSplash.jsx), the tab bar, the questionnaire nav buttons, the instructions slideshow, the bottom shortcut cards and the screen backgrounds. Adding a language therefore only needs strings, never new image exports.


๐Ÿ“‹ Research Questionnaires

Sleep Diaries includes a set of validated one-time research questionnaires accessible from the Profile screen. These complement the daily diary by capturing baseline clinical and chronobiological characteristics of participants.

Note on permissions: Several instruments are protected by copyright. It is the responsibility of the researcher or institution deploying this app to obtain the necessary permissions before using any instrument in a study. See the credit field in data/questionnaires.js or Settings โ†’ Questionnaire credits in the app for per-instrument details.

Available instruments

Instrument Full name Items Scale Measures
ESS Epworth Sleepiness Scale 8 0โ€“3 per item (max 24) Daytime sleepiness
ISI Insomnia Severity Index 7 0โ€“4 per item (max 28) Insomnia severity
DBAS-16 Dysfunctional Beliefs and Attitudes about Sleep 16 0โ€“10 mean (max 10) Sleep-related cognitions
MEQ Morningnessโ€“Eveningness Questionnaire 19 Weighted sum (max 86) Chronotype
PSQI Pittsburgh Sleep Quality Index 17 7-component global (max 21) Sleep quality
RU-SATED Ru-SATED Sleep Health Scale 6 0โ€“4 per item (max 24) Multidimensional sleep health
STOP-BANG STOP-BANG Questionnaire 8 Yes/No count (max 8) OSA risk screening
MCTQ Munich Chronotype Questionnaire 7 MSFsc (clock time) + SJL (hours) Chronotype + social jetlag

How it works

Questionnaires appear in the Profile modal under a dedicated section. Each can be completed at any time, but results are withheld until 14 morning diary entries have been collected โ€” matching the same threshold as the final report. This ensures results reflect a participant who has completed an adequate baseline period.

Once the threshold is met, the scored result and a colour-banded interpretation are shown both in the profile and on the completion screen. A Redo option is available for follow-up timepoints, with a confirmation prompt before overwriting any existing result.

Adding a new questionnaire

All questionnaire definitions live in data/questionnaires.js. Each instrument is a plain JavaScript object:

export const MY_SCALE = {
  id:           'myscale',
  title:        'My Scale',
  shortTitle:   'MS',
  beta:         true,
  credit:       'Author, A. (Year). Journal, vol(issue), ppโ€“pp. ยฉ Rights holder.',
  instructions: 'Instructions shown to the participant before item 1.',
  reference:    'Short citation string shown on the result screen.',
  items: [
    {
      id: 'ms1', number: 1,
      text: 'Question text',
      type: 'scale_0_3',       // see supported input types below
      options: [ ... ],
    },
  ],
  score: (answers) => /* return a number or object */,
  interpret: (score) => ({
    label: 'Label',
    color: '#hex',
    description: 'Plain-language description shown to the participant.',
  }),
};

// Add to the registry:
export const QUESTIONNAIRES = [..., MY_SCALE];

Supported input types

Type Description
scale_0_3 4-option labelled scale (0โ€“3)
scale_0_4 5-option labelled scale (0โ€“4)
scale_0_10 11-point circular picker (0โ€“10)
scale_1_10 10-option labelled scale (1โ€“10)
single_choice Pick one from a list of options with explicit values
yes_no Yes / No
frequency_3 Rarely or never / Sometimes / Usually or always
frequency_4 Not during the past month / <once/week / 1โ€“2ร—/week / โ‰ฅ3ร—/week
time HH:MM stepper
duration_min Integer minutes stepper
number Integer stepper with min/max/unit

Any item can also include an optional hint string, which renders as a small info box below the question text โ€” useful for clarifying ambiguous items (e.g. the MCTQ free-day bedtime question).

Copyright and permissions

Several instruments are protected by copyright. The credit field on each definition (visible in Settings โ†’ Questionnaire credits) lists the citation and permission status. A summary:

Instrument Status
ESS ยฉ Murray W. Johns โ€” permission required for commercial use
ISI ยฉ Charles M. Morin โ€” available for non-commercial research
DBAS-16 ยฉ Charles M. Morin โ€” available via MAPI Research Trust
MEQ Public domain
PSQI ยฉ University of Pittsburgh โ€” permission required; contact authors
RU-SATED ยฉ University of Pittsburgh โ€” permission required; contact authors
STOP-BANG ยฉ University Health Network, Toronto โ€” free for non-commercial research (stopbang.ca)
MCTQ ยฉ Till Roenneberg, LMU Munich โ€” free for non-commercial research (thewep.org)
KSS Freely available for research use (defined but not currently active)

It is the responsibility of the researcher or institution deploying this app to obtain the necessary permissions before using any instrument in a study.


๐Ÿ“ฅ Importing Data

Entries exported as JSON from Sleep Diaries can be imported back into the app โ€” useful for restoring a backup, transferring data between devices, or migrating participants between study phases.

How to import

  1. Go to Settings โ†’ Export Data
  2. Scroll to Import from JSON at the bottom
  3. Tap it and select your .json file from Files
  4. If you already have entries on the device, you will be asked how to handle the conflict:
Option What it does
Merge Keeps all existing entries and adds any new ones from the file. Duplicate entries (same date and type) are skipped. Questionnaire results are imported only if not already present.
Replace Deletes all existing entries and questionnaire results, and replaces them with the imported data. Requires a second confirmation.

File format

The import expects a JSON file previously exported by Sleep Diaries. The file must contain an entries array. A questionnaires array is imported if present.

{
  "participant": "Lucas",
  "researchCode": "STUDY-001",
  "exportedAt": "2025-01-15T10:30:00Z",
  "entries": [
    {
      "id": "2025-01-14-morning",
      "type": "morning",
      "date": "2025-01-14",
      "completedAt": "2025-01-14T08:22:00Z",
      "answers": { "...": "..." }
    }
  ],
  "questionnaires": [
    {
      "id": "ess",
      "completedAt": "2025-01-14T09:00:00Z",
      "answers": { "ess1": 2, "ess2": 1, "...": "..." },
      "score": 12
    }
  ]
}

On the web version, tapping Import opens your browser's file picker instead of the native Files app.


๐Ÿ“ฒ Installing as an App

Sleep Diaries is a Progressive Web App (PWA) โ€” it can be installed directly to your home screen from the browser, with no App Store required. Once installed it runs full-screen, works offline, and behaves like a native app.

iOS (Safari)

  1. Open sleepdiaries.circadia-lab.uk in Safari
  2. Tap the Share button (box with arrow pointing up)
  3. Scroll down and tap Add to Home Screen
  4. Tap Add โ€” the app icon will appear on your home screen

Note: PWA installation on iOS only works in Safari, not Chrome or Firefox.

Android (Chrome)

  1. Open sleepdiaries.circadia-lab.uk in Chrome
  2. Tap the three-dot menu (โ‹ฎ) in the top right
  3. Tap Add to Home screen or Install app
  4. Tap Install โ€” the app icon will appear on your home screen

Desktop (Chrome / Edge)

  1. Open sleepdiaries.circadia-lab.uk
  2. Click the install icon (โŠ•) in the address bar
  3. Click Install

๐Ÿ”ง Customising the Question Set

All questions are defined in a single file: data/questions.js

Each question is a plain JavaScript object with a type field that controls how it renders. To add, remove, or reorder questions, simply edit this file โ€” no other changes are needed.

Question object structure

{
  id: 'mq1',              // Unique identifier (used for conditional logic)
  number: 1,              // Display number shown on screen
  text: 'Question text',  // The question shown to the user
  type: 'time',           // Input type (see below)
  defaultValue: { ... },  // Optional starting value
  optional: true,         // If true, user can skip without answering
}

Available input types

Type Description Use for
time 24-hour hour:minute stepper Bedtime, wake time
duration Hours + minutes stepper Time to fall asleep, nap length
yes_no Large Yes / No buttons Binary questions
rating 1โ€“5 labelled option buttons Sleep quality, restedness
number +/- counter with unit label Number of drinks, wake-ups
medication Add/edit/delete entries with dose and time Medication tracking
text_input Multiline free text Comments, notes

Conditional (follow-up) questions

// Parent question
{
  id: 'mq4',
  text: 'Did you wake up during the night?',
  type: 'yes_no',
  followUp: 'mq4b',
},

// Follow-up โ€” only shown if mq4 === 'yes'
{
  id: 'mq4b',
  text: 'How many times did you wake up?',
  type: 'number',
  conditionalOn: { id: 'mq4', value: 'yes' },
},

๐ŸŽจ Customising Colours

All colours live in theme/colors.js (fonts are in theme/typography.js):

  • COLORS โ€” the shared brand palette (navy, blue, orange, light blue, background), the green/amber/red status colours used in the final report, and textMuted, the grey used for hints and captions
  • THEME.morning and THEME.evening โ€” the amber and blue looks used by the daily questionnaire, the entry cards and the entry-complete screen. Change a value there and all three follow
import { COLORS, THEME } from '../theme/colors';

THEME.morning.primary;      // '#E07A20' โ€” questionnaire buttons, text, progress bar
THEME.evening.entryFrom;    // gradient start of the evening entry card
COLORS.status.good;         // report green

textMuted is #64748B (about 4.8:1 on white) so small grey text stays readable; if you change it or the entry-card colours, check the contrast ratio. Some older screens still use hex values inline and can move to these tokens over time.


๐Ÿ—บ๏ธ Navigation Architecture

The app uses expo-router with file-based routing:

index.jsx           โ†’ Onboarding (shown on first launch, skipped if name saved)
(tabs)/home         โ†’ Main home screen (+ InstructionsModal + ProfileModal)
(tabs)/entry        โ†’ Entry tab with sleep stats dashboard
(tabs)/settings     โ†’ Settings (includes questionnaire credits)
questionnaire       โ†’ Full-screen questionnaire (slides up, hides tab bar)
past-entries        โ†’ Entry history
final-report        โ†’ Sleep metrics report
export              โ†’ CSV / JSON export + JSON import

The ProfileModal also hosts the QuestionnaireModal inline โ€” tapping Start or Redo on a questionnaire opens it as a page sheet on top of the profile, without leaving the screen. InstructionsModal is a standalone screen in app/ pushed from the home screen.


๐Ÿ’พ Data Storage

All data is stored locally on the device using @react-native-async-storage/async-storage. No data is sent to any server.

// Stored keys:
// 'user_name'            โ†’ participant name string
// 'research_code'        โ†’ optional research study identifier
// 'age_band'             โ†’ optional age group ('under18' | 'adult' | 'older'); device-only, not exported
// 'last_export_at'       โ†’ time of the last successful export (drives the back-up reminder)
// 'data_safety_dismissals' โ†’ when the install / back-up reminders were last dismissed
// 'entries'              โ†’ JSON array of diary entry objects
// 'seen_instructions'    โ†’ 'true' once the instructions modal has been dismissed
// 'questionnaire_{id}'   โ†’ one object per completed one-time questionnaire
// 'medication_presets'    โ†’ JSON array of saved medication preset objects

// Diary entry structure:
{
  id: '2024-01-15-morning',
  type: 'morning',
  date: '2024-01-15',
  completedAt: '2024-01-15T08:32:00Z',
  answers: {
    mq1: { hour: 22, minute: 30 },
    mq4: 'yes',
    mq4b: 2,
    mq11: 4,
    // ...
  }
}

// Questionnaire result structure:
{
  id: 'ess',
  completedAt: '2024-01-15T09:00:00Z',
  answers: { ess1: 2, ess2: 0, /* ... */ },
  score: 12   // number, or object for computed instruments (e.g. MCTQ: { msf_sc, sjl })
}

๐Ÿ”ฌ Research Use

This app implements the Consensus Sleep Diary (CSD) โ€” a standardised instrument for clinical and research settings. The morning questions cover:

  • Sleep onset latency
  • Number and duration of night wakings
  • Early morning awakening
  • Total sleep time (computed)
  • Sleep efficiency (computed)
  • Sleep quality and restedness

Final report metrics

The final report (unlocked after 14 morning entries) automatically computes:

Metric Formula
Total sleep time Time in bed โˆ’ sleep onset latency โˆ’ WASO
Sleep efficiency Total sleep time รท time in bed ร— 100%
Sleep onset latency Average time to fall asleep
WASO Wake after sleep onset
Sleep quality Average of 1โ€“5 ratings
Restedness Average of 1โ€“5 ratings

The report also opens with a sleep pattern actogram (components/ActogramChart.jsx): one bar per night from bedtime to out-of-bed time, shaded by time asleep and time awake in bed, with red markers for the number of night wakings and a dashed line tracing the midpoint of sleep. It shows seven days at a time (swipe or use the arrows), and a day with no entry leaves a visible gap instead of closing up. The waking markers show how many times a participant woke, not when, because the diary records a count and a total duration rather than timestamps.

Age-specific reference ranges

The colour bands on the final report depend on an optional age group (under 18, 18โ€“64, or 65 and over). Participants can set it during onboarding or change it later in the Profile; tapping the selected option again clears it. It is stored only on the device, is not part of CSV/JSON exports, and defaults to the 18โ€“64 ranges when left blank.

Metric Under 18 18โ€“64 65 or over
Sleep duration โ€” green 8โ€“10 h 7โ€“9 h 7โ€“8 h
Sleep duration โ€” amber 7โ€“8 h, 10โ€“11 h 6โ€“7 h, 9โ€“10 h 5โ€“7 h, 8โ€“9 h
Sleep onset latency green โ‰ค30 min, amber 31โ€“45, red >45 green โ‰ค30 min, amber 31โ€“45, red >45 green โ‰ค30 min, amber 31โ€“60, red >60
Wake after sleep onset green โ‰ค20 min, amber 21โ€“50, red โ‰ฅ51 green โ‰ค20 min, amber 21โ€“40, red โ‰ฅ41 green โ‰ค20 min, amber >20 (no red)
Sleep efficiency green โ‰ฅ85%, amber 75โ€“85%, red <75% in every age group

Duration is red outside the amber band. For latency, WASO and efficiency the colours follow the NSF Sleep Quality Consensus Panel (Ohayon et al., 2017, Sleep Health, 3(1), 6โ€“19), which rated each value for each age group as appropriate, uncertain or inappropriate: green = appropriate (good sleep quality), amber = uncertain, red = rated poor. The panel rated sleep latency up to 30 minutes as good at every age. It gave no โ€œpoorโ€ level of WASO for adults 65 and over, so their WASO band is amber above 20 minutes and never red. Efficiency uses โ‰ฅ85% as good and โ‰ค74% as poor for every group (the paper uses โ‰ค64% for 18โ€“25-year-olds, which the app does not model separately). Duration ranges come from the NSF duration recommendations (Hirshkowitz et al., 2015). The under-18 band uses the teenage (14โ€“17) values; younger children need more sleep, so add a band if the app is ever used with them.

All of the numbers, the colour logic and the scale-bar geometry live in utils/referenceRanges.js, so changing a threshold is a one-file edit. The same ranges drive the metric cards, the share card and Settings โ†’ Sleep metric thresholds.

Research code

The onboarding screen includes an optional research code field. This allows researchers to assign a unique identifier to each participant at enrolment. The code is:

  • Saved locally on the device alongside the participant's name
  • Included as a research_code column in CSV exports
  • Included as a researchCode field in JSON exports
  • Cleared when the participant logs out or deletes their account

Participants leave the field blank if they are using the app independently.

Profile screen

The Profile button on the home screen slides up a modal showing:

  • Editable participant name and research code
  • Optional age group, which selects the reference ranges used in the final report
  • Summary stats: morning entries, evening entries, current streak, member since date
  • Questionnaires โ€” one-time research instruments with status badges and Start/Redo buttons
  • Sleep metrics glossary with plain-language explanations of each metric
  • Quick actions: replay instructions, link to circadia-lab.uk

Entry tab stats

The Entry tab shows a live stats dashboard above the entry cards:

  • ๐Ÿ”ฅ Current streak (consecutive days with a morning entry)
  • Morning entries, evening entries, and days in study (always visible)

Adapting for your study

  1. Edit data/questions.js to add, remove, or reorder diary questions
  2. Edit data/questionnaires.js to add, remove, or reorder one-time instruments
  3. Add new input types in app/questionnaire.jsx or app/QuestionnaireModal.jsx
  4. Change the unlock threshold โ€” edit MIN_ENTRIES_FOR_REPORT in utils/constants.js (currently 14); the same constant governs the final report, questionnaire result visibility, and the entry-tab stats dashboard
  5. Connect a backend โ€” replace the AsyncStorage calls in storage/storage.js with API calls

๐Ÿ“„ Citation

Franรงa, L. G. S., Baehl, B., Howard, J., Kussow, F., Luna Colรณn, Y., & Leocadio-Miguel, M. (2026). Sleep Diaries (v1.2.0) [Software]. Circadia Lab. https://doi.org/10.5281/zenodo.19683378


๐Ÿ‘ฅ Authors

Role Names
Principal Investigators Lucas Franรงa, Mario Leocadio-Miguel
Development Lucas Franรงa
Design Bri Baehl, Jacob Howard, Frederic Kussow, Yuliana Luna Colรณn
Swedish translation Jonatan Nyberg

๐ŸŽจ Design Acknowledgement

The app design was created by exchange students โ€” Bri Baehl, Jacob Howard, Frederic Kussow, and Yuliana Luna Colรณn โ€” during the 7th Annual Digital Civics Exchange (DCX), an international programme connecting students across disciplines to co-design civic technologies.

๐ŸŒ dcx.events


๐Ÿค– AI Acknowledgement

Development of this app was assisted by Claude (Anthropic's AI assistant). Claude helped scaffold the React Native codebase, implement navigation, build the questionnaire engine, set up local storage, push notifications, data export, the final report, the localisation system, and the one-time research questionnaire feature.


๐Ÿค Contributing

Contributions are welcome. If you are adapting this for a research study and want to share improvements back, please open a pull request.

  1. Fork the repository
  2. Create a feature branch (git checkout -b feat/my-feature)
  3. Commit your changes (git commit -m 'โœจ feat: add my feature')
  4. Push to the branch (git push origin feat/my-feature)
  5. Open a Pull Request

๐Ÿ“ฆ Dependencies

Package Version Purpose
expo ~55.0.0 Core Expo SDK
expo-router ~55.0.0 File-based navigation
expo-localization ~55.0.12 Device locale detection
react-native 0.83.2 Cross-platform mobile framework
react 19.2.0 React framework
@expo/vector-icons ^15.0.2 Ionicons icon set
@react-native-async-storage/async-storage 2.2.0 Local data persistence
expo-notifications ~55.0.0 Push notification reminders
expo-status-bar ~55.0.0 Status bar control
expo-font ~55.0.4 Custom font loading
react-native-paper ^5.12.0 UI component library
react-native-safe-area-context 5.6.2 Safe area handling
react-native-screens 4.23.0 Native screen management
react-native-svg 15.15.3 SVG rendering (screen backgrounds, entry cards, completion screen, actogram)
react-native-svg-transformer ^1.5.3 SVG imports as React components
babel-preset-expo ~55.0.0 Babel transpilation
expo-document-picker ~55.0.9 JSON file import
react-native-view-shot 4.0.3 Capture React Native views as images (share card)
expo-sharing ~55.0.18 Native file sharing (share card)
expo-blur ~55.0.14 Blur effects (final report background, profile modal)

๐Ÿค Related Tools

  • ๐Ÿงฌ SleepDiaries Protocol โ€” template repo for adapting SleepDiaries to your own study, pinned to a specific release
  • ๐Ÿงช slumbR โ€” R package for reading, scoring and analysing Sleep Diaries exports (docs)
  • ๐Ÿงฎ ScoreMe โ€” researcher-facing web app for scoring questionnaires from JSON
  • ๐ŸŒฑ Teenage Sleep Diaries โ€” fork of the protocol template for adolescent sleep research
  • ๐ŸŒ€ nonparametric-actigraphy-clustering โ€” unsupervised clustering of actigraphy rest-activity profiles using nonparametric methods
  • โšก ACTT_validation_study โ€” validation study for actigraphy-based sleep staging cut-points
  • ๐Ÿ”ฌ circadia-bio โ€” the Circadia Lab GitHub organisation

๐Ÿ“„ Licence

Copyright ยฉ Circadia Lab โ€” Lucas Franรงa & Mario Leocadio-Miguel

Released under the MIT License.

Design by Bri Baehl, Jacob Howard, Frederic Kussow, and Yuliana Luna Colรณn.

Note on third-party questionnaire instruments: The validated sleep questionnaires included in this app (ESS, ISI, DBAS-16, MEQ, PSQI, RU-SATED, STOP-BANG, MCTQ) are the intellectual property of their respective authors and institutions. Their inclusion in this open-source repository does not grant any rights to use them beyond what is permitted by each instrument's licence. See Settings โ†’ Questionnaire credits in the app, or the credit field in data/questionnaires.js, for per-instrument copyright and permission details.


๐Ÿ—๏ธ Roadmap

  • Persist answers with AsyncStorage
  • Show name entered at onboarding on home screen
  • Past entries screen with history view
  • Final report with sleep metrics
  • Push notification reminders (morning + evening)
  • Data export (CSV / JSON) including questionnaire results
  • Web app
  • Progressive Web App (PWA) โ€” installable on iOS, Android, and desktop
  • Offline support via service worker
  • JSON import with merge/replace (including questionnaire results)
  • Optional research code for study participants
  • Profile screen with editable participant info, stats, and metrics glossary
  • Entry tab sleep stats dashboard
  • Automatic deployment via CI/CD
  • Full Portuguese (Brazil) localisation โ€” strings, questions, and image assets
  • SVG support via react-native-svg-transformer
  • One-time research questionnaires (ESS, ISI, DBAS-16, MEQ, PSQI, RU-SATED, STOP-BANG, MCTQ) (beta)
  • Medication presets โ€” auto-populate diary medication questions from saved treatments
  • Share card โ€” share a branded sleep report image from the final report screen
  • Full UI modernisation โ€” glassy card system, gradient backgrounds, blur effects, refined typography and icons throughout
  • Questionnaire result validation and removal of beta flag โ€” all eight instruments now stable
  • Entry date prompt โ€” participants filling in entries between midnight and 14:00 are asked which night the entry belongs to, correctly attributing data for night owls and delayed sleep schedules
  • Swedish localisation โ€” UI and daily diary (research instruments stay in English)
  • Sleep pattern actogram in the final report
  • Entry cards and completion screen rendered in code โ€” no per-language artwork
  • Release branch workflow โ€” production deploys from release through a tag-pinned pull request
  • Age-specific reference ranges โ€” optional age group in onboarding and Profile
  • Central colour theme โ€” morning/evening looks, status colours and muted text in theme/colors.js
  • KSS (Karolinska Sleepiness Scale) โ€” protocol integration pending
  • Backend API integration
  • Additional language support

About

๐ŸŒ™ Open-source sleep diary app for clinical research โ€” built with React Native & Expo. Morning & evening questionnaires, sleep metrics, data export (CSV/JSON), and push notifications.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages