From 07d63e8b5e1d0005c86064c6de6422020f21b296 Mon Sep 17 00:00:00 2001 From: Sarthak Agrawal Date: Sat, 10 Oct 2026 15:51:06 +0530 Subject: [PATCH] perf: defer Clarity until interaction, responsive brand mark Co-Authored-By: Claude Sonnet 5.5 --- landing/src/pages/index.astro | 22 ++++-- marketing/404.html | 24 ++++-- marketing/accessibility/index.html | 24 ++++-- .../index.html | 26 +++++-- marketing/blog/index.html | 24 ++++-- .../index.html | 26 +++++-- .../index.html | 26 +++++-- .../index.html | 26 +++++-- .../index.html | 26 +++++-- .../index.html | 26 +++++-- .../index.html | 26 +++++-- marketing/images/brand/mark-114.webp | Bin 0 -> 1326 bytes marketing/images/brand/mark-38.webp | Bin 0 -> 506 bytes marketing/images/brand/mark-76.webp | Bin 0 -> 766 bytes marketing/index.html | 24 ++++-- marketing/privacy/index.html | 24 ++++-- marketing/release/index.html | 24 ++++-- marketing/support/index.html | 24 ++++-- marketing/terms/index.html | 24 ++++-- marketing/testflight/index.html | 24 ++++-- scripts/build-landing.mjs | 15 +++- src/landing-performance.test.ts | 70 ++++++++++++++++++ 22 files changed, 378 insertions(+), 127 deletions(-) create mode 100644 marketing/images/brand/mark-114.webp create mode 100644 marketing/images/brand/mark-38.webp create mode 100644 marketing/images/brand/mark-76.webp create mode 100644 src/landing-performance.test.ts diff --git a/landing/src/pages/index.astro b/landing/src/pages/index.astro index cb1901e..6580a4d 100644 --- a/landing/src/pages/index.astro +++ b/landing/src/pages/index.astro @@ -28,13 +28,23 @@ if (content.footer) content.footer.studio = studioFromProjects(projects, { curre diff --git a/marketing/404.html b/marketing/404.html index 7f5067d..fc43279 100644 --- a/marketing/404.html +++ b/marketing/404.html @@ -1,13 +1,23 @@ Page not found — Calorie
\ No newline at end of file +
\ No newline at end of file diff --git a/marketing/accessibility/index.html b/marketing/accessibility/index.html index 6ca1707..c7b57b8 100644 --- a/marketing/accessibility/index.html +++ b/marketing/accessibility/index.html @@ -1,13 +1,23 @@ Access is part of the journal. — Calorie
\ No newline at end of file +
\ No newline at end of file diff --git a/marketing/blog/how-to-make-nutrition-targets-transparent-instead-of-opaque/index.html b/marketing/blog/how-to-make-nutrition-targets-transparent-instead-of-opaque/index.html index f539e13..c4bb719 100644 --- a/marketing/blog/how-to-make-nutrition-targets-transparent-instead-of-opaque/index.html +++ b/marketing/blog/how-to-make-nutrition-targets-transparent-instead-of-opaque/index.html @@ -1,13 +1,23 @@ How to Make Nutrition Targets Transparent Instead of Opaque — Calorie
← Calorie journal

Guides

How to Make Nutrition Targets Transparent Instead of Opaque

Learn how to build nutrition targets that show their work, replacing opaque estimates with clear calculations based on fundamental inputs.

Significant Hobbies · · 6 min read

The Problem with Black-Box Nutrition

+
← Calorie journal

Guides

How to Make Nutrition Targets Transparent Instead of Opaque

Learn how to build nutrition targets that show their work, replacing opaque estimates with clear calculations based on fundamental inputs.

Significant Hobbies · · 6 min read

The Problem with Black-Box Nutrition

In the current landscape of digital health tools, a troubling pattern has emerged: the abstraction of basic nutritional math behind layers of opaque artificial intelligence and proprietary algorithms. When users log their food and check their daily targets, they are often presented with a single, authoritative number. If that number changes the next day, the reasoning is rarely explained. Did the system adjust for yesterday’s high carbohydrate intake? Did an invisible activity tracker sync a new workout? Or did a model simply decide it was time for a change?

This lack of transparency creates an adversarial relationship between users and their own data. Instead of feeling empowered, people are left guessing how inputs like weight, age, and activity level translate into the rigid daily budgets they are expected to follow. When nutrition targets are opaque, they stop being tools for understanding and start feeling like arbitrary judgments. The gamification of these opaque numbers—red deficit meters, broken streaks, and punitive alerts—can induce anxiety and encourage an unhealthy fixation on the metrics themselves, rather than the habits they represent.

To build sustainable tools, we must move away from the black box. Nutrition targets should not require a leap of faith. They should be transparent, verifiable, and entirely traceable back to the user’s explicit inputs and established metabolic science.

@@ -126,4 +136,4 @@

Timing and Habit Estimates

Practical Next Action

To apply these principles, start by auditing your current nutrition tracking setup. Look at your daily targets and ask yourself: Do I know exactly how this number was calculated? If the answer is no, it may be time to seek out a tool that prioritizes transparent, mathematically derived estimates over opaque algorithms.

If you are building your own baseline, calculate your resting energy using the Mifflin-St Jeor equation, apply an activity multiplier that matches your lifestyle, and set a goal range (e.g., 75–85% of maintenance for loss). Calculate your protein based on your body weight. By doing the math yourself—or using a tool that shows its work—you regain control over your data and build a more sustainable relationship with your nutrition goals.

-
\ No newline at end of file +
\ No newline at end of file diff --git a/marketing/blog/index.html b/marketing/blog/index.html index f63ca69..5397f9f 100644 --- a/marketing/blog/index.html +++ b/marketing/blog/index.html @@ -1,13 +1,23 @@ Journal — Calorie

Calorie / Journal

Notes from
the product.

Practical guides, observations and updates. Written around what the app actually does.

Guides

Weight trends vs daily weight judgments

Learn why daily weight fluctuations are normal and how focusing on long-term weight trends provides a more accurate and healthier perspective on your progress.

Subscribe via RSS ↗
\ No newline at end of file +

Calorie / Journal

Notes from
the product.

Practical guides, observations and updates. Written around what the app actually does.

Guides

Weight trends vs daily weight judgments

Learn why daily weight fluctuations are normal and how focusing on long-term weight trends provides a more accurate and healthier perspective on your progress.

Subscribe via RSS ↗
\ No newline at end of file diff --git a/marketing/blog/maintenance-relative-goals-for-a-calmer-nutrition-journal/index.html b/marketing/blog/maintenance-relative-goals-for-a-calmer-nutrition-journal/index.html index fdc1f59..d61c685 100644 --- a/marketing/blog/maintenance-relative-goals-for-a-calmer-nutrition-journal/index.html +++ b/marketing/blog/maintenance-relative-goals-for-a-calmer-nutrition-journal/index.html @@ -1,13 +1,23 @@ Maintenance-Relative Goals for a Calmer Nutrition Journal — Calorie
← Calorie journal

Guides

Maintenance-Relative Goals for a Calmer Nutrition Journal

Discover how maintenance-relative goals can transform your nutrition tracking from a source of anxiety to a sustainable, calmer practice.

Significant Hobbies · · 7 min read

Introduction: The Anxiety of Absolute Nutrition Targets

+
← Calorie journal

Guides

Maintenance-Relative Goals for a Calmer Nutrition Journal

Discover how maintenance-relative goals can transform your nutrition tracking from a source of anxiety to a sustainable, calmer practice.

Significant Hobbies · · 7 min read

Introduction: The Anxiety of Absolute Nutrition Targets

Most digital nutrition journals treat your daily eating habits like a high-stakes financial ledger. You are given a fixed budget of calories, and every single bite you take deducts from that allowance. If you exceed the arbitrary number generated by an opaque algorithm, the interface flashes red, warning you of your transgression. This approach misunderstands human psychology and the reality of human metabolism. Instead of providing useful data, it creates an environment of anxiety, moral judgment, and gamified streak pressure. But there is an alternative that prioritizes sustainability and peace of mind: maintenance-relative goals.

By shifting our perspective from rigid numbers to flexible, maintenance-relative ranges, we can transform nutrition tracking from a punitive chore into a supportive, informational tool. This approach respects the natural fluctuations in our daily lives and bodies, fostering a healthier relationship with food and a more consistent logging habit.

Understanding Maintenance-Relative Goals

@@ -129,4 +139,4 @@

Conclusion: A Calmer Approa

A nutrition journal should feel like a reliable, calming presence. It should turn your inputs into useful timing estimates for training, fasting, and sleep, supporting a balanced life. When we shift the focus from strict deficits to sustainable ranges, we create the space for a calmer relationship with food.

Practical Next Action

Take five minutes today to review your current nutrition targets. Try calculating your estimated maintenance calories and setting a target range that spans 300 to 400 calories (e.g., 2,000 to 2,400 kcal) instead of a strict limit. Observe how this small shift changes your mindset the next time you log a meal.

-
\ No newline at end of file +
\ No newline at end of file diff --git a/marketing/blog/one-handed-interaction-design-for-meal-logging/index.html b/marketing/blog/one-handed-interaction-design-for-meal-logging/index.html index 8bdff0d..cb9d76c 100644 --- a/marketing/blog/one-handed-interaction-design-for-meal-logging/index.html +++ b/marketing/blog/one-handed-interaction-design-for-meal-logging/index.html @@ -1,13 +1,23 @@ One-handed interaction design for meal logging — Calorie
← Calorie journal

Guides

One-handed interaction design for meal logging

Explore practical UX patterns for one-handed meal logging, including reachable touch targets, bottom-sheet entry, and predictive quick picks.

Significant Hobbies · · 6 min read

Introduction: The reality of mobile data entry

+
← Calorie journal

Guides

One-handed interaction design for meal logging

Explore practical UX patterns for one-handed meal logging, including reachable touch targets, bottom-sheet entry, and predictive quick picks.

Significant Hobbies · · 6 min read

Introduction: The reality of mobile data entry

When users interact with mobile applications, they rarely do so in a vacuum. The context of use is often fragmented, interrupted, and physically constrained. In nutrition and health tracking, this context becomes even more specific. A user is frequently standing in a bright kitchen, perhaps holding a bowl in one hand, while attempting to log their meal with the phone in the other hand. They log familiar meals immediately after eating, check progress in short bursts, and move on.

If an interface demands two-handed engagement, precise multi-finger gestures, or deep hierarchical navigation, it misunderstands the environment in which it operates. Designing for one-handed use is a deliberate architectural choice that prioritizes reachability, speed, and cognitive ease. This approach requires placing primary actions within the natural sweep of the user’s thumb and stripping away visual noise that complicates rapid data entry.

Designing reachable primary actions

@@ -128,4 +138,4 @@

Summary

The success of a daily utility application relies heavily on its ability to fit seamlessly into the user’s physical environment. For a meal logging app, this means acknowledging that the phone is often held in one hand while the other is busy. By prioritizing reachable touch targets, implementing robust bottom-sheet patterns, leveraging predictive quick picks, and maintaining a clear visual hierarchy, designers can build tools that are not only fast and functional but also reassuring and delightful to use in the briefest of moments.

Practical Next Action

Review your current mobile application’s primary conversion or entry flow. Map the interactive elements against the natural thumb zone of a standard smartphone. If your primary action requires the user to stretch their thumb to the upper third of the screen, experiment with relocating it to a persistent bottom sheet or a floating action button within a 44px minimum touch target.

-
\ No newline at end of file +
\ No newline at end of file diff --git a/marketing/blog/using-familiar-meal-templates-to-reduce-food-entry-friction/index.html b/marketing/blog/using-familiar-meal-templates-to-reduce-food-entry-friction/index.html index f8a6b53..5cccc27 100644 --- a/marketing/blog/using-familiar-meal-templates-to-reduce-food-entry-friction/index.html +++ b/marketing/blog/using-familiar-meal-templates-to-reduce-food-entry-friction/index.html @@ -1,13 +1,23 @@ Using familiar-meal templates to reduce food-entry friction — Calorie
← Calorie journal

Guides

Using familiar-meal templates to reduce food-entry friction

Discover how treating routine meals as templates instead of daily calculations can significantly reduce the friction of daily nutrition logging.

Significant Hobbies · · 6 min read

The real cost of food-entry friction

+
← Calorie journal

Guides

Using familiar-meal templates to reduce food-entry friction

Discover how treating routine meals as templates instead of daily calculations can significantly reduce the friction of daily nutrition logging.

Significant Hobbies · · 6 min read

The real cost of food-entry friction

Daily nutrition tracking often begins with high motivation and meticulous attention to detail. Yet, for many people, the habit breaks down within a few weeks. The failure point is rarely a lack of desire to understand one’s nutritional intake; rather, it is the cumulative friction of the data-entry process itself.

When logging a meal requires opening an application, navigating through multiple search screens, adjusting serving sizes, and verifying individual nutrient values, the task becomes a chore. This friction is particularly damaging when it occurs in the moments immediately following a meal. If the logging process demands two hands, sustained attention, and several minutes of cognitive effort, it will inevitably be deferred.

Deferred logging leads to batch processing at the end of the day, which introduces memory decay and estimation errors. Worse, it divorces the act of logging from the act of eating, turning a tool intended for real-time awareness into an administrative burden. To make nutrition tracking sustainable, the interface must operate at the speed of the user’s routine. Reducing the time it takes to record a familiar meal from minutes to mere seconds is not merely a convenience feature; it is a structural requirement for long-term adherence.

@@ -138,4 +148,4 @@

The impact on sustained trac

Ultimately, by minimizing friction, familiar-meal templates ensure the tool serves the user. This respect for time and cognitive load is the foundation of a sustainable approach to nutritional tracking.

Practical Next Action

Identify the meal you eat most frequently. Take two minutes today to calculate its total calories, protein, carbohydrates, and fibre. Save these aggregate numbers as a single reusable food in your journal. Tomorrow, instead of logging individual ingredients, use this new template to log your meal in one tap.

-
\ No newline at end of file +
\ No newline at end of file diff --git a/marketing/blog/weight-trends-vs-daily-weight-judgments/index.html b/marketing/blog/weight-trends-vs-daily-weight-judgments/index.html index 5925c41..b320d5d 100644 --- a/marketing/blog/weight-trends-vs-daily-weight-judgments/index.html +++ b/marketing/blog/weight-trends-vs-daily-weight-judgments/index.html @@ -1,13 +1,23 @@ Weight trends vs daily weight judgments — Calorie
← Calorie journal

Guides

Weight trends vs daily weight judgments

Learn why daily weight fluctuations are normal and how focusing on long-term weight trends provides a more accurate and healthier perspective on your progress.

Significant Hobbies · · 6 min read

The emotional impact of daily weigh-ins

+
← Calorie journal

Guides

Weight trends vs daily weight judgments

Learn why daily weight fluctuations are normal and how focusing on long-term weight trends provides a more accurate and healthier perspective on your progress.

Significant Hobbies · · 6 min read

The emotional impact of daily weigh-ins

Stepping on the scale can feel like receiving a grade. A lower number brings a sudden burst of motivation and a sense of achievement, validating yesterday’s choices. A higher number often triggers frustration, anxiety, or a lingering belief that your efforts simply aren’t working. This emotional rollercoaster is fueled by the false assumption that daily weight accurately reflects immediate changes in body fat.

The reality is that your body is a highly dynamic system. Weight is a composite measurement of fat, muscle, bone, organs, water, and whatever is currently residing in your digestive tract. Treating daily fluctuations as direct feedback on your nutrition or physical activity is mathematically and physiologically flawed.

When we invest our energy and discipline into changing our habits, it is completely natural to seek immediate validation. However, tying our self-worth or our assessment of our progress to a single daily data point sets us up for disappointment. It is an approach that guarantees frustration because it ignores the fundamental biology of how the human body stores energy, processes food, and manages hydration.

@@ -133,4 +143,4 @@

Practical next action

If daily weigh-ins consistently cause you anxiety, frustration, or lead to erratic dietary choices, you need to change your relationship with the scale.

Option 1: Reduce Frequency. Try weighing yourself only once a week or once every two weeks. Do it under similar conditions (e.g., first thing in the morning, after using the bathroom, before eating or drinking). This immediately eliminates the noise of daily fluctuations.

Option 2: Neutral Data Collection. If you prefer having daily data to build a more accurate moving average in your mind (or on a spreadsheet), practice logging the number with absolute emotional neutrality. Open Calorie, type the number in, hit save, and immediately close the app. Treat the scale weight exactly as you would treat the temperature outside: it is just a piece of information for the day, not a reflection of your worth or a reason to panic. Focus instead on hitting your daily targets for protein, fibre, and hydration.

-
\ No newline at end of file +
\ No newline at end of file diff --git a/marketing/blog/why-a-small-food-journal-does-not-need-an-ai-coach/index.html b/marketing/blog/why-a-small-food-journal-does-not-need-an-ai-coach/index.html index 5254df6..e2a80cd 100644 --- a/marketing/blog/why-a-small-food-journal-does-not-need-an-ai-coach/index.html +++ b/marketing/blog/why-a-small-food-journal-does-not-need-an-ai-coach/index.html @@ -1,13 +1,23 @@ Why a small food journal does not need an AI coach — Calorie
← Calorie journal

Guides

Why a small food journal does not need an AI coach

Explore why Calorie prioritizes transparent, math-based nutrition targets and timing estimates over opaque AI coaching, focusing on speed, privacy, and progress.

Significant Hobbies · · 6 min read

The Rise of the AI Diet Coach

+
← Calorie journal

Guides

Why a small food journal does not need an AI coach

Explore why Calorie prioritizes transparent, math-based nutrition targets and timing estimates over opaque AI coaching, focusing on speed, privacy, and progress.

Significant Hobbies · · 6 min read

The Rise of the AI Diet Coach

In the contemporary landscape of digital health, food journals have rapidly evolved from simple digital diaries into complex ecosystems. The modern user is often greeted not by a blank page, but by an automated “coach”—an artificial intelligence system that analyzes habits, predicts caloric needs, and issues directives on what to eat, when to fast, and how to exercise.

This shift toward AI coaching is marketed as the ultimate solution for nutritional optimization. The promise is that an intelligent system can parse personal data to deliver personalized advice. However, this approach introduces significant friction. When an app becomes a prescriptive coach, it fundamentally changes the relationship between the user and their journal. Instead of a neutral tool for observation, the app becomes an authority figure.

For many users, particularly those building a sustainable awareness of their nutritional intake, this added complexity is unnecessary. Calorie, a small, native food journal, was built on a different premise: a food journal should be a tool for transparent observation, not a black box for opaque instruction. By focusing on four core macronutrients and simple formulas, Calorie demonstrates why a small food journal does not need an AI coach.

@@ -126,4 +136,4 @@

Conclusion

In a market saturated with prescriptive digital coaches, the most radical approach is providing a simple, reliable tool. A small food journal does not need an AI coach because the user is already capable of learning. What the user needs is a clear, precise instrument to record the data—and Calorie provides exactly that.

Next Action

Ready to experience a transparent, math-based approach to food tracking? Return to our Homepage to learn more about our local-first journal, or read our Privacy Policy to understand how we keep your data on your device.

-
\ No newline at end of file +
\ No newline at end of file diff --git a/marketing/blog/why-calories-alone-are-not-enough-for-a-useful-food-journal/index.html b/marketing/blog/why-calories-alone-are-not-enough-for-a-useful-food-journal/index.html index 4c6b004..59655d6 100644 --- a/marketing/blog/why-calories-alone-are-not-enough-for-a-useful-food-journal/index.html +++ b/marketing/blog/why-calories-alone-are-not-enough-for-a-useful-food-journal/index.html @@ -1,13 +1,23 @@ Why calories alone are not enough for a useful food journal — Calorie
← Calorie journal

Guides

Why calories alone are not enough for a useful food journal

Discover why tracking calories is just one part of the picture. Learn how a food journal that includes macros, water, and timing provides better insights.

Significant Hobbies · · 5 min read

The Missing Macros: Protein, Carbs, and Fibre

+
← Calorie journal

Guides

Why calories alone are not enough for a useful food journal

Discover why tracking calories is just one part of the picture. Learn how a food journal that includes macros, water, and timing provides better insights.

Significant Hobbies · · 5 min read

The Missing Macros: Protein, Carbs, and Fibre

When a food journal focuses exclusively on calories, a hundred calories of pure sugar appears mathematically identical to a hundred calories of grilled chicken or broccoli. Your body, however, processes them entirely differently.

A more effective approach breaks energy down into its fundamental building blocks: the core macronutrients. By tracking calories alongside carbohydrates, protein, and fibre, the picture becomes immediately clearer.

    @@ -131,4 +141,4 @@

    Context Over Judgment: Pr

    Next Steps

    If your current approach to tracking food feels like a chore or isn’t providing the insights you need, it might be time to rethink what you are measuring. Move beyond the single daily calorie total.

    Practical Action: For the next three days, try noting not just what you eat, but when you eat it and how much water you drink alongside it. Look for the patterns in your energy levels that a simple calorie count misses. If you want a tool designed specifically for this kind of lightweight, transparent tracking, consider exploring a mobile-first journal that prioritizes speed and privacy over social feeds and opaque algorithms.

    -
\ No newline at end of file +
\ No newline at end of file diff --git a/marketing/images/brand/mark-114.webp b/marketing/images/brand/mark-114.webp new file mode 100644 index 0000000000000000000000000000000000000000..2b9771a5beaa9146228bff057ef55973e9c76ffe GIT binary patch literal 1326 zcmV+}1=0FaNk&E{1pok7MM6+kP&gnO1pok$8UUREDsljF06tM7k42-RArpv|a5x17 zvVdvLBOl+CHL2T!xtSC~t8G`94YqE%jp%>c@7NDwomN&o{(teN$G`F1Gs>reU9-G( z(WUpJna1ydPT0+L_{y+3o6rMx!j*Df=_o(W$)Ay_!Y!RquD6fWjdzDCZq2X(juAe$Ir z4)x09yyJ0auUlP7*F3b#%Yv`~uikx#uk_-E=UuF;i#W+O9@cIhr=7qTZ;qXd z_~*6Tv;VquphN6bsP!NJ*-jr8fOYX+3ulN@EhJS-?t2c?QIE*hiudy#gkb9-6)L>+ z5_88P+lKCW4L>-&aoe;W?r$zIqbKsZotjy2@hnfQGw~Z{9WF4$|M(g|TlSu?0;es9 z*)gLmCjx5Z|NVRa9Bae^UqifIE`Y!6-$i>QGeiU&&p5fqaEgAW`grjLJa3a4f;WcOE!HprMX$GT)US4d^)SS+q^^AC|m|jaLes4B)*jlf0t^-}6*)IDJlC zy2jRKBg_H`iu4}zwtKY^3`8TwnW8~r_%_}qN~?F1yN$M4Y}9%}(zdWOrc+ILkpos< z)p;IUlm}0Il&ZPGgH?gKS#EXgd|&VWhID<;_y3sKr8WS%IETb`u1rVG`-0G7VhxgY zn&9+{PBVcV)2sIf8D$tSM1PN536b{S4)>CjDT)QmS>5QW^2&`v8A?92<1pz!_-%DhMB6#jHmuhl0< zM~}c$(&i>z*-Q=>F!C6Jn!48_y|zYL+x%!ae%>1ndnKtJNn!v`y|x|Ty#)x$t4TfQ zR_MqrHZeuOZok*d^hti|^U3}+8X2cg>3C**x_J!Djj<(+2c+g#%h7oWc6!w}VF>2Q z;y1Vq%05KjF6qSD-tbfZ{&Q}LV24-PylzSRNQi@|L)hzfflGu0doMbflRAB|lSKYG za~_M}^a7WwfdwJ)H<{9 literal 0 HcmV?d00001 diff --git a/marketing/images/brand/mark-38.webp b/marketing/images/brand/mark-38.webp new file mode 100644 index 0000000000000000000000000000000000000000..e3b47626d384a99e519ee55a6ff53c46eca81e08 GIT binary patch literal 506 zcmVhe2CE^hs1lK^Llmx%u>u39h^yRRLDk z-iPF}=yd)$|HSP7_j~=z?*uY8f&Jq?rR8H;=EbxB`8m;gQG+(I$K!~Pg~uFi=npFx z?8p*&y@)BdF!MJCqeV1{so9tE3DzCueFj842NDQQ@=Gf5?z%oEK0c;=lhKnGlRoyuFuq}WD@tL`;&0aOt4|5js9<}!#24=IRD9f z%5(V29q-6T&)YtU@x;wznaML|oTdUIL0~@S=GOkKG(`&YSD$lc1F1FKlyvBQ1bLD_ wz9A7i`DUr;LtF-ej>KgJ2d+2CO||9V+`e1KOABU~B#laX#%te8aK!iE0Q*J%GXMYp literal 0 HcmV?d00001 diff --git a/marketing/images/brand/mark-76.webp b/marketing/images/brand/mark-76.webp new file mode 100644 index 0000000000000000000000000000000000000000..4baa45d3eb09b25c388f69f45d6f92c687ede21a GIT binary patch literal 766 zcmV)xoC zJaqHiv~@Bgum_FItib#ZHkgz2u{<#~@0P2Gy-bN)ZU1Nz`m4$1Qj`7&PR}pAB1d>& zP4dDM{E(mk0RH~%e13jueB1<>lilGHCawu}M^XDK$>Fv$pBMRc;~o+7BBfVRYbhn| z(#F!x8FopAGp07ClE|{nb$c1bxnSngC$2e**N^@nwV!`xi%Uv=C0LN`v90;ZVU%&W z0*&hint-eZD_YG%?N7t|zGh~I-5j|#d=6gHfmOV8K+m%MyaE$sBas2=Poex?e|T8J zeptH+PMIoh)HxUCXU|RN!xCSxIkh#K`41iFoU$UIuYdEqRI#{nifyJmC%;c45xF^^ z7_O3^Zj5|aez3?hRWGfiX5jTuZMmC2ovf9dweAeMYyaz+RnN@t=|O7#+$1=B?wge~ z2-#``@6{FgiqbeAQOhO?8(F42`zPs{Bj}s649LpF zP8Z9f6}i{c>tw8VUy7~f*mtPvbw>XIxCic+C2AB5*H%jjSVm z{wZ8%n*Z*_eU>!#pwTcel*0&-iEM{BQPnZc2HS1@KBX-}N5~SuV0X&t$p;)CHm)jaN~g`eOLY w*7wKy8oGoIrccS3WR_~uC548FP2-a#<>pB~!3+?Iz;xLmPitfG-;z)O0GRE5#sB~S literal 0 HcmV?d00001 diff --git a/marketing/index.html b/marketing/index.html index 540b07f..f18a7d4 100644 --- a/marketing/index.html +++ b/marketing/index.html @@ -1,13 +1,23 @@ Calorie — A private food journal for weight loss.Skip to content

Calorie for iPhone and iPad

A private food journal for weight loss with math you can inspect.

Log meals, four nutrients, water, weight, and routines in seconds. See transparent fasting, exercise, and sleep estimates from your timestamps and targets.

Internal TestFlight betaInternal TestFlight only. No public invite or App Store listing.

Calorie Today on iPhone: energy left for the day, protein, carbs, fat and fibre, and a food journal with breakfast and a snack

Log

Log a familiar meal in seconds.

Reuse a saved food, add a one-off, choose an amount, and keep the real eating time. The journal is designed for one-handed logging immediately after a meal.

Calorie quick log sheet for adding a saved or one-off food with an amount and eating time

Today

Every estimate shows its inputs.

Calorie uses food timestamps, four nutrients, water, routines, weight, and your own targets to estimate fasting, exercise, and sleep windows. The rules stay visible, and the result is never medical advice.

Progress

Compare seven and thirty days.

Review intake, eating rhythm, timing, and weight with the sample size and missing days visible. Progress is context, not a streak or a moral score.

Calorie Progress comparing intake, eating rhythm, timing and weight over seven and thirty days

Private by default

The journal stays yours.

The default journal lives on the device and needs no account. Optional Sign in with Apple can keep a private, user-scoped copy in Cloudflare D1.

Calorie may fit if

you are pursuing weight loss and want a private iPhone or iPad journal with fast logging and timing you can audit.

It is not

medical care, a barcode scanner, or a social feed. It will not prescribe a deficit.

Questions, answered.

Do I need an account?
No. The native journal works on this device without one. Sign in with Apple is optional private sync.
Is it medical advice?
No. Timing suggestions are estimates from the numbers you enter. They are not diagnosis or treatment.
Is the iPhone app on the App Store?
Not yet. This site will not show Apple’s badge until a live apps.apple.com listing exists.
Is Calorie paid?
There is no paid plan or checkout. Access is currently limited to invited internal TestFlight testers, and no permanent free or paid model has been announced.

Log the meal.
See the timing.

Internal TestFlight only. No public invite or App Store listing.

Illustrative artwork

Get Calorie updates

A short note when something new ships. No spam, and you can leave with one click.

Calorie

Private iPhone and iPad journal. Internal TestFlight only; no public invite, App Store listing, paid plan, or checkout. Timing estimates are informational, not medical advice.

Send feedback

Read by the person who builds Calorie.

What is it about?

Sends what you write, this page's address (without query or fragment), and anything you point at or attach.

Opens in a new tab
Skip to content

Calorie for iPhone and iPad

A private food journal for weight loss with math you can inspect.

Log meals, four nutrients, water, weight, and routines in seconds. See transparent fasting, exercise, and sleep estimates from your timestamps and targets.

Internal TestFlight betaInternal TestFlight only. No public invite or App Store listing.

Calorie Today on iPhone: energy left for the day, protein, carbs, fat and fibre, and a food journal with breakfast and a snack

Log

Log a familiar meal in seconds.

Reuse a saved food, add a one-off, choose an amount, and keep the real eating time. The journal is designed for one-handed logging immediately after a meal.

Calorie quick log sheet for adding a saved or one-off food with an amount and eating time

Today

Every estimate shows its inputs.

Calorie uses food timestamps, four nutrients, water, routines, weight, and your own targets to estimate fasting, exercise, and sleep windows. The rules stay visible, and the result is never medical advice.

Progress

Compare seven and thirty days.

Review intake, eating rhythm, timing, and weight with the sample size and missing days visible. Progress is context, not a streak or a moral score.

Calorie Progress comparing intake, eating rhythm, timing and weight over seven and thirty days

Private by default

The journal stays yours.

The default journal lives on the device and needs no account. Optional Sign in with Apple can keep a private, user-scoped copy in Cloudflare D1.

Calorie may fit if

you are pursuing weight loss and want a private iPhone or iPad journal with fast logging and timing you can audit.

It is not

medical care, a barcode scanner, or a social feed. It will not prescribe a deficit.

Questions, answered.

Do I need an account?
No. The native journal works on this device without one. Sign in with Apple is optional private sync.
Is it medical advice?
No. Timing suggestions are estimates from the numbers you enter. They are not diagnosis or treatment.
Is the iPhone app on the App Store?
Not yet. This site will not show Apple’s badge until a live apps.apple.com listing exists.
Is Calorie paid?
There is no paid plan or checkout. Access is currently limited to invited internal TestFlight testers, and no permanent free or paid model has been announced.

Log the meal.
See the timing.

Internal TestFlight only. No public invite or App Store listing.

Illustrative artwork

Get Calorie updates

A short note when something new ships. No spam, and you can leave with one click.

Calorie

Private iPhone and iPad journal. Internal TestFlight only; no public invite, App Store listing, paid plan, or checkout. Timing estimates are informational, not medical advice.

Send feedback

Read by the person who builds Calorie.

What is it about?

Sends what you write, this page's address (without query or fragment), and anything you point at or attach.

Opens in a new tab
Your journal stays yours. — Calorie
\ No newline at end of file +
\ No newline at end of file diff --git a/marketing/release/index.html b/marketing/release/index.html index 71e228a..12910ea 100644 --- a/marketing/release/index.html +++ b/marketing/release/index.html @@ -1,13 +1,23 @@ Release status — Calorie
\ No newline at end of file +
\ No newline at end of file diff --git a/marketing/support/index.html b/marketing/support/index.html index 6dc8782..ac780d2 100644 --- a/marketing/support/index.html +++ b/marketing/support/index.html @@ -1,13 +1,23 @@ Support, without a maze. — Calorie
\ No newline at end of file +
\ No newline at end of file diff --git a/marketing/terms/index.html b/marketing/terms/index.html index 7e6157a..0bdc490 100644 --- a/marketing/terms/index.html +++ b/marketing/terms/index.html @@ -1,13 +1,23 @@ Simple terms. — Calorie
\ No newline at end of file +
\ No newline at end of file diff --git a/marketing/testflight/index.html b/marketing/testflight/index.html index 5144f74..a158bfc 100644 --- a/marketing/testflight/index.html +++ b/marketing/testflight/index.html @@ -1,13 +1,23 @@ The native beta is private. — Calorie
\ No newline at end of file +
\ No newline at end of file diff --git a/scripts/build-landing.mjs b/scripts/build-landing.mjs index 709e49a..eda149d 100644 --- a/scripts/build-landing.mjs +++ b/scripts/build-landing.mjs @@ -1,5 +1,5 @@ import { spawnSync } from 'node:child_process'; -import { cpSync, readFileSync, rmSync } from 'node:fs'; +import { cpSync, readFileSync, rmSync, writeFileSync } from 'node:fs'; import path from 'node:path'; const root = path.resolve(import.meta.dirname, '..'); @@ -15,5 +15,16 @@ if (!readFileSync(path.join(output, 'index.html'), 'utf8').includes('data-fleet- rmSync(path.join(marketing, '_astro'), { recursive: true, force: true }); cpSync(path.join(output, '_astro'), path.join(marketing, '_astro'), { recursive: true }); -cpSync(path.join(output, 'index.html'), path.join(marketing, 'index.html')); +// The shared gallery emits a fixed-size mark; serve matching responsive assets locally. +const html = readFileSync(path.join(output, 'index.html'), 'utf8').replace( + /]*src="\/images\/brand\/mark\.png"[^>]*>/g, + (tag) => { + const width = tag.match(/width="(\d+)"/)[1]; + return tag.replace( + 'src="/images/brand/mark.png"', + `src="/images/brand/mark-76.webp" srcset="/images/brand/mark-38.webp 38w, /images/brand/mark-76.webp 76w, /images/brand/mark-114.webp 114w" sizes="${width}px"` + ); + } +); +writeFileSync(path.join(marketing, 'index.html'), html); console.log('Updated marketing home and Astro assets from landing/.'); diff --git a/src/landing-performance.test.ts b/src/landing-performance.test.ts new file mode 100644 index 0000000..5fb2ba9 --- /dev/null +++ b/src/landing-performance.test.ts @@ -0,0 +1,70 @@ +import { readFileSync, readdirSync } from 'node:fs'; +import { runInNewContext } from 'node:vm'; +import { describe, expect, it, vi } from 'vitest'; + +const marketing = new URL('../marketing/', import.meta.url); +const pages = readdirSync(marketing, { recursive: true }) + .filter((name) => name.endsWith('.html')) + .map((name) => readFileSync(new URL(name, marketing), 'utf8')); +const sources = [ + readFileSync(new URL('../landing/src/pages/index.astro', import.meta.url), 'utf8'), + ...pages, +]; + +describe('landing delivery', () => { + for (const trigger of ['pointerdown', 'keydown', 'touchstart', 'scroll', 'timer']) { + it(`queues Clarity immediately and loads once on ${trigger}`, () => { + for (const source of sources) { + const script = source.match( + /]*>(\(function\(\)\{const clarityProjectId[\s\S]*?)<\/script>/ + )?.[1]; + expect(script).toBeDefined(); + const listeners = new Map void>(); + const insertBefore = vi.fn(); + const setTimeout = vi.fn(); + const clearTimeout = vi.fn(); + const window = { + clarity: undefined as unknown as { (...args: string[]): void; q: string[][] }, + addEventListener: vi.fn((event: string, callback: () => void) => { + listeners.set(event, callback); + }), + removeEventListener: vi.fn((event: string) => { + listeners.delete(event); + }), + }; + runInNewContext(script ?? '', { + window, + document: { + createElement: () => ({}), + getElementsByTagName: () => [{ parentNode: { insertBefore } }], + }, + setTimeout, + clearTimeout, + }); + expect(insertBefore).not.toHaveBeenCalled(); + expect(Array.from(window.clarity.q[0])).toEqual(['set', 'project_id', 'calorie']); + window.clarity('set', 'test', 'queued'); + expect(window.clarity.q).toHaveLength(2); + expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), 90000); + for (const call of window.addEventListener.mock.calls) { + expect(call).toEqual([ + expect.any(String), + expect.any(Function), + { passive: true, once: true }, + ]); + } + const timeout = setTimeout.mock.calls[0][0]; + const callback = trigger === 'timer' ? timeout : listeners.get(trigger); + callback(); + timeout(); + expect(insertBefore).toHaveBeenCalledTimes(1); + expect(insertBefore.mock.calls[0][0]).toMatchObject({ + async: 1, + src: 'https://www.clarity.ms/tag/y6bultfwvf', + }); + expect(listeners.size).toBe(0); + expect(clearTimeout).toHaveBeenCalledTimes(1); + } + }); + } +});