y

Stuck with Apple’s Aperture? Adobe will give you a hand

After the announcement that Apple will not be continuing development of Aperture, Adobe announces the development of a migration tool to help those thinking about switching.




y

The Lost Generation, by Kevin Gilbert

880 billion images will be made this year, in the USA alone. How important is it to makes sure image loss is minimised not to have a Lost Generation?







y

What’s new with Woo: July 2024

What’s happening with WooCommerce in July 2024? Cart and Checkout upgrades, Buy Now, Pay Later, and more!




y

Unique value proposition — Why it matters and how to write one 

What makes consumers choose one company over another? Identify your unique value proposition to make more sales at higher prices. Examples & tips.




y

WooCommerce stores are revving up for Black Friday: The 2024 holiday trends survey

As ecommerce revs up for the holidays, it's time to prepare. Brand new survey data for Black Friday 2024 stats and trends from your friends at Woo.




y

Spain-based DOMMA sees 350% YoY growth with WooCommerce and Google

How the wellness brand DOMMA achieved 350% year-over-year growth with one key tool. Can’t-miss success tips from a successful women-owned brand.




y

Migrating from GoDaddy Website Builder to WooCommerce

Ready to migrate from GoDaddy to WooCommerce? 6 signs you should make the move. GoDaddy vs Woo comparison chart. Pros & cons. 3 ways to switch.




y

2024 Black Friday trends: Top strategies from Woo stores and partners

Black Friday trends: Understand the best practices and favorite tools for your WooCommerce store's Black Friday marketing strategy.




y

Ecommerce business models: Which is best for you?

Which ecommerce business model is best for your idea? Long-term and short-term strategies for operations, profits, and a successful launch.




y

Prepare your checkout for the holidays: 5 ways to reduce cart abandonment with Amazon Pay

Make the most of the holiday shopping season — convert more visitors into customers. Quick changes that can make a big difference in 5 steps.




y

Top Life Project surpasses revenue goals by 59% in year one

How did Top Life Project exceed revenue goals by 59%? The story behind their WooCommerce-powered health brand & booming product launches.




y

Competitive analysis — What to do before you commit to your next great business idea

Planning a new online business? Conduct a competitive analysis to understand your market, beat your rivals, and position your brand for success.




y

Summer paddling, swimming and photography on Horsetooth Reservoir

Stand up paddling During August 2023 I visited Horsetooth Reservoir several times with Starboard Waterline SUP, the same board I paddled in the Missouri River 340 race. It was rather a relaxed paddling with a lot of photography since I […]










y

Jetty








y

No longer an Underdog, Sony cameras and lenses win multiple categories at TIPA 2022 World Awards

The Technical Image Press Association, otherwise known as TIPA, has just released its list of...

The post No longer an Underdog, Sony cameras and lenses win multiple categories at TIPA 2022 World Awards appeared first on Alphatracks.




y

Tidy Birds and Neat Bees: on Conscientiousness in Animals

By Mikel Maria Delgado Aeon Human personality theory has long revolved around what we know as the ‘Big Five’ – five dimensions of personality that cover a large swathe of how humans behave across time and contexts. These dimensions are … Continue reading




y

Biodiversity Isn’t Just Pretty: It Future-Proofs Our World

By Elizabeth Boakes Aeon A small boy hauls enthusiastically on his fishing rod. The line flies up and a needle-spined fish strikes him in the eye. Desperate to stay outdoors, he ignores the pain, but his sight deteriorates over the … Continue reading




y

World Turtle Day – 2018

In its 18th year, World Turtle Day is celebrated around the world on May 23rd, bringing attention to the threats these ancient creatures face. Older than the dinosaurs, turtles have survived this long but their numbers have plummeted due to … Continue reading




y

Antyfest

A project to support international music festivals suffering from Covid19 Its a map and a nest with actual ants the creatures that dont have to follow lockdown rules




y

Is your idea worth doing?

Have you ever been asked to get creative? Or told to think outside the box? If so, you might have had one of two reactions (or maybe a combination of the two):

  1. Hooray! No restrictions. Let’s go! 
  2. Yikes! The possibilities are endless. Where do I start?

Regardless of how you might react, it’s crucial to keep the original ask in mind — not “get creative,” but the reason you were charged with getting creative or thinking outside of the box in the first place. Losing sight of the goal or falling into the trap of thinking that a strategic approach isn’t actually “creative” are the fastest ways to the land of no progress and stifled creativity. 

I think the best ideas come out of a harmonious combination of strategic and creative thinking. I’m not the only one; product designers often have a foundations-first approach to their work where they consider a baseline strategy before jumping into high-fidelity mock-ups. Strategists leverage innovation workshops to both strategically and creatively problem solve. And developers weigh cost and functionality tradeoffs when designing and building reproducible and deployable systems.

Problem solving, creative thinking, and focus are universal components of work-life – and life-life. Leveraging a tool to help you do all three isn’t a cop out, it's a way to help you get to the fun stuff (the ideas worth doing) faster. 

One tool that can help you confidently pursue your idea is an Impact and Feasibility Matrix, which will help you focus and narrow in. Your focus will keep you on track, and narrowing in on what ideas are worth doing will illuminate the way forward. Let’s dive in… 

Focus

Step one is keeping your goal in mind. To do so, revisit these questions often:

  • How does this help solve the problem?
  • How does this contribute to an ideal outcome?

Narrow In

Step two is identifying which creative idea is worth pursuing. One way I like to narrow in and confidently move forward is by plotting ideas on an Impact + Feasibility matrix

Impact is:

  • Reach. What percentage of your audience or stakeholders will be impacted by your idea?
  • Relevance. Does your idea target your key audience? 
  • Longevity. How long will your idea impact your team? 

Feasibility is:

  • Costs. What are your hard costs? This includes both the time investment and monetary investment. 
  • Ease. How easy is your idea to execute? Is this something you can tackle on your own? Will you need to outsource your idea to a partner or vendor? 

The answers to all of these will be unique to your role, the problem you are trying to solve, and your organization. That said, somewhere between impact and feasibility, usually in the upper right quadrant of the matrix, is your sweet spot. This is true regardless of role, problem, or organization. Ideas in the sweet spot are usually worth doing. They reach a relevant audience for your targeted time frame, they are achievable, and within budget.  

Your impact and feasibility matrix will be unique to each problem you are trying to solve. Let’s take a look at some real examples. 

Examples

Problem: Help a newly distributed team settle in to working remotely. 

In the spring of 2020, many organizations (Viget included), were charged with supporting newly distributed teams. Throughout that year, we focused on surprising our team in new ways (think care packages containing branded sweatpants), removing barriers to communication, and improving access to resources (we implemented People Team office hours which we still keep to this day). We did send everyone their favorite candy and had local folks help deliver monitors to their teammates. We still don’t have Viget branded dog swag – maybe one day. 

Problem: Help team members get to know each other during weekly company-wide meetings. 

Each week, we host a company-wide all hands meeting. It’s a tradition we’ve kept since we were founded in 1999. The meeting has evolved over the years and so has our strategy for connection. This is a matrix we revisit often, some ideas we tweak and try again and others like requiring cameras-on or implementing a roll call isn’t something we would consider doing. 

To Sum It Up

The next time you find yourself spinning your wheels, or better yet, the next time you're tasked with thinking outside the box, focus first and plot your ideas on the impact/feasibility matrix. Doing so will help keep you on track and quickly narrow in on which ideas are worth pursuing. 




y

A Guide to Accessibility Resources for Global Accessibility Awareness Day

Global Accessibility Awareness Day (GAAD) is May 16, 2024! GAAD was created to help bring attention and awareness to digital inclusivity. No matter your role on a project team, digital accessibility should always be a priority from start to finish. Why is accessibility so important?

  • Over 1 billion people worldwide have a disability, and that number is growing every day
  • 15% of people with disabilities say they never go online, compared to 5% of people without disabilities, according to Pew Research Center
  • According to a survey by Click-Away Pound, 71% of disabled users are forced to leave a website if they find it difficult to use

Digital accessibility directly impacts people’s ability to access information, buy products, apply for jobs, engage in discussion, and everything else that people do online that is becoming critical for modern life. Accessible spaces even benefit people without disabilities, as it allows anyone to take in content though their preferred method (reading the captions on a video instead of listening in a noisy environment, for example), and often breeds innovation as engineers work to find the best way to be sure everyone can access information equally.

The World Wide Web Consortium (W3C) has developed the Web Content Accessibility Guidelines (WCAG) in an effort to standardize digital accessibility. However, many websites unfortunately fail to meet these standards, leading to a lesser-quality user experience. WebAIM’s yearly report has highlighted some surprising statistics about WCAG across the top 1,000,000 home pages:

  • The most common accessibility failure across home pages is low contrast text
  • 98.1% of home pages have at least one WCAG 2.0 failure
  • On average, there are 56.8 accessibility errors per page (this increased 13.6% from 2023!) 
  • 16.8% of home pages had more than one <h1> tag

As you can see, there is still a lot of work that needs to be done to create a more accessible web for everyone. If you’re interested in learning more about digital accessibility and how to improve accessibility on your own projects, there are plenty of resources and online courses available. Resources range from free, to paid courses, to professional certifications. Below are some courses and resources that we recommend.

Free Courses and Resources

If you’re looking to introduce yourself to digital accessibility, these free resources are a great place to start:  

  • A11ycasts with Rob Dodson - A series of video tutorials on YouTube that highlights topics including semantics, focus, the correct way to use a button, and a11y testing
  • The Beginner’s Guide to Web Accessibility - An article by Dequeue University that summarizes why digital accessibility should be a priority, and how to determine if your website is accessible
  • Common Mistakes with Using Colour in Accessibility - Digital designer Andrée Lange provides insights into how to take color contrast into consideration when designing for the web
  • Deque Accessibility Resources - Dequeue offers a variety of free accessibility resources, including webinars, blog posts, and their accessibility testing browser extension, axe DevTools
  • HTML Semantics and Accessibility Cheat Sheet - WebAIM provides a list of the most common HTML tags that have an impact on digital accessibility
  • MDN Accessibility Tutorials - MDN is an open-source project documenting web technologies, which also includes an informative section on web accessibility documentation and best practices
  • Section 508 ICT Testing Baseline - Outlines minimal accessibility testing requirements for federal agencies subject to Section 508
  • WCAG 2.2 Quick Reference - WCAG are a series of web accessibility guidelines released and maintained by the W3C, with 2.2 being the current version of the guidelines. This page provides a reference to standards that websites should meet in order to meet current accessibility standards
  • Web.dev Learn Accessibility Course - A series of informative articles ranging from beginning a11y topics, to more advanced topics including animation and motion

Deep Dives with Paid Tutorials

If you’re a developer who has experience in accessibility and want to dig more into the topic, these comprehensive tutorials will help you improve your a11y knowledge:

  • Accessible Web Academy - Accessible Web Academy includes more focused a11y courses for designers, developers, content creators, and marketers looking to target specific topics 
  • Inclusive Components - There is a free online summary of Heydon Pickering’s Inclusive Components, but you can also purchase an eBook on the topic. Heydon’s blog provides examples of a pattern library that bakes accessibility into each component
  • Practical Accessibility by Sara Soueidan - Sara Souedien is a prolific front-end developer who specializes in accessibility. Her course, Practical Accessibility, is a comprehensive guide for all developers, from those looking to familiarize themselves with accessibility, to experienced developers looking to expand their a11y knowledge.

Advanced Knowledge with Certifications

As the world’s population and number of disabled users continues to grow, it’s clear that implementing digital accessibility in your products is more important than ever. By implementing the information from these lists, you can help users of all abilities access the content that you share, ensuring a better internet for everyone.




y

How Generative AI Can Add Human Delight to Your Virtual Event

We just celebrated 24 years of Viget. That’s two dozen years! This year, our Spring TTT in celebration of “Viget24” was a virtual extravaganza. We’ve put on a lot of virtual events over the years. Some with really strong themes and swag bags; some that focus on simple, meaningful time together; and others that let us enjoy learning something new as a team. Regardless of the rest of the experience, a key component of all of our virtual events is joyachieved often through intentional levity. We think it’s important to laugh together! We see laughter as a way to expedite connection, and connection leads to rapport which makes us better at collaborating — and in turn leads to more quality products for our clients. 

Experimenting and iterating is a critical way we try to continually get delight right. We’re pretty pleased with one of our experiments from Viget24 that we called “Lovely Spring Day”.

A Lovely Spring Day

As we were brainstorming for this TTT, we thought about how to throw some joyful levity pizzazz into the pieces of our virtual events puzzle that have become pretty standard. How do we add lots of delight without adding lots of time to the action-packed schedule? We zeroed in on the virtual backgrounds we’ve been creating for every event — they add a layer of specialness. Of place. This isn’t any old virtual meeting. This is a TTT! 

A small collection of past event-specific virtual backgrounds

Another key consideration for our team is figuring out creative ways to tie in inspiration from our industry and our work. AI has been an obvious contender —  we’ve discussed it and tied it in to some extent for the past several TTTs. But this time, we wanted to see how we could use AI for delight — marrying it with virtual backgrounds felt obvious. And so, a ”Lovely Spring Day” was born. 

The TL;DR is that we generated custom virtual backgrounds for every Viget employee that encapsulates their “ideal spring day.” We then played a 15-minute guessing game where people tried to guess who the background “belonged to.” Then, people had access to the full folder of AI-generated virtual backgrounds to look through. Vigets could then choose the background that spoke to them most and set it as their background. 

Read on for more on how we put this together!

Pre-Event Survey

To support all of our TTTs, we send out thoughtful pre-event logistics surveys 2-3 weeks before the big day. The survey lets us know where folks are joining from (where can we send their activity + snack packages?) and gives folks a chance to provide input on how the People Team can help folks enjoy and be present for TTT. This time, we also snuck in three questions, just “for giggles.”

  • In one sentence, describe your ideal spring day.
  • List three things that spark joy.
  • What color do you think suits you best?

We did not share why we asked these questions. Sneaky, sneaky! When it’s low-key like this, the element of surprise is often a quick way to level up the delight.

Asking for a Friend

With rich data in hand about what makes people happy in spring, we were ready to generate the backgrounds. I was stoked! I’ve been experimenting with ChatGPT for some time, so it was fun to be able to use the DALL-E 3 side of OpenAI’s GPT-4 model

Who knew Prompt Engineering would be part of my role as a recruiter-who-helps-support-TTT-planning? I played around with a couple different prompts to generate these background images. Ultimately, my goal was to create backgrounds that were meaningfully different from one another but still felt good (i.e., something you might feasibly want to set as your virtual background and nothing freakily AI, like uncanny valley hands).

Here are the prompts I landed on that got me to our set of virtual backgrounds:

  • Please generate an image (dimensions of a virtual meeting background) that encapsulates the vibe of a day with [ BLANK ].
  • Please generate an image (dimensions of a virtual meeting background) that features [ BLANK ].

In the blanks, I wrote the things people included in their surveys. Those blanks were filled with everything ranging from dogs, cats, and friends to beverages, specific temperatures, yard games, carbohydrates, hammocks and more! Sometimes, I’d include a detail I knew about that person myself, even if it wasn’t in their survey. Yes, I occasionally editorialized for both clarity and whimsy! This was for delight purposes, but also helped serve my goal of having the backgrounds be “meaningfully different from one another.” It’s amazing how many people’s ideal spring day is as simple as having 1) moderate temperatures and 2) no pollen!

I generated 55 images. Throughout the process, DALL-E nailed it. I only needed to regenerate 2 or 3 images with clarifiers (and only because they included AI-specific outliers like disembodied hands). Huzzah!

Here are some of my favorites, along with their prompts in the captions. Can you guess who they belong to?

Please generate an image (dimensions of a virtual meeting background) that features an outdoor brewery/taproom in the appalachian mountains. There's a playground with kids in the very distance. In the foreground, frisbee, soccer, volleyball, etc. with friends and family.
Please generate an image that encapsulates the vibe of a day ending with an outdoor dinner with lights near an outdoor shower. There should be some hiking boots scattered about.
Please generate an image that features a nice hot bath after a cold but sunny day, with a beautiful mug of green tea and a box of takeout that looks really good. The calendar shows April 25th.
Please generate an image that encapsulates the vibe of sitting outside in a nice purple adirondack chair with buc-ees paraphernalia around.
Please generate an image that encapsulates the vibe of a sunny, 65 degree day with a slight breeze at the ballpark watching a game. The image should feature cats, baseball, and art.
Please generate an image that encapsulates the vibe of being outside in a canoe along with carbs, bad jokes, and games (video OR board games).
Please generate an image that features endless mountain bike trails, a blue bike with a cup of coffee in the cupholder, and roaming cats.

IRL

Ok, so for the actual activity we had the images ready to go in a private Google Folder. I took twelve of the images and put them in a very simple deck. I shared my screen, introduced the activity, and invited people to guess who they think each image belonged to in Slack. It was so fun seeing people throw out guesses and then narrow in with any verbal hints I gave!

Each image took about a minute. Then, we shared access to the Google Folder, gave folks a couple minutes to choose a background that called to them (their own image or someone else’s), and set it as their background. It felt like a magical moment to witness people finding and resonating with their own image or delighting in the ridiculousness of their coworkers’. We saved about 5 minutes for this piece, which felt right.

The whole Lovely Spring Day activity took just over 15 minutes! It was a perfect way to transition from a long meal break into our next grouping of content. And, we got to see the different backgrounds throughout the rest of the meeting.

Oh, the humanity!

I think this activity was successful for a couple of reasons.

1. People laughed! 

Color commentary in the #ttt Slack channel

2. People felt seen. Some of these backgrounds were incredibly on point. Some of that was due to key folks having well-documented interests and a Slack-Famous Dog. 

Laura Sweltz has a famous love of books and an incredibly iconic beagle named Phoebe.

But some of it was due to the People Team knowing about our people — our coworkers — beyond the sentence they wrote in. This uniquely human involvement helped me call an audible as needed and tweak prompts slightly to make the backgrounds feel even more relatable.

Steven, Carolyn, and Laura Sweltz felt seen.

3. We could commiserate about our eventual AI overlords. (Did you notice that I say “please” in my prompts?!) Listen, Viget has plenty of practical, healthily skeptical people who are dubious about AI. GenAI is not always a fun, lighthearted thing. But using it in a fun, lighthearted way to do something it’s really good at was a nice use case and thought-provoking exposure even for people who are not into it.

4. We could see where we all align, and where we differ! It was amazing to see just how many people love picnics, covet their caffeine, and appreciate a bike ride. It was also cool to see some unique folks who simply crave a rainy spring day, or some beloved Buc-ee’s. What a rich tapestry of individuals — literally!




y

Self-Host Your Identity Provider with authentik

Authentication! What a hassle!

Evans, where's that SAML from Earth!?

You start off simple enough — username / password authentication in your application. Then, well, someone mentions that traditional passwords are a security vulnerability, so maybe we should use one-time passwords. That inevitably leads to discussions about magic links and multi-factor authentication. Next thing you know, one dev is in a corner, rocking back and forth and muttering something about SAML, and another dev just left — walked out the door, never to be seen again.

Well, not to worry, we've got just the tool for you.

authentik is an open-source identity provider written in Python. I'm going to focus on the self-hosted version, but they also offer a paid enterprise plan if you want some extra support.

Self-Hosting

The philosophy of open-source tools and self-hosting is a big, complex topic for another post. In the world of SaaS products, you likely don't need to self-host. I quite like hosted identity providers like Clerk and Auth0. They're good and appropriate solutions for different types of apps and companies.

But I just love to self-host tools. Tinkering and toying with Docker, reverse proxies, and sometimes even server hardware is a lot of fun to me. It does add complexity in some (or many) places, but a little extra complexity means you've got a little more control over your tooling.

Self-hosting also allows me to disconnect from the Internet and still be able to work on features and enhancements in my projects. As long as I've already installed the relevant packages or pulled the right Docker images, I can keep working if I'm in a place where I can't (or don't want to) connect to the Internet. This is a small thing, but really important to me.

authentik makes it really easy to self-host your application. Right out of the gates, they provide a Docker Compose example and a Kubernetes example. Getting authentik running took me about 10 minutes using the Docker Compose example. Most of that was reading. This can make authentik a great tool during the proof-of-concept or beta phase of your application, getting authentication out of the way so you can focus on building the cool and unique features of your app.

Integrations

One of the great things that authentik has waiting for you is a bunch of documentation on integrating with a lot of tools you probably already use. These integrations range from other self-hosted apps like Outline (another favorite of mine) to cloud providers like AWS and even platforms like WordPress.

authentik's integration docs show you how to set up authentik for your existing providers and applications, so no need to dig around for the right configuration. Sure, if you're building your own application, you don't have the luxury of a README (until you write one, of course!), but don't worry — all the documentation you'll need for your choice of providers is at your fingertips. Personally, I'm fan of the OAuth2 provider for most my pet projects, but I also find the Proxy Provider to be a really great tool if you want to secure a static site that doesn't have any means of authenticating users.

Customization

This is a pretty nice default login screen, but maybe a mountain road isn't your vibe. You can change this background, add your own company logo, and add your own CSS. Just add your static files to your authentik deployment and modify to your heart's content.

But actually, that's not even the cool part of the customization to me.

authentik has the concepts of Flows and Stages that are used to determine what steps a user should take to log in, log out, and more. First, you define Stages that represent a single step of authentication — something like requiring a user to enter their username or a password. There's a whole lot to choose from. Once you've set up your Stages, you'll create a Flow, stringing those Stages together until you have a complete process to authenticate, register, or even delete a user. Flows can be imported and exported as .yaml files, making it easy to keep your Flows and Stages synced between different environments.

authentik comes with a pretty reasonable set of default Flows and Stages. If you're setting authentik up just to try it out, you might not need to add anything. They do have a couple of example Flows to get you started, though.

Flows and Stages can feel pretty intimidating. On your dev server, I'd recommend basically deleting all of the default Flows and Stages and building up new ones from scratch. It's the easiest way to learn how these pieces fit together. If you accidentally break something in dev, you can always just drop your database and spin up a fresh install.

Conclusion

authentik is an awesome tool and I've only scratched the surface of what it can do for you. As a self-hosted identity provider, it gives you a lot of control on how your services are authenticated. It's great for local development and beyond, and it has a lot of ready-to-go integrations for services you might already use.

If you're interested in further reading, I'd definitely recommend checking out the docs on Outposts and External Sources.

Hopefully this has given you some inspiration to spin up a local instance of authentik and try it out! It will definitely simplify your authentication needs.

Here's your SAML, Mr. Horrible Gelatinous Blob!




y

Fluid Breakout Layout with CSS Grid

So you're building a site and you've got a nice containing element around your content — but wait! Not all the content is the same width! That nice, neat tube of content is not so much a straight tube as a pile of different sized bricks.

It's a common layout problem, but how do we account for these 'breakout' widths in the layout? There's a couple ways we could go about it:

  • Encapsulate each component and set widths and margins. (Works fine if you have full control but can be fiddly).
  • Force the component out of the containing element with negative margins. (Works fine if there's only a little deviation).
  • Use CSS Grid to build a fluid universal grid! (????).

That last one is what we'll be exploring: how to use CSS Grid definitions to allow for consistent component sizing across all breakpoints — no media queries required!

This is a technique that's based on Ryan Mulligan's 'Layout Breakouts' which is based on Josh Comeau's 'Full-Bleed Layout' and is especially useful when creating a fully fluid layout. This also pairs well with fluid type techniques resulting in layouts that TRULY scale with the viewport size.

Setting Up the Grid #

Here's the layout we're going to be building:

If we break apart the design, we've got 4 possible widths for components:

  • Full-Width
  • Feature
  • Popout
  • Content

We've also go some special side-anchored elements that 'stick' to one of the screen edges but also honor the other element widths. We'll come back to these later on.

Now that we've categorized the widths, lets start drawing column edges and defining areas:

  1. Left margin / Full-Width
  2. Left Feature
  3. Left Popout
  4. Center Content
  5. Right Popout
  6. Right Feature
  7. Right margin / Full-Width

That's a lot of columns!

Yet on mobile, we only need 3 columns, just left margin (1), center content (4), and right margin (7). We want some of these intermediate columns to disappear!

Fortunately, CSS Grid gives us some powerful tools to create the measurements needed—yes, even for the disappearing columns! We won't even have to write any media queries for this one. We can make just ONE definition that works at all sizes.

We'll store our measurements as CSS variables for easy use later on:

:root {
  --gap: clamp(1rem, 4vw, 2rem);
  --full: minmax(var(--gap), 1fr);
  --feature: minmax(0, 12vw);
  --popout: minmax(0, 2rem);
  --content: min(clamp(30rem, 52vw, 60rem), 100% - var(--gap) * 2);
}

Let's break these down.

--gap: clamp(1rem, 4vw, 2rem);

gap will be our side margin, allowing it to stretch up to 2rem at max, with a preferred width of 4vw, but never going below 1rem.

--full: minmax(var(--gap), 1fr);

We're going to use the minmax() function for these next three measurements to say: "If there's room in the CSS Grid, you can expand out to here but then don't go smaller than the minimum".

The full area is going to expand from left edge to right edge (remember we have to split the areas to allow for the other columns) and will double as our margin, so we'll pop in our gap value as our minimum and tell it that it can expand up to 1fr, or basically as much space as the rest of the grid will allow it.

--feature: minmax(0, 12vw);
--popout: minmax(0, 2rem);

The feature and popout both have a minimum value of 0. This is what powers our disappearing columns! As other areas of the grid expand, these will collapse when there's no longer any room for them, essentially taking up no space.

--content: min(clamp(30rem, 52vw, 60rem), 100% - var(--gap) * 2);

And then finally, our content area is our most complex measurement. It's saying, take the minimum value of either:

  1. A fluid measurement that can be 30-60rem (with the help of clamp())
  2. OR full width minus our gap value (but doubled for both left and right values).

These measurements can be changed to fit the needs of your layout. Specifically the feature and popout maximum values and the first content value. For example, our use of vw for the feature means it will fluidly expand out as the screen grows whereas the popout will remain only 2rem larger on each side than the content column.

Now we can assemble these measurements in a CSS grid column definition. We'll name our column edges with [custom-ident] and use the -start and -end endings to help make assignment easier later on.

.grid-breakout {
  display: grid;
  grid-template-columns: [full-start] var(--full)
    [feature-start] var(--feature)
    [popout-start] var(--popout)
    [content-start] var(--content) [content-end]
    var(--popout) [popout-end]
    var(--feature) [feature-end]
    var(--full) [full-end];
}

The definition is complex, but if we visualize the start and end lines of our columns as well as the measurements, it looks like this:

You can see we have our middle content column, our disappearing feature and popout columns, and finally our full columns that double as our margin.

To finish off the definitions, we need to create column assignments. Because we named our columns with custom identifiers and specified the start and stop lines, we don't have to fiddle with grid numbers. We can assign them directly like:

.full {
  grid-column: full;
}

.feature {
  grid-column: feature;
}

.popout {
  grid-column: popout;
}

.content {
  grid-column: content;
}

And if we want to create a default assignment for elements in the grid (which is especially useful if you don't have full control over the markup) you can create one like this:

.grid-breakout > * {
  grid-column: content;
}

Now you can attach any of these classes to components in your grid and have them snap to the width you want.

Watch the screen capture below as the grid scales down. You can see the feature and popout columns disappearing as everything transitions to a mobile width, and then expands back up.

You can see a demo of the base setup here:

Nesting Grids #

Now let's go back to our header element. You can see that though the header is full-width, we actually want its inner content to honor the feature width.

Fortunately, because of the flexible nature of this grid definition, we can repeat the definition and then continue using the same column names on the inner structure. Because our grid only goes one layer deep we're free to replicate as much as we need or even break out and use different layout methods for the component interiors.

<main class="grid-breakout">
  <section class="full grid-breakout">
     <div class="feature">
        <!-- inner content -->
     </div>
  </section>
</main>

You can see it in action here:

Anchoring Left and Right #

Remember those side-anchored components? This is where we need to get a little tricky to line everything up.

Going back to our diagram, we want an element to span MOST of the way across the page, but end at the opposite feature edge. We can reuse our column definitions for the first part.

.feature-left {
  grid-template-columns: full-start / feature-end;
}

Great! That gives us exactly what we want... except for when we try to nest the grids.

Our original grid definition assumes that our content, while different widths, is centered in the window. We have to rethink our inner grid definition a little bit.

We're shaving off one end of the grid, specifically a full definition. So two things need to happen:

  1. We need to adjust our content width to now account for only having one gap.
  2. We need our new grid end to stop at the edge of the feature column.

We can achieve this with a new measurement and a new grid definition:

:root {
  /* previous definitions... */
  --content-inset: min(clamp(30rem, 52vw, 60rem), 100% - var(--gap));
}

.grid-breakout-feature-left {
  display: grid;
  grid-template-columns:
    [full-start] var(--full)
    [feature-start] var(--feature)
    [popout-start] var(--popout)
    [content-start] var(--content-inset) [content-end]
    var(--popout) [popout-end]
    var(--feature) [feature-end full-end];
}

We've replaced the inner content measurement with the new value and combined the feature and full ends with the final line of the template column definition:

[feature-end full-end]

This will allow redefinition inside the new side-anchored component. You will notice that you'll need to supply your own padding for the inner as they no longer have that final margin to prevent it from reaching the new grid edge.

<main class="grid-breakout">
  <section class="feature-left grid-breakout-feature-left">
    <div class="feature">
      <!-- inner content -->
    </div>
  </section>
</main>

If you want to reverse this to be anchored to the right, you can flip the grid definition, moving the double start to the top like:

.grid-breakout-feature-right {
  display: grid;
  grid-template-columns:
    [full-start feature-start] var(--feature)
    [popout-start] var(--popout)
    [content-start] var(--content-inset) [content-end]
    var(--popout) [popout-end]
    var(--feature) [feature-end]
    var(--full) [full-end];
}

You can see a demo of the side-anchored component here:

But What About Tailwind! #

We love using Tailwind at Viget as a Team Accelerator™, and it's straightforward to implement these measurements and definitions in your Tailwind config.

/** @type {import('tailwindcss').Config} */
import plugin from "tailwindcss/plugin";

export default {
  // the rest of your other definitions
  theme: {
    // the rest of your theme definitions
    extend: {
      gridColumn: {
        content: "content",
        popout: "popout",
        feature: "feature",
        full: "full",
        "feature-left": "full-start / feature-end",
      },
      gridTemplateColumns: {
        breakout: `[full-start] var(--full)
            [feature-start] var(--feature)
            [popout-start] var(--popout)
            [content-start] var(--content) [content-end]
            var(--popout) [popout-end]
            var(--feature) [feature-end]
            var(--full) [full-end]`,
        "breakout-feature-left": `[full-start] var(--full)
            [feature-start] var(--feature)
            [popout-start] var(--popout)
            [content-start] var(--content-inset) [content-end]
            var(--popout) [popout-end]
            var(--feature) [feature-end full-end];`,
      },
    },
  },
  plugins: [
    plugin(function ({ addBase }) {
      addBase({
        ":root": {
          // grid sizing variables
          "--gap": "clamp(1rem, 4vw, 2rem)",
          "--full": "minmax(var(--gap), 1fr)",
          "--content": "min(clamp(30rem, 52vw, 60rem), 100% - var(--gap) * 2)",
          "--popout": "minmax(0, 2rem)",
          "--feature": "minmax(0, 12vw)",
          "--content-inset": "min(clamp(30rem, 52vw, 60rem), 100% - var(--gap))",
        },
        // force unspecified content blocks into 'content' grid
        ".grid-cols-breakout > *": {
          "grid-column": "content",
        },
      });
    }),
  ],
};

Everything is effectively the same, but you'll call your grid classes like grid-cols-breakout to set the grid, and your columns like col-feature per Tailwind naming conventions.

Forwards to a Fluid Future! #

And there you have it! A media-query-less fluid breakout layout defined with CSS grid!

While the setup is more complicated at first glance, I've found that the more fluid your layout rules are, the FEWER rules you have to write overall! Especially when paired with fluid type, dynamic viewport units, and all the amazing features that are landing in CSS — it's truly a fluid future!



  • Code
  • Front-end Engineering

y

Balancing Image Speed and Quality with imgix

Users expect a website to load fast. An average web page loads in about 2.5 seconds. The longer the user has to wait, the higher the user bounce rate. There are a lot of factors that go into site speed, but images account for about 75% of the page weight on an application or website. Google’s Core Web Vitals uses several metrics to rank sites. Visual site speed or largest contentful paint affects ROI as slower sites have fewer repeat users and fewer sales.

Without properly sized images, both site speed and image quality are affected. Accordingly, we use several methods to deliver properly sized images. Our primary solution is imgix because it is easy to implement and saves managers and clients time and effort. 

Imgix Key Features

Imgix provides a lot of features — some we consistently use on projects, and others we use in very specific situations. 

Responsive Images

Setting up responsive images can be complex. As the variety of devices and their screen resolutions continue to expand, managing all the different image requirements is increasingly challenging.

Consider this scenario: a website’s images look crisp and clear on a high-resolution monitor. When that same page is viewed on a mobile device, the images are so large the page takes forever to load. A solution could be to upload a smaller image for mobile, right? It's not quite that simple. We need eight or more different sizes of the same image to account for different screen sizes and retina screens. Keeping track of all the image sizes and saving each size gets complex and would be nearly impossible to do manually on a site that has hundreds or thousands of images. 

One of our clients, National Park Foundation (NPF), wanted to clarify its message to better target major donors. Their gorgeous, large scenic images are essential to their website strategy.  NPF needed the images throughout their site to be crisp and clear at all screen sizes. Using imgix, NPF content managers can load high-resolution images to the CMS and not worry about the site's speed or performance. They rely on imgix to deliver the correctly resized image for any user's screen.

Imgix does this with their Device Pixel Ratio and Client Hints which automatically sets the pixel density for the image based on the user's device. Those API parameters can be easily set in the URLs for the image’s `srcset`. This allows developers to set an image width for an image `srcset` and then imgix delivers the right pixel ratio image to the user. We use `srcset` with imgix on other client sites like Bezos Earth Fund and Human Rights Campaign as well.

Resize and Cropping

Imgix allows you to crop images in addition to setting an image’s focal point. So, only one image needs to be uploaded and it can be used at multiple sizes and croppings throughout the site. Let's say we upload a large landscape image, but on some pages we only need to use a portion of the image cropped as a square. Imgix will crop the image and deliver the smaller versions on the pages we need while persisting the larger versions on other pages.

At Viget we use resizing and cropping on our own website, including our articles, to crop the staff photo to a smaller size at the top of the articles. This makes it possible for us to upload the staff photo once and the article image gets created automatically. 

Color Palette 

Another feature that we've used on client sites is the Color Palette API which allows you as many colors as you want from an image. For example, the Shedd Aquarium website that we built uses this feature by pulling a vibrant color from the image and setting it as the background color for the page hero. Aside from taking the manual work out of closely aligning photography with a page’s design, there’s an additional benefit: if you are on a slow connection, you will see a dynamic colored banner at the top before the image loads.

Image Upscaling

Another valuable feature is the ability to upscale images. Even if you upload an image that is low resolution, it can still be used at a higher resolution. This is especially useful for e-commerce sites or applications where users are uploading their images.  The upscale feature uses Generative AI to take a pixelated image and create a higher-resolution image. The final image will not be perfect, but it looks more professional. See the upscale demo on imgix.

Non-upscaled image
Upscaled image using Imgix

PDF Preview Images

There is also a PDF page to image option in imgix. The API enables the generation of a page-specific image preview from the PDF, which can serve as both a thumbnail and a full-size preview. When we built AHIP.org, they had a resources section for their members containing quite a few PDFs. To help with clarity and findability, we used imgix to show previews of the PDF documents to non-members. This feature allows AHIP to upload resource PDFs without having to also upload any thumbnail images. 

Face Detection

Another nice feature is a face detection parameter that you can pass to the API. This allows you to upload a photo and no matter the cropping or size it will keep the face as the focal point of the image. We used this feature on NEA for their team member page. It's great for user profile images that are used in different contexts throughout the site. 

Video Streaming

Videos have become a key design element on websites. However, determining which service to use for embedding those videos is an ongoing topic of discussion. Video platforms enable you to integrate the video onto the page, yet they introduce scripts that may impede page loading speed. Imgix offers a video embed service that allows content managers to keep all the images and videos in one place. The videos are automatically encoded to Adaptive Bitrate Streaming to get the best compression and video quality. So, videos load fast and look great on mobile and desktop. 

Imgix Video API with Adaptive Bitrate Streaming

Performance 

A lot of CMSs have image transformations built in. An image transformation encompasses everything for that image including responsive sizes, cropping, resizing, and face detection from the original. This is great for small sets of images, but transformations quickly get out of hand the more images there are on a site. For example, the homepage of the National Park Foundation has a minimum of 96 image transformations. 

Processing all of those image transformations uses a lot of server resources. Imgix saves the images and delivers them through their CDN. The imgix image CDN has an average of 0.15 milliseconds return on requests which enables images to load as quickly as possible. The CDN also caches the images on CDN edge nodes making them immediately available for future requests. 

Flexibility

Imgix is flexible enough to work with almost any site structure; including WordPress, Craft CMS, Shopify, React, Ruby on Rails, Python, and more (see the full list). So, whether a site is a WordPress site or a Rails application, imgix fits right into the ecosystem. And, even better: you don’t have to rebuild your web app or website to gain the benefits of image performance, which can save you a lot of time and money.

Setting up imgix on an existing website is easy. Imgix can connect to existing asset storage sources like AWS, Azure, or a web folder on the same domain. Once the image source is set up, a developer can start passing parameters to the API

Cost

Imgix is free for 1,000 images which makes it easy to integrate and grow with your site. Pricing goes to $750/yr for 5,000 images and $3,000/yr for 25,000 images. In their pricing structure, “images” are categorized as origin images, so the count only includes original images and not transformed ones. So, you could have hundreds of images and thousands of image transformations all being delivered through a CDN for free.

Conclusion

Ensuring fast site speed isn't just important. It is vital. It's the cornerstone of a successful online presence, directly influencing search engine rankings, user satisfaction, and ultimately, your return on investment. Properly sized and optimized images are key to ensuring your site loads quickly and displays correctly for users across various devices.

We have found that imgix enables our team to efficiently create projects with diverse image options, saving managers and developers valuable time. Our clients benefit from reduced server space and an increased site speed. Imgix’s API is comprehensive, so you can use one tool for all features and options around site images — from cropping and resizing to face detection and automated color palettes, to video and beyond. Having used imgix for the past five years to support the wide-ranging needs of our clients, we feel confident recommending it and using it again and again. 

Users expect a website to load fast, and imgix is a reliable way to make sure that happens. 




y

Your Website Transition Checklist

When onboarding a new partner to redesign your website, take over maintenance, or rescue a project going sideways, you'll need to carefully transition access to a variety of critical systems and tools. And if you're navigating a contentious relationship or onboarding into a new organization without documentation, you might not know where to start.

Does that sound scary? It doesn't have to be. 

Here's a comprehensive checklist to ensure that you retain full control of your website and avoid any potential hiccups during a transition.

  1. Codebase access. Ensure you have ownership or administrative access to the existing codebase or code repository. Popular platforms like Bitbucket and GitHub are often used for this purpose.
  2. Content Management System access. Ensure you have the highest level of access (super admin) for your Content Management System (CMS). 
  3. Hosting information and access. Gather all hosting information and ensure you have access to the account that owns the workspace. This is crucial to prevent unauthorized updates or changes to your site. For hosted platforms, you’ll need Owner access, not just Administrator access. 
  4. Additional services information and access. This might include your domain registrar (e.g., GoDaddy), DNS settings, email services, your content delivery network (CDN), if applicable. This could also include any third-party services that are integrated with your website. Common examples might include: Algolia, Hubspot, Stripe, etc. 
  5. Analytics and Data. Make sure you have access to all analytics tools used to monitor your website traffic and user behavior. This might include both old Google Universal Analytics data and current GA4 data, Google Tag Manager, or any other analytics services used on your website (e.g., Mixpanel, Hotjar, Adobe Analytics, etc.). 
  6. Backups. Secure a full backup of your site, including the file system. Plugins like UpdraftPlus for WordPress can be very helpful for this process. Also, ensure you have backups of shared files, such as those in Google Drive, Box, or Dropbox.
  7. Design Assets. Retain copies of raw design assets (e.g., Figma files). We always transfer ownership of Figma files to our client teams to ensure they have the ability to extend the design system in the future.
  8. Licenses. Make sure you own any required licenses, such as font/photo licenses, CMS licenses, API keys, or premium plugins. We insist that our client teams purchase any required licenses/subscriptions using their corporate information so we’re never blocking access to those critical resources.

Transitioning website partners can be a smooth process with foresight and preparation. While ideally there would never be gaps in access to these critical resources and services, by following this checklist, you can ensure that you’re not missing anything when offboarding old partners or getting your bearings with a new team or organization. 

Do you need help figuring out how this checklist might apply to your situation? Be in touch, and we’d be happy to discuss your current status and suggest next steps for your website transition. 




y

10 Things I Learned in My 10 Weeks at Viget

This summer, I was the Application Developer Intern at Viget. This being my first internship, I was pleasantly surprised by how much I learned. Rather than being tasked with fetching coffee or doing busy work, the internship focused primarily on our growth and development as interns. As my time at Viget comes to a close, I wanted to reflect on ten key things I learned during my experience here.

Following the real-world development cycle

Going into this internship, my development process involved me sitting down and coding until the feature was completed, and that's it. During this internship, I learned and practiced the development cycle used at Viget. For each feature, I created a Branch. Then, I submitted a Pull Request once it was completed. After that, my advisor reviewed my code and gave feedback. Once I had completed the requested changes (if any), I would rebase and merge into the main branch. This cycle made the code cleaner, and the feedback on my code always ensured I was going in the right direction.

Maintaining a clean git history

During my development process at Viget, my advisor ensured I took the necessary steps to maintain a clean git history in my projects. I put the corresponding issue number next to each git commit and pull request. This made it much easier to see which commits belonged to which feature when reviewing git history. I also learned to always use “rebase and merge” rather than “create a merge commit” when merging a pull request. This helped when reviewing git history as merge commits make it much more difficult to understand what’s going on, and rebase and merge provided a clean git history.

Getting introduced to DevOps

Nevin Morgan hosted a MicroClass where he went over the basics of DevOps. Going in, I didn’t know much about DevOps, but the class gave me a solid understanding of the basics. DevOps is a combination of philosophies, practices, and tools designed to improve the speed of development. Their responsibilities include:

  • Keeping Communication clear for development teams
  • Making sure teams continue collaborating
  • Ensuring deployments are quick and reliable

I also got the chance to pair with Nevin when he set up AWS deployment for one of my projects, and when he was setting up Grafana for Viget. Getting to see DevOps in action gave me a good idea of what goes into being part of the DevOps team.

Learning to work with clients

At the start of our intern group project, Nathan Long gave us a presentation on what it's like to work with clients. He covered the typical client project cycle, client presentations, and how to handle client feedback. For our project, we simulated a client relationship with Viget as our client. They provided us with their requirements, and me and the other interns planned out the details of what we would deliver. Throughout the process, we gave several client presentations, received valuable feedback, and iterated on our product. Two weeks later, we had a finished product, which we presented to the client in a live demo. This whole process was designed to mimic what Viget goes through with real clients, and seeing the different perspective required when working with clients was really eye-opening for me.

Exploring digital accessibility

Nathan Schmidt hosted a MicroClass for the interns on Accessibility. He gave us an overview of what digital accessibility is and who it impacts. I learned that digital accessibility is the lens through which we ensure that people of all abilities, and particularly those with disabilities, are able to engage with the digital world. Every website is graded to a level set from the Web Content Accessibility Guidelines (WCAG). These guidelines include video captions, text size, color contrast, and many more requirements. It is the industry standard to follow these WCAG guidelines so that your website can be accessible to a broad range of consumers.

Building confidence in public speaking

When the summer began and I learned that I would need to present to the entire company, I felt intimidated. Public speaking has always been a source of anxiety for me, but I had numerous opportunities to work on this skill. Throughout the summer, I became increasingly confident. First, my fellow interns and I presented our group project to everyone at Viget at the company-wide all hands meeting known as TTT. I presented my personal project to the Dev team, discussing the libraries I used and walking through my code. The most significant presentation I delivered was my final one, where I spoke to everyone at Viget about my Gap Year through a Viget Tradition known as LabShares. Public speaking is a skill that improves with practice, and the various opportunities I had greatly boosted my confidence in this area.

Diving into Vanilla JavaScript

Going into this summer, I had never written a line of JavaScript in my life. I quickly learned that JavaScript is essential if you’re going to work in web development. On my personal project, which was an audio sharing social media app, I had a for you page, and I wanted to make the page update as soon as the user went to the next sound. This would require me to write JavaScript. I went through and wrote Vanilla JavaScript to update all the necessary information from the server's response. Although it was a challenging and tedious process, it significantly enhanced my understanding of how websites work and the role of JavaScript in web development.

Getting my feet wet with Rails

For the first half of the internship, I got my foothold in Ruby on Rails. This was my first time writing in Ruby, so there was a bit of a learning curve. I started with the Rails tutorial and then made a Hacker News clone. This exposed me to a broad range of the application stack and got me prepared for the Intern project, where I also used Rails. I found Rails’ Model, View, Controller setup to be very intuitive, so the learning process was relatively painless.

Discovering the benefits of Tailwind

Being the only Application Developer Intern, my focus throughout the internship was primarily on the back-end. However, I did have the chance to use Tailwind for the first time during my personal project. The biggest thing that stuck out to me was how it was convenient to not have to go through and change the stylesheets myself. With Tailwind's utility-first approach, you can quickly apply predefined classes for spacing, colors, typography, and more, without having to write custom CSS. This makes it much faster to prototype and iterate on designs, as you can see changes immediately by simply adjusting the class names in your HTML.

Exploring the Basics of React

Chris Manning hosted a MicroClass on React. I had never actually used React, but he made the class very beginner friendly. React is a JavaScript library, whose main strength is how dynamically it responds to user input and cascades UI changes. Chris went over JSX and React components, props, children, and state memory. I didn’t have time to actually write any React this summer, but I appreciate that Chris hosted this class after I said React was something I was interested in!

Reflecting on what I’ve learned here at Viget, I realize how invaluable this experience has been for both my personal and professional growth. From learning Rails and JavaScript, to understanding the intricacies of client relationships, I've gained a wealth of knowledge that extends far beyond technical skills. The opportunity to work alongside experienced professionals and receive constructive feedback has been a huge source of development for me. As I move forward, I am excited to apply these lessons and continue exploring the world of Software Development, confident in the foundation this internship has provided.



  • Code
  • News & Culture
  • Back-end Engineering
  • Internships and Apprenticeships

y

Evolving Traditions: 15 Years of Viget Internships

This week we will bid farewell to our fifteenth cohort of summer interns. Ciel Park (UI Developer Intern), Faye Stover (Product Designer Intern), and Paul McKissock (Application Developer Intern) joined our team ten weeks ago and have been hard at work learning and growing, teaching and sharing, and iterating ever since – and so have we. 

Viget’s 15th Summer Internship Cohort: Faye Stover, Paul McKissock, Ciel Park (left to right)

At Viget we are committed to fostering curiosity and drive both for budding engineers and designers but also for our team of full-timers who are eager to learn themselves and flex their mentorship muscles. As we’ve shared over the years, the internship is one of our favorite traditions and while a lot has changed in fifteen years, that commitment remains the same. 

Here’s a quick look at three core aspects of the Viget internship that remain flexible. 

Cohort size and available roles.

We are not married to a specific number of interns. We recruit for and match interns with available mentors who serve as our interns’ dedicated advisors.

Working location. 

This summer our interns primarily worked from our Falls Church, Virginia headquarters. We required interns to work in the office for the first three weeks of the program and the last. During weeks four through nine they were able to work remotely two to three days a week. In the past the internship has been fully in-person and fully remote

Cross-discipline internship project. 

Interns can expect cross-discipline collaboration during their time at Viget but how exactly that takes shape remains flexible. In years past interns spent 8 weeks coming up with, designing and building a working product. This year, with our smaller cohort of interns, we opted for a smaller approach to the group project. The project was pre-defined, scoped by our advisors, and happened over just two short weeks.   

Earlier this summer we hosted an internship alumni panel and invited Hayley McMillon (2022 Summer Cohort), Andrea Brucculeri (2019), Gabriel Kay (2019), and Vigenesh Gopalan (2018) to discuss lessons learned at Viget, life after Viget, underrated skills worth developing, tips for remote collaboration and more. The event was open to all and both current staff and other alums sat in on the moderated panel discussion. It was awesome, and everyone – long-timers and interns alike – left feeling inspired. This is my favorite aspect of the internship, our alumni network, and how our interns graduate to be active contributors.

Summer 2024 Internship Alumni Panel

I’m looking forward to staying in touch with Ciel, Faye, and Paul and I cannot wait to see all the wonderful things they accomplish. 

Does this sound like an experience you want to be a part of? We’ll host our 16th cohort of college students and recent grads next summer. Bookmark our internship page to keep an eye on future opportunities. 



  • News & Culture
  • Internships and Apprenticeships

y

Motion Magic: Project Insights From My Viget Internship

When we open an app or website, we do so to accomplish a task or find information. A well-designed user experience ensures users can achieve their goals efficiently. But what keeps us engaged beyond basic functionality? What differentiates a mundane interface from an exciting one? In my opinion as an up and coming UI developer, one key element is motion.

During my summer internship at Viget, I had the opportunity to dive deep into the world of agency work. From getting the chance to contribute to client sites to participating in a hackathon and pursuing a personal project, I seriously leveled up my stack and gained valuable development experience. Not to mention the amount I learned from exceptional, dedicated mentorship and micro-classes on everything from React to SQL to business models. 

However, coming into the internship, I had the specific goal of learning how to add motion to my web projects. I walked in on day one with no idea where to start, and now I’m leaving my last week with a complex knowledge of Rive, canvas elements, JavaScript animation, GSAP, and more. Here’s how… 

Spinet

In this two week hackathon project, I worked alongside Faye and Paul, the Product Designer and App Developer interns, to create a spinning wheel name picker. During the first week, I took on branding and visual design work. 

I spent the second week implementing wireframes. Through this project I learned how to transform client specifications into design directions, a style guide, and ultimately, UI components.

For this app, the motion of the spinning wheel was critical to the experience. Initially, client feedback indicated that the spin felt too uniform. I adjusted the motion parameters by extending the slowdown time and changing the easing function from linear to cubic, which increased feelings of suspense at the end of the spin animation. 

To add a level of joy and celebration to the winner announcement popup at the end of a spin, I incorporated confetti animations. In doing so, I discovered the world of JavaScript animation libraries that make implementing animations as easy as simple as adding the script to my HTML and adjusting the timing and placement of the animation object. Finally, we had ultimately decided on a modern, clean-cut video game aesthetic for the branding, and pulled this in through inspired sound effects, the logo design, and a 3D button component with a click animation accomplished entirely through Tailwind. 

Luna chatbot

After the hackathon, I got the chance to work on a personal project of my choice: an AI mental health chatbot inspired by tools like Woebot and EarKick. I was motivated by the question of what could make conversational AI feel less intimidating and more empathetic. My answer was an AI support companion with an animated avatar to enhance feelings of emotional connection and understanding. 

To get started, I experimented with various chatbot APIs and found that the Llama3 model was the best at following system prompts and offered the most natural interactions. A huge part of this project was the chatbot’s expression animations. I surveyed several popular tools and found Rive was the best fit for this, offering intricate animation capabilities, easy web integration, and a state machine for managing overlapping states and complex transitions.

The first step of animating in Rive is to create a design. Luckily, Rive has a vibrant open-source community, and I learned a lot from examining and remixing community files. The second step was learning to create the animations themselves. This was my first time animating anything, but the concept of keyframes was relatively intuitive, and the UI reminded me of video editing software, like iMovie, I’d used in the past.

The third and most challenging step for me was making all the animations work together in a state machine. 

This is the logic that connects animations together, taking input values that determine when to transition between states. Getting smooth animations between emotional states required a lot of rewiring and experimenting. Finally, embedding the Rive file in my project and linking the emotion data from API responses to the animation inputs was relatively straightforward using vanilla JavaScript. 

In conclusion

Animations, whether simple or complex, add a layer of interactivity and visual interest to digital products. Over a short 10 weeks, my internship projects allowed me to explore UI development, modern animation tools, and motion using CSS and JavaScript.

If you’re interested in bringing ideas to life and sparking joy through motion design, then diving into a passion project, seeking inspiration from the community, and exploring tools like Rive and GSAP will definitely kickstart your journey!



  • Code
  • Internships and Apprenticeships

y

The Keys to Successful Concept Testing: Planning

Concept testing is a research method that explores how a user perceives or interacts with a new idea. It usually takes place early in a project, and involves putting ideas into the “real world” to see how users will react to them.

Not every project needs to include concept testing, but it can make your solutions more user-centered. Involving users in the design process leads to products, sites, and experiences that are more aligned with user wants and needs — and ultimately more successful.

Concept testing is most useful when exploring ideas that are novel, complex, or risky. It can also help your team:

  • Generate more purposeful, user-centered ideas.
  • Identify which ideas provide the greatest value to users. 
  • Prioritize the most promising idea(s), saving time and money.
  • Evaluate any significant changes you make along the way.

I’ll cover how we use concept testing at Viget to help our clients gain clarity and develop user-centered solutions. 

This article will be part of a three-part series focused on concept testing. First, we’ll focus on planning out your concept testing. 

Form a clear plan

A successful concept test has a well-defined plan at its foundation from the start. At Viget, we work with clients to define what you want to learn, and who you want to learn from. 

Let’s imagine that you and your team are redesigning an online food delivery platform, and you have some new concepts that you want to test to see if they resonate with users.   

Focus on what you want to learn.

Start by defining research objectives. Think of these objectives as your north stars that will guide you and your team. You’ll use these for initial alignment, and then to frame what the prototype needs to do, and what feedback you really need.

You can create a strong set of objectives by asking:

  • What initially sparked the motivation to test?
  • Where do you have the most uncertainty about your concept?
  • What are the key things you need to know through testing?

Teams usually have a lot of questions, and feel pressure to answer all of them at once. Resist the pressure! Instead, focus on the most pressing and critical — it will allow you to dive deeper into the most important areas in a session. Otherwise, you may not have the depth you need to move forward when you finish the testing.

Let’s say you've developed new solutions that span the whole user journey of online food delivery. You could spend a whole research session asking questions that cover all that breadth, but you would get much more depth by focusing on one particular moment in the journey, like the online ordering experience.

Think about who you want to talk to (and be holistic).

If you aren’t intentional about who you test with, you can end up with feedback that may not be applicable. Ideally, you’re talking to existing customers or people who would use the website or product in the future. Look at behaviors, like whether they’ve used a competitor, or hold specific sentiments, when recruiting participants. Perhaps you’re trying to expand your audience for your new food delivery app, so you may want to talk to people who cook at home frequently as well. 

Don’t forget to think holistically. Consider every person who might interact with this solution, from beginning to end, and who might be affected by it. For your new app, you'll want to test with the diner, but your solutions may also affect the restaurant host/hostess, cooks and cashier’s workflows for example. So you may need to capture their perspectives. 

Opinions aren’t strong evidence.

You may gravitate towards seeking preferences or opinions about your concepts (i.e., “which concept is better?”). But rather than focusing on which concept users like most, it’s more important to uncover user behavior. Preference-centric concept testing won’t teach you about how someone might actually interact with this concept. 

For instance, you’ll learn much more about which new concepts for online food ordering are most beneficial to users if you ask about how they might use it in a scenario. Or even better, you actually have them interact with each one.   

Questions like the ones below will give you stronger indications of user behavior:

  • When was the last time you used [the competitor]?
  • How might this concept fit into your day to day?
  • How would you accomplish this task with the concept?

Avoid asking questions like “Which concept is better?” or “which one do you prefer?” Instead ask why one concept has advantages or disadvantages over another for a user, or how they actually envision it in their daily life. 

Even if the focus of the test is on preference (as is the case for branding or marketing research) it’s still helpful to dive deeper into what a user feels the design is communicating to them and why that prompts a specific reaction.


These key strategies that I’ve covered should get you a jump-start for successfully planning out your first concept test.

In the next article in the series, I'll dive into prototyping.




y

Use Behavioral Analytics Data to Make Your Site More Effective

Behavioral analytics are a great way to get a sense of what users are or are not doing on your website or app. While behavioral analytics may not provide insights into why users are behaving a certain way, this method does provide a quick and cost-effective way to see what your users are currently doing at scale. Knowing how your users are engaging with your website or product can help you make informed decisions that have a positive impact on engagement and conversions.

Here at Viget, we use behavioral analytics data for a number of use cases:

  1. Our client has a specific question about a certain aspect of their website or app (e.g., a specific user flow or content type) and wants to learn more about how and when users are engaging. 
  2. We are redesigning a client’s website and want to get a sense of where the current experience is excelling or falling short.
  3. We are conducting an annual analysis to help clients keep an eye on potential areas of growth or stagnation. 
  4. We are reviewing behavioral changes on a site or app after launching a new experience or feature to assess performance.

But what kind of insights can you expect to find from behavioral analytics data? 

It ultimately depends on the website or app, the users, and the kinds of questions you are asking, but let’s go through a few different examples of what kind of information you can gain from behavioral analytics tools.


Who is using your website or product?

Understanding who is using your website can provide helpful context on your user base and potentially unlock growth with new user groups you may have been unaware of. To investigate this, we may look at geographic location, language, device type, and any other demographic information that may be available. Sometimes this kind of data provides what I like to call descriptive information—information that often doesn’t feel immediately actionable but can become more useful relative to other data points. This could come from comparing your data to last year, to industry standards, to other content on the website, or it might come from comparing it to an assumption that an individual or organization holds. 

Here are some examples of findings that shed light on who was using the website or product:

32% of sessions were from users outside the United States. 
  Through a previously conducted survey, we were aware that some users were looking for content that was not specific to the United States. This metric helped us better gauge the size of that need.
97% of Canadian sessions interacted with the website in English, with only 3% of Canadian sessions using French.
  We were unsure to what degree French content needed to be prioritized and this metric helped provide a sense of scale.
15% of searches were conducted on a mobile device. 
  Although 15% may seem low, this metric was actually higher than expected because there were known issues with the mobile search experience. This demonstrated that even though the mobile experience was harder to use than the desktop version, users were still inclined to use it, further illustrating the importance of improving the mobile experience. 

How do users get to your website or product?

Knowing how users navigate to your website or product can highlight what traffic sources are particularly effective in driving conversions, but it can also help to provide important context on user expectations or goals. To understand this, we look at both the source/medium that brought them to the website as well as the first page they viewed. 

For example, users might:

  • Come from google and land on a blog article
  • Go directly to your home page
  • Come from an email referral to a donation page 
  • Learn about you from ChatGPT and land on your About page

From there, we might look at engagement rate, conversion rates, or other metrics to get a sense of what these users are doing and whether anything stands out as particularly effective or ineffective. 

Here are some examples of acquisition insights that informed our understanding and approach:

Only 10% of sessions started on the home page, with most users starting much deeper in the site on content-specific pages.
  Because only a small portion of users entered on the homepage, we could not solely rely on homepage messaging to orient users to the site. This highlighted the importance of providing sufficient context on any page of the site to ensure that users navigate to their desired content, regardless of what page they land on.
Although the paid ads were effective in driving users to the website, those sessions had abnormally high bounce rates, with one traffic source having a 95% bounce rate. 
  This indicated a potential mismatch between what users expected based on the ad, and what was actually on the page.
Organic search brought in a large amount of new traffic to their site through the blog pages and while users engaged with the blog content, they were not engaging with the CTAs. 
  Because these new users were potentially learning about this organization for the first time, the donation CTAs were likely not the best fit, and we recommended shifting the CTAs on those pages to focus more on learning about the organization.

What content or features do users engage with?

Here is where we start to get to the meat of what your users are actually doing on your website or product. Knowing what users are doing and what they’re not using can help to establish priorities and inform decisions. You might be surprised to learn that users are actually engaging with specific features or content quite a bit, but others are barely used. If the content or feature is surprisingly popular, then we likely don’t want to outright remove it and may instead consider iterating or leveraging that offering more. If users aren’t engaging with content or a feature, it may be worth considering the effort to maintain and iterate on that offering. 

Here are some examples of engagement insights that helped us identify opportunities related to content or features:

Less than 1% of users were engaging with a particular feature. 
  These same users were showing high engagement with other features though, indicating that users either didn’t know this feature existed, knew the feature existed but didn’t understand the value add, or the feature was simply not something they needed.
For a highly engaged audience, there wasn’t a standout page that most users visited. These users viewed a variety of pages across multiple sessions, typically viewing highly specific content pages. 
  This indicated that instead of relying on a single page to drive conversions, getting users to the specific details they needed was likely a better approach in getting users to try the product.
Nearly 84K sessions engaged with a particular content type. 
  While this was lower than other content types, it was much higher than expected. It was largely organic traffic and the sessions were highly engaged. We recommended doing some additional research to better understand the potential opportunities with that type of content.

What is the user journey or path?

Another major area of investigation is the sequence of steps users take when viewing content or completing certain actions. This could be perusing content on the website, going through a signup funnel, or checking out to make a purchase. 

This helps us identify:

  • the actual paths that lead to conversions (which is not always the path we assume it is) 
  • areas where users drop off at key points in the funnel
  • moments where users have to “turn around” in the journey, because the path laid before them doesn’t align with their needs 

This information can help you build towards a frictionless experience that encourages users to sign up, complete a purchase, or find the resources they need.

Here are some examples of user journey insights that helped us understand where there were existing points of friction for users:

While the CTA to demo the product appealed to users and they were quick to engage with it, it often resulted in users backtracking to the previous page. 
  We hypothesized that users were eager to get to the demo, but were moving too quickly and missed important context, resulting in them having to go back to a previous page. We were able to confirm this with user testing and recommended transitioning some of that context to the CTA page.

What “turning around” in the user journey can look like:

A select few products had abnormally high drop off rates, but at different stages depending on the product. 
  For one product, there was an abnormally high cart-abandonment rate, and for another product, there was an abnormally low add-to-cart rate. Based on these findings we recommended looking further into what is impacting a user’s purchasing decisions.

What dropoff can look like at different stages:

The Ecosystem at Large

Some clients have a larger ecosystem of products or services, and it’s important to look at how users engage with and navigate across the ecosystem. This might include subdomains for a shop, a marketing site versus the product site, help documentation, etc. By looking at the larger ecosystem we can reveal important connections that are missing or connections that could be strengthened.

Here are some examples of insights that demonstrated a need for changes in those ecosystem connections:

For sessions where a user was looking for a particular kind of resource, 95% of the searches were done exclusively in a single subdomain or microsite.
  Through user interviews we were able to confirm that this siloed experience was intentional for experienced users but unintentional for less-experienced users, who were largely unaware of the other parts of the ecosystem that were available. We recommended making changes to improve discoverability of those other areas.
For sessions where a user navigated between two domains, 75% of sessions navigated to the other domain to view documentation specifically.
  Yet, depending on the product, sometimes the documentation was hosted on a subdomain specific to documentation and sometimes it was available on the product domain. This created an inconsistent experience where for some products, users could find what they needed on the product website, but for other products, users were sent to an entirely different subdomain. We recommended creating a more consistent experience for users, where regardless of the product, the documentation would be found in the same location. 

Here at Viget, there are a wide variety of insights we may discover for any one project through behavioral analytics. These insights can help to identify new user groups, help to prioritize content or features maintenance and updates, or bring to attention moments in the user journey that are causing friction. These opportunities can help you bring in new users and retain your existing users, by providing an experience that aligns with their needs, whether that is finding resources, getting involved in a community, or making a purchase.  

If you’re interested in making your website or application more effective for your users by leveraging the power of behavioral analytics data, we’d love to hear from you




y

Setting up a Python Project Using asdf, PDM, and Ruff

When I was tasked with looking into alternative ways to set up a new Python project (not just using the good ol' pip and requirements.txt setup), I decided to try to find the tools that felt best to me, as someone who writes Python and Ruby. On this journey, I found a way to manage dependencies in Python that felt as good as bundler, among other great tools.

The Runtime Version Manager #

asdf has been my primary tool of choice for language version management for multiple years now. The ease of adding plugins and switching between versions of those plugins at a local or global level has saved me massive amounts of time compared to alternatives.

If you've never set up asdf before, follow the instructions here to get it set up. For reference, I use fish for my shell, so I installed asdf using the "Fish & Git" section.

Once you have asdf on your machine, the next step is to add the plugins you need for your project. Plugins are the actual tools that you want to manage the versions of, like NodeJS, Python, Ruby, etc. For the purposes here, I'll start with adding the plugin for Python:

asdf plugin-add python

Once you have added a plugin to asdf, you're ready to install various versions of that plugin. Since we just installed Python, we can install the version we want:

asdf install python 3.12.4
# OR if we want to just use whatever the latest version is
asdf install python latest

Once the version you want is installed, you can tell asdf to use that version in the current directory by running:

asdf local python 3.12.4
# OR 
asdf local python latest

depending on which version of python you installed.

The Dependency Manager #

In the past, I just used pip install and requirements file(s) to handle most of this. I knew of other options, like pipx or pipenv, but I still have never tried using them. I was more interested in finding a dependency manager that did these things in a significantly different way than what I was used to with pip.

Therefore, I wanted to find something that felt similar to bundler for Ruby. Luckily, very early on in my journey here, I found PDM.

Upon reading what PDM did, I immediately decided to try it out and get a feel for what it offered. Some key notes for me that piqued my interest:

  • Lockfile support
  • Can run scripts in the "PDM environment"
    • pdm run flask run -p 3000 executes the normal flask run -p 3000 command within the context of your installed packages with PDM.
    • In other words, it adheres to PEP 582 and allows you to run project commands without needing to be in a virtual environment, which to me is a big plus.
  • Similar commands to bundler
    • pdm run => bundle exec
    • pdm install => bundle install
    • pdm add <package> => bundle add <gem-name>
      • Note: My workflow was almost always to just add gem <gem-name> to the Gemfile rather than using bundle add, but there is no direct 1:1 equivalent of a Gemfile with PDM.

Installing PDM #

PDM has its own asdf plugin, so let's just use that here as well! Running:

asdf plugin-add pdm

adds the plugin itself to asdf, and running:

asdf install pdm latest 
# can replace 'latest' with a specific version number here too

installs the latest version of PDM. Finally, set the local version with:

asdf local pdm latest
Side note about asdf local
  asdf local creates a .tool-versions file (if it doesn't already exist) in the current working directory, and appends the plugin and version number to it. At this point, the directory in which you ran asdf local python 3.12.4 and asdf local pdm latest should have that .tool-versions file, and the contents should be a line each for Python and PDM with their associated version numbers. This way, if someone else pulls down your project, they can just run asdf install and it will install the versions of those plugins, assuming the user has the necessary plugins added themselves.

Now that we have PDM and Python set up, we're ready to use PDM to install whichever packages we need. For simplicity, let's set up a simple Flask app:

pdm add flask flask-sqlalchemy flask-htmx

This line adds Flask, Flask-SQLAlchemy and Flask HTMX. Flask is a web application framework, Flask-SQLAlchemy adds SQLAlchemy and its ORM, and HTMX builds on top of HTML to allow you to write more powerful HTML where you'd otherwise need some JS. Side note, but HTMX is really cool. If you haven't used it before, give it a go! I'm even a part of the exclusive group of HTMX CEOs.

Linting and Formatting #

Finally, I wanted to find a way to avoid pulling in multiple packages (commonly, Black, Flake8 and isort) to handle linting and formatting, which felt to me like it could be the job of one tool.

Pretty quickly I was able to find Ruff which did everything I wanted it to, along with being really fast (thanks Rust ????).

First things first, we need to install Ruff. Since it's a Python package, we can do it using PDM:

pdm add ruff

Once it's installed, we can use ruff check and ruff format to lint and format, respectively. Note that since we installed via PDM, we need to prepend those ruff calls with pdm run:

pdm run ruff check --fix

This runs the linter and fixes any issues found (if they are automatically fixable). The linter can also be run in --watch mode:

pdm run ruff check --watch

which re-lints on every saved change and tells you of any new errors it finds.

The Ruff formatter is similar to use:

pdm run ruff format

which will automatically fix any formatting issues that it finds and can fix. If you want to use this in CI (which you should), you can use the --check flag that will instead exit with a non-zero status code, rather than actually formatting the files:

pdm run ruff format --check

Bringing it all together #

Working with projects set up this way is much easier than how I used to do it. Using tools like asdf, PDM, and Ruff rather than pyenv, pip, and Black/Flake8/isort make both setting up projects and pulling down/installing existing projects more straightforward. I hope the contents of this article are helpful to anyone interested in setting up Python projects in a similar way.




y

Some Thoughts after a Major Ruby on Rails Upgrade

For the past few weeks, I've been upgrading an older, fairly large Ruby on Rails app from Rails 5.2 to Rails 7.1 and from Ruby 2.7 to Ruby 3.3. During this time, I have also made the switch from Webpacker to Vite for asset bundling and made various JS and CSS upgrades to go along with that change. Here are a few takeaways from the experience.

Upgrade Regularly #

First, I know I am probably preaching to the choir with this one, but just upgrading your tech as you go and whenever you can is great. It prevents you from being in the position that I was in–having to make such a big jump all in one go. It also makes sure you keep getting security upgrades, and more security is never a bad thing. If you are up for it, you can even automate the process like GitHub does for their Rails upgrades or by using something like Dependabot for notifying you on when to upgrade dependencies.

Commit Often #

This is good advice for any project, but I think it is specifically good when working through issues that arise from upgrading. Whenever I have done a larger upgrade, there’s always at least one tricky issue that takes time to diagnose. This leads to me experimenting and trying a few different things before I figure out the actual fix. Committing often allows me to reset back away from these false paths whenever I decide to go down a new one. But I could also commit these false paths if I'm stuck, store them away in a separate branch, and come back to them later if I feel like an approach is worth a second look.

Leave Code Comments #

If you have a particularly confusing piece of code where its purpose or function is unclear, leave a comment. This is another piece of advice that is relevant at any time, but I found those comments to be extra helpful during this latest round of upgrades. There were several instances of code that had not been touched in years (and never touched by me) causing errors after upgrading the underlying tech. Some of these were well commented, which made it much easier to understand their purpose and decide how to fix them—or even whether to keep them. On the flip side, there were some pieces of code that were not well documented, which made fixing the errors much harder.

Avoid Fancy Code #

As somewhat of an alternative to the code comments, you can also just avoid fancier code. Try seeing if any code that is fairly complex can be simplified into something a bit easier to understand. Also, you want to avoid calling any private APIs that might change out from under you during your upgrade process which can lead to all sorts of weird bugs and behavior. I'm not saying do this completely in place of relevant comments, but simplifying where you can will somewhat cut back the need for them.

Be Selective with Dependencies #

When upgrading a massive Rails app and the Javascript associated with said app, you are often going to have to upgrade some of your dependencies as well. The more of these you have to upgrade, the higher chance you have of breaking something, so it is important to be selective when choosing these dependencies. During these upgrades, I ran into several issues caused by a dependency that really was not doing much for us in the grand scheme of things, but was causing more than its fair share of issues. If you want to read more about how to go about choosing dependencies, feel free to reference my colleague Sol's article on the subject.

The End #

I don't think these insights are particularly original or profound, but hopefully they give you something to think about as you make major upgrades on your own app or as you think ahead to future upgrades.



  • Code
  • Front-end Engineering
  • Back-end Engineering
  • Tooling

y

Agency Partnerships: A Rising Tide Lifts All Boats

For agencies like ours, success doesn’t come from being an expert at everything—a big part of it is complementing our expertise and working hand-in-hand with like-minded partners who share our values and standards.

These partnerships haven't just boosted what we can do, they've created opportunities for us to engage with new clients. Here's how these collaborations have made us—and our partners—stronger:

  1. Incremental Value: We have a deep respect for expertise. We believe If you try to be an expert at everything, it’s difficult to be exceptional at anything. By teaming up with partners who bring different skills and services to the table, we get access to all sorts of proficiencies we wouldn't have on our own, adding value to prospective and existing clients. Instead of “That’s not our area of expertise”, now it’s “Yes, we can help with that.” These alliances empower us to deliver a higher level of service and comprehensive results for our clients.
  2. Mutual Scalability: Sometimes, there’s a ton of demand for what we do, and it's hard to keep up. Strategic partnerships mean we can call in reinforcements when we need them. By tapping into our partners' talent pools, we can handle even the most time-sensitive client demands without sacrificing quality or speed. And it’s mutual. When our team has time available, we are the reinforcements instead.
  3. More Leads, More Growth: In a crowded market, having a steady stream of clients is crucial. Naturally, every knock on our door can’t be a great fit. Through our partnerships, we've built a network of agencies that share our values, quality standards, and culture. By working closely together and passing leads back and forth, we've created a symbiotic ecosystem where projects flow smoothly, keeping all of us busy and growing.
  4. Reaching New Frontiers: Exploring new markets or industries can be risky, especially if you don't know the terrain. That's where partnerships come in handy. With an experienced partner on your team, it cracks open a door to reach new customers that may have otherwise been too difficult to open on your own. By teaming up with others who know the ropes in different areas (e.g. machine learning, hardware prototyping, reputation management, etc.), we can expand our reach, and establish ourselves in new segments with confidence.
  5. Getting Creative Together: Innovation flourishes when different minds come together under a set of constraints. By teaming up with partners who bring fresh ideas to the table, whether through smaller things like adding feedback to a partner’s open-source library, or bigger things like discussing AI’s impact on the web, we create a space where new approaches can flourish. (And, well, it’s our namesake after all).
  6. Professional Development: Values like “learn & grow” are part of a rewarding career at Viget. The symbiotic ecosystem created in our partner network provides opportunities for knowledge sharing. Partners help us solidify new skills including teaching others. Our own expertise shared with our peers gets reciprocated—each agency broadening the other’s horizons and leveling up one another’s teams. 

In the end, strategic partnerships are an important ingredient in our recipe for success. They give us access to all sorts of perks we wouldn't have on our own, and they help us build a community of successful agencies and contractors who all value the power of teamwork. 




y

5 Ways to Make Your Next In-Person All-Hands Event Worthwhile

In recent years, as distributed work has become the norm, all-hands trips have become more commonplace. Even companies that have always done them now see their importance in a new light. They are expensive and demanding for everyone involved, but when they’re done well they can be incredibly impactful. Are you bringing your team together and feeling the stress of getting it right? Designing the time together takes strategic thinking, logistics planning, and the confidence to ask everyone to contribute to the event’s success.

Last week, we came together to connect, celebrate each other, and look forward to a bright future in our quarterly all-hands event we call Third Third Thursday or TTT. It was our first in-person all-hands event since May 2023. At Viget, we actively build our culture together. The responsibility doesn’t fall on just a few individuals' shoulders. Our events are successful because individuals show up, speak up, listen, and honor the limited time we have together in-person. This is evident in the chats over breakfast pastries, the all-in approach to competitions breakout sessions, and the peer talks and discussions throughout our events. This connection and camaraderie doesn’t just happen, we work hard to make it happen. 

Reflecting on last week’s event (and 7 years of other events), I want to share these five key planning tips to help you craft a successful event. 

Leverage your physical space to help achieve your event goals. This fall we had a smaller number of attendees and we wanted to encourage discussion throughout the event so we set up the room in large U shape to foster conversation. We also made the most of our exterior space, which featured a fire escape staircase, by hosting an egg drop competition. 

Over communicate, especially around when team members can expect breaks and when they can expect to be fed. As the event lead, I share my phone number multiple times ahead of and throughout the event. We also make sure to communicate in dedicated channels, including an event Slack channel for all attendees, a behind-the-scenes Slack channel for presenters only, and an event website. We share important key information like bus schedules and flight confirmations via email. In advance of the big day, we shared this slide with our team to both inform and inspire. 

Leave room for unstructured time and connection. Over the years we learned that some of the best discussions and a-ha moments come from chats over a meal or a snack during the “unplanned” parts of the event. Now we plan ahead for these, leaving ample time for unplanned, impromptu a-has. We think about airport Uber rides, charter bus rides, morning runs, evening board games, or late-night drinks and look for ways to grease the wheels of serendipity. This was especially important for us this fall since it had been so long since the last time we all gathered together

Look for ways to celebrate what is unique to your company. One pretty fantastic thing that comes with a quarter century in business is the community we’ve built along the way. We make a point to keep up with previous Viget employees who we proudly call our alumni. We love our alumni and enjoy recognizing their contributions to Viget. One way we do so is with annual picnics, which we host when the most current Viget employees are in town for an event. These picnics are often a great mix of reconnections and networking.

Find ways to surprise and delight. Think big and small. For example, this fall we put colored pencils and butcher block paper out during our meeting time. Our autumnal decor included blue(ish) and orange pumpkins (Viget colors!). We made a subtle callout to an internal project by serving french fries as our afternoon snack. And we surprised our team with Unreal treats for their bus rides home. The treats served as dessert and a means for us to introduce our next in-person event, our spring TTT, aka Viget25. 

Some companies advocate for all-hand retreats to be social and relaxing, but not “productive.” They tout a meeting-free event. At Viget, we see the meeting time as crucial because that is when peers share knowledge, reflect on their recent work, showcase client impact, and highlight new ideas and personal growth. Similarly, our co-founders reflect on Viget’s performance and share thoughts on the upcoming business direction. The meeting sparks genuine inspiration and creates a time for us to remember what brought us to Viget in the first place – to build world class tech in support of our clients. 

On the heels of a successful gathering, it’s time to start planning the next one. For our next event we’ll head to the Allegheny Mountains where we’ll leverage a unique and memorable venue, offer plenty of unstructured time for connection (with each other and nature), loop in alumni where appropriate, plan inspiring meeting content, enjoy many meals and treats together, and of course find ways to surprise and delight. 

Work-related travel isn't for everyone, but if you know someone who appreciates the idea of dedicated time to connect with and celebrate their peers, we’re hiring. And to all the culture champions and event planners out there, good luck with your next all-hands! 




y

Why the Cheapest Hourly Rate Often isn’t the Cheapest Option

When choosing an outsourcing partner for design and development, many decision-makers naturally start by comparing hourly rates. At first glance, it seems logical: a lower hourly rate means lower project costs, right?

The truth is, hourly rates can be a misleading metric. The actual cost of outsourcing is much more complex than the dollar amount tied to hourly rates. In this article, we’ll explore why focusing on hourly rates can obscure the true cost of a project and why it’s crucial to dig deeper when evaluating potential partners. I’ll end by suggesting a few things to focus on instead of or in addition to the hourly rate.

Efficiency vs. Hourly Rates

Imagine you have two outsourcing options for a specific task:

  • Pat: A developer who charges $100/hour and takes 3 hours to complete the task. 
  • Terry: A developer who charges $200/hour but only takes 2 hours to complete the same task.

Pat’s hourly rate is lower and Pat’s total cost looks cheaper. The total cost for Pat is $300, while for Terry, it's $400. But there's more at play than the hourly breakdown.

Terry may be faster because they are more skilled, experienced, or familiar with the problem. They produce a higher-quality output that might need little to no revision, while Pat may deliver work requiring additional oversight, rework, or fine-tuning.

This brings us to a crucial point: efficiency and expertise often outweigh raw hourly cost.

Hidden Costs of Oversight and Management

The cost of managing lower-cost teams can quickly add up. Inexperienced or less skilled developers often require more:

  • Guidance and supervision: You or your in-house team may have to spend significant time managing or directing work, which adds hidden costs to the project.
  • Rework and revisions: Less-experienced teams may not get it right the first time, and even small mistakes can snowball into major issues that need to be fixed later on.
  • Communication barriers: Some outsourcing teams might not be as effective in communicating progress or roadblocks, which can slow down the entire project and lead to missed deadlines.

Each of these factors chips away at the apparent "savings" from choosing a lower hourly rate.

Quality: The Long-Term Investment

Design and development work (insourced or outsourced) is an investment, not just a cost. High-quality work may come with a higher hourly rate, but the long-term savings are substantial:

  • Fewer bugs and technical debt: A more experienced development team will likely deliver better code, resulting in fewer bugs and long-term maintenance issues. A more experienced designer is more likely to think through and design for all edge cases, filling in all the gaps.
  • Faster delivery: A skilled team is often more familiar with best practices, frameworks, and tools that allow them to complete tasks efficiently.
  • Scalability: High-quality designers and developers think ahead and design systems that can scale with your needs, preventing costly future refactoring.

The Cost of "Cheap" Work

Sometimes, "cheap" work ends up being the most expensive in the long run. Lower-quality outsourcing might require you to:

  • Hire another team to fix or rebuild the work.
  • Delay product launches due to unanticipated project overruns.
  • Damage customer trust by releasing subpar products riddled with bugs or poor design.

In some cases, teams that seem "affordable" may not have the expertise to foresee potential pitfalls, which means costly issues arise later in the process.

Calculating the Total Cost of Ownership

To truly compare outsourcing options, decision-makers should consider the total cost of ownership (TCO), not just the hourly rate. TCO includes:

  • Efficiency: How quickly and effectively can the team complete the work?
  • Oversight: How much management and guidance will the team require?
  • Quality: Will the output meet your expectations, or will it need significant revisions or rework?
  • Maintenance: What will it cost to maintain or scale the system after the initial work is done?

A team with a higher hourly rate but lower total costs in these areas may be the more cost-effective choice in the long run. For a more complete example:

  • Pat: Your $100/hr developer completes a task in 3 hours ($300), requires 1 hour of oversight from an in-house Senior Developer ($150), and eventually needs to be refactored or rebuilt entirely ($1,000).
  • Terry: Your $200/hr developer completed a task in 2 hours ($400) based on a 10-minute overview from an in-house Senior Developer ($15), and makes an above-and-beyond measurable impact on page performance (priceless).

The best long-term investment becomes more clear when you consider all the variables. 

Conclusion: Think Beyond Hourly Rates

When investing in design or development, your goal should be to maximize ROI, not minimize hourly rates. When comparing outsourcing options, focus on the bigger picture—their efficiency, quality, and the hidden costs of oversight and management. Consider how your prospective partners measure up in terms of:

  • Results: can they point to clear results of their work in which they played some critical role?
  • References: would previous clients choose to hire them again (indicating they are worth their cost)?
  • Communication: do they respond quickly and with clarity?
  • Expertise: do they provide opinions and advice or are they simply order takers?
  • Relevance: is their prior experience directly relevant to your needs? 
  • If not, do they have a track record for navigating novelty well?

The right team might not always be the cheapest on paper, but they’ll deliver the greatest long-term value. Outsourcing isn’t about getting work done cheaply—it’s about getting it done right, and more often than not, the old mantra “you get what you pay for” holds.




y

The Keys to Successful Concept Testing: Prototyping

This is part two of a three-part series on how to successfully conduct concept testing with users, focused on prototyping. Check out part one (planning) to learn more.
 

Prototype your concepts

Once a well-aligned research plan has been crafted, it’s time to create a prototype (or multiple) based on your concept. There are a plethora of ways you can create prototypes that communicate your concepts to users; I’ll cover strategies that will help spark meaningful reactions and conversation.

Provide context to ground your concept

We humans as a whole are poor predictors of our own future behaviors, so it’s really important that your concept testing simulates the future experience you’re trying to test. Ideally, you want to ground your concepts, so a participant can envision it in their own day-to-day. One of the best ways to do this is by building in context, whether into the prototype itself or in the way you actually test out the concepts.

You can ground a participant in what they would actually do by: 

  • Adding small contextual details into the prototype (e.g. the participant’s name or location). 
  • Providing the participant with a realistic scenario to frame the prototypes
  • Designing a certain scenario into the actual prototype (e.g. error messages appear in).  
  • Conducting the test in the actual or simulated environment where it will be used. 

Grounding a participant can make a difference in how someone interacts with your prototype. Let’s imagine you and your team are redesigning a part of an online food delivery platform for restaurants, specifically the parts that hosts and cashiers use. When you put your concept to the test, you can ground participants by “simulating” a lunch rush atmosphere (distractions, loud noises, etc).

Build real-ish prototypes

It might sound counterintuitive but you don’t need high-fidelity prototypes for concept testing. While high-fidelity prototypes may best simulate the future experience, that level of fidelity may not be feasible for a few reasons: 

  • You don’t have the time to create something at that level of detail or complexity before testing.
  • You don’t have the details fleshed out yet.
  • You want your users to help define these details with you. 

Low to mid-fidelity (or as I like to call “real-ish”) prototypes can still get you to the insights you need and even have some unexpected benefits. It’s easier for research participants to focus on overarching concepts when interacting with low-fidelity prototypes. Higher fidelity prototypes tend to invoke feedback hyper-focused on the details. With lower-fidelity, research participants are more likely to provide critical feedback on ideas, since they don’t seem as “final.” You can also leave out certain details in a low-fidelity concept, which allows you to brainstorm with participants.

Again, crafting context is a large part of building out an idea that starts to feel “real” enough for a user to invoke a response. Some examples of real-ish prototypes with just enough context include: 

  • Setting the stage with realistic scenarios for how and when research participants would reach out to an AI chat bot in a therapy app.
  • Creating initial wireframes for a ride-sharing app that research participants test out in a simulated car ride experience, to understand what info is most helpful at each moment on the ride.
  • Sending research participants “updates” on their food delivery order, to learn what participants might want to know about their order’s progress. 

Be selective about which concepts to show

You may have several concepts (or variations on a single concept) that you want to prototype out, and test through research. They may all feel exciting and important, but showing too many in one session can leave a research participant with decision fatigue. Even if you need to test multiple concepts to move forward, you don’t want to show every single one you’ve come up with.

Instead, you’ll want to be selective. One way to help you decide which concepts are best to test is by mapping them out on a matrix.

Let’s imagine again you and your team have generated multiple concepts for your food delivery app that aim to tempt users to order takeout more frequently. Perhaps some concepts focus on individualized recommendations, while other concepts show social trends. First, create a matrix that has extreme aspects of the concepts on each end and place them where you think they might belong. 

Then, ask yourself a few questions: 

  • Are there two concepts that are too similar to each other? 
  • Is this concept playing it too safe?

These kinds of concepts may not give you useful feedback because they’re not distinct enough or they’re too neutral over all. Instead, you’ll want to select concepts that are on the edges of your extremes. Those concepts will allow you to learn much more about your users and how they might interact with your concepts in the future.


These tips will help you craft prototypes that research participants can more easily and accurately react to. 

To end this series, I’ll discuss how to prepare for the actual testing in my next article.