{"id":119,"date":"2026-07-28T10:20:06","date_gmt":"2026-07-28T10:20:06","guid":{"rendered":"https:\/\/demensdeum.com\/blog\/2026\/07\/28\/mama-calendar\/"},"modified":"2026-07-28T10:20:06","modified_gmt":"2026-07-28T10:20:06","slug":"mama-calendar","status":"publish","type":"post","link":"https:\/\/demensdeum.com\/blog\/2026\/07\/28\/mama-calendar\/","title":{"rendered":"Mama Calendar &#8211; cross-platform reminder app"},"content":{"rendered":"<p>Mama Calendar is a cross-platform events and reminders application written in React Native (Expo) with two backend implementations: Node.js + MongoDB and PHP + MariaDB.<\/p>\n<p>The application allows you to create events with emoji categorization, select the type of repetition (once, annually, monthly, weekly, daily) and view important events for the next 3 days in a separate \u201cImportant Events\u201d tab.<\/p>\n<h2>Technology stack<\/h2>\n<p>The frontend is written in React Native 0.86 via Expo SDK 57 with TypeScript, Expo Router for navigation and <code>react-native-reanimated<\/code> for animations. Expo-symbols are used for icons (SF Symbols on iOS, Material icons on Android\/Web).<\/p>\n<p>The backend is implemented in two versions:<\/p>\n<ul>\n<li><b>Node.js:<\/b> Express 4, MongoDB 8 via native driver, custom authentication with scrypt + salt, manual token management. Docker Compose brings up the client (nginx), server and MongoDB.<\/li>\n<li><b>PHP:<\/b> PHP 8.2 without frameworks, PDO + MariaDB 11, bcrypt for password hashing, your own router and PSR-4 autoloading via Composer.<\/li>\n<\/ul>\n<h2>Application functions<\/h2>\n<ul>\n<li><b>Registration and authorization:<\/b> simple system with username\/password and Bearer tokens<\/li>\n<li><b>CRUD events:<\/b> create, view, edit and delete events with date, emoji and repeat type<\/li>\n<li><b>Smart filtering:<\/b> The Important Events tab shows events for the next 3 days, taking into account repetition rules. For example, annual events show the nearest annual occurrence, monthly &#8211; by day of the month, weekly &#8211; by day of the week<\/li>\n<li><b>Emoji picker:<\/b> 20 preset emoji for quick categorization of events<\/li>\n<li><b>Highlighting today&#8217;s events:<\/b> Today&#8217;s events are highlighted with a red background (#B71C1C)<\/li>\n<li><b>Dark theme:<\/b> Automatic detection of system color scheme with separate palettes for light and dark theme<\/li>\n<li><b>Internationalization:<\/b> Russian and English languages \u200b\u200bvia React Context<\/li>\n<li><b>\u0410\u043d\u0438\u043c\u0430\u0446\u0438\u0438:<\/b> \u0430\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0441\u043f\u043b\u044d\u0448-\u0441\u043a\u0440\u0438\u043d \u0441 Keyframe API \u0438 \u0443\u043f\u0440\u0443\u0433\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u044f\u0446\u0438\u0435\u0439, \u0430\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0438\u043a\u043e\u043d\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0438\u043c\u0441\u044f \u0441\u0432\u0435\u0447\u0435\u043d\u0438\u0435\u043c<\/li>\n<li><b>Admin endpoints:<\/b> managing users, tokens and clearing the database through master tokens<\/li>\n<\/ul>\n<h2>Why two backend implementations?<\/h2>\n<p>The Node.js version is the main one, but the PHP version exists as an alternative for more classic hosting. The API is completely identical, which allows you to switch between them without changing the client code.<\/p>\n<h2>Infrastructure<\/h2>\n<p>The entire stack is raised through Docker Compose: the client is assembled through a multistage build (Expo export \u2192 nginx alpine), a server on Node.js, MongoDB 8. For the PHP version there is a separate compose file with MariaDB 11 and phpunit for tests.<\/p>\n<p>The assembly of the web version is automated by a PowerShell script that patches the API_URL before <code>expo export<\/code> and restores the originals after.<\/p>\n<h2>Output<\/h2>\n<p>Mama Calendar is a full-featured cross-platform application that covers the full cycle: from mobile and web frontend on React Native to two server-side options. The project is interesting for its architecture, use of modern Expo SDK capabilities and dual backend implementation.<\/p>\n<h2>Links<\/h2>\n<p><a href=\"https:\/\/github.com\/zefir1990\/Mama-Calendar\" rel=\"noopener\" target=\"_blank\">https:\/\/github.com\/zefir1990\/Mama-Calendar<\/a><br \/>\n<a href=\"https:\/\/demensdeum.com\/software\/mama-calendar\/events\" rel=\"noopener\" target=\"_blank\">https:\/\/demensdeum.com\/software\/mama-calendar\/events<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Mama Calendar is a cross-platform events and reminders application written in React Native (Expo) with two backend implementations: Node.js + MongoDB and PHP + MariaDB. The application allows you to create events with emoji categorization, select the type of repetition (once, annually, monthly, weekly, daily) and view important events for the next 3 days in [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[],"class_list":["post-119","post","type-post","status-publish","format-standard","hentry","category-software"],"translation":{"provider":"WPGlobus","version":"3.0.3","language":"en","enabled_languages":["en","ru","zh","de","ja","fr","es","pt","hi"],"languages":{"en":{"title":true,"content":true,"excerpt":false},"ru":{"title":true,"content":true,"excerpt":false},"zh":{"title":true,"content":true,"excerpt":false},"de":{"title":true,"content":true,"excerpt":false},"ja":{"title":true,"content":true,"excerpt":false},"fr":{"title":true,"content":true,"excerpt":false},"es":{"title":false,"content":false,"excerpt":false},"pt":{"title":true,"content":true,"excerpt":false},"hi":{"title":true,"content":true,"excerpt":false}}},"_links":{"self":[{"href":"https:\/\/demensdeum.com\/blog\/wp-json\/wp\/v2\/posts\/119","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/demensdeum.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/demensdeum.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/wp-json\/wp\/v2\/comments?post=119"}],"version-history":[{"count":0,"href":"https:\/\/demensdeum.com\/blog\/wp-json\/wp\/v2\/posts\/119\/revisions"}],"wp:attachment":[{"href":"https:\/\/demensdeum.com\/blog\/wp-json\/wp\/v2\/media?parent=119"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/wp-json\/wp\/v2\/categories?post=119"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/wp-json\/wp\/v2\/tags?post=119"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}