<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Klivvr]]></title><description><![CDATA[Klivvr]]></description><link>https://blog.klivvr.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1748259447591/266fa528-1ab9-4949-a227-ddd43c6dea51.png</url><title>Klivvr</title><link>https://blog.klivvr.com</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 12 Apr 2026 16:56:53 GMT</lastBuildDate><atom:link href="https://blog.klivvr.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Coherence Without Comprehension: Inside How AI Writes Language]]></title><description><![CDATA[You type a complex question into ChatGPT or Claude. The cursor blinks. Then language begins to appear — measured, coherent, sometimes even poetic. Clauses follow clauses. Conclusions seem to emerge wi]]></description><link>https://blog.klivvr.com/coherence-without-comprehension-inside-how-ai-writes-language</link><guid isPermaLink="true">https://blog.klivvr.com/coherence-without-comprehension-inside-how-ai-writes-language</guid><category><![CDATA[AI]]></category><category><![CDATA[AI Tool ]]></category><dc:creator><![CDATA[Muhammad Youssef]]></dc:creator><pubDate>Tue, 31 Mar 2026 09:31:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6604268355f046aa6a2be990/5fe19cf9-af01-42b8-b384-5bb08af02e2c.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You type a complex question into ChatGPT or Claude. The cursor blinks. Then language begins to appear — measured, coherent, sometimes even poetic. Clauses follow clauses. Conclusions seem to emerge with intent. It feels as though something on the other side has already seen the end of the thought and is now walking you toward it.</p>
<p>That impression is false.</p>
<p>The model does not know what it will say. Not the paragraph. Not the sentence. Not even the next word. There is no internal narrative, no latent plan waiting to be revealed. At every step, the system is confronted with a single question: <strong>given everything so far, what “word” is most likely to come next?</strong></p>
<p>What you are witnessing is not intelligence as we understand it. It is coherence without comprehension. Structure emerging from a process that never plans, never reflects, and never understands. The gap between those two realities is where the illusion lives.</p>
<p>To see why this illusion is so convincing, we have to look at what actually happens between the moment you hit <em>Send</em> and the moment the first word appears.</p>
<h2><strong>TL;DR</strong></h2>
<p>By the end of this article, you’ll be able to look at a prompt and predict how the model will respond to it and why. You’ll see what makes a prompt collapse into noise, what makes another lock the model into clarity, and how the same system can feel intelligent or incompetent depending on how you engage it.</p>
<p>But to get there, we first need to strip away the illusion and examine the machinery underneath.</p>
<hr />
<h2><strong>From Prompt to Text: The Language Generation Pipeline</strong></h2>
<p>When you press <strong>Send</strong>, nothing starts “thinking.”<br />Instead, your prompt enters a sequence of transformations — each step moving it further away from human language and closer to raw computation.</p>
<p>First, the sentence is broken into pieces.<br />Those pieces are <strong>translated into numbers</strong>.<br />The numbers are <strong>compared to establish context</strong>.<br />Every possible continuation is <strong>evaluated and scored</strong>.<br />One option is <strong>chosen and locked in</strong>.</p>
<p>That single choice is then fed back into the system, and the entire sequence runs again.</p>
<p>This loop repeats once for every word that appears on your screen.</p>
<img src="https://cdn.hashnode.com/uploads/covers/665eba0c2633f499941c2331/1bc2a274-9d1b-4149-ba8a-df85640bca4b.png" alt="" style="display:block;margin:0 auto" />

<p>In technical terms, the process consists of five phases:</p>
<ol>
<li><p><strong>Tokenization:</strong> Language is fractured into discrete units that the model can operate on.</p>
</li>
<li><p><strong>Embeddings:</strong> Those units are lifted out of text entirely and placed into a numerical space of meaning.</p>
</li>
<li><p><strong>The Transformer:</strong> Context is processed through layers of attention, deciding what matters and what doesn’t.</p>
</li>
<li><p><strong>Probabilities:</strong> Every possible continuation is evaluated and scored.</p>
</li>
<li><p><strong>Sampling:</strong> A single option is selected, fixed in place, and fed back into the system.</p>
</li>
</ol>
<p>Nothing here runs once. There is no final pass, no overview, no plan.<br />Only a loop executed at scale, where language emerges one <strong>irreversible choice at a time</strong>.</p>
<p>To make sense of how such a simple loop can produce such convincing language, we need to slow it down and examine each phase in isolation. Starting with the very first transformation your text undergoes.</p>
<h2><strong>1) Tokenization: Breaking Language Apart</strong></h2>
<img src="https://cdn.hashnode.com/uploads/covers/665eba0c2633f499941c2331/2d084ed9-3745-4f4b-9250-180b391b7599.png" alt="" style="display:block;margin:0 auto" />

<p>The first myth to let go of is simple: <strong>tokens are not words</strong>.</p>
<p>Tokens are fragments. Sometimes a full word, sometimes a syllable, sometimes a piece of punctuation. Shaped by statistical efficiency, not by grammar. Tokenizers are trained in advance on vast collections of text to compress language as effectively as possible. Frequently occurring patterns are kept whole. Rarer or longer words are broken apart. “<em>The”</em> might be a single token; “<em>indistinguishable”</em> might become several.</p>
<p>All of this happens <strong>before</strong> the neural network is involved. No attention, no probabilities, no reasoning. Just a deterministic conversion from text to symbols. By the time the model begins operating, your prompt is no longer language at all. It’s a sequence of integers.</p>
<h2><strong>2) Embeddings: Turning Symbols into Geometry</strong></h2>
<img src="https://cdn.hashnode.com/uploads/covers/665eba0c2633f499941c2331/6aaf13ca-9c28-4142-b15f-ff73524f399d.png" alt="" style="display:block;margin:0 auto" />

<p>Once language has been broken into tokens, an even less intuitive step follows: those numbers still carry no meaning.</p>
<p>A token ID is nothing more than an index in a lookup table. On its own, it encodes no semantics, no context, and no notion of relatedness. “<em>Dog”</em> and “<em>database”</em> might sit next to each other numerically or be separated by thousands of indices — the distance is arbitrary. If the model tried to operate on these token IDs directly, every token would be equally meaningless.</p>
<p>So the next step is not language processing. It’s a <strong>coordinate assignment</strong>.</p>
<p>Each token ID is mapped to a high-dimensional vector — a long list of numbers that places it at a specific position in space. This space is not linguistic. It is geometric. Distance, direction, and relative position are the only signals that exist.</p>
<p>Tokens that appear in similar contexts across massive amounts of text are placed near one another. Tokens that rarely co-occur drift farther apart. Over time, structure emerges — not because anyone defined it, but because statistical patterns enforce it.</p>
<p>This is how relationships take shape:</p>
<ul>
<li><p><code>Function</code>, <code>method</code>, and <code>procedure</code> fall into the same neighborhood.</p>
</li>
<li><p><code>Java</code>, <code>Python</code>, and <code>JavaScript</code> occupy adjacent regions.</p>
</li>
<li><p><code>Python</code> the programming language and <code>Python</code> the snake are pushed far apart.</p>
</li>
</ul>
<p>No rules were written for this. No ontology was designed. The geometry formed itself. Once tokens become vectors, meaning is no longer symbolic. It becomes <strong>spatial</strong>.</p>
<ul>
<li><p>Similarity is represented as distance.</p>
</li>
<li><p>Analogy becomes direction.</p>
</li>
<li><p>Context becomes movement through this space.</p>
</li>
</ul>
<p><a href="https://medium.com/@bateiko/vector-vs-embedding-whats-the-real-difference-e59b4775e2a1"><img src="https://cdn.hashnode.com/uploads/covers/665eba0c2633f499941c2331/8e9515de-8897-45b2-8b62-49fe20604f57.png" alt="" style="display:block;margin:0 auto" /></a></p>
<p>For the first time in the pipeline, the model has something it can actually operate on. These vectors — not words, not tokens — are what enter the transformer.</p>
<p>And this is where context begins to matter.</p>
<h2><strong>3) The Transformer: Context Is a Mixing Problem</strong></h2>
<img src="https://cdn.hashnode.com/uploads/covers/665eba0c2633f499941c2331/8cc3779b-7bcd-47c5-a7c8-72cd4f2f6936.png" alt="" style="display:block;margin:0 auto" />

<p>By the time data reaches the transformer, language is already gone.</p>
<p>What the model receives is a sequence of vectors — points in a geometric space that encode meaning and similarity. But at this stage, each vector still stands mostly alone. It knows <em>what</em> it represents, but not <em>how it relates</em> to everything else around it.</p>
<p>The transformer’s job is to change that.</p>
<p>At its core, the transformer is not a reasoning engine. It doesn’t think or plan. Instead, it acts as a <strong>context mixer</strong>. Its role is to repeatedly take a set of vectors and rewrite each one in terms of all the others.</p>
<p>This happens through a mechanism called <strong>attention</strong>.</p>
<h3><strong>3.1) Attention: Deciding What Matters</strong></h3>
<p>For every token in a sequence, the transformer asks a simple question: “<em>Which other tokens should influence me right now — and by how much?”</em></p>
<p>For example: “The cat sat on the mat because it was tired.”</p>
<p>What does “<em>it”</em> refer to? Not the mat. The cat.</p>
<p>Humans resolve this instantly. The transformer does it numerically. When processing the vector for “<em>it”</em>, the attention mechanism assigns more weight to “<em>cat”</em> than to “<em>mat”</em>, even though “<em>mat”</em> appears closer in the sentence.</p>
<p>This isn’t logic in the human sense. It’s pattern recognition at scale. Across millions of examples, the model has learned that “<em>tired”</em> usually applies to living things, not objects.</p>
<p>Attention works by comparing vectors and assigning weights — numbers that determine how much each token influences every other token.</p>
<h3><strong>3.2) Multi-Head Attention: Multiple Perspectives at Once</strong></h3>
<p>This process doesn’t happen just once.</p>
<p>It runs <strong>in parallel</strong>, using what are called “<em>attention heads”</em>. Each head can focus on different kinds of relationships, such as:</p>
<ul>
<li><p>Grammatical structure</p>
</li>
<li><p>Semantic similarity</p>
</li>
<li><p>Positional cues</p>
</li>
</ul>
<p>One head might track subject–verb agreement. Another might follow references like “<em>it”</em> or “<em>they”</em>. Another might focus on the overall topic of the sentence.</p>
<p>None of these roles is predefined. They emerge naturally because different patterns help the model make better predictions.</p>
<h3><strong>3.3) Depth: Building Meaning Layer by Layer</strong></h3>
<p>After attention is applied, the vectors are updated. Each token now carries information not just about itself, but about its relationship to the entire sequence.</p>
<p>Then the process repeats.</p>
<p>Modern models stack dozens of these layers. Early layers tend to capture local structure. Later layers encode broader, more abstract context. With each pass, the representation becomes richer and more specific.</p>
<p>By the time the vectors leave the transformer, they no longer represent isolated meanings. They represent <strong>meaning in context</strong>. Not just “<em>cat”</em>. But “<em>this”</em> cat, in “<em>this sentence”</em>, for “<em>this purpose”</em>.</p>
<h3><strong>3.4) What the Transformer Is Not</strong></h3>
<p>There is no memory of past conversations here. No internal narrative. No global understanding of the prompt.</p>
<p>The transformer doesn’t know what it’s saying. It continuously rewrites vectors based on how they relate to one another. What feels like reasoning is the accumulated effect of repeated context mixing.</p>
<p>And once that mixing is done, the model moves on to its next step. It has to decide what comes next.</p>
<h2><strong>4) Probabilities: Scoring the Future</strong></h2>
<img src="https://cdn.hashnode.com/uploads/covers/665eba0c2633f499941c2331/d5b354ec-c89b-49aa-81bd-027c99cc094b.png" alt="" style="display:block;margin:0 auto" />

<p>Once the transformer finishes mixing context, its work is complete.</p>
<p>What comes out is a final set of vectors — each one encoding everything the model knows <em>at this moment</em> about the sequence so far. But nothing has been turned into text yet. There are no words. No sentences. Just numbers.</p>
<p>Now the model must answer a single question: “<strong>Given everything so far, what should come next?”</strong></p>
<p>To do that, it considers <strong>every possible next token</strong> in its vocabulary.</p>
<p>Not a handful.<br />Not the top few.<br /><strong>All of them.</strong></p>
<p>For modern models, that can mean tens or even hundreds of thousands of possibilities.</p>
<h3><strong>4.1) From Context to Scores</strong></h3>
<p>The final transformer layer assigns a score to every possible next token. These scores are called <strong>logits</strong>.</p>
<p>On their own, logits don’t mean much. They’re just raw numbers:</p>
<ul>
<li><p>positive or negative</p>
</li>
<li><p>large or small</p>
</li>
</ul>
<p>To turn them into something usable, the model applies a mathematical function called <strong>softmax</strong>.</p>
<p>Softmax converts those raw scores into a probability distribution:</p>
<ul>
<li><p>Every token receives a probability</p>
</li>
<li><p>All probabilities sum to 1</p>
</li>
<li><p>Higher scores become higher probabilities</p>
</li>
</ul>
<p>At this point, the model still hasn’t chosen anything. It has simply produced a <strong>ranked list of possibilities</strong>.</p>
<p>For a prompt like “What is Python?”, the distribution might look something like this:</p>
<ul>
<li><p>“is” → 23%</p>
</li>
<li><p>“was” → 14%</p>
</li>
<li><p>“means” → 6%</p>
</li>
<li><p>thousands of other tokens → fractions of a percent each</p>
</li>
</ul>
<p>This is the core reality of language generation. The model does not decide what to say. It produces a <strong>probability distribution</strong> over what <em>could</em> come next.</p>
<h3><strong>4.2) Plausibility, Not Truth</strong></h3>
<p>This is also where a crucial limitation appears. The probabilities don’t represent truth. They represent plausibility.</p>
<p>The model has no built-in concept of correctness. It doesn’t verify facts or check consistency against reality. It simply assigns higher probability to sequences that look like things it has seen before.</p>
<p>This is why models can sound confident while being wrong.</p>
<p>When a model hallucinates, it isn’t lying. It’s selecting a high-probability continuation that happens to be false. The system knows how convincing answers are shaped. Not whether they’re correct.</p>
<p>At this stage, everything is still potential. Nothing has been committed. That happens next. The model must make a choice.</p>
<h2><strong>5) Sampling: Committing to One Path</strong></h2>
<img src="https://cdn.hashnode.com/uploads/covers/665eba0c2633f499941c2331/811b105e-58dd-45a3-b688-9317d1ceb450.png" alt="" style="display:block;margin:0 auto" />

<p>Up to this point, nothing has actually been generated.</p>
<p>The model has:</p>
<ul>
<li><p>Broken text into tokens</p>
</li>
<li><p>Embedded them into geometry</p>
</li>
<li><p>Mixed context through attention</p>
</li>
<li><p>Scored every possible next token</p>
</li>
</ul>
<p>But it hasn’t <em>chosen</em> anything yet.</p>
<p>What it holds now is a probability distribution — a map of futures, each weighted by likelihood. Sampling is the moment where possibility collapses into reality. This is where the model commits.</p>
<h4>5.1) Choosing Is Not Picking the Best</h4>
<p>A common misconception is that the model always selects the most likely next token. It doesn’t.</p>
<p>If it did, every response would be painfully predictable. The same phrasing. The same structures. The same answers every time.</p>
<p>Instead, the model <strong>samples</strong> from the probability distribution.</p>
<p>That means:</p>
<ul>
<li><p>Highly probable tokens are <em>more likely</em> to be chosen</p>
</li>
<li><p>Less probable tokens are <em>still possible</em></p>
</li>
<li><p>Extremely unlikely tokens are effectively ignored</p>
</li>
</ul>
<p>This controlled randomness is what allows language to feel flexible rather than mechanical.</p>
<h4>5.2) Temperature: Controlling Risk</h4>
<p>Sampling behavior is shaped by a parameter called <strong>temperature</strong>.</p>
<p>Temperature adjusts how sharp or flat the probability distribution is before a token is selected.</p>
<ul>
<li><p>Low temperature sharpens the distribution</p>
<ul>
<li><p>The top tokens dominate</p>
</li>
<li><p>Outputs become focused, conservative, repetitive</p>
</li>
</ul>
</li>
<li><p>High temperature flattens the distribution</p>
<ul>
<li><p>Lower-probability tokens get more weight</p>
</li>
<li><p>Outputs become more creative, but less reliable</p>
</li>
</ul>
</li>
</ul>
<p>At temperature zero (theoretical), the model would always pick the single most likely token. At very high temperatures, generation becomes chaotic. Most real-world systems operate somewhere in between.</p>
<h4>5.3) Guardrails: Limiting the Space</h4>
<p>Additional techniques are often applied to prevent sampling from drifting into nonsense.</p>
<p>Two common ones:</p>
<ul>
<li><p>**Top-k sampling<br />**Only the top <em>k</em> most probable tokens are considered. Everything else is discarded.</p>
</li>
<li><p>**Top-p (nucleus) sampling<br />**Tokens are considered until their cumulative probability reaches <em>p</em> (for example, 90%). The tail is ignored.</p>
</li>
</ul>
<p>These methods don’t change what the model <em>knows</em>. They change which futures are allowed to choose from.</p>
<h4>5.4) One Token at a Time</h4>
<p>After sampling, a single token is selected. That token is appended to the sequence, then the entire process starts again:</p>
<ul>
<li><p>The new token is embedded</p>
</li>
<li><p>Context is remixed</p>
</li>
<li><p>Probabilities are recomputed</p>
</li>
<li><p>Another token is sampled</p>
</li>
</ul>
<p>There is no master plan. No outline. No awareness of where the sentence is going. Each step is local. Each choice depends only on what exists so far. What feels like a coherent paragraph is actually the result of hundreds or thousands of tiny commitments, made one token at a time.</p>
<h4>What Looks Like Intent Is Just Momentum</h4>
<p>The model does not know where it is heading. It doesn’t aim for conclusions. It doesn’t plan punchlines. It doesn’t hold goals in mind.</p>
<p>What emerges instead is <strong>statistical momentum</strong>. Once a direction is chosen, future probabilities reinforce it. Style stabilizes. Topic narrows. Coherence appears. Not because the model understands the destination. But because every step reshapes the landscape of what comes next.</p>
<p>And with that final commitment, language reappears. One token at a time.</p>
<h3>6) How to Leverage This When Using AI Agents</h3>
<p>Once you understand how models actually operate, a lot of “prompt magic” stops being magic.</p>
<ul>
<li><p>AI agents don’t reason globally.</p>
</li>
<li><p>They don’t plan end-to-end.</p>
</li>
<li><p>They don’t hold intent across time.</p>
</li>
</ul>
<p>They sample one token at a time, conditioned on the context you give them. That means <strong>your primary lever is context shaping</strong>.</p>
<h4>6.1) Control Behavior by Controlling Context</h4>
<p>Models don’t follow intent — they follow context. Clear structure, constraints, and framing sharpen the probability space and produce more reliable behavior than vague instructions ever will.</p>
<p>Good example</p>
<blockquote>
<p>You are a senior backend engineer.</p>
<p>Task: Review the following function for concurrency issues.</p>
<p>Constraints:</p>
<ul>
<li><p>Focus only on thread safety</p>
</li>
<li><p>Ignore performance concerns</p>
</li>
<li><p>Respond in bullet points</p>
</li>
</ul>
</blockquote>
<p>Bad example</p>
<blockquote>
<p>Can you look at this code and tell me if it's okay?</p>
</blockquote>
<h4>6.2) Think in Trajectories, Not Prompts</h4>
<p>Early tokens set direction. The opening lines determine tone, depth, and structure. Treat prompts as the start of a trajectory, not a single instruction.</p>
<p>Good example</p>
<blockquote>
<p>We are writing a technical design review.</p>
<p>Audience: senior engineers.</p>
<p>Tone: precise, critical, neutral.</p>
<p>Begin by summarizing the core architectural tradeoff.</p>
</blockquote>
<p>Bad example</p>
<blockquote>
<p>Explain this architecture.</p>
</blockquote>
<h4>6.3) Use Examples to Collapse Ambiguity</h4>
<p>Examples reduce interpretation space. They show the model exactly which patterns to reinforce and which to ignore.</p>
<p>Good example</p>
<blockquote>
<p>Convert requirements into acceptance criteria.</p>
<p>Example:<br />Requirement: User can reset password<br />Acceptance Criteria:</p>
<ul>
<li><p>User receives reset email</p>
</li>
<li><p>Link expires after 15 minutes</p>
</li>
<li><p>Password meets policy</p>
</li>
</ul>
<p>Now convert:<br />Requirement: User can export data</p>
</blockquote>
<p>Bad example</p>
<blockquote>
<p>Write acceptance criteria for this feature.</p>
</blockquote>
<h4>6.4) Break Tasks into Stable States</h4>
<p>Long, open-ended goals degrade output quality. Breaking work into phases keeps context sharp and reduces error accumulation.</p>
<p>Good example</p>
<blockquote>
<p>Step 1: Summarize the problem in one paragraph.</p>
<p>Step 2: List possible approaches.</p>
<p>Step 3: Evaluate tradeoffs.</p>
<p>Step 4: Recommend one option.</p>
<p>Proceed step by step.</p>
</blockquote>
<p>Bad example</p>
<blockquote>
<p>Figure out the best solution and explain everything.</p>
</blockquote>
<h4>6.5) Design for Correction, Not Perfection</h4>
<p>Models commit sequentially. Errors compound. Build feedback loops that reintroduce context and allow correction.</p>
<p>Good example</p>
<blockquote>
<p>Answer the question.</p>
<p>Then:</p>
<ul>
<li><p>List your assumptions</p>
</li>
<li><p>Identify potential errors</p>
</li>
<li><p>Revise the answer if needed</p>
</li>
</ul>
</blockquote>
<p>Bad example</p>
<blockquote>
<p>Give me the final answer.</p>
</blockquote>
<h4>6.6) Shape Context, Don’t Command Intelligence</h4>
<p>Agents aren’t planners or thinkers. They’re probabilistic systems responding to context. Precision beats authority.</p>
<p>Good example</p>
<blockquote>
<p>Here is the format you must follow:</p>
<ul>
<li><p>Assumption</p>
</li>
<li><p>Reasoning</p>
</li>
<li><p>Conclusion</p>
</li>
</ul>
<p>If information is missing, say so explicitly.</p>
</blockquote>
<p>Bad example</p>
<blockquote>
<p>Be smart and figure it out.</p>
</blockquote>
<hr />
<h3>Final Thoughts</h3>
<p>What you’ve seen here isn’t a story about intelligence. It’s a story about mechanics.</p>
<p>From prompt to token, from token to vector, from vectors to probabilities, and from probabilities to a single irreversible choice. Language emerges without understanding, intention, or awareness. Coherence is not evidence of thought. It’s the result of structure, scale, and statistical momentum.</p>
<p>Once you understand this pipeline, AI stops feeling mysterious. You stop asking <em>“What does it know?”</em> and start asking <em>“What context am I shaping?”</em> The difference is subtle, but it’s where effective use begins.</p>
<p>There is no mind in the machine. But there is a system. And systems, once understood, can be guided.</p>
<hr />
<h4>Thanks for reading through 🙌🏼. If you found this post useful, please share it through your circles.</h4>
]]></content:encoded></item><item><title><![CDATA[The Silent Scan]]></title><description><![CDATA[Picture this… A stranger walks up to your house at 3 AM. They quietly check your windows, test the door handle, then slip away. Your security cameras recorded everything.

But the screen that shows th]]></description><link>https://blog.klivvr.com/the-silent-scan</link><guid isPermaLink="true">https://blog.klivvr.com/the-silent-scan</guid><category><![CDATA[cybersecurity]]></category><category><![CDATA[SIEM]]></category><category><![CDATA[SOC]]></category><category><![CDATA[Security Operations Center ]]></category><category><![CDATA[ThreatDetection]]></category><category><![CDATA[blueteam]]></category><category><![CDATA[cyberattack]]></category><category><![CDATA[reconnaissance ]]></category><category><![CDATA[hacking]]></category><category><![CDATA[Klivvr]]></category><category><![CDATA[CSOC]]></category><dc:creator><![CDATA[Moustafa S. Kamel]]></dc:creator><pubDate>Tue, 24 Feb 2026 09:32:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6604268355f046aa6a2be990/90e97486-8a27-4a71-9cdf-89a7baa5bb72.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em><strong>Picture this…</strong></em> A stranger walks up to your house at 3 AM. They quietly check your windows, test the door handle, then slip away. Your security cameras recorded everything.</p>
<blockquote>
<p>But the screen that shows the CCTV footages never shows who’s in front of the door, as the camera set to a wrong angle.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769439906477/a03b1283-affb-4b31-94fa-93abe55bbdb9.png" alt="" style="display:block;margin:0 auto" /></blockquote>
<p>That’s what a <strong>Silent Scan</strong> is: real attacker activity captured in logs… but missing from the dashboards analysts rely on to judge the health of their environment.</p>
<p>This article breaks down how that happens, and shows exactly how to stop it.</p>
<hr />
<h2>The Hidden Failure No One Talks About</h2>
<p>Every SIEM boasts dashboards: anomaly charts, trending tables, threat widgets, colorful pies that make us feel informed. But dashboards lie when their filters are narrow.</p>
<p>A SIEM can fully ingest the logs for a port-scan, tag the source as malicious, and even generate an alert… while the dashboard you check every day shows <strong>zero anomalies</strong> involving that host.</p>
<p>That’s not a detection failure. That’s a <strong>visibility failure</strong>, which is worse, because you don’t know what you’re missing.</p>
<h2>A Simple Example That Exposes the Problem</h2>
<p>Imagine a SIEM dashboard powered by a query like:</p>
<pre><code class="language-sql">Show anomalies for destination A or B
</code></pre>
<p>Clean. Simple. Harmless, right?</p>
<p>Now imagine a real attacker probes <strong>IP</strong> <code>C</code>, another security device you forgot to include in that query. The SIEM knows. The logs show it. Threat intelligence screams about it.</p>
<p>But the dashboard? <strong>Zero.</strong> Like the attack never happened.</p>
<p>Junior analysts look at the dashboard and think:</p>
<blockquote>
<p>“All quiet today.”</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769439928098/4af4d2e6-3f9c-45e5-9595-15465de5c1a1.png" alt="" style="display:block;margin:0 auto" /></blockquote>
<p>Hey! It wasn’t.</p>
<hr />
<h2>Let’s Visualize It Clearly</h2>
<p><strong>The Real Attack</strong> A suspicious IP sends repeated connection attempts to a web gateway or firewall. Classic reconnaissance.</p>
<p><strong>Your Security Stack Logs:</strong></p>
<ul>
<li><p>Source IP flagged by threat intel</p>
</li>
<li><p>Repeated port hits</p>
</li>
<li><p>Access denied</p>
</li>
<li><p>Firewall blocks</p>
</li>
<li><p>Potential recon behavior</p>
</li>
</ul>
<blockquote>
<p><strong>What the SIEM Shows in Raw Logs</strong> “<strong>External host scanned a protected endpoint.</strong>”</p>
<p><strong>What the Analyst’s Dashboard Shows</strong> Nothing… No entry… No spike... No anomaly…</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769440805416/1e3fd264-51e0-4a38-8b4e-d4074d06b8e6.gif" alt="" style="display:block;margin:0 auto" /></blockquote>
<p><strong>Why?</strong> Because the dashboard filter only monitors a <em>shortlist</em> of tracked assets, and the scanned one is missing. This is how real attacks hide in plain sight.</p>
<hr />
<h2>Why This Matters</h2>
<p>Attackers don’t start with bombs. They start with knocks.</p>
<p>Reconnaissance is <strong>Phase Zero</strong> of intrusion: mapping defenses, discovering exposed surfaces, testing response behavior. Missing recon is like watching a movie from the middle and wondering why the ending makes no sense.</p>
<p>A blind dashboard means:</p>
<ul>
<li><p>Early-stage threats go unnoticed</p>
</li>
<li><p>Incident timelines become incomplete</p>
</li>
<li><p>Investigations miss crucial clues</p>
</li>
<li><p>Analysts trust visuals that don’t reflect reality</p>
</li>
<li><p>Security relies on luck instead of design</p>
</li>
</ul>
<p>Dashboards aren’t passive screens. They shape how analysts think. <strong>If the dashboards are blind, the team is blind.</strong></p>
<hr />
<h2>Here’s Where It Gets Surprisingly Fun</h2>
<blockquote>
<p>Remember those variables from programming classes? Those boring “boxes” that hold values that can change? SIEMs use the same idea quietly, but far more powerfully.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769440820951/f5677466-f52c-41af-ab86-69f38d465814.webp" alt="" style="display:block;margin:0 auto" /></blockquote>
<p>People often ask: “<strong>Does a SIEM even have variables?</strong>” <strong>Absolutely. They just don’t call them that.</strong></p>
<p>Every SIEM (<a href="https://www.splunk.com/en_us/products/enterprise-security-essentials.html">Splunk</a>, <a href="https://www.microsoft.com/en-us/security/business/siem-and-xdr/microsoft-sentinel">Sentinel</a>, <a href="https://www.elastic.co/security/siem">Elastic</a>, <a href="https://www.ibm.com/products/qradar">QRadar</a>, <a href="https://www.opentext.com/products/enterprise-security-manager">ArcSight</a>, <a href="https://cloud.google.com/security/products/security-operations">Chronicle</a>, whatever your flavor…) gives you structured lists:</p>
<ul>
<li><p>Lookup tables</p>
</li>
<li><p>Watchlists</p>
</li>
<li><p>Reference sets</p>
</li>
<li><p>Dynamic lists</p>
</li>
<li><p>Enrichment tables</p>
</li>
</ul>
<p>These are effectively <strong>security variables</strong>. Instead of hard-coding IPs into queries like a freshman Python homework, you store them in a central list and reference them dynamically.</p>
<h3><strong>Not technical? Doesn’t matter.</strong></h3>
<blockquote>
<p><em><strong>Picture this…</strong></em> You run a nightclub. You don’t memorize every VIP by heart each night. You keep a <strong>VIP list</strong> at the door.</p>
<ul>
<li><p>Name on the list → let them in.</p>
</li>
<li><p>Not on the list → stop, check, verify.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769440079248/f1b81030-df9d-43e7-a9c8-d34d86b36790.png" alt="" style="display:block;margin:0 auto" /></li>
</ul>
</blockquote>
<p>A SIEM works exactly the same way. These lists are the difference between a dashboard that shows <em>reality</em>, and a dashboard that shows whatever tiny slice of reality you remembered to filter for.</p>
<p>And once you understand that, the examples you’re about to see suddenly become painfully clear.</p>
<hr />
<h2>The Fix: Stop Hard-Coding. Start Using Dynamic Asset Lists.</h2>
<p>Those structured lists, the “security variables” your SIEM already provides should become your single source of truth.</p>
<p><strong>Don’t build dashboards like:</strong></p>
<pre><code class="language-sql">destination_asset_ip = 'X' or 'Y' or 'Z'
</code></pre>
<p><strong>Use:</strong></p>
<pre><code class="language-sql">destination_asset_ip in "SECURITY_ASSETS_LIST"
</code></pre>
<p>Then, keep <code>SECURITY_ASSETS_LIST</code> updated automatically with your security solutions:</p>
<ul>
<li><p>Firewalls &amp; WAFs</p>
</li>
<li><p>Reverse proxies &amp; Load balancers</p>
</li>
<li><p>API gateways</p>
</li>
<li><p>Internet-exposed nodes</p>
</li>
<li><p>Pre-prod mirrors</p>
</li>
</ul>
<p>When assets evolve, your dashboards stay accurate… forever.</p>
<hr />
<h2>Realistic Sample: Before vs. After</h2>
<h3>Before (The Dangerous Way)</h3>
<p><strong>Dashboard Query:</strong> <code>Show anomalies only for: 127.0.0.10, 127.0.0.20, 127.0.0.30</code></p>
<ul>
<li><p><strong>Scenario:</strong> IT deploys a new WAF at <code>127.0.0.40</code>.</p>
</li>
<li><p><strong>The Gap:</strong> The dashboard query wasn't updated manually.</p>
</li>
<li><p><strong>The Result:</strong> An attack hits <code>127.0.0.40</code>. The dashboard goes silent.</p>
</li>
</ul>
<h3>After (The Correct Way)</h3>
<p><strong>Dashboard Query:</strong> <code>Show anomalies where destination is in SECURITY_ASSETS_LIST</code></p>
<ul>
<li><p><strong>The List:</strong> <code>SECURITY_ASSETS_LIST</code> automatically updates to include:</p>
<ul>
<li><p><code>127.0.0.10</code></p>
</li>
<li><p><code>127.0.0.20</code></p>
</li>
<li><p><code>127.0.0.30</code></p>
</li>
<li><p><code>127.0.0.40</code></p>
</li>
</ul>
</li>
<li><p><strong>The Result:</strong> Every device speaks. Every scan shows. Every blind spot dies.</p>
</li>
</ul>
<hr />
<h2><strong>The Shadow IT Trap: How Attackers Exploit Blind Spots</strong></h2>
<p><strong>The Setup</strong> A malicious IP sends sequential connection attempts to a "Shadow IT" server, a dev machine spun up for testing that didn't make it onto the official Excel spreadsheet.</p>
<p><strong>Raw Logs (SIEM sees):</strong></p>
<ul>
<li><p>Multiple denied hits</p>
</li>
<li><p>Port variations</p>
</li>
<li><p>Threat intel score: High</p>
</li>
<li><p>Behavior: Consistent with probing</p>
</li>
</ul>
<p><strong>Dashboard (SIEM doesn’t show):</strong></p>
<ul>
<li><em>“0 anomalies detected today.”</em></li>
</ul>
<p><strong>Why the contradiction?</strong> The widget tracks only <em>known, pre-selected</em> devices. Attackers don’t attack only the devices you expect. They attack everything. <strong>Your dashboards must reflect that.</strong></p>
<hr />
<h2>A Message to Every Analyst… Especially Beginners</h2>
<p>If you only trust alerts, you’ll miss trends. If you only trust dashboards, you’ll miss the context.</p>
<p><strong>If you want to be better than average, fix the blind spots.</strong></p>
<p>Modern CSOC teams don’t fail because they lack data. They fail because they ignore the data they already have.</p>
<p>The scariest threats aren’t loud. They’re quiet, curious, probing, and waiting for the moment you’re not looking.</p>
<hr />
<h2>Closing Thought</h2>
<p>A SIEM that collects data but doesn’t show it is like a lighthouse with the bulb turned off. It stands tall, looks impressive, and helps exactly no one.</p>
<p>Turn the light on. Start with visibility. Use dynamic asset lists. Make your dashboards honest.</p>
<p>Because the next silent scan won’t announce itself. <strong>But your SIEM should.</strong></p>
<hr />
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769440832347/9a55040b-b8c3-4d02-8d92-f546a3fff8e9.gif" alt="" style="display:block;margin:0 auto" />

<aside>
<h3>By <a href="https://www.linkedin.com/in/0x91k4">Moustafa S. Kamel</a>, Cybersecurity Analyst @ <a href="https://klivvr.com">Klivvr</a> - 2026</h3>
</aside>]]></content:encoded></item><item><title><![CDATA[AWS Lambda for Beginners: A Practical Guide to Serverless Basics, Pricing, and Common Pitfalls]]></title><description><![CDATA[AWS Lambda is often one of the first services developers encounter when stepping into the world of serverless architecture. It bears promises of automatic scaling, no servers to manage, and a usage-based pricing model—all while letting you focus pure...]]></description><link>https://blog.klivvr.com/aws-lambda-for-beginners-a-practical-guide-to-serverless-basics-pricing-and-common-pitfalls</link><guid isPermaLink="true">https://blog.klivvr.com/aws-lambda-for-beginners-a-practical-guide-to-serverless-basics-pricing-and-common-pitfalls</guid><category><![CDATA[AWS]]></category><category><![CDATA[aws lambda]]></category><category><![CDATA[serverless]]></category><category><![CDATA[development]]></category><category><![CDATA[backend]]></category><dc:creator><![CDATA[Karim Fayed]]></dc:creator><pubDate>Tue, 03 Feb 2026 10:35:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1770028021165/93defa7e-06e5-4a69-b1f9-3771471fcfdb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>AWS Lambda is often one of the first services developers encounter when stepping into the world of serverless architecture. It bears promises of automatic scaling, no servers to manage, and a usage-based pricing model—all while letting you focus purely on writing code. Sounds simple, right? In practice, Lambda <em>is</em> powerful and approachable, but it also comes with concepts and pitfalls that can confuse beginners if they’re not explained clearly.</p>
<p>This article is written for beginners and focuses on clarity and practical understanding of basic and simple lambdas, rather than diving deep into internal implementation details and optimizations. If you are already familiar with the basics and looking for more advanced reading on <a target="_blank" href="https://medium.com/@karim.m.fayed/real-world-aws-lambda-optimization-what-they-dont-teach-in-the-docs-b8c26fa3a371">l</a>ambda optimizations, <a target="_blank" href="https://medium.com/@karim.m.fayed/real-world-aws-lambda-optimization-what-they-dont-teach-in-the-docs-b8c26fa3a371">click here</a>.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:1400/1*O3hHLLA-R0C2kQhAIvbWbw.jpeg" alt /></p>
<p>For this guide, we’ll be discussing</p>
<ol>
<li><p>What Is AWS Lambda?</p>
</li>
<li><p>What Does <em>Serverless</em> Mean?</p>
</li>
<li><p>Why Use AWS Lambda?</p>
</li>
<li><p>Core Lambda Concepts</p>
</li>
<li><p>Lambda Execution Lifecycle</p>
</li>
<li><p>Creating Your First Lambda Function</p>
</li>
<li><p>How Pricing Works</p>
</li>
<li><p>Common Errors</p>
</li>
<li><p>Lambda Drawbacks &amp; Limitations</p>
</li>
</ol>
<h2 id="heading-what-is-aws-lambda"><strong>What Is AWS Lambda?</strong></h2>
<p>AWS Lambda is a compute service and a core building block of serverless architectures. Unlike traditional servers, it puts your code at the center of focus by allowing you to run it without provisioning or managing any servers.</p>
<p>You simply upload your code, define when it should run and AWS handles:</p>
<ul>
<li><p>Server provisioning</p>
</li>
<li><p>Scaling</p>
</li>
<li><p>Availability</p>
</li>
<li><p>Infrastructure maintenance</p>
</li>
</ul>
<p>In addition, you are charged <strong>only when your code runs.</strong></p>
<h2 id="heading-what-does-serverless-mean"><strong>What Does <em>Serverless</em> Mean?</strong></h2>
<p>Serverless doesn’t mean there are no servers.</p>
<p>It means:</p>
<ul>
<li><p>You don’t manage servers</p>
</li>
<li><p>You don’t worry about capacity</p>
</li>
<li><p>You don’t scale manually</p>
</li>
</ul>
<p>AWS owns the infrastructure; <strong>you own the code.</strong></p>
<h3 id="heading-traditional-vs-serverless"><strong>Traditional vs Serverless</strong></h3>
<p><strong>Traditional App</strong></p>
<p><img src="https://miro.medium.com/v2/resize:fit:1400/1*PFkba3uLjxP24mw7MVRcWg.png" alt /></p>
<p><strong>Serverless App</strong></p>
<p><img src="https://miro.medium.com/v2/resize:fit:1400/1*gytIB1oswPbclYNwnryruw.png" alt /></p>
<p>This shift allows teams to move faster and put more focus on business logic.</p>
<h2 id="heading-why-use-aws-lambda"><strong>Why Use AWS Lambda?</strong></h2>
<p>Lambda is ideal when you want to:</p>
<ul>
<li><p>Build quickly</p>
</li>
<li><p>Scale automatically</p>
</li>
<li><p>Reduce operational overhead</p>
</li>
<li><p>Pay only for usage</p>
</li>
</ul>
<h3 id="heading-common-use-cases"><strong>Common Use Cases</strong></h3>
<ul>
<li><p>APIs (With API Gateway)</p>
</li>
<li><p>File processing (S3 events)</p>
</li>
<li><p>Background jobs</p>
</li>
<li><p>Scheduled tasks (cron jobs)</p>
</li>
<li><p>Event-driven microservices</p>
</li>
</ul>
<h2 id="heading-core-lambda-concepts"><strong>Core Lambda Concepts</strong></h2>
<p>Before writing your code and using Lambda, you need to understand a few terminologies and fundamentals.</p>
<h3 id="heading-execution-role"><strong>Execution Role</strong></h3>
<p>An IAM role that defines <strong>what your Lambda is allowed to access</strong>.</p>
<h3 id="heading-function"><strong>Function</strong></h3>
<p>The unit of code you deploy and execute in AWS Lambda.</p>
<h3 id="heading-handler"><strong>Handler</strong></h3>
<p>The entry point AWS calls when the function runs.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> handler = <span class="hljs-keyword">async</span> (): <span class="hljs-built_in">Promise</span>&lt;<span class="hljs-built_in">string</span>&gt; =&gt; {
  <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello from Lambda"</span>;
};
</code></pre>
<h3 id="heading-event"><strong>Event</strong></h3>
<p>The input passed to your function to trigger it (HTTP request, S3 event, message, etc.).</p>
<h3 id="heading-trigger"><strong>Trigger</strong></h3>
<p>The AWS service that invokes your function.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:1400/1*KNLk2dh2hGv5VwQjod0B0A.png" alt /></p>
<h2 id="heading-lambda-execution-lifecycle"><strong>Lambda Execution Lifecycle</strong></h2>
<p>Understanding the lifecycle helps you avoid performance and cost issues.</p>
<h3 id="heading-1-cold-start"><strong>1. Cold Start</strong></h3>
<ul>
<li><p>AWS creates a new execution environment</p>
</li>
<li><p>Your code is loaded</p>
</li>
<li><p>Initialization code runs</p>
</li>
</ul>
<h3 id="heading-2-invocation"><strong>2. Invocation</strong></h3>
<ul>
<li><p>The handler function is executed</p>
</li>
<li><p>Your logic processes the event</p>
</li>
</ul>
<h3 id="heading-3-warm-start"><strong>3. Warm Start</strong></h3>
<ul>
<li><p>The environment may be reused if the Lambda finishes execution and hasn’t expired yet (still within its TTL).</p>
</li>
<li><p>Execution is much faster</p>
</li>
</ul>
<p>Code outside the handler runs <strong>once per environment</strong>, not per request.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:1400/1*Cdy1mSYJkhzG_nZ5d3tLJQ.png" alt /></p>
<h2 id="heading-creating-your-first-lambda-function"><strong>Creating Your First Lambda Function</strong></h2>
<p>At a high level:</p>
<ol>
<li><p>Open the AWS Lambda console</p>
</li>
<li><p>Create a new function</p>
</li>
<li><p>Choose a runtime (Node.js, Python, Java, Go, etc.)</p>
</li>
<li><p>Write or upload your code</p>
</li>
<li><p>Configure permissions</p>
</li>
<li><p>Add a trigger</p>
</li>
</ol>
<h3 id="heading-simple-example-nodejs"><strong>Simple Example (Node.js)</strong></h3>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { APIGatewayProxyEvent} <span class="hljs-keyword">from</span> <span class="hljs-string">"aws-lambda"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> handler = <span class="hljs-keyword">async</span> (event: APIGatewayProxyEvent): <span class="hljs-built_in">Promise</span>&lt;APIGatewayProxyResult&gt; =&gt; {
  <span class="hljs-keyword">return</span> {
    statusCode: <span class="hljs-number">200</span>,
    body: <span class="hljs-built_in">JSON</span>.stringify({
      message: <span class="hljs-string">"Hello from AWS Lambda 🚀"</span>,
    }),
  };
};
</code></pre>
<p>Once deployed, this function can be invoked via an API or event.</p>
<h2 id="heading-how-pricing-works"><strong>How Pricing Works</strong></h2>
<p>AWS Lambda pricing is based on actual usage, not idle time.</p>
<h3 id="heading-1-invocations"><strong>1. Invocations</strong></h3>
<p>You pay per function call.</p>
<h3 id="heading-2-execution-duration"><strong>2. Execution Duration</strong></h3>
<p>You pay for:</p>
<ul>
<li><p>Memory allocated</p>
</li>
<li><p>Execution time (milliseconds)</p>
</li>
</ul>
<p>Cost = Invocations + (Memory × Execution Time)</p>
<p>Important notes:</p>
<ul>
<li><p>More memory also means more CPU</p>
</li>
<li><p>Faster execution can <strong>reduce total cost</strong></p>
</li>
<li><p>Free tier covers many small projects</p>
</li>
</ul>
<h2 id="heading-common-errors"><strong>Common Errors</strong></h2>
<h3 id="heading-cannot-find-module"><strong>Cannot find module</strong></h3>
<p>I like to think of this as AWS Lambda’s <em>welcome message</em>—one of the first and most common errors you’ll hit as a new Lambda user. This typically occurs when:</p>
<ul>
<li><p>Dependencies weren’t included in the deployment package (<code>node_modules</code> <strong>missing or incomplete</strong>)</p>
</li>
<li><p>The build output is incorrect or <strong>bundled incorrectly</strong> for Lambda</p>
</li>
<li><p>Runtime versions don’t match</p>
</li>
<li><p>The module is <strong>not included in the deployment package</strong></p>
</li>
<li><p>The module name or import path is <strong>incorrect</strong></p>
</li>
</ul>
<blockquote>
<p><strong><em>Tip: Always inspect what gets deployed.</em></strong></p>
</blockquote>
<h3 id="heading-permission-errors-access-denied"><strong>Permission Errors (Access Denied)</strong></h3>
<p>Permission errors mainly occur when lambdas try to perform certain actions that extend to other services and are caused by:</p>
<ul>
<li><p>Missing IAM permissions</p>
</li>
<li><p>Incorrect execution role</p>
</li>
</ul>
<blockquote>
<p><strong><em>Note:</em></strong> <em>If Lambda can’t access a service, check IAM first.</em></p>
</blockquote>
<h3 id="heading-timeout-errors"><strong>Timeout Errors</strong></h3>
<p>Lambda has a configurable timeout. Long‑running tasks may require:</p>
<ul>
<li><p>Increasing timeout</p>
</li>
<li><p>Breaking work into smaller async tasks</p>
</li>
</ul>
<h2 id="heading-lambda-drawbacks-amp-limitations"><strong>Lambda Drawbacks &amp; Limitations</strong></h2>
<p>With all the amazing features that Lambda offers, unfortunately, like everything else, it is not all sunshine and rainbows. There are cons that you have to deal with when using lambda and understanding its limitations early will save you from painful refactors later.</p>
<h3 id="heading-cold-starts"><strong>Cold Starts</strong></h3>
<ul>
<li><p>Noticeable delay for user-facing APIs</p>
</li>
<li><p>Worse with heavy dependencies or VPC-enabled Lambdas</p>
</li>
</ul>
<p>Bad choice when building latency-sensitive APIs</p>
<p><strong>Alternative services:</strong> AWS App Runner, ECS / EC2</p>
<h3 id="heading-execution-time-limits"><strong>Execution Time Limits</strong></h3>
<p>Lambda functions have a <strong>maximum execution time (15 minutes)</strong>.</p>
<ul>
<li><p>Not suitable for long-running tasks</p>
</li>
<li><p>Jobs can’t “just keep running.”</p>
</li>
</ul>
<p>Bad for Background tasks that may run for hours (Video encoding or large file processing or Long ETL jobs)</p>
<p><strong>Alternative services:</strong> AWS Batch, Fargate, ECS / EC2</p>
<h3 id="heading-limited-local-state-amp-ephemeral-environment"><strong>Limited Local State &amp; Ephemeral Environment</strong></h3>
<p>Lambda execution environments are <strong>stateless by design</strong>.</p>
<p><strong>Why it matters:</strong></p>
<ul>
<li><p>You can’t rely on in-memory state between invocations</p>
</li>
<li><p>The filesystem is temporary</p>
</li>
</ul>
<p><strong>Alternative services:</strong> Use it with DynamoDB to persist state, ECS / EC2</p>
<h3 id="heading-debugging-amp-observability-can-be-tricky"><strong>Debugging &amp; Observability Can Be Tricky</strong></h3>
<p>Debugging distributed, event-driven systems is harder than debugging a single server.</p>
<p><strong>Common challenges:</strong></p>
<ul>
<li><p>Logs scattered across CloudWatch</p>
</li>
<li><p>Harder to reproduce issues locally</p>
</li>
<li><p>Tracing async flows requires extra tooling</p>
</li>
</ul>
<p><strong>The points above make Lambda a poor choice if:</strong></p>
<ul>
<li><p>Your app relies heavily on <strong>local caching</strong></p>
</li>
<li><p>You need <strong>session-based or sticky state</strong></p>
</li>
<li><p>You’re porting a legacy monolith that assumes persistent memory</p>
</li>
<li><p>Your team is new to cloud-native debugging</p>
</li>
</ul>
<p><strong>Alternative services:</strong> OpenTelemetry, ECS / EC2 for familiar debugging patterns and tooling</p>
<h2 id="heading-closing-thoughts"><strong>Closing Thoughts</strong></h2>
<p>AWS Lambda is a cornerstone of the AWS ecosystem. Once you understand its execution model and lifecycle, it becomes a powerful tool for building scalable, event-driven architectures while significantly reducing operational complexity. That said, it’s important to remember that Lambda is not a silver bullet and isn’t the right fit for every use case.</p>
<h2 id="heading-resources"><strong>Resources</strong></h2>
<ul>
<li><p><a target="_blank" href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtime-environment.html">https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtime-environment.html</a></p>
</li>
<li><p><a target="_blank" href="https://docs.aws.amazon.com/lambda/latest/dg/typescript-handler.html">https://docs.aws.amazon.com/lambda/latest/dg/typescript-handler.html</a></p>
</li>
<li><p><a target="_blank" href="https://aws.amazon.com/lambda/pricing/">https://aws.amazon.com/lambda/pricing/</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Empower Your Kids with Go Plus]]></title><description><![CDATA[There’s no better feeling than seeing your kids not only make a decision of their own but make the right one! As the importance of financial literacy increases more and more in this day and age, it only makes sense to give them the right tools to be ...]]></description><link>https://blog.klivvr.com/empower-your-kids-with-go-plus</link><guid isPermaLink="true">https://blog.klivvr.com/empower-your-kids-with-go-plus</guid><category><![CDATA[family banking]]></category><category><![CDATA[Go plus]]></category><category><![CDATA[family]]></category><category><![CDATA[Klivvr]]></category><category><![CDATA[KlivvvrGoPlus]]></category><dc:creator><![CDATA[Amira Gamil]]></dc:creator><pubDate>Mon, 18 Nov 2024 13:43:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748788362265/dd460b5b-20eb-4290-87f3-aae39932002e.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There’s no better feeling than seeing your kids not only make a decision of their own but make the right one! As the importance of financial literacy increases more and more in this day and age, it only makes sense to give them the right tools to be as prepared as possible. Grab your Klivvr card and let’s get started ✨</p>
<p>-Add Money in Seconds</p>
<p>The journey in financial literacy starts with just a tap. Add money through InstaPay, Fawry, or any card and start teaching them how to make essential purchases. Seeing money in action is the only way they can truly grasp its value. 💰</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731929657012/da52c871-365f-4ac9-a9aa-df14bb99d73a.jpeg" alt class="image--center mx-auto" /></p>
<p>-Give Them A Card</p>
<p>Don’t give us that worried look 👀 You can request up to 5 cards from a single primary account and watch the magic happen! Not only will this give them some financial autonomy, but you can also freeze their spending whenever it doesn’t stick to your budget! Two birds with one stone?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731929681805/f202e6b8-5220-49ed-b6fe-07dee497b2b9.jpeg" alt class="image--center mx-auto" /></p>
<p>-Watch them in Action</p>
<p>Instead of rushing to the cashier to buy their favorite goodies from Klivvr’s list of partners, let them do the work! Explain how to place the purchases, check the receipt's accuracy, and use their Klivvr card. What’s better than boosting their confidence while teaching them necessary social skills?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731929698473/2d81d9be-1df9-4645-a6fe-f645f4e83448.jpeg" alt class="image--center mx-auto" /></p>
<p>-Analyze Spending Together</p>
<p>After all that spending, it’s only time to reflect back on it! Analyze their monthly purchases and put them into perspective compared to your intended budget. This way, they can know what you expect from them and how to be financially responsible moving forward!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731929716943/509d100a-9dd9-48e8-8e70-92a772128dcb.jpeg" alt class="image--center mx-auto" /></p>
<p>-Let Them Withdraw Cash</p>
<p>Putting them in real-life situations, such as dealing with an ATM, builds key life skills that they will thank you for later! Guide them through the steps needed to withdraw cash so they can be comfortable with it as they grow.</p>
<p>This scratches the surface of all the ways Klivvr Go Plus can help empower your littles! Happy spending 💸</p>
]]></content:encoded></item><item><title><![CDATA[Family Spending 101: How to Use Go Plus Effectively]]></title><description><![CDATA[It’s easy to handle all the weight of financial planning, but why carry the burden when you can easily make it smoother? With Klivvr’s Go Plus plan, you have a constant companion helping you bring your budgeting efforts to light! Here are all the way...]]></description><link>https://blog.klivvr.com/family-spending-101-how-to-use-go-plus-effectively</link><guid isPermaLink="true">https://blog.klivvr.com/family-spending-101-how-to-use-go-plus-effectively</guid><category><![CDATA[Go plus]]></category><category><![CDATA[family]]></category><category><![CDATA[how-to]]></category><dc:creator><![CDATA[Amira Gamil]]></dc:creator><pubDate>Mon, 04 Nov 2024 11:58:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748788423607/bca64e24-5a0f-44e3-8d80-cac61e7e2a6d.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It’s easy to handle all the weight of financial planning, but why carry the burden when you can easily make it smoother? With Klivvr’s Go Plus plan, you have a constant companion helping you bring your budgeting efforts to light! Here are all the ways you can incorporate its different features to make it work best for your family:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://giphy.com/gifs/theoffice-Z06nUGW20bp3VkQSHF">https://giphy.com/gifs/theoffice-Z06nUGW20bp3VkQSHF</a></div>
<p> </p>
<p>-Check Money Transfer Options</p>
<p>Klivvr lets you add money to your card using Instapay, Fawry, or any bank card! Check which ones work best for your family and enjoy instant money transfer relief.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730717703432/23fccbe1-9cb0-4bb1-89f0-005c1c3a92a9.jpeg" alt class="image--center mx-auto" /></p>
<p>-Check Existing Partners</p>
<p>On your Klivvr application, you can see a list of 20+ partners across different categories, such as Lifestyle, Food and beverages, and more! Check which spots are your family’s favorites, and make sure to visit them with your Klivvr card to get a discount!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730717722088/ccb4a120-93b8-471c-a642-78a4b200f72b.jpeg" alt class="image--center mx-auto" /></p>
<p>-Request Multiple Cards</p>
<p>Are your kids always losing cash? Do you delay shopping until your partner comes home because you share a card? Well, it sounds like it is time to request an extra card! The Go Plus plan allows up to 5 cards from one single primary account.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730717747364/4dae1d9b-f8b7-400f-b0b0-5eec3a03b186.jpeg" alt class="image--center mx-auto" /></p>
<p>-Track their Spending!</p>
<p>If your family is always steering away from the budget, well, then it’s time for some interventions! Use the tracker on your Klivvr application and see for yourself what is going wrong and how you can fix it next month.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730717763201/9c16bf97-a544-4a82-9051-9a4b6f119cf8.jpeg" alt class="image--center mx-auto" /></p>
<p>-Stay in Control</p>
<p>We have all fallen prey to that mistake of forgetting our card with our kids, but Klivvr lets you freeze it instantly with a tap! Whenever their spending isn’t looking well or you lose that card for the hundredth time, just freeze it through your application and enjoy the peace of mind.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730717784543/a4870977-8967-45bd-959e-a8a20a002d5b.jpeg" alt class="image--center mx-auto" /></p>
<p>These are some of the ways that you can use Klivvr to be your newest financing best friend! Happy spending with your fam!</p>
]]></content:encoded></item><item><title><![CDATA[Streamlining Design-to-Development with Custom Tools]]></title><description><![CDATA[In the fast-paced world of software development, the journey from design to code is often fraught with challenges. Designers meticulously craft user interfaces, carefully selecting colors, typography, and spacing, yet translating these into code can ...]]></description><link>https://blog.klivvr.com/streamlining-design-to-development-with-custom-tools</link><guid isPermaLink="true">https://blog.klivvr.com/streamlining-design-to-development-with-custom-tools</guid><category><![CDATA[figma]]></category><category><![CDATA[workflow]]></category><category><![CDATA[Python]]></category><category><![CDATA[Design]]></category><category><![CDATA[development]]></category><category><![CDATA[iOS]]></category><dc:creator><![CDATA[Ahmed Ramzy]]></dc:creator><pubDate>Mon, 28 Oct 2024 11:04:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748788473299/cea8de99-324a-4b42-8e46-0c54a4980fd4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the fast-paced world of software development, the journey from design to code is often fraught with challenges. Designers meticulously craft user interfaces, carefully selecting colors, typography, and spacing, yet translating these into code can be time-consuming and error-prone. Our team, developed a custom Figma plugin and Python script, K-Design Wizard, to streamline the design-to-development workflow and harness the power of automation.</p>
<h2 id="heading-maintaining-consistency-with-the-design-system">Maintaining Consistency with the Design System</h2>
<p>K-Design Wizard simplifies the process of maintaining the design system, addressing small but crucial details like text sizes, letter spacing, and color opacity adjustments. Changes, such as letter spacing adjustments from 2.5% to 2% or color opacity tweaks by 0.2%, are seamlessly incorporated without designers or developers having to sift through the details. Designers simply run the plugin, applying the changes instantly. This direct approach helps our team avoid lengthy discussions on minor design tweaks and reduces the chance of manual errors.</p>
<h2 id="heading-the-challenge-bridging-design-and-development">The Challenge: Bridging Design and Development</h2>
<p>Designers work tirelessly in Figma to create pixel-perfect interfaces, but translating these designs into code often involves tedious, manual adjustments. Maintaining design consistency across platforms and screen sizes further complicates the process, as minor discrepancies, like a color or font size mismatch, can alter the intended user experience.</p>
<p>This is where our plugin shines, particularly when faced with maintaining the design system at scale. As our Product Designer, Marium Nour noted, even small updates should feel lightweight and non-intrusive for designers, allowing a natural design flow without a heavy, disruptive impact.</p>
<h2 id="heading-custom-figma-plugin-exporting-design-tokens">Custom Figma Plugin: Exporting Design Tokens</h2>
<p>To address these challenges, we developed a custom Figma plugin that exports design tokens. Design tokens are the atomic elements of a design system – colors, typography, spacing, and other visual properties that define the look and feel of an interface.</p>
<p>Our plugin extracts this crucial information directly from Figma, ensuring that every design decision is captured accurately. It generates JSON files containing:</p>
<ul>
<li><p>Color palettes for both light and dark modes</p>
</li>
<li><p>Typography styles, including font sizes, line heights, and weights</p>
</li>
<li><p>Measurements for spacing and component sizes</p>
</li>
</ul>
<p>Here's a snippet of what the exported JSON might look like for color tokens:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"color"</span>: {
    <span class="hljs-attr">"primary"</span>: {
      <span class="hljs-attr">"base"</span>: { <span class="hljs-attr">"$value"</span>: <span class="hljs-string">"#0077C2"</span> },
      <span class="hljs-attr">"light"</span>: { <span class="hljs-attr">"$value"</span>: <span class="hljs-string">"#4DA3E5"</span> },
      <span class="hljs-attr">"dark"</span>: { <span class="hljs-attr">"$value"</span>: <span class="hljs-string">"#005691"</span> }
    },
    <span class="hljs-attr">"background"</span>: {
      <span class="hljs-attr">"light"</span>: { <span class="hljs-attr">"$value"</span>: <span class="hljs-string">"#FFFFFF"</span> },
      <span class="hljs-attr">"dark"</span>: { <span class="hljs-attr">"$value"</span>: <span class="hljs-string">"#121212"</span> }
    }
  }
}
</code></pre>
<p>By using design tokens, we create a single source of truth that both designers and developers can reference. This approach not only improves consistency but also facilitates easier updates and maintenance of the design system.</p>
<h2 id="heading-k-design-wizard-automating-token-translation">K-Design Wizard: Automating Token Translation</h2>
<p>While exporting design tokens improves design consistency, K-Design Wizard, our Python script, takes it a step further by transforming these JSON files into ready-to-use Swift code. This step eliminates the need for manual code writing, reducing the chance of human error and enhancing the speed of design implementation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730036051066/c4d5b21c-d0f0-42be-af10-1db92ba09638.png" alt class="image--center mx-auto" /></p>
<p>Key features of K-Design Wizard include:</p>
<ol>
<li><p>Generating Swift enums for colors, measurements, and typography styles</p>
</li>
<li><p>Creating GitHub pull requests to update the codebase automatically</p>
</li>
<li><p>Handling both light and dark mode color schemes</p>
</li>
<li><p>Supporting multiple languages for typography (e.g., English and Arabic)</p>
</li>
</ol>
<p>Here's a simplified example of how K-Design Wizard might generate a Swift enum for colors:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">LightColors</span> </span>{
    <span class="hljs-keyword">case</span> primaryBase
    <span class="hljs-keyword">case</span> primaryLight
    <span class="hljs-keyword">case</span> primaryDark
    <span class="hljs-keyword">case</span> backgroundLight
    <span class="hljs-keyword">case</span> backgroundDark

    <span class="hljs-keyword">var</span> value: <span class="hljs-type">String</span> {
        <span class="hljs-keyword">switch</span> <span class="hljs-keyword">self</span> {
        <span class="hljs-keyword">case</span> .primaryBase: <span class="hljs-keyword">return</span> <span class="hljs-string">"#0077C2"</span>
        <span class="hljs-keyword">case</span> .primaryLight: <span class="hljs-keyword">return</span> <span class="hljs-string">"#4DA3E5"</span>
        <span class="hljs-keyword">case</span> .primaryDark: <span class="hljs-keyword">return</span> <span class="hljs-string">"#005691"</span>
        <span class="hljs-keyword">case</span> .backgroundLight: <span class="hljs-keyword">return</span> <span class="hljs-string">"#FFFFFF"</span>
        <span class="hljs-keyword">case</span> .backgroundDark: <span class="hljs-keyword">return</span> <span class="hljs-string">"#121212"</span>
        }
    }
}
</code></pre>
<p>This script eliminates the need for manual code writing, reducing the chance of human error and significantly speeding up the process of implementing design changes.</p>
<h2 id="heading-the-automated-workflow">The Automated Workflow</h2>
<p>With our custom tools in place, the design-to-development workflow becomes a streamlined process:</p>
<ol>
<li><p>Designers make changes in Figma</p>
</li>
<li><p>The custom Figma plugin exports updated design tokens as JSON files</p>
</li>
<li><p>K-Design Wizard processes these JSON files, generating Swift code</p>
</li>
<li><p>The script creates a GitHub pull request with the updated code</p>
</li>
<li><p>Developers review and merge the changes</p>
</li>
</ol>
<p>This automated workflow ensures that design changes are reflected in the codebase quickly and accurately, without manual intervention.</p>
<h2 id="heading-benefits-of-automation">Benefits of Automation</h2>
<p>The advantages of this automated approach are numerous:</p>
<ol>
<li><p><strong>Time Savings</strong>: What once took hours of manual work now happens in minutes.</p>
</li>
<li><p><strong>Reduced Human Error</strong>: Automated code generation eliminates typos and misinterpretations.</p>
</li>
<li><p><strong>Improved Consistency</strong>: Design tokens ensure that the same values are used throughout the application.</p>
</li>
<li><p><strong>Faster Iteration Cycles</strong>: Quick implementation of design changes allows for more rapid prototyping and refinement.</p>
</li>
<li><p><strong>Better Collaboration</strong>: Designers can see their changes reflected in code almost immediately, fostering better understanding between design and development teams.</p>
</li>
</ol>
<h2 id="heading-implementation-and-integration">Implementation and Integration</h2>
<p>To implement this workflow in your own projects:</p>
<ol>
<li><p>Install the custom Figma plugin in your Figma workspace.</p>
</li>
<li><p>Set up K-Design Wizard on your local machine or CI/CD pipeline:</p>
<ul>
<li><p>Ensure Python is installed</p>
</li>
<li><p>Install required dependencies (<code>pip install PyGithub</code>)</p>
</li>
<li><p>Configure GitHub access token for PR creation</p>
</li>
</ul>
</li>
<li><p>Establish a process for running the script when design tokens are updated</p>
</li>
<li><p>Train your team on the new workflow and tools</p>
</li>
</ol>
<p>Here's a simplified snippet of how you might use the generated Swift code in your iOS app:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> SwiftUI

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">ContentView</span>: <span class="hljs-title">View</span> </span>{
    <span class="hljs-keyword">var</span> body: some <span class="hljs-type">View</span> {
        <span class="hljs-type">Text</span>(<span class="hljs-string">"Hello, World!"</span>)
            .foregroundColor(<span class="hljs-type">Color</span>(colorString: <span class="hljs-type">LightColors</span>.primaryBase.value))
            .padding(<span class="hljs-type">Space</span>.medium.cgFloat)
            .background(<span class="hljs-type">Color</span>(colorString: <span class="hljs-type">LightColors</span>.backgroundLight.value))
    }
}
</code></pre>
<p>Remember, the key to successful adoption is clear communication and documentation. Make sure all team members understand the benefits and processes involved.</p>
<h2 id="heading-future-improvements-and-possibilities">Future Improvements and Possibilities</h2>
<p>While our current setup has greatly improved our workflow, there's always room for enhancement:</p>
<ul>
<li><p>Expand support for other programming languages (e.g., Kotlin for Android development)</p>
</li>
<li><p>Integrate with design systems to generate component code automatically</p>
</li>
<li><p>Develop a web interface for non-technical team members to trigger updates</p>
</li>
<li><p>Implement version control for design tokens to track changes over time</p>
</li>
</ul>
<p>The possibilities for further automating and optimizing the design-to-development process are endless. As we continue to refine our tools, we're excited to see how they will evolve to meet future challenges.</p>
<h2 id="heading-a-new-era-of-efficiency-in-design-and-development">A New Era of Efficiency in Design and Development</h2>
<p>By creating custom tools that bridge the gap between design and development, we've not only saved time and reduced errors but also fostered a more collaborative environment. Our Figma plugin and K-Design Wizard script demonstrate the power of automation in solving real-world development challenges.</p>
<p>We encourage all teams facing similar design-to-development hurdles to explore custom automation solutions. The initial investment in developing these tools pays off manifold in improved efficiency, consistency, and team satisfaction.</p>
<p>Remember, the goal is not just to make the process faster, but to create space for creativity and innovation. By automating the mundane, we free ourselves to focus on what truly matters – creating exceptional user experiences.</p>
]]></content:encoded></item><item><title><![CDATA[Comprehensive Guide to Glassmorphism in Jetpack Compose]]></title><description><![CDATA[Wondering how to add a sleek, modern glassmorphic effect to your Android app? Look no further! In this article, we'll embark on an exciting journey to implement the GlassmorphicLayer component in Jetpack Compose. Get ready, because we're about to tra...]]></description><link>https://blog.klivvr.com/comprehensive-guide-to-glassmorphism-in-jetpack-compose</link><guid isPermaLink="true">https://blog.klivvr.com/comprehensive-guide-to-glassmorphism-in-jetpack-compose</guid><category><![CDATA[glassmorphism]]></category><category><![CDATA[Klivvr]]></category><category><![CDATA[fintech]]></category><category><![CDATA[Android]]></category><category><![CDATA[Jetpack Compose]]></category><category><![CDATA[development]]></category><category><![CDATA[tech ]]></category><dc:creator><![CDATA[Muhammad Youssef]]></dc:creator><pubDate>Tue, 15 Oct 2024 11:14:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748788509313/efcd00b0-9501-4028-803f-294cc8cae275.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Wondering how to add a sleek, modern glassmorphic effect to your Android app? Look no further! In this article, we'll embark on an exciting journey to implement the GlassmorphicLayer component in Jetpack Compose. Get ready, because we're about to transform your UI from basic to sleek!</p>
<h2 id="heading-what-is-glassmorphism-and-why-should-you-care">What is Glassmorphism, and Why Should You Care?</h2>
<p>Before we dive into the code, let's talk about what glassmorphism is and why it's causing such a buzz in the design world. Glassmorphism is a design trend that creates a frosted glass effect in user interfaces. It typically involves:</p>
<ol>
<li><p>A semi-transparent background</p>
</li>
<li><p>A subtle blur effect</p>
</li>
<li><p>Light borders or shadows to create depth</p>
</li>
</ol>
<p>Glassmorphism can give your app a:</p>
<ul>
<li><p>Modern and sleek look</p>
</li>
<li><p>More depth and layered</p>
</li>
<li><p>Visually interesting without being overwhelming</p>
</li>
</ul>
<p>Plus, it's a great way to make your app stand out in a sea of flat designs!</p>
<h2 id="heading-setting-the-stage-the-glassmorphiclayer-component">Setting the Stage: The GlassmorphicLayer Component</h2>
<p>Now that we know what we're aiming for, let's introduce the star of our show: the GlassmorphicLayer component. This nifty piece of Jetpack Compose magic will allow us to create stunning glassmorphic effects with ease.</p>
<p>Here's a sneak peek at what we'll be working with:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">GlassmorphicLayer</span><span class="hljs-params">(
    modifier: <span class="hljs-type">Modifier</span> = Modifier,
    backgroundDimColor: <span class="hljs-type">Color</span> = Color.Transparent,
    transitionStiffness: <span class="hljs-type">Float</span> = Spring.StiffnessMediumLow,
    blurSourceView: <span class="hljs-type">View</span> = LocalView.current.rootView.findViewById(android.R.id.content)</span></span>,
    contentEnterAnimation: EnterTransition = getDefaultEnterAnimation(transitionStiffness),
    contentExitAnimation: ExitTransition = getDefaultExitAnimation(transitionStiffness),
    onDismissRequest: () -&gt; <span class="hljs-built_in">Unit</span>,
    content: <span class="hljs-meta">@Composable</span> BoxScope.() -&gt; <span class="hljs-built_in">Unit</span>,
) {
    <span class="hljs-comment">// The magic happens here!</span>
}
</code></pre>
<p>Don't worry if this looks intimidating – we'll break it down step by step!</p>
<h2 id="heading-the-journey-begins-understanding-the-components">The Journey Begins: Understanding the Components</h2>
<p>Our journey to glassmorphic greatness involves three main parts:</p>
<ol>
<li><p>The main GlassmorphicLayer component</p>
</li>
<li><p>A helper component called ScreenContentGlassmorphedLayer</p>
</li>
<li><p>A custom Modifier extension named <code>glassmorph()</code></p>
</li>
</ol>
<p>Let's explore each of these:</p>
<h3 id="heading-1-glassmorphiclayer-the-conductor-of-our-glassmorphic-orchestra">1. GlassmorphicLayer: The Conductor of Our Glassmorphic Orchestra</h3>
<p>This is the main component you'll use in your app. Think of it as the conductor of an orchestra, harmonizing all elements to achieve a cohesive glassmorphic effect.</p>
<p>Key responsibilities:</p>
<ul>
<li><p>Managing the visibility of the glass effect and content</p>
</li>
<li><p>Handling animations</p>
</li>
<li><p>Coordinating the blur effect</p>
</li>
</ul>
<h3 id="heading-2-screencontentglassmorphedlayer-the-background-artist">2. ScreenContentGlassmorphedLayer: The Background Artist</h3>
<p>This behind-the-scenes component creates the blurred background that gives our glassmorphic effect its signature look.</p>
<p>What it does:</p>
<ul>
<li><p>Captures a snapshot of your app's current view</p>
</li>
<li><p>Applies a blur effect to this snapshot</p>
</li>
<li><p>Displays the blurred image with smooth animations</p>
</li>
</ul>
<h3 id="heading-3-glassmorph-modifier-the-special-effects-wizard">3. <code>glassmorph()</code> Modifier: The Special Effects Wizard</h3>
<p>This custom Modifier extension is where the real magic happens. It applies the blur effect and handles the animations that make our glassmorphic layer come to life.</p>
<p>Its superpowers:</p>
<ul>
<li><p>Animating the blur radius</p>
</li>
<li><p>Controlling the visibility of the blur effect</p>
</li>
</ul>
<h2 id="heading-the-implementation-adventure-a-step-by-step-guide">The Implementation Adventure: A Step-by-Step Guide</h2>
<p>Now that we know the key players, let's walk through how to implement the GlassmorphicLayer in your app. Don't worry; we'll take it one step at a time!</p>
<h3 id="heading-step-1-set-up-your-project">Step 1: Set Up Your Project</h3>
<p>Ensure Jetpack Compose is set up in your Android project. If you haven't done this yet, check out the <a target="_blank" href="https://developer.android.com/jetpack/compose/setup">official Jetpack Compose documentation</a> for guidance.</p>
<h3 id="heading-step-2-import-the-glassmorphiclayer">Step 2: Import the GlassmorphicLayer</h3>
<p>Add this import statement at the top of your Kotlin file:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">import</span> com.design.components.GlassmorphicLayer
</code></pre>
<h3 id="heading-step-3-use-glassmorphiclayer-in-your-composable">Step 3: Use GlassmorphicLayer in Your Composable</h3>
<p>Here's a simple example of how to use the GlassmorphicLayer:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">MyGlassmorphicScreen</span><span class="hljs-params">()</span></span> {
    GlassmorphicLayer(
        backgroundDimColor = Color.Black.copy(alpha = <span class="hljs-number">0.5f</span>),
        onDismissRequest = { showGlass = <span class="hljs-literal">false</span> }
    ) {
        <span class="hljs-comment">// Content inside the glassmorphic layer</span>
        Text(
            text = <span class="hljs-string">"Glassmorphic Content"</span>,
            modifier = Modifier.align(Alignment.Center)
        )
    }
}
</code></pre>
<p>This example shows a glassmorphic layer on top of the current screen content with some text inside. Cool, right?</p>
<h2 id="heading-customization-making-it-your-own">Customization: Making It Your Own</h2>
<p>Now that we have our glassmorphic layer up and running, let's explore some ways to customize it and make it truly yours!</p>
<h3 id="heading-1-change-the-background-dim">1. Change the Background Dim</h3>
<p>Want to set the mood? Adjust the <code>backgroundDimColor</code>:</p>
<pre><code class="lang-kotlin">backgroundDimColor = Color.Blue.copy(alpha = <span class="hljs-number">0.3f</span>)
</code></pre>
<h3 id="heading-2-tweak-the-animation-speed">2. Tweak the Animation Speed</h3>
<p>Make it snappy or smooth by modifying <code>transitionStiffness</code>:</p>
<pre><code class="lang-kotlin">transitionStiffness = Spring.StiffnessHigh <span class="hljs-comment">// for faster animations</span>
</code></pre>
<h3 id="heading-3-create-custom-animations">3. Create Custom Animations</h3>
<p>Want your glassmorphic layer to make a grand entrance? Provide your own enter and exit animations:</p>
<pre><code class="lang-kotlin">contentEnterAnimation = slideInVertically() + fadeIn()
contentExitAnimation = slideOutVertically() + fadeOut()
</code></pre>
<h3 id="heading-4-blur-a-specific-view">4. Blur a Specific View</h3>
<p>Get focused by blurring a specific view instead of the whole screen:</p>
<pre><code class="lang-kotlin">blurSourceView = myCustomView
</code></pre>
<h2 id="heading-the-secret-sauce-implementing-the-blur-effect">The Secret Sauce: Implementing the Blur Effect</h2>
<p>Now, let's dive into the heart of our glassmorphic effect: the blur implementation. This is where things get really interesting!</p>
<h3 id="heading-blurring-across-android-versions">Blurring Across Android Versions</h3>
<p>One of the challenges in implementing a consistent glassmorphic effect is dealing with different Android versions. Our GlassmorphicLayer component handles this elegantly:</p>
<ul>
<li><p>On Android 12 and above: We use the blur modifier directly on the current view snapshot.</p>
</li>
<li><p>On lower Android versions: We apply the blurring on the snapshot bitmap itself.</p>
</li>
</ul>
<p>Let's break this down step by step:</p>
<h3 id="heading-step-1-capturing-the-view-as-a-bitmap">Step 1: Capturing the View as a Bitmap</h3>
<p>First, we need to capture our current view as a bitmap. Here's how we do it:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> View.<span class="hljs-title">captureViewAsBitmap</span><span class="hljs-params">(callback: (<span class="hljs-type">Bitmap</span>?) -&gt; <span class="hljs-type">Unit</span>)</span></span> {
    <span class="hljs-keyword">val</span> window = context.findActivity()?.window
    <span class="hljs-keyword">if</span> (window == <span class="hljs-literal">null</span>) {
        callback(<span class="hljs-literal">null</span>)
    } <span class="hljs-keyword">else</span> {
        captureViewAsBitmap(window, callback)
    }
}

<span class="hljs-function"><span class="hljs-keyword">fun</span> View.<span class="hljs-title">captureViewAsBitmap</span><span class="hljs-params">(
    window: <span class="hljs-type">Window</span>,
    callback: (<span class="hljs-type">Bitmap</span>?) -&gt; <span class="hljs-type">Unit</span>,
)</span></span> {
    <span class="hljs-keyword">val</span> bitmap =
        Bitmap.createBitmap(
            <span class="hljs-comment">// The width of the view to be captured</span>
            width,
            <span class="hljs-comment">// The height of the view to be captured</span>
            height,
            <span class="hljs-comment">// The bitmap configuration (32-bit color with alpha)</span>
            Bitmap.Config.ARGB_8888,
        )
    <span class="hljs-keyword">val</span> location = IntArray(<span class="hljs-number">2</span>)
    <span class="hljs-comment">// Gets the location of the view within the window</span>
    getLocationInWindow(location)
    <span class="hljs-keyword">val</span> bounds =
        Rect(
            location[<span class="hljs-number">0</span>], <span class="hljs-comment">// Left bound</span>
            location[<span class="hljs-number">1</span>], <span class="hljs-comment">// Top bound</span>
            location[<span class="hljs-number">0</span>] + width, <span class="hljs-comment">// Right bound</span>
            location[<span class="hljs-number">1</span>] + height, <span class="hljs-comment">// Bottom bound</span>
        )
    runCatching {
        PixelCopy.request(
            window,
            bounds,
            bitmap,
            {
                <span class="hljs-keyword">when</span> (it) {
                    <span class="hljs-comment">// Capture succeeded</span>
                    PixelCopy.SUCCESS -&gt; callback(bitmap)
                    <span class="hljs-comment">// Capture failed</span>
                    <span class="hljs-keyword">else</span> -&gt; callback(<span class="hljs-literal">null</span>)
                }
            },
            <span class="hljs-comment">// Ensures the callback is handled on the main thread</span>
            Handler(Looper.getMainLooper()),
        )
    }.onFailure {
        <span class="hljs-comment">// Fallback to return null in case of failure</span>
        callback(<span class="hljs-literal">null</span>)
    }
}
</code></pre>
<p>This function uses a neat trick to find the associated Activity and its window, then captures the view's content as a bitmap.</p>
<h3 id="heading-step-2-applying-the-blur-effect">Step 2: Applying the Blur Effect</h3>
<p>Now comes the magic part - applying the blur effect. For Android versions below 12, we use a custom blur function:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> Bitmap.<span class="hljs-title">blur</span><span class="hljs-params">(context: <span class="hljs-type">Context</span>, radius: <span class="hljs-type">Float</span> = <span class="hljs-number">25</span>F)</span></span>: Bitmap {
    <span class="hljs-comment">// Ensure the blur radius is within the valid range (1 to 25)</span>
    <span class="hljs-keyword">val</span> radiusResolved = radius.coerceIn(<span class="hljs-number">1f</span>, <span class="hljs-number">25f</span>)

    <span class="hljs-comment">// Scale down the bitmap for better performance</span>
    <span class="hljs-keyword">val</span> blurScale = <span class="hljs-number">0.1F</span>
    <span class="hljs-keyword">val</span> blurWidth = (width * blurScale).roundToInt()
    <span class="hljs-keyword">val</span> blurHeight = (height * blurScale).roundToInt()
    <span class="hljs-keyword">val</span> inputBitmap = Bitmap.createScaledBitmap(<span class="hljs-keyword">this</span>, blurWidth, blurHeight, <span class="hljs-literal">false</span>)

    <span class="hljs-comment">// Apply the blur using RenderScript</span>
    <span class="hljs-keyword">val</span> renderScript = RenderScript.create(context)
    <span class="hljs-keyword">val</span> intrinsic = ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript))
    <span class="hljs-keyword">val</span> allocationInput = Allocation.createFromBitmap(renderScript, inputBitmap)
    <span class="hljs-keyword">val</span> allocationOutput = Allocation.createFromBitmap(renderScript, inputBitmap)

    intrinsic.setRadius(radiusResolved)
    intrinsic.setInput(allocationInput)
    intrinsic.forEach(allocationOutput)

    allocationOutput.copyTo(inputBitmap)

    <span class="hljs-comment">// Scale the bitmap back up to the original size</span>
    <span class="hljs-keyword">return</span> Bitmap.createScaledBitmap(inputBitmap, width, height, <span class="hljs-literal">false</span>)
}
</code></pre>
<p>This function does a few cool things:</p>
<ol>
<li><p>It scales down the bitmap for better performance.</p>
</li>
<li><p>Applies the blur using RenderScript (a high-performance runtime that provides computationally intensive operations).</p>
</li>
<li><p>Scales the bitmap back up to its original size.</p>
</li>
</ol>
<h3 id="heading-the-glassmorphic-magic-revealed">The Glassmorphic Magic Revealed</h3>
<p>Now, let's see how we tie this all together in our <code>glassmorph</code> modifier:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Composable</span>
<span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> Modifier.<span class="hljs-title">glassmorph</span><span class="hljs-params">(
    transitionStiffness: <span class="hljs-type">Float</span>,
    visibilityState: <span class="hljs-type">State</span>&lt;<span class="hljs-type">Boolean</span>&gt;,
)</span></span>: Modifier {
    <span class="hljs-keyword">val</span> blur <span class="hljs-keyword">by</span> animateDpAsState(
        targetValue = <span class="hljs-keyword">if</span> (visibilityState.value) <span class="hljs-number">60</span>.dp <span class="hljs-keyword">else</span> <span class="hljs-number">0</span>.dp,
        animationSpec = spring(stiffness = transitionStiffness),
        label = <span class="hljs-string">"glassmorphic effect"</span>,
    )
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.blur(
        radius = blur,
    )
}
</code></pre>
<p>This modifier does something really clever:</p>
<ul>
<li><p>For Android 12 and above, it uses the built-in blur modifier.</p>
</li>
<li><p>For older versions, it captures the view as a bitmap, applies our custom blur function, and then draws the blurred bitmap on top of the original content.</p>
</li>
</ul>
<h2 id="heading-why-this-approach-rocks">Why This Approach Rocks</h2>
<ol>
<li><p><strong>Compatibility</strong>: It works across different Android versions, ensuring a consistent look for all users.</p>
</li>
<li><p><strong>Performance</strong>: By scaling down the bitmap before blurring, we keep things smooth and snappy.</p>
</li>
<li><p><strong>Customizability</strong>: The blur radius is animated, allowing for smooth transitions.</p>
</li>
</ol>
<h2 id="heading-putting-it-all-together">Putting It All Together</h2>
<p>When you use the GlassmorphicLayer in your app, all this complexity is handled for you behind the scenes. You get a beautiful, performant glassmorphic effect without having to worry about the nitty-gritty details of bitmap manipulation or version-specific implementations.</p>
<h2 id="heading-challenges-along-the-way-and-how-to-overcome-them">Challenges Along the Way (and How to Overcome Them)</h2>
<p>As with any journey, you might encounter some bumps in the road. Here are some common challenges and how to overcome them:</p>
<h3 id="heading-1-performance-issues">1. Performance Issues</h3>
<p><strong>Challenge</strong>: The blur effect might be slow on older devices.</p>
<p><strong>Solution</strong>: Use a lower blur radius or disable the effect for low-end devices.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> blurRadius = <span class="hljs-keyword">if</span> (isLowEndDevice()) <span class="hljs-number">0</span>.dp <span class="hljs-keyword">else</span> <span class="hljs-number">10</span>.dp
</code></pre>
<h3 id="heading-2-content-visibility">2. Content Visibility</h3>
<p><strong>Challenge</strong>: Text might be hard to read on the blurred background.</p>
<p><strong>Solution</strong>: Add a semi-opaque background to your content or increase text contrast.</p>
<pre><code class="lang-kotlin">Text(
    <span class="hljs-string">"Glassmorphic Content"</span>,
    modifier = Modifier
        .background(Color.White.copy(alpha = <span class="hljs-number">0.7f</span>))
        .padding(<span class="hljs-number">16</span>.dp),
    color = Color.Black
)
</code></pre>
<h3 id="heading-3-inconsistent-look">3. Inconsistent Look</h3>
<p><strong>Challenge</strong>: The effect looks different on various devices.</p>
<p><strong>Solution</strong>: Test across devices and adjust blur/transparency for consistency.</p>
<h2 id="heading-best-practices-for-your-glassmorphic-journey">Best Practices for Your Glassmorphic Journey</h2>
<p>As you continue to explore and implement glassmorphic effects in your app, keep these best practices in mind:</p>
<ol>
<li><p><strong>Start Simple</strong>: Begin with the basic implementation before adding complex customizations.</p>
</li>
<li><p><strong>Test Frequently</strong>: Check your UI on different devices and screen sizes.</p>
</li>
<li><p><strong>Performance Matters</strong>: Be mindful of performance, especially on lower-end devices.</p>
</li>
<li><p><strong>Accessibility</strong>: Ensure your glassmorphic UI is accessible to all users.</p>
</li>
<li><p><strong>Consistent Design</strong>: Use the effect consistently throughout your app for a cohesive look.</p>
</li>
</ol>
<h2 id="heading-wrapping-up-your-glassmorphic-adventure-awaits">Wrapping Up: Your Glassmorphic Adventure Awaits!</h2>
<p>Congratulations! You've now embarked on the exciting journey of implementing the GlassmorphicLayer in Jetpack Compose. With this powerful tool in your arsenal, you're ready to create stunning, modern UIs that will captivate your users.</p>
<p>Remember, the key to mastering any new technique is practice. So go forth and experiment! Try implementing the GlassmorphicLayer in different parts of your app, play with customizations, and most importantly, have fun with it!</p>
<p>Who knows? Your next app could be the standout with its sleek glassmorphic UI. Happy coding, and may your interfaces always be as smooth as frosted glass!</p>
<p>👉 See full implementation</p>
]]></content:encoded></item><item><title><![CDATA[Swift Macro]]></title><description><![CDATA[With the release of Swift 5.9, Apple introduced a new feature called Macros. Macros allow you to generate code at compile time, helping you avoid repetitive code. The code is generated before your project is built, which may raise concerns about debu...]]></description><link>https://blog.klivvr.com/swift-macro</link><guid isPermaLink="true">https://blog.klivvr.com/swift-macro</guid><category><![CDATA[iOS]]></category><category><![CDATA[Swift]]></category><category><![CDATA[Developer]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[software development]]></category><category><![CDATA[fintech]]></category><category><![CDATA[Klivvr]]></category><dc:creator><![CDATA[Omar Elsayed]]></dc:creator><pubDate>Tue, 01 Oct 2024 09:53:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748788540920/a2f2a774-70a0-4489-81a9-6d72e7ce9174.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>With the release of Swift 5.9, Apple introduced a new feature called Macros. Macros allow you to generate code at compile time, helping you avoid repetitive code. The code is generated before your project is built, which may raise concerns about debugging. However, both the input and output (the code generated by the macro) are checked to ensure they are syntactically valid Swift code.</p>
<p>In the upcoming sections, we will discuss the different types of Macros, provide an example of how to implement your first Macro, explore cases where Macros can enhance our code, and demonstrate how we used them at Klivvr to eliminate boilerplate code.</p>
<h1 id="heading-types-of-macros">Types of Macros</h1>
<ul>
<li><p><strong>Freestanding Macros:</strong> Appear on their own without being attached to any declaration and start with <code>#</code>, such as <code>#Error()</code> and <code>#warning()</code>.</p>
</li>
<li><p><strong>Attached Macros:</strong> Modify the declaration they are attached to, using the <code>@</code> symbol before the name of the Macro.</p>
</li>
</ul>
<h2 id="heading-freestanding-macros">Freestanding Macros</h2>
<p>There are two types of freestanding Macros:</p>
<ul>
<li><p><strong>Expression Freestanding Macro:</strong> Used to create a piece of code that returns a value.</p>
</li>
<li><p><strong>Declaration Freestanding Macro:</strong> Used to create a new declaration.</p>
</li>
</ul>
<h2 id="heading-attached-macros">Attached Macros</h2>
<p>There are five types of attached Macros:</p>
<ul>
<li><p><strong>Attached Peer:</strong> Adds a new declaration alongside the declaration it’s applied to.</p>
</li>
<li><p><strong>Attached Accessor:</strong> Adds accessors (like <code>willSet</code>, <code>didSet</code>, <code>get</code>, <code>set</code>) to the property it’s applied to.</p>
</li>
<li><p><strong>Attached Member Attribute:</strong> Adds attributes to the declarations in the type or extension it’s applied to.</p>
</li>
<li><p><strong>Attached Member:</strong> Adds a new declaration in the type or extension it’s applied to.</p>
</li>
<li><p><strong>Attached Conformance:</strong> Adds conformances to the type or extension it’s applied to.</p>
</li>
</ul>
<p>Now that we’ve explored the available types of Macros, let’s dive into creating a Macro and how it can enhance our codebase.</p>
<h1 id="heading-macro-implementation-example">Macro Implementation Example</h1>
<p>In this section we will explore how to create a Macro that generates a non-optional url from a string. The problem is that we need to check the url value using a guard statement every time we create a url from a string, like so:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727567129007/53966d5f-baad-4d0b-8d47-61427df7524a.png" alt class="image--center mx-auto" /></p>
<p>So we need to avoid this boilerplate code, plus the <code>URL(string: )</code> will always generate a value—the only case where it will generate nil is if the string is empty. We can go one step further by making the macro generates a compile time error if the given string doesn’t follow a certain formate, this will give us the ability to check all the <code>URL</code> in our code during compile time.</p>
<ol>
<li><h2 id="heading-create-a-spm">Create a SPM</h2>
</li>
</ol>
<p>The first step is to open Xcode 😂, then go to <em>file &gt; new &gt; package</em>. Then you will have a pop up like so:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727567148956/3b7970bf-2368-423c-b37f-74466b179e74.png" alt class="image--center mx-auto" /></p>
<p>You will choose Swift Macro and this will open a new Swift Package Manger (SPM) that contains a simple macro implementation called <code>stringify</code>.</p>
<p><strong>Note:</strong> To create a macro, it must be contained in SPM. You can add as many macros as you need in the same SPM. Probably by now you have noticed that the SPM you have created depends on <a target="_blank" href="https://github.com/swiftlang/swift-syntax">swift-syntax</a>, this is the only requirement to create swift macro.</p>
<p>You will end up having something like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727567184446/be4677ab-2295-44ab-863e-bba64e9950ea.png" alt class="image--center mx-auto" /></p>
<ol start="2">
<li><h2 id="heading-declare-a-macro">Declare a Macro</h2>
</li>
</ol>
<p>To declare a macro, we need to specify the type. The goal is to be able to call this macro in any point in our code base without having to add it to a declaration. With that in mind, we will choose the freestanding type for the macro. Going a step further, we’ll need to specify which type of freestanding macro we are going to use. We need the output of the macro to be a <code>URL</code> and this output is not a new declaration so we will use the freestanding expression macro. To write that in code it will be as follows:</p>
<pre><code class="lang-swift">@freestanding(expression)
<span class="hljs-keyword">public</span> macro safeUrlFrom(<span class="hljs-number">_</span> urlString: <span class="hljs-type">String</span>) -&gt; <span class="hljs-type">URL</span> = 
#externalMacro(module: <span class="hljs-string">"MyMacroMacros"</span>, type: <span class="hljs-string">"URLMacro"</span>)
</code></pre>
<p>The notation <code>@freestanding(expression)</code> specifies the type of macro, then we add the <code>public</code> keyword to expose the macro for use outside the SPM. Then you use the <code>macro</code> keyword to declare a new macro then you write the name of the macro and the parameters for it and the return type of the macro. After the <code>=</code> sign you basically tell the compiler where is the implementation of the macro in the SPM using the <code>#externalMacro(module: "MyMacroMacros", type: "URLMacro")</code> , you give it the name of the module that contains the implementation of the macro and the name of type that contains the implementation. This is because the implementation of the macros are contained in <code>struct</code> . Now you have declared the macro in the next step we will see how it will be implemented.</p>
<p><strong>Note:</strong> The declaration of macro is in this file <code>MyMacro</code>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727567268956/8616f41f-232b-4814-a05e-8480fde2e849.png" alt class="image--center mx-auto" /></p>
<ol start="3">
<li><h2 id="heading-implementation-of-the-macro">Implementation of the Macro</h2>
</li>
</ol>
<p>So as we declared in the <code>#externalMacro(module: "MyMacroMacros", type: "URLMacro")</code> the implementation will be in the <code>MyMacroMacros</code> module, you will find a file that already exits in the module, navigate to this file and let’s implement our first macro.</p>
<p>First we will declare a <code>struct</code> called <code>URLMacro</code> as we wrote in the <code>#externalMacro</code> and we will make it conform to the <code>ExpressionMacro</code> protocol since we declared our macro as freestanding expression, it will look like that :</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727567327153/0fdec269-a4ea-43ea-a823-338311e6496c.png" alt class="image--center mx-auto" /></p>
<p>As you see this protocol have only one requirement which is the <code>expansion</code> method which will contains the implementation of the macro, this method is called when the macro is called.</p>
<p>Since our macro takes parameter as an input so we must first check if the arguments where passed and if they are the right type or not other wise we will throw a compile time error. it looks like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727567343590/b8cdc141-b111-448f-a501-01bc8e7cbad3.png" alt class="image--center mx-auto" /></p>
<p>All arguments passed to the macro are accessed through the <code>node.argumentList</code> this will gives us an array of the arguments passed to the macro since we only have one parameter we took only the first element, we made a guard statement to throw a compile time error if we found the first element to be nil (which means the arguments weren’t passed). The <code>argument</code> is of type <code>LabeledExprSyntax</code> which contains the passed value to the macro, if you tried to pass "<a target="_blank" href="http://www.klivvr.com/">www.klivvr.com</a>" as argument and tried to print the value it will look something like this in the console:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727567360127/de61c602-5af0-48a9-bcbc-b96097f58b6c.png" alt class="image--center mx-auto" /></p>
<p><strong>Note:</strong> We’ll get to the details of how we created the <code>URLMacroErrors</code> enum to throw compile time errors at the end of the article.</p>
<p>The second thing we need to do is to check if the type of the argument is of type <code>String</code>. In the swift-syntax package, string is represented by the <code>StringLiteralExprSyntax</code> so basically what we need to do is to type case the argument from <code>LabeledExprSyntax</code> to <code>StringLiteralExprSyntax</code>, if it succeed this means a <code>String</code> was passed, if not this means the argument is not a <code>String</code>. To do this we assed the <code>expression</code> property and casted it using the <code>as(StringLiteralExprSyntax.self)?</code> then we assed the <code>segments</code> which contains the string we want.</p>
<p>To be able to understand what I did next let me explain first what is the <code>StringLiteralExprSyntax</code>. This is basically the tree syntax representation of string type in the <a target="_blank" href="https://github.com/swiftlang/swift-syntax">https://github.com/swiftlang/swift-syntax</a> package, every root of the tree contains a property that represent something in the string type, to understand what I mean let’s print it and see what it looks like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727567377894/31b9e647-2015-4372-bcd2-015c53249ee8.png" alt class="image--center mx-auto" /></p>
<p>As you see this why we assed the <code>segments</code> property to get the string we want, but why it called <code>segments</code>? Because every space in the string is basically a separator between two segments, for example: “Omar is the best 😅😎” here we have 5 <code>segments</code> on the other hand something like "<a target="_blank" href="http://www.klivvr.com/">www.klivvr.com</a>" has only one segment. This is why the second condition in the guard is <code>case .stringSegment(let segment)? = segments.first</code>. This line takes the first element in the <code>segments</code> and makes sure it is equal to the <code>.stringSegment</code> case then we created the urlString from the <code>segment.content.text</code> like:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> urlString = segment.content.text
</code></pre>
<p>The third step we need to do is to check if the string is a valid url or not. If not, we will throw a compile time error, it will look something like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727567401122/948142b1-a894-4236-89c9-fd3248819c84.png" alt class="image--center mx-auto" /></p>
<p>We checked first if we can make a url from the <code>urlString</code> using the <code>URL(string: urlString)</code> then we checked if the url have a <code>host</code> and a <code>scheme</code> or url is a file url at this point we can say it is a valid url. After that we can return the url:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">return</span> <span class="hljs-string">"URL(string: \\(argument))!"</span>
</code></pre>
<p>This <code>ExprSyntax</code> is then converted by the compiler to <code>URL(string: \\(argument))!</code>. Before celebrating our first macro, let’s first see how I created the <code>URLMacroErrors</code> enum to throw compile time errors.</p>
<ol start="4">
<li><h2 id="heading-urlmacroerrors">URLMacroErrors</h2>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727567429050/e4a53c49-85e3-44c2-9a94-95f9110c4c44.png" alt class="image--center mx-auto" /></p>
<p>As you can see, the <code>URLMacroErrors</code> is an enum that conforms to two protocols <code>Errors</code> and the <code>CustomStringConvertible</code>. It has one requirement: the <code>description</code> property, which represents the message that will be represented with the compile time error.</p>
<p><strong>Alert:</strong> Don’t forget to add the type in <code>MyMacroPlugin</code> like so:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727567442201/066186d6-af7d-4c27-a666-63498af8ae48.png" alt class="image--center mx-auto" /></p>
<p>Final outcome is as follows:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727567465008/eda0853d-ebeb-47c7-a877-8a905b771af1.png" alt class="image--center mx-auto" /></p>
<p>The macro succeeded in the first one because we passed a valid url that contains a scheme and a host but for the second one we didn’t specify the scheme hence why it failed.</p>
<h2 id="heading-testing-your-macro">Testing your Macro</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727567479590/c8a9e579-8b1e-47c7-be56-3b737a943336.png" alt class="image--center mx-auto" /></p>
<p>The last step is to test our Macro. To test your macro, add a new key-value pair in the <code>testMacros</code>. The key represent the name of the macro, and the value represent the macro type. In this case, the value is <code>URLMacro.self</code>. Then you will call the <code>assertMacroExpansion</code> method in a test method. It takes two parameters, the <code>originalSource</code> which represent the calling of the macro, and the <code>expandedSource</code> which represents the expected output from the macro. If the actual output is equal, the expected output you wrote in the <code>assertMacroExpansion</code> test will pass, otherwise it will fail.</p>
<h1 id="heading-enhancing-code-efficiency-with-swift-macros">Enhancing Code Efficiency with Swift Macros</h1>
<p>Swift Macros are a powerful feature that enables you to write cleaner, more maintainable code by reducing boilerplate and enforcing compile-time checks. At Klivvr, we’ve started using Macros to streamline our code, and we encourage developers to explore this feature in their projects to enhance efficiency. Good luck as you dive into the world of Swift Macros! 🍀</p>
<h1 id="heading-resources">Resources</h1>
<p>Macro created: <a target="_blank" href="https://github.com/EngOmarElsayed/URLMacro.git">https://github.com/EngOmarElsayed/URLMacro.git</a></p>
<p>Macro examples:</p>
<p><a target="_blank" href="https://github.com/swiftlang/swift-syntax/tree/main/Examples/Tests/MacroExamples/Implementation">https://github.com/swiftlang/swift-syntax/tree/main/Examples/Tests/MacroExamples/Implementation</a></p>
<p>WWDC sessions:</p>
<p><a target="_blank" href="https://developer.apple.com/wwdc23/10166">https://developer.apple.com/wwdc23/10166</a></p>
<p><a target="_blank" href="https://developer.apple.com/wwdc23/10167">https://developer.apple.com/wwdc23/10167</a></p>
]]></content:encoded></item><item><title><![CDATA[Back To School Season: Top Spending Traps]]></title><description><![CDATA[The smell of new notebooks is waking us up from miles away with hints of that September breeze keeping us on our toes. There’s no escape, back to school season is here! Here’s a list of top spending mistakes you should avoid as you prep for this acad...]]></description><link>https://blog.klivvr.com/back-to-school-season-top-spending-traps</link><guid isPermaLink="true">https://blog.klivvr.com/back-to-school-season-top-spending-traps</guid><category><![CDATA[Back to basics]]></category><category><![CDATA[back to school essentials]]></category><category><![CDATA[Klivvr]]></category><category><![CDATA[KlivvvrGoPlus]]></category><dc:creator><![CDATA[Amira Gamil]]></dc:creator><pubDate>Wed, 25 Sep 2024 13:26:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748788579912/a9cb33b7-fff4-4723-b7e0-7088f3b11060.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The smell of new notebooks is waking us up from miles away with hints of that September breeze keeping us on our toes. There’s no escape, back to school season is here! Here’s a list of top spending mistakes you should avoid as you prep for this academic year!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://giphy.com/gifs/showtime-l41YaVemSbdw1yTTi">https://giphy.com/gifs/showtime-l41YaVemSbdw1yTTi</a></div>
<p> </p>
<p>Too Many Supplies:</p>
<p>Schools have this habit of sending unnecessarily long lists of required supplies, even though we all know our kids won’t be needing 50 bottles of acrylic paint of different shades or 3 sets of watercolor brushes. Go through all the from last year and cross them off your list! Be realistic with what your kid <em>actually</em> needs and avoid just-in-case purchases.</p>
<p>Uniform Dilemma:</p>
<p>They grow up so fast, don’t they? No, literally! Size up for all their school uniforms so you don’t need to buy the exact same thing each year for double the price!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://giphy.com/gifs/peteandpete-episode-1-the-adventures-of-pete-and-l3fZWk5fzCU1Juu7m">https://giphy.com/gifs/peteandpete-episode-1-the-adventures-of-pete-and-l3fZWk5fzCU1Juu7m</a></div>
<p> </p>
<p>Last Minute:</p>
<p>Well, waiting till the day before they go back is the perfect move if you want to break the bank. Shop a little bit earlier before prices go crazy! It will also help you avoid the crowd and find everything you need smoothly.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://giphy.com/gifs/target-bullseye-targetstyle-26xBDL9X2vhjHYVRm">https://giphy.com/gifs/target-bullseye-targetstyle-26xBDL9X2vhjHYVRm</a></div>
<p> </p>
<p>Impulsive Buying:</p>
<p>Back to school shopping is the closest thing to the Hunger Games. We need to find the best quality at the best prices. And what does this need? Hunting! Look for different offers and don’t just buy from the first shop you pop into!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://giphy.com/gifs/cruelsummer-ff-freeform-cruel-summer-Gut691HxDXgIUoUEGu">https://giphy.com/gifs/cruelsummer-ff-freeform-cruel-summer-Gut691HxDXgIUoUEGu</a></div>
<p> </p>
<p>Well, this just scratches the surface of what goes down before school starts! Happy shopping with your littles!</p>
]]></content:encoded></item><item><title><![CDATA[A Comprehensive Guide to Implementing a Design System in Jetpack Compose]]></title><description><![CDATA[At Klivvr, our design system is the unsung hero that powers our digital experience from the seamless transactions on your mobile app to the intuitive interface that guides your financial journey. Think of it as the DNA of our product design—coding th...]]></description><link>https://blog.klivvr.com/a-comprehensive-guide-to-implementing-a-design-system-in-jetpack-compose</link><guid isPermaLink="true">https://blog.klivvr.com/a-comprehensive-guide-to-implementing-a-design-system-in-jetpack-compose</guid><category><![CDATA[Design Systems]]></category><category><![CDATA[Jetpack Compose]]></category><category><![CDATA[Android]]></category><category><![CDATA[Design]]></category><category><![CDATA[Klivvr]]></category><dc:creator><![CDATA[Muhammad Youssef]]></dc:creator><pubDate>Mon, 16 Sep 2024 08:32:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748788641628/63eb1c98-e2fa-4b16-97e7-af0f500db962.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>At Klivvr, our design system is the unsung hero that powers our digital experience from the seamless transactions on your mobile app to the intuitive interface that guides your financial journey. Think of it as the DNA of our product design—coding the visual and interactive elements that make Klivvr feel effortlessly smooth and reliable. Colors, icons, and buttons all play their part, creating a user experience so cohesive and polished that you don’t even have to think about it.</p>
<p>Without a design system, you’re navigating a risky terrain—where each inconsistency could lead to confusion, weaken our brand identity, or leave users frustrated. In this article, we’ll unpack the essentials of design systems, delve into why they’re crucial to Klivvr’s success, and show you how to build one that not only elevates our digital presence but also shields it from design disarray.</p>
<p>We’ll also explore how design systems can revolutionize your approach to Android app design and guide you through implementing them in Jetpack Compose, making Klivvr’s user experience even more seamless and engaging.</p>
<h1 id="heading-what-is-a-design-system">What is a Design System?</h1>
<p>At its core, a design system is a collection of standardized building blocks and guidelines that ensure consistency across products and experiences. For us, it’s like having a blueprint that offers a unified language and structured framework, guiding our teams through the complex process of crafting digital financial solutions. This approach streamlines the design and development process, minimizing the need to reinvent elements and patterns, which saves valuable time and effort as we build and scale our products and interfaces.</p>
<h1 id="heading-components-of-a-design-system">Components of a Design System</h1>
<p>You can visualize the hierarchy in design systems like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724145727466/129e13d0-5c91-4367-8d03-2f9ea4601ae1.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-1-foundation">1) Foundation</h3>
<p>These are the building blocks that establish your product’s visual language, defining its look and feel through elements like color and typography. They also include icons, logos, illustrations, and crucial guidelines for accessibility and brand consistency, ensuring that everything from voice to tone aligns with your product’s identity.</p>
<h3 id="heading-2-components">2) Components</h3>
<p>Here, you’ll discover reusable visual elements and interaction patterns that shape your product’s common interface and behavior. This includes templates, layouts, interaction patterns, code snippets, and components—each backed by detailed documentation to ensure consistency and efficiency throughout the design and development process.</p>
<h3 id="heading-3-design-system">3) Design System</h3>
<p>At the top of the hierarchy is the design system itself—a comprehensive, ever-evolving resource that unites all foundational elements, components, and guidelines. It encompasses technical specifications, design tokens, documentation, and best practices, along with core principles and processes to steer UX design and product development across your entire ecosystem.</p>
<h1 id="heading-why-use-a-design-system">Why Use a Design System?</h1>
<p>The true power of a design system lies in its ability to streamline workflows, ensure consistency across products, and foster collaboration among cross-functional teams. Whether you’re starting small or scaling across multiple platforms, a design system empowers the team to achieve more with less—not only in designing features but in bringing them to life.</p>
<p>At Klivvr, our design system serves as a single source of truth, eliminating design redundancy and speeding up the development process. Rather than spending time recreating components, our designers can draw from a library of brand-approved, development-ready options to quickly build out designs. With components crafted using code, tokens, and animation presets our developers can translate these designs into functional, accessible code in a fraction of the time. This approach has revolutionized Klivvr’s product development lifecycle, enabling us to bring products to market faster and deliver a seamless user experience.</p>
<h1 id="heading-design-system-in-jetpack-compose">Design System in Jetpack Compose</h1>
<p>Jetpack Compose streamlines the implementation of a design system, making it easy to create a consistent look and feel for your app through theming, components, and more.</p>
<h2 id="heading-getting-started">Getting Started</h2>
<pre><code class="lang-kotlin">implementation <span class="hljs-string">"androidx.compose.material3:material3:<span class="hljs-variable">$material3_version</span>"</span>
</code></pre>
<p>Once the dependency is added, you can start integrating Material Design elements such as color, typography, and shape into your apps, ensuring a cohesive and polished user experience.</p>
<h2 id="heading-foundation">Foundation</h2>
<p>The foundation consists of essential subsystems like color schemes, typography, shapes, spacing, and themes. Customizing these elements automatically updates the components in your app, ensuring a consistent and personalized design throughout.</p>
<h3 id="heading-color-schemes">Color Schemes</h3>
<p>The foundation of a color scheme is based on a set of key colors—primary, success, alert, danger, and neutral. Each of these colors corresponds to a tonal palette comprising several tones, which are utilized by Material components. For example:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">object</span> Color {
    <span class="hljs-keyword">object</span> Base {
        <span class="hljs-keyword">val</span> black = Color(<span class="hljs-number">0xFF000000</span>)
        <span class="hljs-keyword">val</span> white = Color(<span class="hljs-number">0xFFffffff</span>)
    }

    <span class="hljs-keyword">object</span> Light {
        <span class="hljs-keyword">val</span> primary50 = Color(<span class="hljs-number">0xFFF3EEFE</span>)
        <span class="hljs-keyword">val</span> primary100 = Color(<span class="hljs-number">0xFFDECFFC</span>)

        <span class="hljs-keyword">val</span> success50 = Color(<span class="hljs-number">0xFFD8FDDE</span>)
        <span class="hljs-keyword">val</span> success100 = Color(<span class="hljs-number">0xFFB2E6CC</span>)

        <span class="hljs-keyword">val</span> alert50 = Color(<span class="hljs-number">0xFFFDF3D8</span>)
        <span class="hljs-keyword">val</span> alert100 = Color(<span class="hljs-number">0xFFFCE6A4</span>)

        <span class="hljs-keyword">val</span> danger50 = Color(<span class="hljs-number">0xFFF7E3E7</span>)
        <span class="hljs-keyword">val</span> danger100 = Color(<span class="hljs-number">0xFFF1A7B5</span>)

        <span class="hljs-keyword">val</span> neutral50 = Color(<span class="hljs-number">0xFFF4F4F6</span>)
        <span class="hljs-keyword">val</span> neutral100 = Color(<span class="hljs-number">0xFFECECEF</span>)
    }

    <span class="hljs-keyword">object</span> Dark {
        <span class="hljs-keyword">val</span> primary50 = Color(<span class="hljs-number">0xFFDFD3F8</span>)
        <span class="hljs-keyword">val</span> primary100 = Color(<span class="hljs-number">0xFFB397ED</span>)

        <span class="hljs-keyword">val</span> success50 = Color(<span class="hljs-number">0xFFDCF9E1</span>)
        <span class="hljs-keyword">val</span> success100 = Color(<span class="hljs-number">0xFFB8E0CC</span>)

        <span class="hljs-keyword">val</span> alert50 = Color(<span class="hljs-number">0xFFFBF2DA</span>)
        <span class="hljs-keyword">val</span> alert100 = Color(<span class="hljs-number">0xFFF6E3AA</span>)

        <span class="hljs-keyword">val</span> danger50 = Color(<span class="hljs-number">0xFFF6E4E8</span>)
        <span class="hljs-keyword">val</span> danger100 = Color(<span class="hljs-number">0xFFEBADB9</span>)

        <span class="hljs-keyword">val</span> neutral50 = Color(<span class="hljs-number">0xFFF5F5F5</span>)
        <span class="hljs-keyword">val</span> neutral100 = Color(<span class="hljs-number">0xFFECECEF</span>)
    }
}
</code></pre>
<p>Next, we need to establish the color tokens.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Design tokens encapsulate the small, recurring design choices that shape a design system’s visual style. By replacing static values, such as hex codes for colors with intuitive names, tokens enhance clarity and maintain consistency throughout your design system. They serve as the foundational building blocks for all UI elements, ensuring that the same tokens are utilized across designs, tools, and code, creating a cohesive experience at every level.</div>
</div>

<p><strong>Color Tokens Contract</strong></p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">internal</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">ColorTokens</span> </span>{
    <span class="hljs-comment">// Base</span>
    <span class="hljs-keyword">val</span> baseWhite: Color
    <span class="hljs-keyword">val</span> baseBlack: Color

    <span class="hljs-comment">// Background</span>
    <span class="hljs-keyword">val</span> background: Color
    <span class="hljs-keyword">val</span> onBackground: Color
    <span class="hljs-keyword">val</span> onBackgroundVariant: Color

    <span class="hljs-comment">// Primary</span>
    <span class="hljs-keyword">val</span> primary: Color
    <span class="hljs-keyword">val</span> onPrimary: Color
    <span class="hljs-keyword">val</span> primaryContainer: Color
    <span class="hljs-keyword">val</span> onPrimaryContainer: Color

    <span class="hljs-comment">// Success</span>
    <span class="hljs-keyword">val</span> success: Color
    <span class="hljs-keyword">val</span> onSuccess: Color
    <span class="hljs-keyword">val</span> successContainer: Color
    <span class="hljs-keyword">val</span> onSuccessContainer: Color

    <span class="hljs-comment">// Alert</span>
    <span class="hljs-keyword">val</span> alert: Color
    <span class="hljs-keyword">val</span> onAlert: Color
    <span class="hljs-keyword">val</span> alertContainer: Color
    <span class="hljs-keyword">val</span> onAlertContainer: Color

    <span class="hljs-comment">// Error</span>
    <span class="hljs-keyword">val</span> error: Color
    <span class="hljs-keyword">val</span> onError: Color
    <span class="hljs-keyword">val</span> errorContainer: Color
    <span class="hljs-keyword">val</span> onErrorContainer: Color

    <span class="hljs-comment">// Surface</span>
    <span class="hljs-keyword">val</span> surface: Color
    <span class="hljs-keyword">val</span> surfaceContainer: Color
    <span class="hljs-keyword">val</span> surfaceDim: Color
    <span class="hljs-keyword">val</span> onSurface: Color
    <span class="hljs-keyword">val</span> onSurfaceVariant: Color

    <span class="hljs-comment">// outline</span>
    <span class="hljs-keyword">val</span> outline: Color
    <span class="hljs-keyword">val</span> outlineVariant: Color
}
</code></pre>
<p><strong>Light Color Tokens</strong></p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">object</span> LightColorTokens : ColorTokens {
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> baseWhite = Color.Base.white
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> baseBlack = Color.Base.black
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> background = Color.Light.neutral50
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> onBackground = Color.Light.neutral900
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> onBackgroundVariant = Color.Light.neutral500
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> primary = Color.Light.primary400
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> onPrimary = Color.Base.white
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> primaryContainer = Color.Light.primary50
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> onPrimaryContainer = Color.Light.primary400
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> success = Color.Light.success600
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> onSuccess = Color.Base.white
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> successContainer = Color.Light.success50
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> onSuccessContainer = Color.Light.success600
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> alert = Color.Light.alert400
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> onAlert = Color.Light.alert900
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> alertContainer = Color.Light.alert50
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> onAlertContainer = Color.Light.alert900
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> error = Color.Light.danger400
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> onError = Color.Base.white
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> errorContainer = Color.Light.danger50
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> onErrorContainer = Color.Light.danger400
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> surface = Color.Base.white
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> surfaceContainer = Color.Light.neutral50
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> surfaceDim = Color.Light.neutral200
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> onSurface = Color.Light.neutral900
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> onSurfaceVariant = Color.Light.neutral500
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> outline = Color.Base.black.copy(alpha = .<span class="hljs-number">1F</span>)
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> outlineVariant = Color.Base.black.copy(alpha = .<span class="hljs-number">06F</span>)
}
</code></pre>
<p>As you can see, color tokens enhance the design process by replacing static values with intuitive names like “primary” or “on primary.” This method also allows us to define different values for light mode and dark mode while maintaining meaningful naming conventions, ensuring a seamless and adaptable user experience.</p>
<p>Next, we need to integrate the color schemes into a format that Material Design can recognize. We achieve this by creating a color scheme and passing in the color token values. While it’s possible to manually create a custom color scheme, it’s typically more efficient to generate one using your brand’s source colors. Here’s how to do it:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> colorScheme
    <span class="hljs-meta">@Composable</span>
    <span class="hljs-keyword">get</span>() =
        <span class="hljs-keyword">if</span> (isSystemInDarkTheme()) {
            darkColorScheme
        } <span class="hljs-keyword">else</span> {
            lightColorScheme
        }

<span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> lightColorScheme =
    lightColorScheme(
        primary = LightColorTokens.primary,
        onPrimary = LightColorTokens.onPrimary,
        primaryContainer = LightColorTokens.primaryContainer,
        onPrimaryContainer = LightColorTokens.onPrimaryContainer,
        secondary = Color.Light.primary200,
        onSecondary = Color.Light.neutral900,
        background = LightColorTokens.background,
        onBackground = LightColorTokens.onBackground,
        surface = LightColorTokens.surface,
        onSurface = LightColorTokens.onSurface,
        surfaceVariant = LightColorTokens.surfaceDim,
        onSurfaceVariant = LightColorTokens.onSurfaceVariant,
        surfaceContainer = LightColorTokens.surfaceContainer,
        error = LightColorTokens.error,
        onError = LightColorTokens.onError,
        errorContainer = LightColorTokens.errorContainer,
        onErrorContainer = LightColorTokens.onErrorContainer,
        outline = LightColorTokens.outline,
        outlineVariant = LightColorTokens.outlineVariant,
        scrim = LightColorTokens.baseBlack,
    )

<span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> darkColorScheme =
    darkColorScheme(
        primary = DarkColorTokens.primary,
        onPrimary = DarkColorTokens.onPrimary,
        primaryContainer = DarkColorTokens.primaryContainer,
        onPrimaryContainer = DarkColorTokens.onPrimaryContainer,
        secondary = Color.Dark.primary200,
        onSecondary = Color.Dark.neutral900,
        background = DarkColorTokens.background,
        onBackground = DarkColorTokens.onBackground,
        surface = DarkColorTokens.surface,
        onSurface = DarkColorTokens.onSurface,
        surfaceVariant = DarkColorTokens.surfaceDim,
        onSurfaceVariant = DarkColorTokens.onSurfaceVariant,
        surfaceContainer = DarkColorTokens.surfaceContainer,
        error = DarkColorTokens.error,
        onError = DarkColorTokens.onError,
        errorContainer = DarkColorTokens.errorContainer,
        onErrorContainer = DarkColorTokens.onErrorContainer,
        outline = DarkColorTokens.outline,
        outlineVariant = DarkColorTokens.outlineVariant,
        scrim = DarkColorTokens.baseBlack,
    )
</code></pre>
<p>Next, let’s incorporate the color schemes into our custom theme.</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">KlivvrTheme</span><span class="hljs-params">(
    content: @<span class="hljs-type">Composable</span> () -&gt; <span class="hljs-type">Unit</span>,
)</span></span> {
    MaterialTheme(
        colorScheme = colorScheme,
        content = content,
    )
}
</code></pre>
<p><strong>Usage</strong></p>
<pre><code class="lang-kotlin">KlivvrTheme {
    Text(
        color = MaterialTheme.colorScheme.primary,
        text = <span class="hljs-string">"Awesome text"</span>,
    )
}
</code></pre>
<p>That’s it! Your text color will now dynamically adjust in response to dark mode changes. Furthermore, with color tokens in place, altering the color values is as easy as directing a token to a different color value, and these changes will reflect instantly across the project without requiring any adjustments to the UI components.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">For custom colors that aren’t defined by Material Design (such as “success”), we can add them as extension functions to the <code>MaterialTheme.colorScheme</code>. This enables us to access these colors in the same way we access other colors within the Material theme.</div>
</div>

<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> ColorScheme.success: Color
    <span class="hljs-meta">@Composable</span>
    <span class="hljs-keyword">get</span>() =
        <span class="hljs-keyword">if</span> (isSystemInDarkTheme()) {
            DarkColorTokens.success
        } <span class="hljs-keyword">else</span> {
            LightColorTokens.success
        }
</code></pre>
<hr />
<h3 id="heading-typography">Typography</h3>
<p>Typography is just as fundamental to a design system as colors and components. Establishing patterns for consistent and legible typography early in the design process is essential. This approach not only facilitates scaling typography across various applications and devices but also simplifies the handoff between designers and developers.</p>
<p>Material Design outlines a type scale with a streamlined naming and grouping system that includes <code>display</code>, <code>headline</code>, <code>title</code>, <code>body</code>, and <code>label</code>. Each category is further divided into <code>large</code>, <code>medium</code>, and <code>small</code> sizes, ensuring clarity and coherence throughout your design.</p>
<p>Similar to the color scheme, we will start by defining the text style contract.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">internal</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">TextStyles</span> </span>{
    <span class="hljs-keyword">val</span> displayLarge: TextStyle
    <span class="hljs-keyword">val</span> displayMedium: TextStyle
    <span class="hljs-keyword">val</span> displaySmall: TextStyle

    <span class="hljs-keyword">val</span> headingLarge: TextStyle
    <span class="hljs-keyword">val</span> headingMedium: TextStyle
    <span class="hljs-keyword">val</span> headingSmall: TextStyle

    <span class="hljs-keyword">val</span> titleLarge: TextStyle
    <span class="hljs-keyword">val</span> titleMedium: TextStyle
    <span class="hljs-keyword">val</span> titleSmall: TextStyle

    <span class="hljs-keyword">val</span> bodyLarge: TextStyle
    <span class="hljs-keyword">val</span> bodyMedium: TextStyle
    <span class="hljs-keyword">val</span> bodySmall: TextStyle

    <span class="hljs-keyword">val</span> labelLarge: TextStyle
    <span class="hljs-keyword">val</span> labelMedium: TextStyle
    <span class="hljs-keyword">val</span> labelSmall: TextStyle
}
</code></pre>
<p>Next, we can define different styles of implementation for dark and light modes tailored to each locale. For example:</p>
<p><strong>English text styles (Light/Dark)</strong></p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-keyword">object</span> TypeEN {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> fontFamilyResId = R.font.hauora

    <span class="hljs-keyword">object</span> Light : TextStyles {
        <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> displayLarge =
            getTextStyle(
                fontFamilyResId = fontFamilyResId,
                fontSize = <span class="hljs-number">56</span>.sp,
                lineHeight = <span class="hljs-number">60</span>.sp,
                weight = <span class="hljs-number">700</span>,
                letterSpacing = -<span class="hljs-number">1.20f</span>,
            )
       <span class="hljs-comment">// Same goes for the rest</span>
    }
}

<span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getTextStyle</span><span class="hljs-params">(
    fontFamilyResId: <span class="hljs-type">Int</span>,
    fontSize: <span class="hljs-type">TextUnit</span>,
    lineHeight: <span class="hljs-type">TextUnit</span>,
    weight: <span class="hljs-type">Int</span>,
    letterSpacing: <span class="hljs-type">Float</span>,
)</span></span> = TextStyle(
    fontFamily =
        FontFamily(
            Font(
                resId = fontFamilyResId,
                variationSettings = FontVariation.Settings(FontVariation.weight(weight)),
            ),
        ),
    fontSize = fontSize,
    lineHeight = lineHeight,
    letterSpacing = (letterSpacing / <span class="hljs-number">100</span>) * fontSize,
)
</code></pre>
<p>Next, we can generate our Material Design typography in the same way we created the color scheme.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> typography
    <span class="hljs-meta">@Composable</span>
    <span class="hljs-keyword">get</span>() =
        <span class="hljs-keyword">if</span> (isSystemInDarkTheme()) {
            TypeEnDark
        } <span class="hljs-keyword">else</span> {
            TypeEnLight
        }

<span class="hljs-keyword">val</span> TypeEnLight = Typography(
    displayMedium = TypeEN.Light.displayMedium,
    headlineLarge = TypeEN.Light.headingLarge,
    headlineMedium = TypeEN.Light.headingMedium,
    headlineSmall = TypeEN.Light.headingSmall,
    titleLarge = TypeEN.Light.titleLarge,
    titleMedium = TypeEN.Light.titleMedium,
    titleSmall = TypeEN.Light.titleSmall,
    bodyLarge = TypeEN.Light.bodyLarge,
    bodyMedium = TypeEN.Light.bodyMedium,
    bodySmall = TypeEN.Light.bodySmall,
    labelLarge = TypeEN.Light.labelLarge,
    labelMedium = TypeEN.Light.labelMedium,
    labelSmall = TypeEN.Light.labelSmall,
)

<span class="hljs-keyword">val</span> TypeEnDark = Typography(
    displayMedium = TypeEN.Dark.displayMedium,
    headlineLarge = TypeEN.Dark.headingLarge,
    headlineMedium = TypeEN.Dark.headingMedium,
    headlineSmall = TypeEN.Dark.headingSmall,
    titleLarge = TypeEN.Dark.titleLarge,
    titleMedium = TypeEN.Dark.titleMedium,
    titleSmall = TypeEN.Dark.titleSmall,
    bodyLarge = TypeEN.Dark.bodyLarge,
    bodyMedium = TypeEN.Dark.bodyMedium,
    bodySmall = TypeEN.Dark.bodySmall,
    labelLarge = TypeEN.Dark.labelLarge,
    labelMedium = TypeEN.Dark.labelMedium,
    labelSmall = TypeEN.Dark.labelSmall,
)
</code></pre>
<p>Next, let’s incorporate the typography into our custom theme.​</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">KlivvrTheme</span><span class="hljs-params">(
    content: @<span class="hljs-type">Composable</span> () -&gt; <span class="hljs-type">Unit</span>,
)</span></span> {
    MaterialTheme(
        colorScheme = colorScheme,
        typography = typography,
        content = content,
    )
}
</code></pre>
<p><strong>Usage</strong></p>
<pre><code class="lang-kotlin">KlivvrTheme {
    Text(
        color = MaterialTheme.colorScheme.primary,
        style = MaterialTheme.typography.bodyMedium,
        text = <span class="hljs-string">"Awesome text"</span>,
    )
}
</code></pre>
<p>That’s it! Your typography will now dynamically adjust in response to dark mode or locale changes. Plus, with typography tokens in place, updating the text styles is as simple as modifying the text style attributes, and these changes will instantly reflect across the project without requiring any adjustments to the UI components.</p>
<hr />
<h3 id="heading-spacing">Spacing</h3>
<p>A spacing system streamlines the creation of page layouts and UI. The consistent and intentional use of a spacing system fosters a more harmonious experience for the end user. A well-defined spacing system also lays the groundwork for responsive design and customizable UI density, enhancing the overall quality and accessibility of our products in the future.</p>
<p>Unlike color schemes and typography, spacing isn’t a predefined attribute in the Material theme. However, we can achieve similar declarative behavior by utilizing extension functions.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">object</span> Space {
    <span class="hljs-keyword">val</span> space100 = <span class="hljs-number">4</span>.dp
    <span class="hljs-keyword">val</span> space200 = <span class="hljs-number">8</span>.dp
    <span class="hljs-keyword">val</span> space300 = <span class="hljs-number">12</span>.dp
    <span class="hljs-keyword">val</span> space400 = <span class="hljs-number">16</span>.dp
    <span class="hljs-keyword">val</span> space500 = <span class="hljs-number">20</span>.dp
    <span class="hljs-keyword">val</span> space600 = <span class="hljs-number">24</span>.dp
    <span class="hljs-keyword">val</span> space800 = <span class="hljs-number">32</span>.dp
}

<span class="hljs-keyword">val</span> MaterialTheme.spaces <span class="hljs-keyword">get</span>() = Space
</code></pre>
<p><strong>Usage</strong></p>
<pre><code class="lang-kotlin">KlivvrTheme {
    Text(
        modifier = Modifier.padding(MaterialTheme.spaces.space400),
        color = MaterialTheme.colorScheme.primary,
        style = MaterialTheme.typography.bodyMedium,
        text = <span class="hljs-string">"Awesome text"</span>,
    )
}
</code></pre>
<hr />
<h1 id="heading-tldr">TL;DR</h1>
<blockquote>
<p>Design systems are crucial for crafting consistent and cohesive digital experiences, incorporating elements such as colors, typography, and components. They streamline workflows, uphold brand consistency, and enhance collaboration among cross-functional teams. This article delves into the fundamentals of design systems, highlighting their significance and offering insights on how to build and implement them effectively—particularly in Android app development using Jetpack Compose. It provides detailed guidance on creating color schemes, typography, and spacing systems to ensure a seamless and adaptable user experience.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[What is Context in Android?]]></title><description><![CDATA[As an Android developer, you work with Context daily. But have you ever wondered what Context actually is and why it’s essential? Let's dive into some common scenarios and break them down together.
Accessing String Resources
Imagine you've added a st...]]></description><link>https://blog.klivvr.com/what-is-context-in-android</link><guid isPermaLink="true">https://blog.klivvr.com/what-is-context-in-android</guid><category><![CDATA[Android]]></category><category><![CDATA[fintech]]></category><category><![CDATA[Klivvr]]></category><category><![CDATA[Developer]]></category><category><![CDATA[development]]></category><dc:creator><![CDATA[Ahmed Tawfek]]></dc:creator><pubDate>Mon, 09 Sep 2024 10:11:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748788734594/7c0951f8-3b03-4da9-a5f5-909a7cdb6dce.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As an Android developer, you work with Context daily. But have you ever wondered what Context actually is and why it’s essential? Let's dive into some common scenarios and break them down together.</p>
<h2 id="heading-accessing-string-resources">Accessing String Resources</h2>
<p>Imagine you've added a string in your resources file like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725584753674/90643e98-c806-4e6e-b1f3-9fcc6b62cf51.png" alt class="image--center mx-auto" /></p>
<p>Now, you want to access this string in your code. Here's what that might look like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725584773408/dd39dc82-4192-4fea-bd1f-37f4945ca415.png" alt class="image--center mx-auto" /></p>
<p>To get this string, you first need to use Context. But why?</p>
<h3 id="heading-why-context-is-necessary">Why Context is Necessary</h3>
<p>Android stores resources like strings, drawables, and colors using its framework. When you create a resource file, the Android framework handles its storage. But when you want to retrieve this file, you need to ask the system for it. Here’s where <strong>Context</strong> comes in.</p>
<p><strong>Context</strong> is your gateway to the Android system—it allows you to communicate with the operating system to access resources, services, and more.</p>
<p>Think of it like communicating with a friend. To reach them, you use your mobile phone, which acts as a bridge. Similarly, <strong>Context</strong> is the bridge between your app and the Android system.</p>
<p><strong>In summary: Context is the bridge between you and the operating system.</strong></p>
<h2 id="heading-why-views-need-context">Why Views Need Context</h2>
<p>Every view in Android requires <strong>Context</strong>. Why? Because views often need to access system resources—like colors, strings, or the current app mode (light or dark). To retrieve these resources, the view needs to communicate with the system, which is done through <strong>Context</strong>.</p>
<h2 id="heading-different-types-of-context-in-android">Different Types of Context in Android</h2>
<p>Android provides five main types of <strong>Context</strong>:</p>
<ul>
<li><p>Application Context</p>
</li>
<li><p>Activity Context</p>
</li>
<li><p>Service Context</p>
</li>
<li><p>BroadcastReceiver Context</p>
</li>
<li><p>Content Provider Context</p>
</li>
</ul>
<p>You're probably most familiar with <strong>Application</strong> and <strong>Activity</strong> contexts, as they're the ones you use most frequently. However, each type serves a different purpose and provides access to different system resources.</p>
<h3 id="heading-misconceptions-about-memory-leaks">Misconceptions About Memory Leaks</h3>
<p>A common concern when using <strong>Context</strong> is avoiding memory leaks. Let’s go through two scenarios:</p>
<p><strong>Scenario 1: Accessing SharedPreferences in an Activity</strong></p>
<p>If you use <code>getApplicationContext()</code> to access <strong>SharedPreferences</strong>, will it cause a memory leak? <strong>No, it won’t.</strong></p>
<p><strong>Scenario 2: Holding a Reference to an Activity in the Application Class</strong></p>
<p>If you hold a reference to an <strong>Activity</strong> in your <strong>Application</strong> class, will it cause a memory leak? <strong>Yes, it will.</strong> The garbage collector can’t reclaim the memory used by the <strong>Activity</strong> if the <strong>Application</strong> class holds a reference to it, leading to a memory leak.</p>
<p>This highlights the importance of using the right <strong>Context</strong> in the right situation.</p>
<h2 id="heading-responsibilities-of-different-contexts">Responsibilities of Different Contexts</h2>
<p>Each type of <strong>Context</strong> has specific responsibilities. For example:</p>
<ul>
<li>The <strong>Application Context</strong> cannot start a dialogue. Let’s see what happens when you try:</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725584809934/3f66fb92-60af-46f6-858f-f7a682b85138.png" alt class="image--center mx-auto" /></p>
<p>When you run this code, you’ll get the following error:</p>
<p><strong>android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?</strong></p>
<p>This shows that each <strong>Context</strong> type has specific limitations and responsibilities. Here’s a table that outlines what each type of <strong>Context</strong> can and cannot do:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725584830733/9f83aa34-eadb-4595-b52a-b6acabd28f2c.png" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[The Critical Role of PII Confidentiality in Financial Services]]></title><description><![CDATA[In the digital age, the protection of Personally Identifiable Information (PII) is paramount, especially in the financial sector, where the stakes are incredibly high. PII refers to any data that could potentially identify a specific individual, such...]]></description><link>https://blog.klivvr.com/the-critical-role-of-pii-confidentiality-in-financial-services</link><guid isPermaLink="true">https://blog.klivvr.com/the-critical-role-of-pii-confidentiality-in-financial-services</guid><category><![CDATA[fintech]]></category><category><![CDATA[Security]]></category><category><![CDATA[encryption]]></category><category><![CDATA[privacy]]></category><category><![CDATA[Klivvr]]></category><dc:creator><![CDATA[Muhammad Abdel Aal]]></dc:creator><pubDate>Tue, 03 Sep 2024 12:35:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748788795125/891cf312-1936-4d2e-895a-4c23abec8723.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the digital age, the protection of Personally Identifiable Information (PII) is paramount, especially in the financial sector, where the stakes are incredibly high. PII refers to any data that could potentially identify a specific individual, such as name, address, contact details, and financial records. In Egypt, your National ID is a primary example of PII, acting like the Social Security Number (SSN) in other countries.</p>
<p>The financial services industry is a prime target for cybercriminals due to the sensitive nature of the information it holds. At Klivvr, we recognize the gravity of this responsibility and are committed to safeguarding the PII of our clients while innovating within the regulatory framework.</p>
<h1 id="heading-why-pii-confidentiality-matters-in-financial-services">Why PII Confidentiality Matters in Financial Services</h1>
<p>The financial sector handles an enormous amount of sensitive data daily. From loan applications to transaction records, PII is constantly in transit and at risk of exposure. A breach of this information can lead to severe consequences, including identity theft, financial loss, and a loss of trust in the institution.</p>
<p>Regulatory bodies like the Central Bank of Egypt (CBE) and the Financial Regulatory Authority (FRA) impose strict guidelines on how financial institutions manage PII. Compliance with these regulations is not just about avoiding penalties; it is about maintaining the integrity of the financial system and protecting the rights of individuals.</p>
<p>At Klivvr, we understand that safeguarding PII is not just a regulatory requirement but a core aspect of our responsibility to our clients. We continuously innovate to enhance our security measures, ensuring that our practices are always in line with the latest regulatory standards.</p>
<h1 id="heading-securing-pii-best-practices">Securing PII: Best Practices</h1>
<ol>
<li><p><strong>Data Encryption:</strong> One of the most effective ways to protect PII is through encryption. By converting data into a secure format, even if intercepted, it cannot be read without the appropriate decryption key. We employ advanced encryption techniques to protect PII at all stages—whether at rest, in transit, or in use.</p>
</li>
<li><p><strong>Access Controls:</strong> Limiting access to PII is crucial. Only authorized personnel should have access to sensitive information, and this access should be regularly reviewed and adjusted based on roles and responsibilities. We implement strict access controls, ensuring that PII is accessible only to those who need it to perform their duties.</p>
</li>
<li><p><strong>Regular Audits and Monitoring:</strong> Continuous monitoring and regular audits are essential to detect and respond to potential security breaches promptly. We utilize state-of-the-art monitoring tools that provide real-time alerts and detailed audit trails, ensuring that any suspicious activity is identified and addressed immediately.</p>
</li>
<li><p><strong>Data Masking:</strong> Data masking techniques are used to protect PII in non-production environments, such as development and testing. This ensures that sensitive information is not exposed unnecessarily during these processes. We apply data masking across all relevant systems to minimize the risk of PII exposure.</p>
</li>
<li><p><strong>Employee Training:</strong> Human error remains one of the most significant risks to PII confidentiality. Regular training ensures that all employees are aware of the importance of PII security and understand how to handle it appropriately. We conduct ongoing training sessions to keep our team updated on the latest security protocols and best practices.</p>
</li>
</ol>
<h1 id="heading-challenges-and-considerations">Challenges and Considerations</h1>
<p>Securing PII is not without its challenges. The ever-evolving nature of cyber threats means that financial institutions must stay ahead of the curve. We are committed to continuous improvement, investing in the latest technologies and methodologies to enhance our security posture.</p>
<h1 id="heading-alternative-viewpoints">Alternative Viewpoints</h1>
<ul>
<li><p><strong>Innovation vs. Regulation:</strong> Some argue that over-regulation can stifle innovation in financial services. While it is true that compliance can introduce additional steps and complexities, we see regulation as an opportunity to innovate securely. By integrating compliance into our innovation process, we ensure that our solutions are both cutting-edge and safe.</p>
</li>
<li><p><strong>Balancing Security with User Experience:</strong> Others emphasize the importance of balancing security with user experience. We believe that robust security should not come at the cost of usability. We strive to create solutions that are secure yet intuitive, providing our clients with peace of mind and a seamless experience.</p>
</li>
</ul>
<h1 id="heading-path-forward">Path Forward</h1>
<p>As the financial landscape continues to evolve, the importance of PII confidentiality cannot be overstated. At Klivvr, we are committed to leading by example, ensuring that our practices not only comply with regulations but also set new standards for innovation and security in the financial services sector. By staying vigilant and proactive, we aim to protect our clients' information while fostering a culture of trust and integrity.</p>
]]></content:encoded></item><item><title><![CDATA[The Journey of Launching An Android Activity]]></title><description><![CDATA[You're an Android developer; you know very well how to launch an Android activity and by the time you are reading this you probably did it a zillion times. But have you ever wondered why it's done this way? Why do we use intents to create an activity...]]></description><link>https://blog.klivvr.com/the-journey-of-launching-an-android-activity</link><guid isPermaLink="true">https://blog.klivvr.com/the-journey-of-launching-an-android-activity</guid><category><![CDATA[Android]]></category><category><![CDATA[development]]></category><category><![CDATA[tech ]]></category><category><![CDATA[fintech]]></category><dc:creator><![CDATA[Muhammad Youssef]]></dc:creator><pubDate>Mon, 26 Aug 2024 10:39:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748788816056/0ebef568-63ae-4155-8b02-97dd08b50863.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You're an Android developer; you know very well how to launch an Android activity and by the time you are reading this you probably did it a zillion times. But have you ever wondered why it's done this way? Why do we use intents to create an activity object? What makes an activity object unique from any other Java object? After all, it’s still a Java object, right? So, where, when, and how does the <code>new Activity()</code> statement get executed? What happens before an activity gets created? In this article, we’ll take a behind-the-scenes look at what happens when you launch an Android activity. This discussion assumes you’re familiar with Java, object-oriented programming (OOP) principles, and Android development fundamentals.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724588478151/133af26c-7cbc-416b-9116-ecf55a938e81.png" alt class="image--center mx-auto" /></p>
<hr />
<p>Let’s start by creating a project with an activity and override the default constructor. The simplest way to check the path to a constructor is by placing a breakpoint on it. It will enable us to walk through all the calls and explore the implemented code to find exactly what we want. Executing the project will result in the following:</p>
<p><img src="https://miro.medium.com/v2/resize:fit:2000/1*aQnI3GLHyaqzqs2qttJcSg.png" alt="Android studio debugger" class="image--center mx-auto" /></p>
<blockquote>
<p><em>In any Unix-based operating system, the first thing the kernel does is to execute</em> <a target="_blank" href="https://en.m.wikipedia.org/wiki/Init"><em>init process</em></a><em>. Init is the root/parent of all processes executing on Linux.</em></p>
</blockquote>
<p>As we can see at the very bottom of the debugger frames, Android internally calls something called <a target="_blank" href="https://android.googlesource.com/platform/frameworks/base.git/+/master/core/java/com/android/internal/os/ZygoteInit.java#70"><code>ZygoteInit</code></a></p>
<h1 id="heading-what-is-zygoteinit">What is ZygoteInit</h1>
<p>As the name suggests, <a target="_blank" href="https://android.googlesource.com/platform/frameworks/base.git/+/master/core/java/com/android/internal/os/ZygoteInit.java#70"><code>ZygoteInit</code></a> is the genesis of the Android application. It gets its name from a dictionary definition: “The initial cell formed when a new organism is produced."</p>
<p>Android at its core has a process called <a target="_blank" href="https://elinux.org/Android_Zygote_Startup"><code>Zygote</code></a>, which starts at <a target="_blank" href="https://en.m.wikipedia.org/wiki/Init">init</a>. It’s a special Android OS process that enables shared code across Dalvik/Art VM. This process is a “warmed-up” process, meaning it preloads all the classes and resources that an app may potentially need at runtime into the system’s memory. It then forks itself to start a well-managed process called <a target="_blank" href="https://android.googlesource.com/platform/frameworks/base/+/7d276c3/services/java/com/android/server/SystemServer.java#848"><code>SystemServer</code></a> which initializes all core platform services it houses. One of the core services that gets started by <code>SystemServer</code>, which is particularly relevant here, is <a target="_blank" href="https://android.googlesource.com/platform/frameworks/base/+/4f868ed/services/core/java/com/android/server/am/ActivityManagerService.java#231"><code>ActivityManagerService</code></a><strong>.</strong></p>
<p><img src="https://miro.medium.com/v2/resize:fit:1000/0*ZkByvPGBmvH6zoMT.gif" alt class="image--center mx-auto" /></p>
<h1 id="heading-activitymanagerservice-where-the-magic-happens">ActivityManagerService: Where the Magic Happens</h1>
<p>ActivityManagerService is responsible for creating new Activity thread processes, maintaining the Activity lifecycle, and managing the activity stack. During its startup, it performs three main steps:</p>
<h2 id="heading-1-collect-target-activity-information">1. <strong>Collect Target Activity Information</strong></h2>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="85a44e00fdfaea874704259203a2038e"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/Muhammadyoussef/85a44e00fdfaea874704259203a2038e" class="embed-card">https://gist.github.com/Muhammadyoussef/85a44e00fdfaea874704259203a2038e</a></div><p> </p>
<blockquote>
<p><a target="_blank" href="https://android.googlesource.com/platform/frameworks/base/+/4f868ed/services/core/java/com/android/server/am/ActivityManagerService.java#3334">Full implementation: <code>ActivityManagerService.resolveActivityInfo()</code></a></p>
</blockquote>
<p>The first step is to collect information about the target activity. This is done by calling <code>resolveIntent()</code> method on some hidden implementation for <a target="_blank" href="https://android.googlesource.com/platform/frameworks/base/+/483f3b06ea84440a082e21b68ec2c2e54046f5a6/core/java/android/content/pm/IPackageManager.aidl#45"><code>IPackageManager</code></a> interface. The target information is then saved back into the intent object to avoid redoing this step.</p>
<h2 id="heading-2-check-user-privileges">2. <strong>Check User Privileges</strong></h2>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="ec06cb6212923492050744aaed1abcb9"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/Muhammadyoussef/ec06cb6212923492050744aaed1abcb9" class="embed-card">https://gist.github.com/Muhammadyoussef/ec06cb6212923492050744aaed1abcb9</a></div><p> </p>
<blockquote>
<p><a target="_blank" href="https://android.googlesource.com/platform/frameworks/base/+/4f868ed/services/core/java/com/android/server/am/ActivityManagerService.java#7388">Full implementation: <code>ActivityManagerService.grantUriPermissionLocked()</code></a></p>
</blockquote>
<p>The next step is to check if the user has sufficient privileges to invoke the target activity. This is typically done by calling <a target="_blank" href="https://android.googlesource.com/platform/frameworks/base/+/4f868ed/services/core/java/com/android/server/am/ActivityManagerService.java#7388"><code>grantUriPermissionLocked()</code></a> which ensures:</p>
<ol>
<li><p>The target package has a valid <a target="_blank" href="https://en.m.wikipedia.org/wiki/UID">UID</a> associated with it.</p>
</li>
<li><p>The UID is used to check if the target package can grant permission to access the URI by calling <a target="_blank" href="https://android.googlesource.com/platform/frameworks/base/+/4f868ed/services/core/java/com/android/server/am/ActivityManagerService.java#7227"><code>checkGrantUriPermissionLocked()</code></a></p>
</li>
<li><p>After ensuring that the caller has all the necessary permissions, <a target="_blank" href="https://android.googlesource.com/platform/frameworks/base/+/4f868ed/services/core/java/com/android/server/am/ActivityManagerService.java#7360"><code>grantUriPermissionUncheckedLocked()</code></a> grants them to the target package.</p>
</li>
</ol>
<p><img src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExd2V6Nmw2Z3Y2Njg4Z3hvdjFtajhhbDJraG1zeGY2b3o3OWowY2huaCZlcD12MV9naWZzX3NlYXJjaCZjdD1n/u65me2nV3nGlG/giphy.gif" alt class="image--center mx-auto" /></p>
<h2 id="heading-3-activity-object-instantiation">3. <strong>Activity Object Instantiation</strong></h2>
<p>Now to the juicy stuff, it’s time to check if the ProcessRecord already exists for the process. If the ProcessRecord is null, the ActivityManagerService must create a new process to instantiate the activity—duh. The instantiation is done with the help of <a target="_blank" href="https://android.googlesource.com/platform/frameworks/base/+/d630f105e8bc0021541aacb4dc6498a49048ecea/core/java/android/app/ActivityThread.java#114"><code>ActivityThread</code></a> class.</p>
<p>At this point, all required permissions have been granted, all the information about the target activity has been stored in the intent object, and the system has made sure that the user has all the privileges to invoke the target activity. Now it’s time to instantiate and launch the target Activity. This phase can be divided into three sub-phases:</p>
<h3 id="heading-31-get-the-environment-ready">3.1. <strong>Get the Environment Ready</strong></h3>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="b52bc0fb9bdf1bc19b1939a878c3af9e"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/Muhammadyoussef/b52bc0fb9bdf1bc19b1939a878c3af9e" class="embed-card">https://gist.github.com/Muhammadyoussef/b52bc0fb9bdf1bc19b1939a878c3af9e</a></div><p> </p>
<blockquote>
<p><a target="_blank" href="https://android.googlesource.com/platform/frameworks/base/+/d630f105e8bc0021541aacb4dc6498a49048ecea/core/java/android/app/ActivityThread.java#1758">Full implementation:</a> <a target="_blank" href="https://gist.github.com/Muhammadyoussef/b52bc0fb9bdf1bc19b1939a878c3af9e#file-activitythread-handlelaunchactivity-java"><code>ActivityThread.handleLaunchActivity()</code></a></p>
</blockquote>
<p>First things first, let’s get the environment ready. It does so by calling <a target="_blank" href="https://android.googlesource.com/platform/frameworks/base/+/d630f105e8bc0021541aacb4dc6498a49048ecea/core/java/android/app/ActivityThread.java#1758"><code>handleLaunchActivity()</code></a><em>.</em> This ensures that configurations are up to date, the graphics environment is initialized, and the <a target="_blank" href="https://android.googlesource.com/platform/frameworks/base/+/0e40462e11d27eb859b829b112cecb8c6f0d7afb/core/java/android/view/WindowManagerGlobal.java#39"><code>WindowManager</code></a> is set up.</p>
<h3 id="heading-32-retrieve-the-previously-collected-information">3.2. <strong>Retrieve the Previously Collected Information</strong></h3>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="5c9cdbc0273a7517b4d0b7d8324bb518"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/Muhammadyoussef/5c9cdbc0273a7517b4d0b7d8324bb518" class="embed-card">https://gist.github.com/Muhammadyoussef/5c9cdbc0273a7517b4d0b7d8324bb518</a></div><p> </p>
<blockquote>
<p><a target="_blank" href="https://android.googlesource.com/platform/frameworks/base/+/d630f105e8bc0021541aacb4dc6498a49048ecea/core/java/android/app/ActivityThread.java#1640"><em>Full implementation:</em></a> <a target="_blank" href="https://gist.github.com/Muhammadyoussef/5c9cdbc0273a7517b4d0b7d8324bb518"><code>ActivityThread: performLaunchActivity()</code></a></p>
</blockquote>
<p>Next, previously collected information, such as ComponentName is retrieved, and the baseContext is created to prepare for instantiation.</p>
<h3 id="heading-33-the-instantiation">3.3. <strong>The Instantiation</strong></h3>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="6942bb7301bb9a868bfbb487879d8052"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/Muhammadyoussef/6942bb7301bb9a868bfbb487879d8052" class="embed-card">https://gist.github.com/Muhammadyoussef/6942bb7301bb9a868bfbb487879d8052</a></div><p> </p>
<blockquote>
<p><a target="_blank" href="https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/AppComponentFactory.java#78"><em>Full implementation:</em></a> <a target="_blank" href="https://gist.github.com/Muhammadyoussef/6942bb7301bb9a868bfbb487879d8052"><code>AppComponentFactory.instantiateActivity()</code></a></p>
</blockquote>
<p>This is where it gets interesting. Android uses the help of <a target="_blank" href="https://stackoverflow.com/a/37632/7330512">Java's reflection library</a> to execute the <code>new Activity()</code> statement. It does so by calling <a target="_blank" href="https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/Instrumentation.java#1211"><code>newActivity()</code></a> method on the <code>Instrumentation</code> object which then delegates the action to the<code>AppComponentFactory</code> object by calling <a target="_blank" href="https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/AppComponentFactory.java#78"><code>instantiateActivity()</code></a> method.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:1000/0*2wSWSjnavwHXkm06.gif" alt class="image--center mx-auto" /></p>
<p>After instantiation,<a target="_blank" href="https://android.googlesource.com/platform/frameworks/base/+/d630f105e8bc0021541aacb4dc6498a49048ecea/core/java/android/app/ActivityThread.java#114"><code>ActivityThread</code></a> proceeds by calling <a target="_blank" href="https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/Instrumentation.java#1271"><code>callActivityOnCreate()</code></a>. And this is the start of what we all know as <em>Activity Life Cycle</em> 😄</p>
<h1 id="heading-tldr">TL;DR</h1>
<blockquote>
<p>This article delves into the behind-the-scenes process of launching Android activities, exploring why intents are used and what makes an Activity object unique. It covers the role of the Zygote process, the initialization of core services by SystemServer, and the crucial functions of ActivityManagerService. The article explains how the system collects target activity information, checks user privileges, and instantiates the Activity object using Java reflection. By the end, you'll understand the detailed steps involved in the activity lifecycle from creation to launch.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[Travel 101 with Klivvr]]></title><description><![CDATA[It’s summer season, and Klivvr is all about being extra this summer! Here are all the ways you can use your Klivvr card for a summer trip to remember!
https://giphy.com/gifs/fsnNbATnG7YT2lSfQV
 
-Staycation
First off, do you want to keep the trip low...]]></description><link>https://blog.klivvr.com/travel-101-with-klivvr</link><guid isPermaLink="true">https://blog.klivvr.com/travel-101-with-klivvr</guid><category><![CDATA[Travel]]></category><category><![CDATA[Klivvr]]></category><category><![CDATA[guide]]></category><category><![CDATA[Benefits]]></category><category><![CDATA[partnership]]></category><dc:creator><![CDATA[Amira Gamil]]></dc:creator><pubDate>Tue, 20 Aug 2024 11:11:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748788851348/16d11537-ca99-4a38-9cb5-7e457bdd4a98.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It’s summer season, and Klivvr is all about being extra this summer! Here are all the ways you can use your Klivvr card for a summer trip to remember!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://giphy.com/gifs/fsnNbATnG7YT2lSfQV">https://giphy.com/gifs/fsnNbATnG7YT2lSfQV</a></div>
<p> </p>
<p>-Staycation</p>
<p>First off, do you want to keep the trip lowkey and go for a staycation? Visit Kempinski Somabay with your Klivvr card and get 10% off!</p>
<p>-Fit checks!</p>
<p>Prepping for the trip is sometimes more exciting than the trip itself. Bring your Pinterest board to life with our range of partners! Whether you want new sneakers, a fancy dress, or just some basics for your summer getaway, check out our list of lifestyle partners and get up to 25% off!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://giphy.com/gifs/news-andre-leon-talley-andr-TNYJFvFWfJochIuKx5">https://giphy.com/gifs/news-andre-leon-talley-andr-TNYJFvFWfJochIuKx5</a></div>
<p> </p>
<p>-Summer Glam</p>
<p>Get the summer look of your dreams at Al Sagheer Salon and get 15% off when you pay with your Klivvr card.</p>
<p>-Lock it!</p>
<p>There’s nothing scarier than losing your card, but it gets scarier when it happens while you’re out of town! But with Klivvr, you can easily lock your card with a tap through the Klivvr app!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://giphy.com/gifs/season-14-the-simpsons-14x12-xT5LMWKbnu7CiQeG3e">https://giphy.com/gifs/season-14-the-simpsons-14x12-xT5LMWKbnu7CiQeG3e</a></div>
<p> </p>
<p>-Extra cards</p>
<p>Want to have a romantic dinner with your partner but your kids are all about the nearby amusement park? No more fighting over the card. Request an extra card for your account and let everyone have the trip the way they want!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://giphy.com/gifs/starwars-star-wars-episode-2-3ohuAreLeoYwnaQyuk">https://giphy.com/gifs/starwars-star-wars-episode-2-3ohuAreLeoYwnaQyuk</a></div>
<p> </p>
<p>-Spend &amp; Earn</p>
<p>With our cashback offers and K-points program, rest assured that you will keep earning all trip long every time you spend with your Klivvr card!</p>
<p>-Track your spending</p>
<p>Summer trips can make us get a bit carried away. But with Klivvr, you can set spending goals and have daily insights on your spending to make sure you are on the right track all trip long!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://giphy.com/gifs/culture--think-hmm-d3mlE7uhX8KFgEmY">https://giphy.com/gifs/culture--think-hmm-d3mlE7uhX8KFgEmY</a></div>
<p> </p>
<p>To sum it up, we got you covered. See you by the sea! 🌊</p>
]]></content:encoded></item><item><title><![CDATA[Swift Cairo: An iOS Community]]></title><description><![CDATA[Tech communities play a pivotal role in the professional development of software engineers. These communities provide a space where individuals with shared interests can come together, exchange knowledge, and collaborate on projects. This collective ...]]></description><link>https://blog.klivvr.com/swift-cairo-an-ios-community</link><guid isPermaLink="true">https://blog.klivvr.com/swift-cairo-an-ios-community</guid><category><![CDATA[swift cairo]]></category><category><![CDATA[Swift]]></category><category><![CDATA[iOS]]></category><category><![CDATA[tech ]]></category><category><![CDATA[community]]></category><category><![CDATA[Klivvr]]></category><dc:creator><![CDATA[Ahmed Ramzy]]></dc:creator><pubDate>Mon, 19 Aug 2024 13:28:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748788884768/8e8a0bce-903c-4066-b87c-081da91a77b7.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Tech communities play a pivotal role in the professional development of software engineers. These communities provide a space where individuals with shared interests can come together, exchange knowledge, and collaborate on projects. This collective environment fosters learning, offering engineers the opportunity to stay updated with the latest industry trends, tools, and best practices.</p>
<p>One of the key benefits to being part of a tech community is the access to a diverse range of experiences and perspectives. Members come from various backgrounds and levels of expertise, creating a rich environment for knowledge exchange. Whether you're a beginner looking to learn the basics or an experienced engineer seeking to refine your skills, tech communities offer valuable insights and resources.</p>
<p>Moreover, communities often host events such as meetups, workshops, and hackathons, to provide hands-on experience and opportunities to apply new concepts in real-world scenarios. These activities not only enhance technical skills but also foster collaboration and teamwork, which are essential in the software development industry.</p>
<p>Networking is another significant advantage. Being part of a tech community allows engineers to build connections with like-minded professionals, mentors, and potential collaborators. These relationships can lead to job opportunities, partnerships, or simply a strong support system within the industry.</p>
<p>In essence, tech communities serve as a catalyst for growth. They encourage continuous learning, provide a platform for sharing knowledge, and help engineers stay motivated and engaged in their field. For iOS engineers in particular, communities like Swift Cairo offer a specialized environment where members can deepen their expertise in Swift and related technologies, ultimately becoming better and more well-rounded software engineers.</p>
<h2 id="heading-the-story-of-swift-cairo">The Story of Swift Cairo</h2>
<p>Swift Cairo was established in 2018 by <a target="_blank" href="https://www.linkedin.com/in/abdulrhmaneaita/">Abdoelrahman Eaita</a> and <a target="_blank" href="https://www.linkedin.com/in/attiamo/">Attia Elsayed</a>, sparked by a simple tweet that asked, "Yala community?" This straightforward question became the catalyst for what would grow into a thriving local hub for iOS engineers. Seizing the momentum, they began reaching out to companies, creating social media channels, and organizing what would become the community’s first offline meetup. This initial event marked the beginning of a journey that has since connected and supported countless engineers in Egypt, helping them to refine their skills and advance in their careers. Later on, <a target="_blank" href="https://www.linkedin.com/in/moelnaggar14/">Mohamed El-Naggar</a> joined as a Co-Founder, playing a crucial role in managing the community's activities and contributing to its ongoing success.</p>
<h2 id="heading-community-activities">Community Activities</h2>
<p>The heart of Swift Cairo's activities lies in our beloved monthly offline meetup. This event brings together iOS engineers from across Egypt, hosted within the offices of various tech companies. During these meetups, two or more engineers take the stage to deliver talks on a range of topics that are valuable to all attendees, whether they're seasoned professionals or just starting out.</p>
<p>The real magic happens during the breaks, where community members have the chance to network, share experiences, and forge lasting connections. These moments of interaction are where bonds are formed, ideas are exchanged, and memories are made—making each meetup an unforgettable experience that goes beyond just technical learning.</p>
<p>In addition to our offline meetups, the community engages in several other activities. We host reading sessions where members join online meetings to explore and discuss the source code from various open-source projects. This collaborative effort deepens our understanding and sparks insightful conversations.</p>
<p>We also send out a weekly 2newsletter, sharing useful articles, tools, industry news, and job opportunities with our community members. Additionally, we organize workshops focused on specific topics, offering both online and offline sessions to teach and engage our members with learning new skills and concepts.</p>
<p>Our community also hosts a podcast, where Eaita invites different guests for each episode to discuss topics that are relevant and valuable to our members.</p>
<p>We also maintain a Slack channel that serves as our community’s digital hub. Here, members can ask questions, share job opportunities, or engage in random discussions, fostering a sense of camaraderie and continuous support among peers.</p>
<p>Beyond these activities, we also provide services to companies within the tech industry. We assist with hiring processes, conduct interviews, and even recommend talented engineers from our community. In some cases, our members have also taken on projects or worked directly with these companies, further strengthening the connection between Swift Cairo and the broader tech ecosystem.</p>
<h2 id="heading-the-impact-of-covid-19">The Impact of COVID-19</h2>
<p>The COVID-19 pandemic was undeniably a challenging time for everyone, and our community was no exception. As mentioned earlier, the heart of our activities has always been our in-person meetups. However, with the onset of the pandemic, we had to pause all offline events to prioritize the safety of our members.</p>
<p>While this period felt like a dark era for our community, it also presented an opportunity to adapt and innovate. We began hosting online webinars and virtual meetups, providing a platform for our members to continue learning and staying connected. We also found creative ways to maintain our sense of community, whether it was through online gaming sessions, casual virtual hangouts, or simply supporting one another during these tough times.</p>
<p>Despite the challenges, this period of adjustment allowed us to explore new ways of engaging with our community and keeping the spirit of Swift Cairo alive, even when we couldn't meet in person.</p>
<h2 id="heading-the-comeback">The Comeback</h2>
<p>After the pandemic subsided, our community faced new challenges. Many of our senior members, including our two beloved founders, had moved abroad, leaving us in a period of transition. For a while, we struggled to regain the momentum that had once driven Swift Cairo.</p>
<p>Recognizing the need for fresh leadership, Attia decided to pass the torch. He posed a simple question to the community: "Who wants to give back to the community?" The response was overwhelming, with many members eager to step up and contribute. After a series of friendly calls and discussions, Attia made his decision.</p>
<p>Meet the new team behind Swift Cairo: <a target="_blank" href="https://www.linkedin.com/in/iramzyy/">Ahmed Ramzy</a>, <a target="_blank" href="https://www.linkedin.com/in/asmaa-tarek/">Asmaa Tarek</a>, <a target="_blank" href="https://www.linkedin.com/in/aramy23/">Ahmed Ramy</a>, <a target="_blank" href="https://www.linkedin.com/in/devibrahimhamed/">Ibrahim Hamed</a>, and <a target="_blank" href="https://www.linkedin.com/in/norhan-boghdadi/">Nourhan Boghdadi</a>.</p>
<p>We have taken on the responsibility to continue the journey and further develop the community. With a renewed sense of purpose, we made a triumphant return to our offline meetups, and there's much more on the horizon. The story of Swift Cairo is far from over, and we're excited to see where the next chapter takes us.</p>
<h2 id="heading-my-story">My Story</h2>
<p>As a junior iOS engineer, I joined Swift Cairo in 2018, and eagerly attended most of the meetups. I vividly remember the excitement I felt before each event and the joy that came with receiving the meetup invitation. Every time, I returned home with a notebook full of key points, new concepts to explore, and ideas to deepen my understanding.</p>
<p>The community wasn't just about the meetups; I frequently posted questions on our Slack channel, where other members generously offered their help and guidance. These interactions played a significant role in shaping my career, providing me with the knowledge and support I needed to grow as an engineer.</p>
<p>Now, as a senior iOS engineer, I feel a deep sense of responsibility to give back. The community has been instrumental in my journey, and I’m committed to helping new engineers improve their skills and advance in their careers, just as the community did for me</p>
<h2 id="heading-whats-next"><strong>What’s Next</strong></h2>
<p>Our mission is clear: "Take Egypt's engineers to the next level." To achieve this, we’re focusing on elevating the quality and scope of our meetups. We plan to explore a variety of perspectives, recognizing that it’s not always about the source code. We aim to provide a more holistic approach to engineering by diving into topics that broaden our understanding of the field.</p>
<p>In addition to our enhanced meetups, we have some exciting workshops in the pipeline, designed to challenge and inspire our members. These workshops will be announced very soon, and we can’t wait to see how they will further contribute to the growth of our community.</p>
<p>The journey of Swift Cairo is far from over, and we’re more committed than ever to help our engineers reach new heights.</p>
<h2 id="heading-tech-communities-the-key-to-opportunities">Tech Communities: The Key to Opportunities</h2>
<p>At Swift Cairo, we believe that every member has the power to make an impact. If you have an idea that could benefit the community, we’re always open to hearing it. Even small actions can have significant effects. For example, as you’re reading this, we’re excited to announce that we're partnering up with Klivvr for our next meetup on the 28th of August. This kind of support is invaluable, and it all starts with conversations. You can help by talking to your company’s management about our community and the positive impact it’s having on Egypt’s tech scene.</p>
<p>There are many ways to contribute. You can share useful tips, write articles, or even volunteer as a speaker for one of our upcoming meetups. Every contribution, big or small, helps us continue to grow and support our members.</p>
<p>Stay informed on our latests events and meetups by following us on <a target="_blank" href="https://x.com/SwiftCairo">X</a> and <a target="_blank" href="https://www.linkedin.com/company/swift-cairo">LinkedIn</a>.</p>
<h2 id="heading-special-thanks">Special Thanks</h2>
<p>I want to extend my heartfelt greetings to everyone whose part of the Swift Cairo community. Whether you’ve been with us since the beginning or just joined, your participation and enthusiasm are what make this community so special. Together, we’ve built a space where iOS engineers can learn, grow, and support each other, and that’s something truly worth celebrating.</p>
<p>Thank you for being a part of this journey. Let’s continue to push the boundaries, share our knowledge, and take Swift Cairo to even greater heights. Here’s to the future of our community and the incredible things we’ll achieve together!</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Money: A Walk Down Money Lane]]></title><description><![CDATA[Once upon a time on our planet, people traded cows for chickens. Simpler times, indeed. But let's be honest, who wants to drag a farm around while shopping? That’s what humanity wondered back then too, so someone, somewhere decided to use coins inste...]]></description><link>https://blog.klivvr.com/understanding-money-a-walk-down-money-lane</link><guid isPermaLink="true">https://blog.klivvr.com/understanding-money-a-walk-down-money-lane</guid><category><![CDATA[fintech]]></category><category><![CDATA[money]]></category><category><![CDATA[Klivvr]]></category><category><![CDATA[finance]]></category><dc:creator><![CDATA[Mohamed Mokhtar]]></dc:creator><pubDate>Mon, 12 Aug 2024 14:06:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748788911158/8dbf85e9-98c8-4657-9a3b-4fd8eee4a7d1.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Once upon a time on our planet, people traded cows for chickens. Simpler times, indeed. But let's be honest, who wants to drag a farm around while shopping? That’s what humanity wondered back then too, so someone, somewhere decided to use coins instead. Cool, golden, shiny coins. Those were trendy and hip for a while until banks came around.</p>
<p>People started thinking, "Hey, why not store our precious coins somewhere safe?" Banks then created paper bills, like little certificates for the gold people left behind. The concept of notes became popular; people liked the idea of storing all their heavy gold with the bank, and receiving a bank note as proof of ownership.</p>
<p>Fast forward to today...</p>
<p><img src="https://miro.medium.com/v2/resize:fit:828/format:webp/1*xgI1il5BJLihVMJYIxLd6Q.gif" alt class="image--center mx-auto" /></p>
<p>Money has gone through a major glow-up. The internet revolution spread and took over the world. People built online stores, and others bought from them. Physical wallets became digital wallets. Traditional banking gave way to digital banking. Physical money notes turned into digital money notes.</p>
<p>Money got a major glow-up in the internet era. We're talking digital wallets, online shopping, cryptocurrencies, and even apps like Klivvr to help us manage it all. Money has become a cultural icon, a topic for books, a muse for rappers, and a driving force behind dreams.</p>
<h2 id="heading-money-is-mindset">Money Is Mindset</h2>
<p>Money isn’t just a tool we use to renew our mobile internet bundle. Money is more than just numbers; it's personal. In <em>The Psychology of Money</em> Morgan Housel explains that our financial decisions aren't always logical. They're shaped by our unique experiences, upbringing, and emotions. What seems like a smart move for one person might be totally different for another. Housel further elaborates on how money has become a mindset, a reflection of a person’s dreams and values, a maker of visions and a creator of visionaries.</p>
<h2 id="heading-money-talks-are-you-listening">Money Talks, Are You Listening?</h2>
<p>Speaking of mindsets, Napoleon Hill says in his book <em>Think and Grow Rich</em> that your thoughts are like money magnets. Desire, faith, imagination, decisiveness, and persistence are all tools we humans can use to attract and generate massive wealth. Manifestation, eh? So, visualize that dream vacation with your new shiny car, and who knows? It might just come true. ✨</p>
<h2 id="heading-financial-freedom-more-than-just-money-in-the-bank">Financial Freedom: More Than Just Money in the Bank</h2>
<p>Let's get real: Financial freedom isn't just about having a juicy bank account. It's about having the freedom to live life on your own terms. It's about chasing your passions, exploring the world, and making memories that last a lifetime. You do NOT need a man in finance, trust funds, 6'5, blue eyes (or be one yourself) to be good with money. It's more about controlling your impulses, developing good habits, and making consistent choices over time.</p>
<h2 id="heading-klivvr-your-money-companion">Klivvr: Your Money Companion</h2>
<p>We understand money. Klivvr knows that money isn't just about numbers. We're here to make your financial life easier, more fun, and less stressful. Whether you're sending money to your bestie, splitting bills with your roommates, or saving for that dream vacation, we've got your back.</p>
]]></content:encoded></item><item><title><![CDATA[Sky High Content: A UX Writer’s Guide to Problem Solving]]></title><description><![CDATA[Every writer dreads publishing a post only to find a typo. For UX writers, this struggle extends further: releasing in-app content and discovering that an error message fails to clearly explain the issue or offer a solution.
This not only frustrates ...]]></description><link>https://blog.klivvr.com/sky-high-content-a-ux-writers-guide-to-problem-solving</link><guid isPermaLink="true">https://blog.klivvr.com/sky-high-content-a-ux-writers-guide-to-problem-solving</guid><category><![CDATA[UX]]></category><category><![CDATA[ux writing]]></category><category><![CDATA[writing]]></category><category><![CDATA[OTA]]></category><category><![CDATA[fintech]]></category><dc:creator><![CDATA[Salma Sabry]]></dc:creator><pubDate>Mon, 05 Aug 2024 12:33:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748788941216/0b9081dd-9120-487d-b713-026dad403737.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Every writer dreads publishing a post only to find a typo. For UX writers, this struggle extends further: releasing in-app content and discovering that an error message fails to clearly explain the issue or offer a solution.</p>
<p>This not only frustrates the user but also you, the UX writer, especially when the fix has to wait for the next app update.</p>
<h1 id="heading-over-the-air-and-quick-fixes">Over-the-Air and Quick Fixes</h1>
<p>In our previous <a target="_blank" href="https://blog.klivvr.com/klivvr-revamp-the-fun-in-funds#clucl2y7h000k08jqhds3dprh">blog</a>, we discussed how using Phrase Strings—our localization tool—enabled us to efficiently introduce Klivvr's Arabic version. Phrase helps us manage content in both English and Arabic seamlessly.</p>
<p>While this made managing content easier, it still didn’t solve the need to create a new release for every content modification. Here comes in the real star: over-the-air (OTA). OTA was a win-win: it allowed me to make quick fixes, and introduce new translations with little to no reliance on developers, which freed them from content-related tasks.</p>
<h2 id="heading-how-it-works"><strong>How it Works</strong></h2>
<p>To implement OTA, we linked our app project file on Phrase to a distribution where our developers included the SDK into their projects. After this was setup, we simply look up existing keys and change their content or add translations. With every change, a new OTA release is made, that reflects instantly, as opposed to an app release. This saved us time, and allowed us to skip the store’s approval.</p>
<p>Here’s what Mohamed Hisham, our iOS lead had to say:</p>
<blockquote>
<p>Before Phrase over-the-air, fixing even a single string error meant a full build release—often over the weekend. My keyboard saw more spilled spaghetti than I'd care to admit. But implementing Phrase was a breeze; all I had to do was include the SDK in my project, and we were good to go. Now, we fix those pesky typos without a new release, and my keyboard stays clean. It's a win-win! Plus, our localization process is faster and more efficient than ever, making our whole team happy.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722852244555/c4c57b00-b505-4060-94d1-d0c8616e1c31.png" alt class="image--center mx-auto" /></p>
<p><em>Creating a release allows us to filter our changes by tags, and specify the app versions using these changes apply to.</em></p>
<h2 id="heading-real-world-example-improving-error-messages"><strong>Real-World Example: Improving Error Messages</strong></h2>
<p>Following up on the pickle we found ourselves into at the start of the article, in one of our older screens our users received a generic error message when they were not connected to the internet. The message read:</p>
<p><strong>Heading:</strong> "Something went wrong"<br /><strong>Description:</strong> "We could not process your request. Try again later."</p>
<p>This message was confusing and did not help users understand the actual issue. Using OTA updates, we quickly improved this by changing the values of the existing keys to:</p>
<p><strong>Heading:</strong> "No Internet Connection"<br /><strong>Description:</strong> "Make sure you're connected to the internet and try again."</p>
<p>This change was implemented instantly without needing a full app update, enhancing user experience and reducing frustration.</p>
<h1 id="heading-stay-informed-amp-inspired">Stay Informed &amp; Inspired</h1>
<p>The ability to make quick, efficient updates using OTA has transformed our approach to UX writing. By utilizing this technology, we can always ensure that app updates are reserved for design, and technical changes, while also allowing our users to have a smoother, more intuitive experience.</p>
]]></content:encoded></item><item><title><![CDATA[Bridging the Gap Between Education and Real-World Experience]]></title><description><![CDATA[Ever wondered why internships are such a big deal? Well, they’re like the ultimate career hack! Internships bridge the gap between what you learn in school and what you do in the real world. They’re all about diving into the nitty-gritty of your chos...]]></description><link>https://blog.klivvr.com/bridging-the-gap-between-education-and-real-world-experience</link><guid isPermaLink="true">https://blog.klivvr.com/bridging-the-gap-between-education-and-real-world-experience</guid><category><![CDATA[internships]]></category><category><![CDATA[internship]]></category><category><![CDATA[fintech]]></category><dc:creator><![CDATA[Ahmed Ramzy]]></dc:creator><pubDate>Mon, 29 Jul 2024 12:46:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748788964968/0d1f82bb-b11f-4d4c-8c31-7a6c2e752084.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Ever wondered why internships are such a big deal? Well, they’re like the ultimate career hack! Internships bridge the gap between what you learn in school and what you do in the real world. They’re all about diving into the nitty-gritty of your chosen field, getting hands-on experience, and making those classroom lessons come alive.</p>
<p>For you, a future intern, an internship means building skills, making connections, and getting a taste of what your future career looks like. And for forward-thinking companies like Klivvr, it’s a chance to meet fresh talents and see new ideas in action. Our interns bring energy and innovation, helping us stay ahead of the curve.</p>
<h2 id="heading-defining-the-process">Defining the Process</h2>
<p>At Klivvr, we’ve meticulously crafted an internship program focused on growth and learning. It’s not just about doing the work; it’s about becoming an integral part of the team and making a real impact. Hatem Maamoun, our VP of Engineering, posed a pivotal question to our team: "Who wants to contribute to the internship program?" Immediately, Muhammed Youssef, Mohammed El-Sheikh, Moataz Mohammed, Haidy Emad, Kerolles Magdy, Mohammed Sherief, Mohammed El Hinamy, and myself—Ahmed Ramzy—stepped up to the challenge.</p>
<p>He then entrusted us with the task of designing the entire program—from the projects interns would work on, to the screening process, and the management of their daily tasks. Meanwhile, Yacoub Yassin, former Product Manager, took charge of mentoring the product manager intern, and Mai Soliman, our UX Researcher, dedicated herself to guiding the product design interns.</p>
<p>Together, we brainstormed various ideas and agreed on the following approach: We sought talent with a solid grasp of programming basics and strong problem-solving skills, along with foundational knowledge of relevant technologies (iOS, Android, and Backend). The interns would be tasked with working on a project that provides hands-on learning experience within Klivvr.</p>
<p>Each of us would manage the interns for a week, ensuring they receive diverse perspectives and guidance. We also coordinated with other departments to provide valuable learning sessions on topics crucial to our operations. This immersive approach allowed our interns to engage fully, gaining a realistic experience of workplace dynamics.</p>
<h2 id="heading-meet-our-2023-interns">Meet our 2023 Interns</h2>
<p>After filtering numerous CVs, our HR team conducted interviews with 40 candidates across different teams to ensure they met our criteria. We selected eight interns for the engineering team, three for product design, and one for product management. Our internship program underscores Klivvr's commitment to diversity and inclusion.</p>
<p>Meet our talented interns: Eman Mohammed, Dalia Hamada, Nadeen Serag, Mariam Ame, Muhamed Magdy, and John Nabil joined our engineering team. Shaza Omar, Marium Nour, and Muhamed Ashraf enriched our product design team, while Mohammed Adel took on the role of a product manager. Each intern brought a unique perspective, and the excitement to learn and grow professionally.</p>
<p>For the engineering team, Eman, Dalia, Nadeen, Mariam, Muhamed, and Keroless were eager to delve into programming, software development, and system architecture. They aimed to strengthen their technical skills while contributing to innovative projects that push the boundaries of technology.</p>
<p>In the realm of product design, Shaza, Marium, and Muhamed were driven by creativity and user-centric design principles. They aspired to craft intuitive user interfaces and engaging experiences that resonate with Klivvr’s users.</p>
<p>As for Mohammed Adel, our product manager intern, he focused on mastering the art of product lifecycle management, from ideation to delivery. He collaborated across teams, ensuring that our products exceed customer expectations.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722239465342/290b0190-7ccf-46e9-9095-52290ad034f7.jpeg" alt class="image--center mx-auto" /></p>
<p><em>Our Interns with our tech team on their last day</em></p>
<h2 id="heading-the-program">The Program</h2>
<p>At Klivvr, we are committed to offering interns a transformative experience through our structured internship program. It begins with a thorough orientation and onboarding process designed to familiarize interns with our company culture, values, and operational dynamics. During this period, interns also receive comprehensive training on our systems, tools, and best practices, ensuring they are well-prepared to contribute effectively from day one.</p>
<p>On their first day, we onboarded the interns to the project they would be working on—the Klivvr social app, a platform designed for Klivvr employees to communicate, celebrate, and have fun together. We introduced them to their mentors, who would guide them each week, and provided an overview of the internship program. This included the goals, expectations, and resources available to support their learning and development.</p>
<p>On the second day, the interns began by reviewing their backlogs and familiarizing themselves with Kanban boards. This was crucial for them to understand how tasks are managed and prioritized. They learned how to extract technical details from tasks and effectively plan their work.</p>
<p>A typical day for our interns started with a daily stand-up meeting, where they discussed their progress, planned for the day, and addressed any blockers they encountered. This practice not only kept everyone on the same page but also fostered a collaborative environment.</p>
<p>Following the stand-up, interns would dive into their project work, applying their skills and learning through hands-on experience. Regular mentorship sessions were a key feature of the program. These sessions alternated between technical topics—such as coding practices, system architecture, and debugging techniques—and soft skills, including effective communication, teamwork, and problem-solving.</p>
<p>Mentorship and supervision formed the backbone of our program. Each intern was paired with a mentor who provided guidance and support throughout the internship. Mentors shared valuable industry insights, offered career advice, and helped interns navigate challenges. Regular check-ins and mentoring sessions ensured that interns received continuous feedback, enabling them to learn and grow professionally.</p>
<p>Feedback and evaluation were integral components of our program. Interns received constructive feedback on their work and performance from mentors and project leads. This feedback was instrumental in identifying strengths and areas for improvement, fostering a culture of continuous learning and development. Formal evaluations provided interns with a holistic view of their progress and achievements, recognizing their contributions and preparing them for future career opportunities.</p>
<p>In addition to project work, we arranged off-topic sessions where interns could learn from other departments. The data team, information security team, product team, and HR team each conducted sessions to explain and demonstrate their roles and impact on the company. These sessions were designed to give interns a broader understanding of how different functions contribute to the success of the company.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722239736898/fe7d7528-02df-4316-903c-3b6e52c6f9db.jpeg" alt class="image--center mx-auto" /></p>
<p><em>Our interns attending a session held by the Data Team</em></p>
<p>To ensure individual attention and address any concerns, we scheduled regular one-on-one meetings. These sessions allowed mentors to provide personalized feedback, discuss any challenges interns were facing, and offer additional support as needed. This personalized approach helped interns feel valued and supported throughout their journey.</p>
<h2 id="heading-the-impact">The Impact</h2>
<p>The internship program at Klivvr has yielded remarkable outcomes for our interns. By the end of the program, our interns gained hands-on experience, enhanced their technical skills, and developed essential soft skills like teamwork, communication, and problem-solving. Additionally, many of our interns secured excellent opportunities at other leading companies in the tech industry, a testament to the solid foundation they built during their time with us.</p>
<p>The impact of our internship program on Klivvr has been significant and multifaceted. Interns brought fresh perspectives and innovative ideas, infusing our projects with new energy and creativity. Moreover, integrating interns into our teams fostered a culture of mentorship and continuous learning among our staff. By engaging with the interns, our employees honed their leadership and teaching skills, creating a more collaborative and dynamic work environment. We are continuously working on enhancing our internship program to provide an even more enriching experience.</p>
<h2 id="heading-testimony-amp-advice-for-future-interns">Testimony &amp; Advice for Future Interns</h2>
<p>Marium's journey at Klivvr was significantly influenced by the mentorship she received. "I was able to understand how important research is, and we don’t just decide this is how we want the product to look like and that’s it. t is a continuous loop where you try, test, get feedback, and improve," she shared. While shadowing one of our designers, Ahmed Badry, she learned the intricacies of the design process and the value of persistent learning.</p>
<p>Adel's path to becoming a full-time product manager at Klivvr began with a specific goal in mind. "There was a big learning curve, and I had the opportunity to build so much during the two-month internship. When I got the opportunity to continue, it was the cherry on top. I believed that my learning journey was not over at Klivvr," Adel recounted. He emphasized the importance of understanding the relationship between the product team and other departments. "Dealing with different stakeholders with their varying positions, and the relation between product and tech, was the most valuable thing I learned at Klivvr," he explained.</p>
<p>Marium and Adel, now full-time employees at Klivvr, have some advice for future interns. "Push yourself and give it your maximum effort. Don’t take it lightly; take it as a real job and push yourself," Marium advises. Adel adds, "Work on real products, don’t overthink the policies, and push yourself to your maximum effort</p>
]]></content:encoded></item><item><title><![CDATA[What is “funflation”?]]></title><description><![CDATA[We’ve all heard of “YOLO”, “money comes and goes” and “girl maths”. But when “funflation” entered the equation, we knew things were getting serious and that we had to keep up. So, what does this new funky term mean exactly?
https://giphy.com/gifs/bro...]]></description><link>https://blog.klivvr.com/what-is-funflation</link><guid isPermaLink="true">https://blog.klivvr.com/what-is-funflation</guid><category><![CDATA[funflation]]></category><category><![CDATA[digital bank]]></category><category><![CDATA[fintech]]></category><category><![CDATA[Klivvr]]></category><category><![CDATA[KlivvvrGoPlus]]></category><dc:creator><![CDATA[Amira Gamil]]></dc:creator><pubDate>Tue, 23 Jul 2024 13:47:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748788996277/78d836d2-8291-4ea2-bb9d-6183aed44411.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We’ve all heard of “YOLO”, “money comes and goes” and “girl maths”. But when “funflation” entered the equation, we knew things were getting serious and that we had to keep up. So, what does this new funky term mean exactly?</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://giphy.com/gifs/brooklynninenine-tv-nbc-brooklyn-99-VgfGPXUVuX6tWov6Kj">https://giphy.com/gifs/brooklynninenine-tv-nbc-brooklyn-99-VgfGPXUVuX6tWov6Kj</a></div>
<p> </p>
<p>Well, economists noticed a new spending pattern post-COVID, which is that we are all about having fun now. Statistics show that despite rising prices, people started going crazy for things that were “forbidden” during the months of lockdown, such as concert tickets and flights. This was the case for the majority of people, whether they could actually afford these purchases or not.</p>
<p>Some people call it “revenge spending”, others could argue that it’s a form of FOMO in fear of another lockdown, but what we’re sure of is that a lot of people have ditched saving for the moment. </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://giphy.com/gifs/amy-poehler-yolo-chewing-gum-84EQtaETcza8w">https://giphy.com/gifs/amy-poehler-yolo-chewing-gum-84EQtaETcza8w</a></div>
<p> </p>
<p>According to a research done by American software company Intuit in January 2023, 2 in 3 Gen-Zers perceive money as a tool “to support their other interests in life”. So, whether it be the latest Eras Tour or the UEFA, people are prioritizing experiencing new things rather than being financially secure.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://giphy.com/gifs/taylorswift-taylor-swift-taylorswift13-the-eras-tour-M6HMAgtqGHrI330ZH7">https://giphy.com/gifs/taylorswift-taylor-swift-taylorswift13-the-eras-tour-M6HMAgtqGHrI330ZH7</a></div>
<p> </p>
<p>It’s like we cling onto the tiniest possible trends just to go all out and be as extra as possible. I mean, Barbenheimer? Spending up to 500 LE for a cinema ticket, a strikingly pink outfit and an overpriced box of popcorn? In this economy?</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://giphy.com/gifs/friday-myposts-ddd0HBTakik00">https://giphy.com/gifs/friday-myposts-ddd0HBTakik00</a></div>
<p> </p>
<p>This could be due to the fact that people no longer see financial security as evitable, and thus have resorted to living life to the fullest instead. This is especially the case due to how COVID-19 have impacted everyone’s social life, which explains why the live entertainment industry is everyone’s number one priority right now when it comes to spending. They’re making up for all the days we spent bored to death stuck at home with nowhere to go! </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://giphy.com/gifs/moodman-chVgEkHr9oYz4ZPGeU">https://giphy.com/gifs/moodman-chVgEkHr9oYz4ZPGeU</a></div>
<p> </p>
<p>But whether funflation is just a spending trend or will lead to a tragic financial downfall, it’s interesting to observe how sociology and finances interact in motion!</p>
]]></content:encoded></item><item><title><![CDATA[Budgeting Guide for Sahel Season]]></title><description><![CDATA[You check the calendar anxiously, biting your lips, shuffling through your empty wallet, and muttering “summer" through gritted teeth.


We know that horrified face all too well, but it doesn’t have to be like that! Here’s how you can financially pre...]]></description><link>https://blog.klivvr.com/budgeting-guide-for-sahel-season</link><guid isPermaLink="true">https://blog.klivvr.com/budgeting-guide-for-sahel-season</guid><category><![CDATA[budget]]></category><category><![CDATA[Financial Services]]></category><category><![CDATA[summer]]></category><dc:creator><![CDATA[Amira Gamil]]></dc:creator><pubDate>Wed, 17 Jul 2024 13:21:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748789018972/251d3640-551e-4c64-8910-71a07a4336eb.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You check the calendar anxiously, biting your lips, shuffling through your empty wallet, and muttering “summer" through gritted teeth.</p>
<iframe src="https://giphy.com/embed/XDGEiOU1Dt7Lq" width="480" height="269" class="giphy-embed"></iframe>

<p>We know that horrified face all too well, but it doesn’t have to be like that! Here’s how you can financially prepare for the summer season like a pro!</p>
<p>-<strong>Plan ahead</strong></p>
<p>Start listing all your expenses for the holiday early in advance, so that nothing comes as a surprise! Writing down all the expected costs will help you stay in control so that you can know exactly what you need for the coming period. This includes checking the possible travel destinations, hotel prices, renting options, and other incurred costs that come with the warmer months.</p>
<iframe src="https://giphy.com/embed/l1Eted76BinAkF7YA" width="480" height="271" class="giphy-embed"></iframe>

<p>-<strong>Determine your income</strong></p>
<p>It’s an equation that doesn’t stop at analyzing expenses. You need to analyze all sources of revenue so you can measure what will be left off at the end after paying your expenses (your income!). By being realistic with the money that will be available for you, you can more accurately anticipate how your spending can go!</p>
<p>-<strong>Track your spending</strong></p>
<p>As your summer getaway comes closer, start being aware of how your bank account is looking. Track how your spending is going so you can check if there is any unnecessary costs you can ditch in order to be good to go. Setting realistic expectations is key to smooth spending!</p>
<iframe src="https://giphy.com/embed/l0G16tpHNHtsDTSWA" width="480" height="367" class="giphy-embed"></iframe>

<p>-<strong>Start budgeting</strong></p>
<p>Now that you’ve calculated the available money, start allocating it to each category of the trip's expenses depending on their priority. This ensures that you won’t be surprised by how much you need as it approaches. Oh and please, let's beware of needs vs wants!</p>
<p>-<strong>Spend smart</strong></p>
<p>Summer doesn’t have to be a burden on your paycheck! Look for discounts, cashback, and rewards programs to get all you dream of at a discounted price. (Take a look at Klivvr's partners while you're at it!)</p>
<iframe src="https://giphy.com/embed/3o7TKqbBuNfcLMTXSo" width="480" height="314" class="giphy-embed"></iframe>

<p>-<strong>Have fun!</strong></p>
<p>Money comes and goes but these sweet summer memories last forever! As long as you plan and spend cautiously, you can rest assured that summer 2024 will go as smoothly as ever.</p>
]]></content:encoded></item></channel></rss>