Archive

Archive for the ‘’ Category

Navigating The Challenges Of Modern Open-Source Authoring: Lessons Learned

January 21st, 2025 No comments

This article is a sponsored by Storyblok

Open source is the backbone of modern software development. As someone deeply involved in both community-driven and company-driven open source, I’ve had the privilege of experiencing its diverse approaches firsthand. This article dives into what modern OSS (Open Source) authoring looks like, focusing on front-end JavaScript libraries such as TresJS and tools I’ve contributed to at Storyblok.

But let me be clear:

There’s no universal playbook for OSS. Every language, framework, and project has its own workflows, rules, and culture — and that’s okay. These variations are what make open source so adaptable and diverse.

The Art Of OSS Authoring

Authoring an open-source project often begins with scratching your own itch — solving a problem you face as a developer. But as your “experiment” gains traction, the challenge shifts to addressing diverse use cases while maintaining the simplicity and focus of the original idea.

Take TresJS as an example. All I wanted was to add 3D to my personal Nuxt portfolio, but at that time, there wasn’t a maintained, feature-rich alternative to React Three Fiber in VueJS. So, I decided to create one. Funny enough, after two years after the library’s launch, my portfolio remains unfinished.

Community-driven OSS Authoring: Lessons From TresJS

Continuing with TresJS as an example of a community-driven OSS project, the community has been an integral part of its growth, offering ideas, filing issues (around 531 in total), and submitting pull requests (around 936 PRs) of which 90% eventually made it to production. As an author, this is the best thing that can happen — it’s probably one of the biggest reasons I fell in love with open source. The continuous collaboration creates an environment where new ideas can evolve into meaningful contributions.

However, it also comes with its own challenges. The more ideas come in, the harder it becomes to maintain the project’s focus on its original purpose.

As authors, it’s our responsibility to keep the vision of the library clear — even if that means saying no to great ideas from the community.

Over time, some of the most consistent collaborators became part of a core team, helping to share the responsibility of maintaining the library and ensuring it stays aligned with its original goals.

Another crucial aspect of scaling a project, especially one like TresJS, which has grown into an ecosystem of packages, is the ability to delegate. The more the project expands, the more essential it becomes to distribute responsibilities among contributors. Delegation helps in reducing the burden of the massive workload and empowers contributors to take ownership of specific areas. As a core author, it’s equally important to provide the necessary tools, CI workflows, and clear conventions to make the process of contributing as simple and efficient as possible. A well-prepared foundation ensures that new and existing collaborators can focus on what truly matters — pushing the project forward.

Company-driven OSS Authoring: The Storyblok Perspective

Now that we’ve explored the bright spots and challenges of community-driven OSS let’s jump into a different realm: company-driven OSS.

I had experience with inner-source and open-source in previous companies, so I already had a grasp of how OSS works in the context of a company environment. However, my most meaningful experience would come later, specifically earlier this year, when I switched my role from DevRel to a full-time Developer Experience Engineer, and I say “full-time” because before taking the role, I was already contributing to Storyblok’s SDK ecosystem.

At Storyblok, open source plays a crucial role in how we engage with developers and how they seamlessly use our product with their favorite framework. Our goal is to provide the same developer experience regardless of the flavor, making the experience of using Storyblok as simple, effective, and enjoyable as possible.

To achieve this, it’s crucial to balance the needs of the developer community — which often reflect the needs of the clients they work for — with the company’s broader goals. One of the things I find more challenging is managing expectations. For instance, while the community may want feature requests and bug fixes to be implemented quickly, the company’s priorities might dictate focusing on stability, scalability, and often strategic integrations. Clear communication and prioritization are key to maintaining healthy alignment and trust between both sides.

One of the unique advantages of company-driven open source is the availability of resources:

  • Dedicated engineering time,
  • Infrastructure (which many OSS authors often cannot afford),
  • Access to knowledge from internal teams like design, QA, and product management.

However, this setup often comes with the challenge of dealing with legacy codebases — typically written by developers who may not be familiar with OSS principles. This can lead to inconsistencies in structure, testing, and documentation that require significant refactoring before the project can align with open-source best practices.

Navigating The Spectrum: Community vs. Company

I like to think of community-driven OSS as being like jazz music—freeform, improvised, and deeply collaborative. In contrast, company-driven OSS resembles an orchestra, with a conductor guiding the performance and ensuring all the pieces fit together seamlessly.

The truth is that most OSS projects — if not the vast majority — exist somewhere along this spectrum. For example, TresJS began as a purely community-driven project, but as it matured and gained traction, elements of structured decision-making — more typical of company-driven projects — became necessary to maintain focus and scalability. Together with the core team, we defined a vision and goals for the project to ensure it continued to grow without losing sight of its original purpose.

Interestingly, the reverse is also true: Company-driven OSS can benefit significantly from the fast-paced innovation seen in community-driven projects.

Many of the improvements I’ve introduced to the Storyblok ecosystem since joining were inspired by ideas first explored in TresJS. For instance, migrating the TresJS ecosystem to pnpm workspaces demonstrated how streamlined dependency management could improve development workflows like playgrounds and e2e — an approach we gradually adapted later for Storyblok’s ecosystem.

Similarly, transitioning Storyblok testing from Jest to Vitest, with its improved performance and developer experience, was influenced by how testing is approached in community-driven projects. Likewise, our switch from Prettier to ESLint’s v9 flat configuration with auto-fix helped consolidate linting and formatting into a single workflow, streamlining developer productivity.

Even more granular processes, such as modernizing CI workflows, found their way into Storyblok. TresJS’s evolution from a single monolithic release action to granular steps for linting, testing, and building provided a blueprint for enhancing our pipelines at Storyblok. We also adopted continuous release practices inspired by pkg.pr.new, enabling faster delivery of incremental changes and testing package releases in real client projects to gather immediate feedback before merging the PRs.

That said, TresJS also benefited from my experiences at Storyblok, which had a more mature and battle-tested ecosystem, particularly in adopting automated processes. For example, we integrated Dependabot to keep dependencies up to date and used auto-merge to reduce manual intervention for minor updates, freeing up contributors’ time for more meaningful work. We also implemented an automatic release pipeline using GitHub Actions, inspired by Storyblok’s workflows, ensuring smoother and more reliable releases for the TresJS ecosystem.

The Challenges of Modern OSS Authoring

Throughout this article, we’ve touched on several modern OSS challenges, but if one deserves the crown, it’s managing breaking changes and maintaining compatibility. We know how fast the pace of technology is, especially on the web, and users expect libraries and tools to keep up with the latest trends. I’m not the first person to say that hype-driven development can be fun, but it is inherently risky and not your best ally when building reliable, high-performance software — especially in enterprise contexts.

Breaking changes exist. That’s why semantic versioning comes into play to make our lives easier. However, it is equally important to balance innovation with stability. This becomes more crucial when introducing new features or refactoring for better performance, breaking existing APIs. One key lesson I’ve learned — particularly during my time at Storyblok — is the importance of clear communication. Changelogs, migration guides, and deprecation warnings are invaluable tools to smoothen the transition for users.

A practical example:

My first project as a Developer Experience Engineer was introducing @storyblok/richtext, a library for rich-text processing that (at the time of writing) sees around 172k downloads per month. The library was crafted during my time as a DevRel, but transitioning users to it from the previous rich-text implementation across the ecosystem required careful planning. Since the library would become a dependency of the fundamental JS SDK — and from there propagate to all the framework SDKs — together with my manager, we planned a multi-month transition with a retro-compatible period before the major release. This included communication campaigns, thorough documentation, and gradual adoption to minimize disruption.

Despite these efforts, mistakes happened — and that’s okay. During the rich-text transition, there were instances where updates didn’t arrive on time or where communication and documentation were temporarily out of sync. This led to confusion within the community, which we addressed by providing timely support on GitHub issues and Discord. These moments served as reminders that even with semantic versioning, modular architectures, and meticulous planning, OSS authoring is never perfect. Mistakes are part of the process.

And that takes us to the following point.

Conclusion

Open-source authoring is a journey of continuous learning. Each misstep offers a chance to improve, and each success reinforces the value of collaboration and experimentation.

There’s no “perfect” way to do OSS, and that’s the beauty of it. Every project has its own set of workflows, challenges, and quirks shaped by the community and its contributors. These differences make open source adaptable, dynamic, fun, and, above all, impactful. No matter if you’re building something entirely new or contributing to an existing project, remember that progress, not perfection, is the goal.

So, keep contributing, experimenting, and sharing your work. Every pull request, issue, and idea you put forward brings value &mdashp not just to your project but to the broader ecosystem.

Happy coding!

Categories: Others Tags:

3 Essential Design Trends, January 2025

January 20th, 2025 No comments

From circles to background text elements to high-drama imagery, 2025 is off to a great start with these website design trends.

Categories: Designing, Others Tags:

Fancy Menu Navigation Using Anchor Positioning

January 17th, 2025 No comments

You have for sure heard about the new CSS Anchor Positioning, right? It’s a feature that allows you to link any element from the page to another one, i.e., the anchor. It’s useful for all the tooltip stuff, but it can also create a lot of other nice effects.

In this article, we will study menu navigation where I rely on anchor positioning to create a nice hover effect on links.

CodePen Embed Fallback

Cool, right? We have a sliding effect where the blue rectangle adjusts to fit perfectly with the text content over a nice transition. If you are new to anchor positioning, this example is perfect for you because it’s simple and allows you to discover the basics of this new feature. We will also study another example so stay until the end!

Note that only Chromium-based browsers fully support anchor positioning at the time I’m writing this. You’ll want to view the demos in a browser like Chrome or Edge until the feature is more widely supported in other browsers.

The initial configuration

Let’s start with the HTML structure which is nothing but a nav element containing an unordered list of links:

<nav>
  <ul>
    <li><a href="#">Home</a></li>
    <li class="active"><a href="#">About</a></li>
    <li><a href="#">Projects</a></li>
    <li><a href="#">Blog</a></li>
    <li><a href="#">Contact</a></li>
  </ul>
</nav>

We will not spend too much time explaining this structure because it can be different if your use case is different. Simply ensure the semantic is relevant to what you are trying to do. As for the CSS part, we will start with some basic styling to create a horizontal menu navigation.

ul {
  padding: 0;
  margin: 0;
  list-style: none;
  display: flex;
  gap: .5rem;
  font-size: 2.2rem;
}

ul li a {
  color: #000;
  text-decoration: none;
  font-weight: 900;
  line-height: 1.5;
  padding-inline: .2em;
  display: block;
}

Nothing fancy so far. We remove some default styling and use Flexbox to align the elements horizontally.

CodePen Embed Fallback

Sliding effect

First off, let’s understand how the effect works. At first glance, it looks like we have one rectangle that shrinks to a small height, moves to the hovered element, and then grows to full height. That’s the visual effect, but in reality, more than one element is involved!

Here is the first demo where I am using different colors to better see what is happening.

CodePen Embed Fallback

Each menu item has its own “element” that shrinks or grows. Then we have a common “element” (the one in red) that slides between the different menu items. The first effect is done using a background animation and the second one is where anchor positioning comes into play!

The background animation

We will animate the height of a CSS gradient for this first part:

/* 1 */
ul li {
  background: 
    conic-gradient(lightblue 0 0)
    bottom/100% 0% no-repeat;
  transition: .2s;
}

/* 2 */
ul li:is(:hover,.active) {
  background-size: 100% 100%;
  transition: .2s .2s;
}

/* 3 */
ul:has(li:hover) li.active:not(:hover) {
  background-size: 100% 0%;
  transition: .2s;
}

We’ve defined a gradient with a 100% width and 0% height, placed at the bottom. The gradient syntax may look strange, but it’s the shortest one that allows me to have a single-color gradient.

Related: “How to correctly define a one-color gradient”

Then, if the menu item is hovered or has the .active class, we make the height equal to 100%. Note the use of the delay here to make sure the growing happens after the shrinking.

Finally, we need to handle a special case with the .active item. If we hover any item (that is not the active one), then the .active item gets the shirking effect (the gradient height is equal to 0%). That’s the purpose of the third selector in the code.

CodePen Embed Fallback

Our first animation is done! Notice how the growing begins after the shrinking completes because of the delay we defined in the second selector.

The anchor positioning animation

The first animation was quite easy because each item had its own background animation, meaning we didn’t have to care about the text content since the background automatically fills the whole space.

We will use one element for the second animation that slides between all the menu items while adapting its width to fit the text of each item. This is where anchor positioning can help us.

Let’s start with the following code:

ul:before {
  content:"";
  position: absolute;
  position-anchor: --li;
  background: red;
  transition: .2s;
}

ul li:is(:hover, .active) {
  anchor-name: --li;
}

ul:has(li:hover) li.active:not(:hover) {
  anchor-name: none;
}

To avoid adding an extra element, I will prefer using a pseudo-element on the ul. It should be absolutely-positioned and we will rely on two properties to activate the anchor positioning.

We define the anchor with the anchor-name property. When a menu item is hovered or has the .active class, it becomes the anchor element. We also have to remove the anchor from the .active item if another item is in a hovered state (hence, the last selector in the code). In other words, only one anchor is defined at a time.

Then we use the position-anchor property to link the pseudo-element to the anchor. Notice how both use the same notation --li. It’s similar to how, for example, we define @keyframes with a specific name and later use it inside an animation property. Keep in mind that you have to use the syntax, meaning the name must always start with two dashes (--).

CodePen Embed Fallback

The pseudo-element is correctly placed but nothing is visible because we didn’t define any dimension! Let’s add the following code:

ul:before {
  bottom: anchor(bottom);
  left: anchor(left);
  right: anchor(right);
  height: .2em;  
}

The height property is trivial but the anchor() is a newcomer. Here’s how Juan Diego describes it in the Almanac:

The CSS anchor() function takes an anchor element’s side and resolves to the where it is positioned. It can only be used in inset properties (e.g. top, bottom, bottom, left, right, etc.), normally to place an absolute-positioned element relative to an anchor.

Let’s check the MDN page as well:

The anchor() CSS function can be used within an anchor-positioned element’s inset property values, returning a length value relative to the position of the edges of its associated anchor element.

Usually, we use left: 0 to place an absolute element at the left edge of its containing block (i.e., the nearest ancestor having position: relative). The left: anchor(left) will do the same but instead of the containing block, it will consider the associated anchor element.

That’s all — we are done! Hover the menu items in the below demo and see how the pseudo-element slides between them.

CodePen Embed Fallback

Each time you hover over a menu item it becomes the new anchor for the pseudo-element (the ul:before). This also means that the anchor(...) values will change creating the sliding effect! Let’s not forget the use of the transition which is important otherwise, we will have an abrupt change.

We can also write the code differently like this:

ul:before {
  content:"";
  position: absolute;
  inset: auto anchor(right, --li) anchor(bottom, --li) anchor(left, --li);
  height: .2em;  
  background: red;
  transition: .2s;
}

In other words, we can rely on the inset shorthand instead of using physical properties like left, right, and bottom, and instead of defining position-anchor, we can include the anchor’s name inside the anchor() function. We are repeating the same name three times which is probably not optimal here but in some situations, you may want your element to consider multiple anchors, and in such cases, this syntax will make sense.

Combining both effects

Now, we combine both effects and, tada, the illusion is perfect!

CodePen Embed Fallback

Pay attention to the transition values where the delay is important:

ul:before {
  transition: .2s .2s;
}

ul li {
  transition: .2s;
}

ul li:is(:hover,.active) {
  transition: .2s .4s;
}

ul:has(li:hover) li.active:not(:hover) {
  transition: .2s;
}

We have a sequence of three animations — shrink the height of the gradient, slide the pseudo-element, and grow the height of the gradient — so we need to have delays between them to pull everything together. That’s why for the sliding of the pseudo-element we have a delay equal to the duration of one animation (transition: .2 .2s) and for the growing part the delay is equal to twice the duration (transition: .2s .4s).

Bouncy effect? Why not?!

Let’s try another fancy animation in which the highlight rectangle morphs into a small circle, jumps to the next item, and transforms back into a rectangle again!

CodePen Embed Fallback

I won’t explain too much for this example as it’s your homework to dissect the code! I’ll offer a few hints so you can unpack what’s happening.

Like the previous effect, we have a combination of two animations. For the first one, I will use the pseudo-element of each menu item where I will adjust the dimension and the border-radius to simulate the morphing. For the second animation, I will use the ul pseudo-element to create a small circle that I move between the menu items.

Here is another version of the demo with different coloration and a slower transition to better visualize each animation:

CodePen Embed Fallback

The tricky part is the jumping effect where I am using a strange cubic-bezier() but I have a detailed article where I explain the technique in my CSS-Tricks article “Advanced CSS Animation Using cubic-bezier().

Conclusion

I hope you enjoyed this little experimentation using the anchor positioning feature. We only looked at three properties/values but it’s enough to prepare you for this new feature. The anchor-name and position-anchor properties are the mandatory pieces for linking one element (often called a “target” element in this context) to another element (what we call an “anchor” element in this context). From there, you have the anchor() function to control the position.

Related: CSS Anchor Positioning Guide


Fancy Menu Navigation Using Anchor Positioning originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

Categories: Designing, Others Tags:

The Dark Side of Reddit: How Communities Are Turning Toxic

January 17th, 2025 No comments

Reddit faces growing toxicity, with issues like hate speech, misinformation, and radicalization exacerbated by its anonymity and algorithms. The platform must balance free speech with effective moderation to address these challenges.

Categories: Designing, Others Tags:

An Ode To Side Project Time

January 17th, 2025 No comments

There seemed to be a hot minute when the tech industry understood the value of idle tinkering and made a point of providing ‘side project time’ as an explicit working perk. The concept endures — I’m lucky enough to work somewhere that has it — but it seems to have been outpaced in recent years by the endless charge toward efficiency.

This seems a shame. We can’t optimize our way to quality solutions and original ideas. To try is a self-defeating fantasy. The value of side project time is hard to overstate, and more workplaces should not just provide it but actively encourage it.

Here’s why.

What Is Side Project Time?

Side project time pops up under different names. At the Guardian, it’s 10% time, for example. Whatever the name, it amounts to the same thing: dedicated space and time during working hours for people to work on pet projects, independent learning, and personal development.

Google founders Larry Page and Sergey Brin famously highlighted the practice as part of the company’s initial public offering in 2004, writing:

“We encourage our employees, in addition to their regular projects, to spend 20% of their time working on what they think will most benefit Google. This empowers them to be more creative and innovative. Many of our significant advances have happened in this manner. For example, AdSense for content and Google News were both prototyped in “20% time.” Most risky projects fizzle, often teaching us something. Others succeed and become attractive businesses.”

— Larry Page and Sergey Brin

The extent to which Google still supports the practice 20 years on is hazy, and though other tech big hitters talk a good game, it doesn’t seem terribly widespread. The concept threatened to become mainstream for a while but has receded.

The Ode

There are countless benefits to side project time, both on an individual and corporate level. Whether your priorities are personal growth or making lines, it ought to be on your radar.

Individuals

On an individual level, side project time frees up people to explore ideas and concepts that interest them. This is good in itself. We all, of course, hope to nurture existing skills and develop new ones in our day-to-day work. Sometimes day to day work provides that. Sometimes it doesn’t. In either case, side project time opens up new avenues for exploration.

It is also a space in which the waters can clear. I’ve previously written about the lessons of zen philosophy as they relate to pet project maintenance, with a major aspect being the value of not doing. Getting things done isn’t always the same as making things better.

The fog of constant activity — or productivity — can actually keep us from seeing better solutions to problems. Side project time makes for clearer minds to take back with us into the day-to-day grind.

Dedicated side project time facilitates personal growth, exploration, and learning. This is obviously good for the individual, but for the project too, because where are the benefits going to be felt?

Companies

There are a couple of examples of similar company outlooks I’d like to highlight. One is Pixar’s philosophy — as outlined by co-founder Ed Catmull — of protecting ‘ugly babies’, i.e. rough, unformed ideas:

“A new thing is hard to define; it’s not attractive, and it requires protection. When I was a researcher at DARPA, I had protection for what was ill-defined. Every new idea in any field needs protection. Pixar is set up to protect our director’s ugly baby.”

— Ed Catmull

He goes on to point out that they must eventually stand on their own two feet if they are to step out of the sandbox, but that formative time is vital to their development.

The mention of DARPA (the Defense Advanced Research Projects Agency), a research and development agency, highlights this outlook, with Bell Labs being one of its shining examples. Its work has received ten Nobel Prizes and five Turing Awards over the years.

As journalist Jon Gertner summarised in The Idea Factory: Bell Labs and the Great Age of American Innovation:

“It is now received wisdom that innovation and competitiveness are closely linked. But Bell Labs’ history demonstrates that the truth is actually far more complicated…creative environments that foster a rich exchange of ideas are far more important in eliciting new insights than are the forces of competition.”

— Jon Gertner

It’s a long-term outlook. One Bell employee recalled: “When I first came, there was the philosophy: look, what you’re doing might not be important for ten years or twenty years, but that’s fine, we’ll be there then.”

The cynic might say side project time is research and development for companies without the budget allocation. Even if there is some truth to that, I think the former speaks to a more entwined culture. It’s not innovation over here with these people and business as usual over there with those other people.

Side project time is also a cultural statement: you and your interests are valuable here. It encourages autonomy and innovation. If we only did OKRs with proven value, then original thinking would inevitably fade away.

And let’s be frank: even in purely Machiavellian terms, it benefits employers. You’ll be rewarded with happier, more knowledgeable employees and higher retention. You may even wind up with a surprising new product.

Give It A Spin

Side project time is a slow burner but an invaluable thing to cultivate. Any readers in a position to try side project time will reap the benefits in time.

Some of the best things in life come from idle tinkering. Let people do their thing. Give their ideas space to grow, and they will. And they might just be brilliant.

Further Reading

Categories: Others Tags:

10 Free Resources for Web Designers, January 2025

January 16th, 2025 No comments

Looking for a tool to make web designing easier? This list is packed with freebies, from tools to themes to fonts, you’ll find something you can use here.

Categories: Designing, Others Tags:

On-Device AI: Building Smarter, Faster, And Private Applications

January 16th, 2025 No comments

It’s not too far-fetched to say AI is a pretty handy tool that we all rely on for everyday tasks. It handles tasks like recognizing faces, understanding or cloning speech, analyzing large data, and creating personalized app experiences, such as music playlists based on your listening habits or workout plans matched to your progress.

But here’s the catch:

Where AI tool actually lives and does its work matters a lot.

Take self-driving cars, for example. These types of cars need AI to process data from cameras, sensors, and other inputs to make split-second decisions, such as detecting obstacles or adjusting speed for sharp turns. Now, if all that processing depends on the cloud, network latency connection issues could lead to delayed responses or system failures. That’s why the AI should operate directly within the car. This ensures the car responds instantly without needing direct access to the internet.

This is what we call On-Device AI (ODAI). Simply put, ODAI means AI does its job right where you are — on your phone, your car, or your wearable device, and so on — without a real need to connect to the cloud or internet in some cases. More precisely, this kind of setup is categorized as Embedded AI (EMAI), where the intelligence is embedded into the device itself.

Okay, I mentioned ODAI and then EMAI as a subset that falls under the umbrella of ODAI. However, EMAI is slightly different from other terms you might come across, such as Edge AI, Web AI, and Cloud AI. So, what’s the difference? Here’s a quick breakdown:

  • Edge AI
    It refers to running AI models directly on devices instead of relying on remote servers or the cloud. A simple example of this is a security camera that can analyze footage right where it is. It processes everything locally and is close to where the data is collected.
  • Embedded AI
    In this case, AI algorithms are built inside the device or hardware itself, so it functions as if the device has its own mini AI brain. I mentioned self-driving cars earlier — another example is AI-powered drones, which can monitor areas or map terrains. One of the main differences between the two is that EMAI uses dedicated chips integrated with AI models and algorithms to perform intelligent tasks locally.
  • Cloud AI
    This is when the AI lives and relies on the cloud or remote servers. When you use a language translation app, the app sends the text you want to be translated to a cloud-based server, where the AI processes it and the translation back. The entire operation happens in the cloud, so it requires an internet connection to work.
  • Web AI
    These are tools or apps that run in your browser or are part of websites or online platforms. You might see product suggestions that match your preferences based on what you’ve looked at or purchased before. However, these tools often rely on AI models hosted in the cloud to analyze data and generate recommendations.

The main difference? It’s about where the AI does the work: on your device, nearby, or somewhere far off in the cloud or web.

What Makes On-Device AI Useful

On-device AI is, first and foremost, about privacy — keeping your data secure and under your control. It processes everything directly on your device, avoiding the need to send personal data to external servers (cloud). So, what exactly makes this technology worth using?

Real-Time Processing

On-device AI processes data instantly because it doesn’t need to send anything to the cloud. For example, think of a smart doorbell — it recognizes a visitor’s face right away and notifies you. If it had to wait for cloud servers to analyze the image, there’d be a delay, which wouldn’t be practical for quick notifications.

Enhanced Privacy and Security

Picture this: You are opening an app using voice commands or calling a friend and receiving a summary of the conversation afterward. Your phone processes the audio data locally, and the AI system handles everything directly on your device without the help of external servers. This way, your data stays private, secure, and under your control.

Offline Functionality

A big win of ODAI is that it doesn’t need the internet to work, which means it can function even in areas with poor or no connectivity. You can take modern GPS navigation systems in a car as an example; they give you turn-by-turn directions with no signal, making sure you still get where you need to go.

Reduced Latency

ODAI AI skips out the round trip of sending data to the cloud and waiting for a response. This means that when you make a change, like adjusting a setting, the device processes the input immediately, making your experience smoother and more responsive.

The Technical Pieces Of The On-Device AI Puzzle

At its core, ODAI uses special hardware and efficient model designs to carry out tasks directly on devices like smartphones, smartwatches, and Internet of Things (IoT) gadgets. Thanks to the advances in hardware technology, AI can now work locally, especially for tasks requiring AI-specific computer processing, such as the following:

  • Neural Processing Units (NPUs)
    These chips are specifically designed for AI and optimized for neural nets, deep learning, and machine learning applications. They can handle large-scale AI training efficiently while consuming minimal power.
  • Graphics Processing Units (GPUs)
    Known for processing multiple tasks simultaneously, GPUs excel in speeding up AI operations, particularly with massive datasets.

Here’s a look at some innovative AI chips in the industry:

Product Organization Key Features
Spiking Neural Network Chip Indian Institute of Technology Ultra-low power consumption
Hierarchical Learning Processor Ceromorphic Alternative transistor structure
Intelligent Processing Units (IPUs) Graphcore Multiple products targeting end devices and cloud
Katana Edge AI Synaptics Combines vision, motion, and sound detection
ET-SoC-1 Chip Esperanto Technology Built on RISC-V for AI and non-AI workloads
NeuRRAM CEA–Leti Biologically inspired neuromorphic processor based on resistive RAM (RRAM)

These chips or AI accelerators show different ways to make devices more efficient, use less power, and run advanced AI tasks.

Techniques For Optimizing AI Models

Creating AI models that fit resource-constrained devices often requires combining clever hardware utilization with techniques to make models smaller and more efficient. I’d like to cover a few choice examples of how teams are optimizing AI for increased performance using less energy.

Meta’s MobileLLM

Meta’s approach to ODAI introduced a model built specifically for smartphones. Instead of scaling traditional models, they designed MobileLLM from scratch to balance efficiency and performance. One key innovation was increasing the number of smaller layers rather than having fewer large ones. This design choice improved the model’s accuracy and speed while keeping it lightweight. You can try out the model either on Hugging Face or using vLLM, a library for LLM inference and serving.

Quantization

This simplifies a model’s internal calculations by using lower-precision numbers, such as 8-bit integers, instead of 32-bit floating-point numbers. Quantization significantly reduces memory requirements and computation costs, often with minimal impact on model accuracy.

Pruning

Neural networks contain many weights (connections between neurons), but not all are crucial. Pruning identifies and removes less important weights, resulting in a smaller, faster model without significant accuracy loss.

Matrix Decomposition

Large matrices are a core component of AI models. Matrix decomposition splits these into smaller matrices, reducing computational complexity while approximating the original model’s behavior.

Knowledge Distillation

This technique involves training a smaller model (the “student”) to mimic the outputs of a larger, pre-trained model (the “teacher”). The smaller model learns to replicate the teacher’s behavior, achieving similar accuracy while being more efficient. For instance, DistilBERT successfully reduced BERT’s size by 40% while retaining 97% of its performance.

Technologies Used For On-Device AI

Well, all the model compression techniques and specialized chips are cool because they’re what make ODAI possible. But what’s even more interesting for us as developers is actually putting these tools to work. This section covers some of the key technologies and frameworks that make ODAI accessible.

MediaPipe Solutions

MediaPipe Solutions is a developer toolkit for adding AI-powered features to apps and devices. It offers cross-platform, customizable tools that are optimized for running AI locally, from real-time video analysis to natural language processing.

At the heart of MediaPipe Solutions is MediaPipe Tasks, a core library that lets developers deploy ML solutions with minimal code. It’s designed for platforms like Android, Python, and Web/JavaScript, so you can easily integrate AI into a wide range of applications.

MediaPipe also provides various specialized tasks for different AI needs:

  • LLM Inference API
    This API runs lightweight large language models (LLMs) entirely on-device for tasks like text generation and summarization. It supports several open models like Gemma and external options like Phi-2.
  • Object Detection
    The tool helps you Identify and locate objects in images or videos, which is ideal for real-time applications like detecting animals, people, or objects right on the device.
  • Image Segmentation
    MediaPipe can also segment images, such as isolating a person from the background in a video feed, allowing it to separate objects in both single images (like photos) and continuous video streams (like live video or recorded footage).

LiteRT

LiteRT or Lite Runtime (previously called TensorFlow Lite) is a lightweight and high-performance runtime designed for ODAI. It supports running pre-trained models or converting TensorFlow, PyTorch, and JAX models to a LiteRT-compatible format using AI Edge tools.

Model Explorer

Model Explorer is a visualization tool that helps you analyze machine learning models and graphs. It simplifies the process of preparing these models for on-device AI deployment, letting you understand the structure of your models and fine-tune them for better performance.

You can use Model Explorer locally or in Colab for testing and experimenting.

ExecuTorch

If you’re familiar with PyTorch, ExecuTorch makes it easy to deploy models to mobile, wearables, and edge devices. It’s part of the PyTorch Edge ecosystem, which supports building AI experiences for edge devices like embedded systems and microcontrollers.

Large Language Models For On-Device AI

Gemini is a powerful AI model that doesn’t just excel in processing text or images. It can also handle multiple types of data seamlessly. The best part? It’s designed to work right on your devices.

For on-device use, there’s Gemini Nano, a lightweight version of the model. It’s built to perform efficiently while keeping everything private.

What can Gemini Nano do?

  • Call Notes on Pixel devices
    This feature creates private summaries and transcripts of conversations. It works entirely on-device, ensuring privacy for everyone involved.
  • Pixel Recorder app
    With the help of Gemini Nano and AICore, the app provides an on-device summarization feature, making it easy to extract key points from recordings.
  • TalkBack
    Enhances the accessibility feature on Android phones by providing clear descriptions of images, thanks to Nano’s multimodal capabilities.

Note: It’s similar to an application we built using LLaVA in a previous article.

Gemini Nano is far from the only language model designed specifically for ODAI. I’ve collected a few others that are worth mentioning:

Model Developer Research Paper
Octopus v2 NexaAI On-device language model for super agent
OpenELM Apple ML Research A significant large language model integrated within iOS to enhance application functionalities
Ferret-v2 Apple Ferret-v2 significantly improves upon its predecessor, introducing enhanced visual processing capabilities and an advanced training regimen
MiniCPM Tsinghua University A GPT-4V Level Multimodal LLM on Your Phone
Phi-3 Microsoft Phi-3 Technical Report: A Highly Capable Language Model Locally on Your Phone

The Trade-Offs of Using On-Device AI

Building AI into devices can be exciting and practical, but it’s not without its challenges. While you may get a lightweight, private solution for your app, there are a few compromises along the way. Here’s a look at some of them:

Limited Resources

Phones, wearables, and similar devices don’t have the same computing power as larger machines. This means AI models must fit within limited storage and memory while running efficiently. Additionally, running AI can drain the battery, so the models need to be optimized to balance power usage and performance.

Data and Updates

AI in devices like drones, self-driving cars, and other similar devices process data quickly, using sensors or lidar to make decisions. However, these models or the system itself don’t usually get real-time updates or additional training unless they are connected to the cloud. Without these updates and regular model training, the system may struggle with new situations.

Biases

Biases in training data are a common challenge in AI, and ODAI models are no exception. These biases can lead to unfair decisions or errors, like misidentifying people. For ODAI, keeping these models fair and reliable means not only addressing these biases during training but also ensuring the solutions work efficiently within the device’s constraints.

These aren’t the only challenges of on-device AI. It’s still a new and growing technology, and the small number of professionals in the field makes it harder to implement.

Conclusion

Choosing between on-device and cloud-based AI comes down to what your application needs most. Here’s a quick comparison to make things clear:

Aspect On-Device AI Cloud-Based AI
Privacy Data stays on the device, ensuring privacy. Data is sent to the cloud, raising potential privacy concerns.
Latency Processes instantly with no delay. Relies on internet speed, which can introduce delays.
Connectivity Works offline, making it reliable in any setting. Requires a stable internet connection.
Processing Power Limited by device hardware. Leverages the power of cloud servers for complex tasks.
Cost No ongoing server expenses. Can incur continuous cloud infrastructure costs.

For apps that need fast processing and strong privacy, ODAI is the way to go. On the other hand, cloud-based AI is better when you need more computing power and frequent updates. The choice depends on your project’s needs and what matters most to you.

Categories: Others Tags:

Web-Slinger.css: Across the Swiper-Verse

January 15th, 2025 No comments

My previous article warned that horizontal motion on Tinder has irreversible consequences. I’ll save venting on that topic for a different blog, but at first glance, swipe-based navigation seems like it could be a job for Web-Slinger.css, your friendly neighborhood experimental pure CSS Wow.js replacement for one-way scroll-triggered animations. I haven’t managed to fit that description into a theme song yet, but I’m working on it.

In the meantime, can Web-Slinger.css swing a pure CSS Tinder-style swiping interaction to indicate liking or disliking an element? More importantly, will this experiment give me an excuse to use an image of Spider Pig, in response to popular demand in the bustling comments section of my previous article? Behold the Spider Pig swiper, which I propose as a replacement for captchas because every human with a pulse loves Spider Pig. With that unbiased statement in mind, swipe left or right below (only Chrome and Edge for now) to reveal a counter showing how many people share your stance on Spider Pig.

CodePen Embed Fallback

Broaden your horizons

The crackpot who invented Web-Slinger.css seems not to have considered horizontal scrolling, but we can patch that maniac’s monstrous creation like so:

[class^="scroll-trigger-"] {
  view-timeline-axis: x;
}

This overrides the default behavior for marker elements with class names using the Web-Slinger convention of scroll-trigger-n, which activates one-way, scroll-triggered animations. By setting the timeline axis to x, the scroll triggers only run when they are revealed by scrolling horizontally rather than vertically (which is the default). Otherwise, the triggers would run straightaway because although they are out of view due to the container’s width, they will all be above the fold vertically when we implement our swiper.

My steps in laying the foundation for the above demo were to fork this awesome JavaScript demo of Tinder-style swiping by Nikolay Talanov, strip out the JavaScript and all the cards except for one, then import Web-Slinger.css and introduce the horizontal patch explained above. Next, I changed the card’s container to position: fixed, and introduced three scroll-snapping boxes side-by-side, each the height and width of the viewport. I set the middle slide to scroll-align: center so that the user starts in the middle of the page and has the option to scroll backwards or forwards.

Sidenote: When unconventionally using scroll-driven animations like this, a good mindset is that the scrollable element needn’t be responsible for conventionally scrolling anything visible on the page. This approach is reminiscent of how the first thing you do when using checkbox hacks is hide the checkbox and make the label look like something else. We leverage the CSS-driven behaviors of a scrollable element, but we don’t need the default UI behavior.

I put a div marked with scroll-trigger-1 on the third slide and used it to activate a rejection animation on the card like this:

<div class="demo__card on-scroll-trigger-1 reject">
  <!-- HTML for the card -->
</div>

<main>
  <div class="slide">
  </div>
  <div id="middle" class="slide">
  </div>
  <div class="slide">
      <div class="scroll-trigger-1"></div>
  </div>
</main>

It worked the way I expected! I knew this would be easy! (Narrator: it isn’t, you’ll see why next.)

<div class="on-scroll-trigger-2 accept">
  <div class="demo__card on-scroll-trigger-2 reject">
  <!-- HTML for the card -->
  </div>
</div>

<main>
  <div class="slide">
      <div class="scroll-trigger-2"></div>
  </div>
  <div id="middle" class="slide">
  </div>
  <div class="slide">
      <div class="scroll-trigger-1"></div>
  </div>
</main>

After adding this, Spider Pig is automatically ”liked” when the page loads. That would be appropriate for a card that shows a person like myself who everybody automatically likes — after all, a middle-aged guy who spends his days and nights hacking CSS is quite a catch. By contrast, it is possible Spider Pig isn’t everyone’s cup of tea. So, let’s understand why the swipe right implementation would behave differently than the swipe left implementation when we thought we applied the same principles to both implementations.

Take a step back

This bug drove home to me what view-timeline does and doesn’t do. The lunatic creator of Web-Slinger.css relied on tech that wasn’t made for animations which run only when the user scrolls backwards.

This visualizer shows that no matter what options you choose for animation-range, the subject wants to complete its animation after it has crossed the viewport in the scrolling direction — which is exactly what we do not want to happen in this particular case.

Fortunately, our friendly neighborhood Bramus from the Chrome Developer Team has a cool demo showing how to detect scroll direction in CSS. Using the clever --scroll-direction CSS custom property Bramus made, we can ensure Spider Pig animates at the right time rather than on load. The trick is to control the appearance of .scroll-trigger-2 using a style query like this:

:root {
  animation: adjust-slide-index 3s steps(3, end), adjust-pos 1s;
  animation-timeline: scroll(root x);
}
@property --slide-index {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}

@keyframes adjust-slide-index {
  to {
    --slide-index: 3;
  }
}

.scroll-trigger-2  {
  display: none;
}

@container style(--scroll-direction: -1) and style(--slide-index: 0) {
  .scroll-trigger-2 {
    display: block;
  }
}

That style query means that the marker with the .scroll-trigger-2 class will not be rendered until we are on the previous slide and reach it by scrolling backward. Notice that we also introduced another variable named --slide-index, which is controlled by a three-second scroll-driven animation with three steps. It counts the slide we are on, and it is used because we want the user to swipe decisively to activate the dislike animation. We don’t want just any slight breeze to trigger a dislike.

When the swipe has been concluded, one more like (I’m superhuman)

As mentioned at the outset, measuring how many CSS-Tricks readers dislike Spider Pig versus how many have a soul is important. To capture this crucial stat, I’m using a third-party counter image as a background for the card underneath the Spider Pig card. It is third-party, but hopefully, it will always work because the website looks like it has survived since the dawn of the internet. I shouldn’t complain because the price is right. I chose the least 1990s-looking counter and used it like this:

@container style(--scroll-trigger-1: 1) {
  .result {
    background-image: url('https://counter6.optistats.ovh/private/freecounterstat.php?c=qbgw71kxx1stgsf5shmwrb2aflk5wecz');
    background-repeat: no-repeat;
    background-attachment: fixed;
    background-position: center;
  }

  .counter-description::after {
    content: 'who like spider pig';
  }

  .scroll-trigger-2 {
    display: none;
  }
}

@container style(--scroll-trigger-2: 1) {
  .result {
    background-image: url('https://counter6.optistats.ovh/private/freecounterstat.php?c=abtwsn99snah6wq42nhnsmbp6pxbrwtj');
    background-repeat: no-repeat;
    background-attachment: fixed;
    background-position: center;
  }

  .counter-description::after {
    content: 'who dislike spider pig';
  }

  .scroll-trigger-1 {
    display: none;
  }
}

Scrolls of wisdom: Lessons learned

This hack turned out more complex than I expected, mostly because of the complexity of using scroll-triggered animations that only run when you meet an element by scrolling backward which goes against assumptions made by the current API. That’s a good thing to know and understand. Still, it’s amazing how much power is hidden in the current spec. We can style things based on extremely specific scrolling behaviors if we believe in ourselves. The current API had to be hacked to unlock that power, but I wish we could do something like:

[class^="scroll-trigger-"] {
  view-timeline-axis: x;
  view-timeline-direction: backwards; /* <-- this is speculative. do not use! */
}

With an API like that allowing the swipe-right scroll trigger to behave the way I originally imagined, the Spider Pig swiper would not require hacking.

I dream of wider browser support for scroll-driven animations. But I hope to see the spec evolve to give us more flexibility to encourage designers to build nonlinear storytelling into the experiences they create. If not, once animation timelines land in more browsers, it might be time to make Web-Slinger.css more complete and production-ready, to make the more advanced scrolling use cases accessible to the average CSS user.


Web-Slinger.css: Across the Swiper-Verse originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

Categories: Designing, Others Tags:

The Usability Myth: Users Don’t Really Know What They Want (and That’s Totally OK!)

January 15th, 2025 No comments

Users’ feedback is shaped by biases, emotions, and familiarity with the status quo. Great UX design requires balancing empathy with vision, using user insights as a guide—not the rulebook.

Categories: Designing, Others Tags:

Photoshop Launches Live Co-Editing in Private Beta

January 14th, 2025 No comments

Adobe has introduced live co-editing in Photoshop, now available in private beta, allowing multiple users to collaborate on the same document in real time. This innovative feature streamlines workflows, eliminates versioning issues, and fosters seamless creative teamwork across the globe.

Categories: Designing, Others Tags: