ea

New Minimal & Responsive Theme Released at Themify

I just wanted to announce a new WordPress theme that I designed called Elemin. It is minimal theme coded with Google font, CSS3, Javascript and HTML5. The design is completely fluid and responsive (using CSS3 Media Queries). This means the layout automatically adapts based on the user’s viewport. To see it in action, visit the […]






ea

22 passive income ideas to achieve financial freedom

Earn while you sleep: Realistic passive income ideas you can pursue part time! Ditch the 9-5 with the right idea, hard work, & these essential tools.




ea

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.




ea

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.






ea

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




ea

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. 




ea

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

ea

Handling Spelling Mistakes with Postgres Full Text Search

Background #

Postgres Full Text Search (FTS) is a great way to implement site search on a website running Postgres already, without requiring additional infrastructure.

On a recent engagement with a client, we were deciding between Postgres FTS and ElasticSearch. Ultimately we chose FTS because we could spin it up without having to add extra infrastructure, as we would with ElasticSearch.

Since the project was written in Ruby on Rails, we were able to use the excellent PgSearch gem to implement FTS in ActiveRecord.

Multisearch #

As we wanted a general site search, we needed to utilize multisearch. Multisearch combines multiple ActiveRecord models into one search 'document' table that you can search against. For example, if a user searches for some search term, and the search is configured for multisearch, then every single model that we mark as multisearchable will be searched for that term at the same time. See here for more detail.

Search Features #

PgSearch allows for different search features, tsearch, trigram, and dmetaphone. The default is tsearch, which uses the built-in Postgres Full Text Search.

This was great for our use case, since it also comes with highlighting, a feature that was required. The highlighting is from a field returned by Postgres FTS, where it returns the text around the search term for context and bolds the search terms.

Spelling Mistakes #

Unfortunately, tsearch does not handle misspelled words. However, as I mentioned before, PgSearch allows for other search features!

And trigram is a feature that can be installed via a Postgres extension (pg_trgm) that does just that.

Trigram #

  • The idea behind trigram search is to split pieces of text into sets of three-letter segments, and compare the sets to one another
  • If two trigram sets are similar enough, we assume there was a spelling mistake, and return the document with the correctly-spelled term.
  • As a quick example (ignoring whitespace): Consider the word Viget. Viget would make trigrams:
[vig, ige, get]
  • Now, consider our evil twin agency, Qiget. They would make trigrams
[qig, ige, get]
  • The two trigram sets match very closely, with only one of the trigrams not being the same. Thus, if we were to compare these with pg_trgm, we could reasonably tell that anyone typing 'Qiget' must have been actually looking for 'Viget', and just misspelled it.

Working Trigram into our existing solution #

PgSearch allows us to use multiple search features at once, so we can use tsearch and trigram side by side. Note that we cannot just replace tsearch with trigram due to needing some features in tsearch that are exclusive to it. Here is what an example configuration might look like.

PgSearch.multisearch_options = {
  using: {
    tsearch: {
      prefix: true,
      highlight: {
        MaxFragments: 1
      }
    },
    trigram: { 
      only: [:content]
    }
  }
}

Trigram (and timelines) causing issues #

While it was easy to slot Trigram into our multisearch, it caused a pretty serious performance hit. We were seeing 50x-75x slower searches with both features combined than with just tsearch. We needed to find a way to balance performance with handling misspellings

At the point that handling misspellings became prioritized, the entire search feature was almost fully QA'd and about ready to go out. There wasn't much time left in the budget to find a good solution for the issue.

This thread from the PgSearch repo sums it up pretty well – there were multiple other users that were/are having similar issues as we were. The top-rated comment in this thread is someone mentioning that the solution was to just use ElasticSearch ('top-rated' is doing a lot of heavy lifting. It did have the most likes...at two). We needed to find some sort of middle ground solution that we could act on quickly.

Postgres Documentation saves the day #

In the docs for the Trigram Postgres extension, the writers give an idea for using Trigram in conjunction with Full Text Search. The general idea is to create a separate words table that has a Trigram index on it.

Something like this worked for us. Note that we added an additional step with a temporary table. This was to allow us to filter out words that included non-alphabet characters.

execute <<-SQL
  -- Need to make a temp table so we can remove non-alphabet characters like websites
  CREATE TEMP TABLE temp_words AS
    SELECT word FROM ts_stat('SELECT to_tsvector(''simple'', content) FROM pg_search_documents');

  CREATE TABLE pg_search_words (
    id SERIAL PRIMARY KEY,
    word text
  );

  INSERT INTO pg_search_words (word)
    SELECT word
    FROM temp_words
    WHERE word ~ '^[a-zA-Z]+$';
  
  CREATE INDEX pg_words_idx ON pg_search_words USING GIN (word gin_trgm_ops);
  
  DROP TABLE temp_words;
SQL

This words table is therefore populated with every unique word that exists in your search content table. For us, this table was pretty large.

result = ActiveRecord::Base.connection.execute("SELECT COUNT(*) FROM pg_search_words").first['count']
puts result.first['count']
# => 1118644

Keeping the words table up-to-date #

As mentioned in the docs, this table is separate from your search table. Therefore, it needs to be either periodically regenerated or at least have any new words added to search content also added to this table.

One way to achieve this is with a trigger, which adds all new words (still filtering out non-alphabet characters) that are inserted into the documents table to the words table

create_trigger("pg_search_documents_after_insert_update_row_tr", generated: true, compatibility: 1)
  .on("pg_search_documents")
  .after(:insert, :update) do
  <<-SQL_ACTIONS
    CREATE TEMP TABLE temp_words AS
      SELECT word FROM ts_stat('SELECT to_tsvector(''simple'', ' || quote_literal(NEW.content) || ')');

    INSERT INTO pg_search_words (word)
      SELECT word
      FROM temp_words
      WHERE word ~ '^[a-zA-Z]+$';

    DROP TABLE temp_words;
  SQL_ACTIONS

end

Note that this does not handle records being deleted from the table – that would need to be something separate.

How we used the words table #

Assuming for simplicity the user's search term is a single word, if the search returns no results, we compare the search term's trigram set to the trigram index on the words table, and return the closest match.

Then, we'd show the closest match in a "Did you mean {correctly-spelled word}?" that hyperlinks to a search of the correctly-spelled word

Given more time, I would have liked to explore options to speed up the combined FTS and Trigram search. I'm certain we could have improved on the performance issues, but I can't say for sure that we could have gotten the search time down to a reasonable amount.

A future enhancement that would be pretty simple is to automatically search for that correctly-spelled word, removing the prompt to click the link. We could also change the text to something like "Showing results for {correctly-spelled word}".

Ultimately, I think with the situation at hand, we made the right call implementing Trigram this way. The search is just as fast as before, and now in the case of misspellings, a user just has to follow the link to the correctly-spelled word and they will see the results they wanted very quickly.




ea

What is a Headless CMS and When Should I Use One?

When starting a new project, decision makers are faced with the dilemma of choosing a content management system (CMS). Sometimes, it’s not that simple and they must choose whether to go with a traditional CMS or a headless CMS. Both offer unique benefits and cater to different needs, making it crucial to understand when each makes sense for your project. Let’s take a look at some considerations that can help you make the right decision.

What is a Traditional CMS?

Traditional CMS’s – like Craft CMS, WordPress, and Drupal – offer a pre-packaged solution for content creation, management, and delivery. They include powerful interfaces with content editing capabilities and templating out of the box, enabling you to create sites with ease. A traditional CMS can be monolithic because the back-end and front-end are tightly coupled. Using a traditional CMS typically means you are using all of the tools included to achieve your goal.

What is a Headless CMS?

A Headless CMS is like a Traditional CMS in that it includes content creation and management tools. But it differs in the fact that the back-end content management system is decoupled from the front-end (presentation layer), allowing developers to use any technology stack they prefer for building the front-end of the site. The back-end acts as an API with its only purpose being to serve content from the database. There are CMS options like ContentfulPayload, and Strapi that are built to be headless. Popular traditional CMS’s like Craft CMS and WordPress also offer headless variants.

The Restaurant Analogy

Let’s simplify things a bit more and look at the decision using an analogy; a restaurant.

Traditional Restaurant (Traditional CMS)

Imagine a restaurant where the kitchen and dining room are connected. The chefs cook the food, and the waitstaff serve it directly to the customers in the same building. This setup means that everything is closely integrated, and the kitchen (back-end) is tightly coupled to the dining experience (front-end). Picture a scenario where the restaurant decides to change from table service to buffet style. The food now needs to be prepared in advance and delivered to the front of house in a different way, potentially even requiring new equipment. The restaurant needs to be reconfigured to not only accommodate the buffet but also to interface with the kitchen differently. Because the restaurant and kitchen are coupled, both sides would require work in order to accommodate a shift in strategy. 

Ghost Kitchen (Headless CMS)

Now, think of a ghost (or cloud) kitchen where food is prepared centrally but can be delivered to various locations or dining experiences. The kitchen (back-end) focuses solely on cooking (content creation and management) and doesn't worry about where the food is served. Instead, the meals (content) can be delivered to different endpoints like food trucks, home deliveries, or partner restaurants (or in our case websites, mobile apps, etc.). This separation allows more flexibility in how and where the content is delivered without changing the core cooking process. If a new experience requires new equipment or processes, the kitchen can be expanded without affecting the front-end experience.

When to Use a Headless CMS

Omni-Channel Content Delivery 

If you consistently need to deliver content across multiple platforms (websites, mobile apps, IoT devices), a headless CMS is ideal because it can serve the same content through APIs to any front-end. The front-end can be swapped out without any need for development to the back-end.

Scalability and Flexibility

If you want the ability to keep your content management system up-to-date independently of the presentation layer, a headless CMS can allow for more agile and scalable development. This could be especially useful if you anticipate needing to redesign or update parts of the front-end frequently without affecting the back-end content.

Front-end Framework Preferences

Maybe your team has developers who are very proficient in a particular JavaScript framework, like Next.js, SvelteKit, or Astro. The time needed to learn a new templating language could push you past your deadline. Maybe you have some cool interactive interface in mind? A headless CMS can provide the raw content for your developers to build highly custom, tailor-made front-ends in whatever language or framework they please.

Security

Going headless can offer security advantages due to its decoupled nature. By communicating via API to the front-end, data access can be controlled more granularly. Because the back-end is only responsible for content management and delivery, fewer plugins are typically used which means a smaller chance of vulnerabilities due to third-party software.

Hosting & Infrastructure

A cloud-based headless CMS offers additional advantages over a self-hosted headless CMS. It can simplify maintenance and operating costs since the cloud provider is responsible for updates and security of the platform. Cloud-based solutions like Strapi Cloud often come with integrated security features, automatic backups, and disaster recovery options.

Which will you choose?

While the flexibility and security a headless CMS offers may be great benefits, it may not be necessary for every project and could even introduce complexity. It’s important to consider the long-term purpose of the project and who will be responsible for maintaining it as well as authoring content. If your primary focus is on managing and delivering content in a structured manner with rapid development, a traditional CMS can be an excellent choice. But if you feel any of the examples I’ve laid out above align with your project’s requirements then a headless CMS may be right for you! 

Whatever route you take, remember that both Craft CMS and WordPress can be used in traditional or headless applications and are a fine choice either way! Now you know the differences between a traditional and headless CMS, and an informed decision can be made. If you have more questions or a project you think could benefit from a traditional or headless CMS, we’d love to help!




ea

Building Well-Connected Distributed Teams

Five years ago, without consciously trying, I would have noticed if a coworker was taking a break, feeling extra chatty, or looking hyper-focused. I got to choose whether to respond and how I might build rapport by responding (I’m sure I didn’t always get it right). Now that more of the Viget team works from home than in an office, I feel a loss. I have less awareness of other people's states of mind and fewer chances to demonstrate my interest. I need to learn new ways of connecting. 

I took notice when Adam Grant recently posted about pebbling

Sending memes, links, and videos to others isn't trivial. It signals that you're thinking of them and want them to share your joy. It's known as pebbling, based on penguins gifting pebbles to potential partners. Pebbling is an act of care. Every pebble is a bid for connection.” 

Grant acknowledges that the term "pebbling" comes from penguins, but he also uses the phrase “bid for connection,” which I associate with John Gottman. Gottman is a well-known psychologist who has researched marital stability and relationships. His work provides insights into how small interactions, or "bids," play a crucial role in building strong relationships. 

Gottman defines a "bid" as any attempt from one person to another for attention, affirmation, affection, or any positive connection. A bid can be as explicit as saying, “I had such a hard day,” or as random as saying, “Did you see the size of that red bird?” The impact of responding with interest (turning toward) or ignoring or dismissing (turning away from) significantly influences the quality of the relationship. A simple, “Tell me what happened,” or “What? No, I missed it!” can foster closeness and trust. Silence or something like, “Here we go again,” will spark feelings of neglect and distance.

Gottman's research is widely cited and has impacted my understanding of relationships.  I'm interested in bids for connection at work, particularly as our work environment has changed dramatically in recent years.

Connections at Work

Finding the right balance of work and non-work is a central challenge for most of us as we navigate demands on our time and energy. I generally hope work is a small enough part of a person’s life that they have time for many other things, but also that their work environment is engaging and meaningful enough that they enjoy it. I hope friendships emerge at work, mostly through collaboration or out of the gaps between responsibilities. 

As remote work has become commonplace, I find it’s harder to foster connections than it was before. The lack of proximity, and therefore organic social interactions, makes it harder for me to know my coworkers and be known by them. I’m not advocating for returning to offices. I’m noticing that after working with people for years in an office, I knew them better – their nerves before a presentation, their ability to set new people at ease, their grandma’s soup recipe, their knack for deadpan humor – and that made my life better. While many of my coworkers collaborate with each other daily through pair programming, design critiques, or iteration planning meetings, my work on a small People Team has always been less collaborative. For me, fewer organic in-person interactions means fewer interactions of any kind at work. 

The decline in ad-hoc opportunities for connecting impacts us all differently, but I am particularly interested because an aspect of my role at Viget is to nurture a strong company culture. For us that means a culture where we do excellent work, learn a lot, support each other, and – yes – make some friends. I’m looking for ways we can adapt our employee engagement efforts to the new work environment and evolve how we cultivate alignment.

The concept of "bids for connection" seems useful for understanding the building blocks of connection and, over time, friendships. As a mostly remote company, I want to be sure we’re asking: How do people make bids? How do others respond to them? What parts of the work environment encourage us to turn towards a bid? 

Bids While Distributed

There needs to be “space” for these interactions to happen across a distributed company, and we need to notice what is working and why. One opportunity for bids to play out is in recurring meetings. At Viget, we try to be efficient with our time, but we also build in time for informal interactions.  

Daily Stand-up Meetings

The discipline and project teams that do daily stand-ups are careful to keep them brief. These meetings need to be reliably quick-paced in order to fulfill their purpose. Still, without sacrificing efficiency, these meetings can spark strong bids for connection. Sharing work updates in small, daily increments encourages people to open up about specific elements of their progress. The specificity allows for connection in ways that broad strokes do not. Hearing someone say, “Progress was slow, but I’m finally done with the feature,” I might respond, “Oh, good.” But hearing someone say, “If I don’t figure out how to debug this API integration by noon, we need to update the launch timeline," gives me a chance to be curious, helpful, and invested in something very specific. 

Weekly All-Hands Meeting

Every Friday, our whole company meets for about an hour. The first 15 minutes are deliberately set aside for informal conversations and sharing, which mostly happens over Slack. We often play music or show a live stream of something noteworthy, like an eagle’s nest, to which we can react. Someone might share where they were when they first heard this song. Someone else might reveal they are an experienced falconer. The whole company gets a chance to see or hear these things, and while only a handful may react, we are all building shared awareness and memories.

Monthly Team Meeting

During a team meeting, a small group of same-discipline-peers comes together to talk shop, share lessons learned, or bond. These meetings allow for exercises that don’t scale to a whole company – like getting feedback or planning progress – and over time, certain activities can become team favorites. A monthly “rose, bud, thorn” or an annual “sharing circle” ritual prompts people to share in ways that otherwise might feel too awkward or vulnerable.

 

Another way to make and respond to bids for connection across locations is on Slack. Different kinds of Slack channels offer different kinds of opportunities.

Interest-based Slack Channels

At Viget we have channels like #woodworking, #sewing, #starwars, #hot-sauce, #gardening, #home-improvement, and many, many more. These types of channels allow people to go deeper than they might in more general channels. You know you’re talking to like-minded people, so why not dive fully into your opinion on robot vacuum cleaners?

"Random" Slack Channel

In our #random channel, I’ve seen everything from a heads up on free Firehouse subs to a recommendation for an estate planning system. The responses vary, too – sometimes they spark day-long conversations. At a minimum, posts will get a smattering of emoji responses and the impact can be significant. For example, a post might get a sympathetic :heart: but then a couple :same: or :it-me: come in and before you know it, there’s a subset of coworkers who realize they share the same rare phobia. I also think a share in #random can signal, “I’m between tasks. I’m open to distractions right now,” and folks can follow up with a DM.

Project-Specific Slack Channel

In channels where everyone is working on the same project with shared goals, stresses, and deadlines, we might see bids that build momentum. A PM might post something in the morning to encourage the team to rally behind a tough deadline. A designer might post mid-week, acknowledging the drudgery of certain tasks, implicitly giving everyone else permission to do the same. A developer might be slowly building a little arsenal of inside jokes and call-backs over weeks, dropping a note at just the right time to get others laughing. Someone might turn one of those jokes into a custom emoji that lives well beyond the project timeline and every time that inside-joke-emoji gets used, it's a bid for folks who worked on that team to recognize each other and reconnect. 

Recognizing Bids

We all grew up learning in-person social norms and have a mostly shared understanding of what’s considered warm, polite, stand-off-ish, or rude in the workplace. Now that we’re distributed, we may need to learn to recognize new signals and define new norms. 

A bid is an action that invites connection, but sometimes the action is so small, we might not notice it or realize it has potential value. Understanding the concept of bids can help us notice them and respond with more awareness. 

If we train ourselves to see bids for what they are and respond accordingly, we may get more mileage out of the limited impromptu interactions we have as remote coworkers. Actions like responding to an open-ended question in a Slack channel or acknowledging someone’s request for help during a meeting go a long way. Each response builds trust and camaraderie, even if in tiny doses. When a comment or question is ignored or dismissed, the negative effect is compounding; that person is less likely to reach out again.

Adam Grant said sharing memes and links are a way to invite someone to share in your joy.  At a distributed company, “bids” take a lot of different shapes, but they all communicate things like, “I am here,” and “let’s work together,” and “you can trust me.”

I’m encouraged to think we already have some infrastructure in place at Viget to support remote bids for connection. I’m excited to work with Aubrey Lear and others to find ways to evolve that infrastructure. We’ll continue to hire people who want to develop friendships with coworkers and who are willing to take personal responsibility for making and turning towards bids. Together, we can make sure Viget remains a great place to work as the workplace continues to evolve.




ea

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

ea

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

ea

Craft 5: What It Means For Super Table Page Builders

If you’re like us, you’ve likely built ‘page builder’ fields in Craft CMS using Matrix. But sometimes you need more than a block. We use Super Table to create ‘page sections’ that include some extra settings (like background color, controls for width, etc.). We can then nest a Matrix field to control page blocks within the Page Section (Super Table). This has worked well for us in the past but there's a new, simpler way to achieve this starting in Craft 5.

Upgrading a site from Craft 4 to Craft 5 can seem intimidating. Even more so when your site relies on complex content models like the one I described above. You might think, okay I'll upgrade to Craft 5 and then look into migrating to the newer method in the future. Well, now is the time. Verbb has announced that Super Table has reached end-of-life.  While there is a Craft 5 compatible version available, it won't receive updates. That means now is the perfect time to migrate your Super Table fields to native Matrix fields.

Craft 5 makes the process easy by converting Matrix blocks to entry types automatically during the upgrade. This guide will walk you through the process. We'll cover preparation, the upgrades themselves, and steps to clean up afterward. As you’ll see below, the process is actually quite simple and nothing to stress over!

An example page builder using Super Table with a nested Matrix in Craft 4

Preparing for the Upgrade

The first step in any upgrade is preparation. Start by backing up your site’s database. This ensures that you can restore your site to its previous state if anything goes wrong during the upgrade process. We use (and love) DDEV here at Viget, so this guide will be leveraging it. But you can easily adapt the commands if you are not. To create a database backup, run:

❯ ddev snapshot

Next, review the compatibility of your installed plugins. Check the Plugin Store or the author’s site to confirm that each plugin has a Craft 5 compatible version. Make a list of any plugins that need updating or replacing. Super Table will need to be updated to at least version 4.0.0.

It's also essential to familiarize yourself with the Craft 5 Upgrade Guide. This guide provides detailed information on the changes, new features, and potential breaking changes in Craft 5, helping you understand what to expect. It serves as a fantastic set of instructions to get your site upgraded.

The Upgrade Process

Once you're prepared, you can begin the upgrade process. Per the Craft Upgrade Guide, we will update Craft and plugins at the same time. Open your editor and modify your composer.json with the new versions of your plugins. The two for sure we will need to modify are:

"craftcms/cms": "^5.0.0",
"verbb/super-table": "^4.0.0",

After you've checked all your versions and are ready to proceed, run:

❯ ddev composer update

This command will update Craft (and its dependencies) and all your plugins to the latest version compatible with Craft 5. After updating, you need to run the database migrations to complete the upgrade. This can be accomplished by running:

❯ ddev craft up

During this upgrade process, Craft 5 automatically converts all of your existing Matrix blocks to entry types. This conversion requires no interaction from you, streamlining one of the most complex aspects of the upgrade. After it’s finished, all of your non-reusable matrix blocks are now their own reusable entry type.

Craft 5 automatically converted the matrix blocks to their own entry types

Updating Super Table Fields and Templates

With the Matrix blocks converted to entry types, you need to reconfigure any Super Table fields to be Matrix fields.

Update Super Table Fields:

  • Browse to SettingsFields and edit any Super Table fields
  • Change the field type from Super Table to Matrix (there will be no content loss when switching from Super Table to Matrix)
  • Select the entry type to use (Craft has already created one for you)
  • Save the field
  • That's it!
Changing the field type from Super Table to Matrix (with no content loss)

Review Your Templates: #

  • If you've been working with Super Table content as part of entry queried data, you may not need to make template changes at all

  • Search your templates for craft.superTable to find any direct queries of Super Table blocks and replace them with entry queries


At this point, you have removed your dependency on Super Table and have a page builder entirely built with Matrix fields. What were previously Super Table blocks are now a custom Entry Type and what were Matrix blocks are now also Entry Types. This allows you to have nested Matrix within Matrix thanks to Craft’s Entrification plan.

A nested Matrix in Matrix page builder at last!
Our page builder looks just like before, only now it adds entries instead of blocks

Cleaning Up After the Upgrade

After updating your fields and templates, it's time to clean up. First, uninstall the Super Table plugin. Navigate to SettingsPlugins in the Control Panel to uninstall the plugin. Then remove it from your project by running:

❯ ddev composer remove verbb/super-table

Thoroughly test your site to ensure everything is functioning correctly. Pay close attention to the entry types where you used Super Table fields, confirming that authoring and your front-end work as expected.

Additionally, you can also take this opportunity to clean up your fields and entry types. Craft 5’s reusable fields and entry types give you ample opportunity to consolidate and Craft 5 provides new utilities to make this process as simple as possible.

  • fields/auto-merge — Automatically discovers functionally identical fields and merges their uses together.
  • fields/merge — Manually merge one field into another of the same type and update uses of the merged field.
  • entry-types/merge — Merge one entry type into another and update uses of the merged entry type.

That’s it!

Upgrading from Craft 4 to Craft 5 and transitioning from Super Table is incredibly simple, thanks to Craft 5’s automatic conversion of Matrix blocks to entry types. Super Table will no longer be maintained moving forward, and it's better to switch to the native Craft solution for better long-term support. By following these steps, you can quickly tackle the change and take advantage of the new features and improvements in Craft 5. With careful planning, thorough testing, and a few commands, you’ll have your page builder working again in Craft 5 in no time. Happy upgrading!




ea

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.




ea

RIP a Livecast #639 – Leak After Leak

We kick things off by talking about the early 2000s. We also discuss the latest Machine Gun Kelly drama. Then, we discuss a group of metalheads who were denied an […]




ea

RIP a Livecast #640 – Neigh Means Neigh

We kick things off by talking about Facebook's downtime. We learn about some of the less-flattering things GG Allin did. We briefly speak to Jordan from Dark Saga, a band […]




ea

RIP a Livecast #642 – Vinceable

We kick off the show talking about the sad news of Vince Neil falling off a stage last weekend. We talk about Rob Zombie's Munsters reboot and then transition into […]



  • RIP a Livecast

ea

RIP a Livecast #646 – Joke Treadmill

We kick off this week's show with an important announcement. Loni joins us this week. We discuss the Brass Against onstage urination incident in great detail. We talk about Ace […]




ea

RIP a LIVECAST #649 – Specially Speaking

It's a new era for the show, and we kick it off with a new voice. Sid explains all the different types of Drag Race there are. Rob explains poppers. […]



  • RIP a Livecast

ea

RIP a Livecast #654 – Excessive Wind-Breaking

We kick things off by discussing our new Twitch channel. We review Alex Skolnick's new rap video about the Capitol riots. We discuss the new Fresh Prince of Bel-Air reboot. […]



  • RIP a Livecast

ea

Holographic technology’s transition from science fiction to reality

In science fiction literature and films, holography has received much attention. These tales frequently depict holograms as entertainment, communication tools, or live creatures. Their depiction in these sources is typically far more sophisticated than what is now technologically feasible. Holography is beginning to play a more significant part in current communications and technologies as technology […]




ea

FOB Kitchen, Great New Filipino Hot Spot in Oakland, California

I had the pleasure to try FOB Kitchen last night, a hot new Telegraph Avenue Oakland Filipino menu in Oakland (Thanks cristina_thebaker!). 5179 Telegraph Ave, Oakland, CA 94609. You would not know it from the unassuming Temescal strip mall setting, but once inside you are treated to an amazing and flavorful Filipino menu from this …




ea

Bill Dane Pictures …it’s not pretty. 50 Years of Photographs I’m Still in Love

“It seems to me that the subject of Bill Dane�s pictures is the discovery of lyric beauty in Oakland, or the discovery of surprise and delight in what we had been told was a wasteland of boredom, the discovery of classical measure in the heart of God�s own junkyard, the discovery of a kind of …




ea

A Beautiful Spring Begins With Fall Planting

By University of Illinois News Have you ever admired the vibrant colors of spring flowers and wondered how to create this beauty in your own landscape? “The time to plant for spring bloomers is now,” said University of Illinois Extension … Continue reading




ea

Top Tips for Developing a Creative Flyer

Flyers are a fantastic way to promote your business, especially considering how easily they can be distributed among members of the public. Since you’re likely to be spending your hard-earned cash on this very effective marketing tool, it is essential to take the right steps when designing your flyer, ensuring you display your skill set … Continue reading Top Tips for Developing a Creative Flyer

The post Top Tips for Developing a Creative Flyer appeared first on Design Shard.




ea

Wrike for Designers and Creatives

Collaborating on an online project management software for marketing is a huge part of being a designer or a creative, and more often than not you are juggling more than one task or project at a time. This makes managing a creative project online for creatives particularly difficult and what’s more, the line managers or … Continue reading Wrike for Designers and Creatives

The post Wrike for Designers and Creatives appeared first on Design Shard.



  • Tips & Tricks
  • managing a creative project online
  • marketing project management tool
  • online project management software for marketing
  • task workflow management software
  • team scheduling software
  • Tools
  • Wrike

ea

Spring Cleaning: Five Ways to Improve Your Ecommerce Site

Spring is on the horizon, so you know what that means. Spring-cleaning time is coming soon too. This yearly refresh is more than just a reminder to dust your home; it’s also a chance to revitalize your ecommerce business, attract new customers and delight loyal shoppers. Here are five easy ways to improve your ecommerce … Continue reading Spring Cleaning: Five Ways to Improve Your Ecommerce Site

The post Spring Cleaning: Five Ways to Improve Your Ecommerce Site appeared first on Design Shard.




ea

Can Your Logo Maker Do This: A Real Designer vs A Logo Maker

  Every business needs a logo and all major ones will view it as a key aspect of their brand building. A logo is the first impression a customer will get of your brand, so it has to look clean, professional and tell a story about who you are and what you do. Which is … Continue reading Can Your Logo Maker Do This: A Real Designer vs A Logo Maker

The post Can Your Logo Maker Do This: A Real Designer vs A Logo Maker appeared first on Design Shard.




ea

10 Tips for Creating the Perfect Animation

An animation is a form of art whereby the artist expresses stories through drawings to the audience. The animation part means that the artist has to use characters that are in motion in order to give the storyline life which is an important factor in any animation. The characters you choose to use are essential … Continue reading 10 Tips for Creating the Perfect Animation

The post 10 Tips for Creating the Perfect Animation appeared first on Design Shard.




ea

How to Show a Facebook Feed in WordPress (5 Easy Steps)

Are you looking for a reliable way to add a Facebook feed to your WordPress site? Adding a custom Facebook feed makes your site more engaging and interactive. At the same time, you also provide social proof of an active online presence, helping you turn your readers into your fans.  The easiest way to add […]

The post How to Show a Facebook Feed in WordPress (5 Easy Steps) first appeared on IsItWP - Free WordPress Theme Detector.




ea

How to Embed Instagram Feed in WordPress (5 Easy Steps)

Are you looking for an easy way to add an Instagram feed to your WordPress site? An Instagram feed helps you showcase your social media content right on your WordPress website. Visitors can view and engage with your Instagram content without having to leave your site. In this step-by-step tutorial, we’ll show you how to […]

The post How to Embed Instagram Feed in WordPress (5 Easy Steps) first appeared on IsItWP - Free WordPress Theme Detector.






ea

What is TikTok App Clone Script? Cost & Features

Social applications have acquired pace more than anything lately, be it online entertainment, video sharing, photograph altering, or whatnot. TikTok App Clone Script, TikTok has been all around the information after a nation forbade its utilization, exhausting the space for an amazing open door. While the general application is easy to use according to a […]

The post What is TikTok App Clone Script? Cost & Features appeared first on WPCult.




ea

bbPress 1.0 Release Candidate 3

Another milestone in the sister application of WordPress; bbPress is that much closer to final release! Check out this video from WordCamp Development day

The post bbPress 1.0 Release Candidate 3 appeared first on WPCult.






ea

Game-Changing Paradigm Shift in Machine Learning!

The landscape of AI is rapidly evolving, presenting both opportunities and challenges. From its historical roots to the current AI wars and the pursuit of Artificial General Intelligence (AGI), AI is a force to be reckoned with. Despite remarkable advancements, current AI systems face limitations in adaptive learning and memory, sparking a paradigm shift towards creating more human-like capabilities.

The post Game-Changing Paradigm Shift in Machine Learning! appeared first on WPCult.




ea

WordPress: Provides a Great Framework for Your Website

It doesn’t really matter in what kind of business you are; it is human behavior to have an urge of standing out of the crowd, of its kind. The same story goes with online business and for an online venture, you need a blog or website of your own. The website you tend to own […]

The post WordPress: Provides a Great Framework for Your Website appeared first on WPCult.




ea

4 Super Easy Ways to Improve SEO

Having a web presence is extremely important when it comes to marketing your business, and search engine optimization (SEO) is one of the best ways to improve your visibility and reach. Some companies don’t have the time or resources to invest in an in-depth and thorough SEO strategy, but that doesn’t mean that they can’t […]

The post 4 Super Easy Ways to Improve SEO appeared first on WPCult.




ea

Grow Your Real Estate Business With Pinterest

Pinterest is a social media website where users share their favorite images from around the web with their followers. Rather than using words to express themselves, Pinterest users use images and photographs instead. Like other forms of social media, Pinterest offers a unique opportunity for real estate agents looking to grow their businesses. With so […]

The post Grow Your Real Estate Business With Pinterest appeared first on WPCult.




ea

Do Smart Research on Keywords for Better Search Engine Optimization

                        Would you like a recipe, if it doesn’t contain salt? Of course not, as it is one of the most important ingredients of food. So does ‘Keywords’ for Search Engine Optimization. This is the reason, that researching keywords is very crucial for your online marketing, as this […]

The post Do Smart Research on Keywords for Better Search Engine Optimization appeared first on WPCult.






ea

Rethinking The Role Of Your UX Teams And Move Beyond Firefighting

Many UX professionals often find themselves working alone, and usually face more projects impacting user experience than they can handle. In this article, Paul Boag explains how UX teams can be transformed into a significant driver of customer-centric innovation within organizations.




ea

If I Was Starting My Career Today: Thoughts After 15 Years Spent In UX Design (Part 1)

In this two-part series, Andrii Zhdan outlines common challenges faced at the start of a design career and offers advice to smooth your journey based on insights from his experience hiring designers. Learn why mastering design tools is crucial, how to build a strong portfolio, and tips for acing your first interviews.