<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:wfw="http://wellformedweb.org/CommentAPI/"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:atom="http://www.w3.org/2005/Atom"
  xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
  xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  >
<channel>
  <title>Solve it once | Blog</title>
  <atom:link href="https://solveitonce.com/rss/blog/" rel="self" type="application/rss+xml" />
  <link>https://solveitonce.com/rss/blog/index.xml</link>
  <description>Solve it once, LLC makes better websites faster and for less money.</description>
  <lastBuildDate>Sun, 01 Dec 2024 19:26:52 GMT</lastBuildDate>
  <language>en</language>
  <sy:updatePeriod>hourly</sy:updatePeriod>
  <sy:updateFrequency>1</sy:updateFrequency>
  <generator>[Jekyll](https://github.com/mojombo/jekyll)</generator>
  
  
  
  
  
    
      <item>
        <title>Star-frost (lovers)</title>
        <link>http://solveitonce.com/blog/star-frost/</link>
        <pubDate>Sun, 21 Jul 2024 00:00:00 EST</pubDate>
        
          
          <dc:creator>Brad Czerniak</dc:creator>
        
        
        
          <category><![CDATA[Drupal]]></category>
        
          <category><![CDATA[Design]]></category>
        
        <guid isPermaLink="true">http://solveitonce.com/blog/star-frost/</guid>
        <description><![CDATA[Steal this content! Everything on this site is under a CC0 license, so you
can copy/paste this without guilt.

First, a bit of housekeeping: in April I took a permanent full-time job with Principal Financial Group
which has led to a change in priorities for Solve it once LLC:


  Treat so1ve as a side business rather than my main source of income
  Limit so1ve billables to around 10 night-and-weekend hours per week
  Prioritize existing clients’ needs over seeking new business
  Keep business expenses and overhead even lower


That’s not to say I’m out of the market entirely! If you have a project or wish to maintain an existing site and think I’d be the right fit, please send an email to brad@solveitonce.com to get the conversation going.

One prominent way you’ll see so1ve’s priorities have changed is that frostdrupal.com is now a static-hosted site based on a local frost instance, rather than a live Drupal site. This ends up saving me about $660 USD annually. Sure, even at my lowest hourly rate that’s less than 9 hours of billable work, but saving the hosting cost means I don’t feel as much pressure to pursue billable hours for my nights and weekends. And it was kind of absurd how quickly I was able to convert it from Drupal to static, so I didn’t exactly lose anything in the process.

Removing managed Drupal hosting and the so1ve site’s third-party e-commerce functionality means Solve it once’s annual expenses are under $300: that’s $50 for state business registration plus the luxury of Google Workspace with a Google Voice number so my personal phone isn’t spammed even more.

If you’re a small business owner like me and the idea of your business only having $300 per year in expenses sounds appealing, please reach out for an hour or two of consultation!

Anyhow, what I really wanted to talk about was committing to Starshot.

so1ve’s Starshot commitment

Going forward, Solve it once would like to make the following commitments, with the timing being dependent on Starshot milestones:


  At the time of Starshot’s initial launch, so1ve will make available one or more recipes based on what was successful in frost
  When the Experience Builder piece of the Starshot project becomes stable and usable, we’ll decommission frost in favor of the Starshot approach
  Since frost has features not slated for Starshot, we will also work to backfill those features and make them available to the community


Recipes

As mentioned in the Unofficial Starshot strategy guide post, a key time-saver and benefit for future Starshot users will be actually-useful default content.

I’m not certain what the plan is for default content as the Starshot project’s announcement of key strategies alluded to, but I pledge that, when Starshot’s initial version goes live by the end of 2024, so1ve will make available a recipe called the “Boring content pack” that provides a big piece of what makes frost great. This pack will include any of the following pages that don’t otherwise come out of the Starshot box:


  About us (five W’s template)
  Press
  Thank you
  403 Access Denied
  404 Not Found
  Accessibility statement
  Privacy policy
  Terms and conditions
  Frequently asked questions


Assuming there are no blockers to do so, in the same timeframe I pledge to make available a “Content strategy pack” recipe that tentatively includes:


  A ‘Plan’ tab on nodes
  A long text field for shared notes per node
  A formatted text field for storing interim content per node
  User reference fields for the Accountable, Consulted, and Informed parties (with the responsible user being the author)
  A View with at least one display that shows every node in a RACI matrix


Consuming sites will be able to extend the content strategy pack with content moderation tweaks, and potentially editor enhancements for the two long text fields if the site’s editorial users find great utility from them.

These two recipes seem the most straightforward to accomplish as one developer within the next 6 months, given the moving target of the brand-new Starshot project. As I’ll discuss below, there are other features I’d like to bring to Starshot but may need more time to accomplish.

Decommission

As an article of good faith and support for the Drupal community, I pledge to decommission the frost project as soon as the Experience Builder initiative is a viable part of Starshot. Since frost putatively competes with Starshot, decommissioning it signals a confidence in the larger community’s ability to offer a superior product.

The decommissioning will occur in stages, in case there are consumers of frost that would otherwise be adversely affected:


  At the time of XB viability, I will no longer provide new releases, including security releases
  3 months after, I will get rid of active releases on the project page
  At the six month mark I will amend the drupal.org project page and GitHub readme to reflect the decommissioned status
  At one year I may replace the frost demo site with a project debrief microsite
  In 2026 and thereafter I may close or remove pages/sites as long as doing so does not cause link rot


I cannot commit to decommissioning frost any sooner than XB viability, since that is the key way that Starshot will be able to improve upon the excellence frost already offers.

Backfill features

frost has a few features that may not lend themselves to quick recipes:


  A Paragraphs entity bundle (which may have to be replaced with another approach) to hold SEO fields that can be token-ed into metatag: Description, news keywords, nofollow, noindex, Social image, Title tag
  Metatag settings based on the Paragraphs bundle
  An SEO Views listing for nodes, taxonomy terms, and commerce products based on the Paragraphs bundle fields
  An easy module for sitewide Contact information that makes the info available as blocks and tokens


I cannot pledge an exact timeframe for the above SEO and management features to become contrib projects geared for Starshot sites, but am optimistic that I can make them available to the community to improve SEO management for Starshot sites.

Of course, frost has a lot of other great features and functionality that would be wonderful to contribute to Starshot, but the vast difference in approaches means it would end up being brand-new work rather than adapting the prior art:


  Automatic class and attribute fields
  Maximum configurability with minimal CSS and JS payload
  Interactive charts built from tablefields
  View and form mode optimizations to show the same content multiple useful ways
  Sensible image styles that prevent unnecessary breakpoint-based payload doubling
  A “kitchen sink” component guide default content page for reviewing and testing all components
  Small, baked-in features of the component library like card animations and media hotspots


If there is community interest in pursuing any of those avenues in a Starshot context, I would be happy to accommodate.

In closing

frost has been a wild ride and a learning experience for me. While I wish it had gotten more traction and community support, I’ll remain encouraged that its spirit if not its actual code will see a future in Starshot.

In these last few months before the decommissioning I will try to cherish each minor-version update and small tweak that comes along. Hopefully soon I’ll find the next big thing on which to focus my zealous attention. Watch this space!
]]></description>
        <content:encoded><![CDATA[<p><strong class="color--third font-size--1p25em">Steal this content! Everything on this site is under a CC0 license, so you
can copy/paste this without guilt.</strong></p>

<p>First, a bit of housekeeping: in April I took a permanent full-time job with <a href="https://www.principal.com/">Principal Financial Group</a>
which has led to a change in priorities for Solve it once LLC:</p>

<ul>
  <li>Treat so1ve as a side business rather than my main source of income</li>
  <li>Limit so1ve billables to around 10 night-and-weekend hours per week</li>
  <li>Prioritize existing clients’ needs over seeking new business</li>
  <li>Keep business expenses and overhead even lower</li>
</ul>

<p>That’s not to say I’m out of the market entirely! If you have a project or wish to maintain an existing site and think I’d be the right fit, <a href="mailto:brad@solveitonce.com">please send an email to brad@solveitonce.com</a> to get the conversation going.</p>

<p>One prominent way you’ll see so1ve’s priorities have changed is that <a href="https://frostdrupal.com/">frostdrupal.com</a> is now a static-hosted site based on a <em>local</em> frost instance, rather than a live Drupal site. This ends up saving me about $660 USD annually. Sure, even at my lowest hourly rate that’s less than 9 hours of billable work, but saving the hosting cost means I don’t feel as much pressure to pursue billable hours for my nights and weekends. And it was kind of absurd how quickly I was able to convert it from Drupal to static, so I didn’t exactly lose anything in the process.</p>

<p>Removing managed Drupal hosting and the so1ve site’s third-party e-commerce functionality means Solve it once’s annual expenses are under $300: that’s $50 for state business registration plus the luxury of <a href="https://workspace.google.com/">Google Workspace</a> with a Google Voice number so my personal phone isn’t spammed even more.</p>

<p>If you’re a small business owner like me and the idea of your business only having $300 per year in expenses sounds appealing, <a href="mailto:brad@solveitonce.com">please reach out for an hour or two of consultation</a>!</p>

<p>Anyhow, what I really wanted to talk about was committing to Starshot.</p>

<h2 id="so1ves-starshot-commitment">so1ve’s Starshot commitment</h2>

<p>Going forward, Solve it once would like to make the following commitments, with the timing being dependent on Starshot milestones:</p>

<ol>
  <li>At the time of Starshot’s initial launch, so1ve will make available one or more recipes based on what was successful in frost</li>
  <li>When the Experience Builder piece of the Starshot project becomes stable and usable, we’ll decommission frost in favor of the Starshot approach</li>
  <li>Since frost has features not slated for Starshot, we will also work to backfill those features and make them available to the community</li>
</ol>

<h3 id="recipes">Recipes</h3>

<p>As mentioned in <a href="https://solveitonce.com/blog/unofficial-starshot-strategy-guide/">the Unofficial Starshot strategy guide post</a>, a key time-saver and benefit for future Starshot users will be actually-useful default content.</p>

<p>I’m not certain what the plan is for default content as the Starshot project’s announcement of key strategies alluded to, but <strong>I pledge that, when Starshot’s initial version goes live by the end of 2024, so1ve will make available a recipe called the “Boring content pack”</strong> that provides a big piece of what makes frost great. This pack will include any of the following pages that don’t otherwise come out of the Starshot box:</p>

<ul>
  <li>About us (five W’s template)</li>
  <li>Press</li>
  <li>Thank you</li>
  <li>403 Access Denied</li>
  <li>404 Not Found</li>
  <li>Accessibility statement</li>
  <li>Privacy policy</li>
  <li>Terms and conditions</li>
  <li>Frequently asked questions</li>
</ul>

<p>Assuming there are no blockers to do so, in the same timeframe <strong>I pledge to make available a “Content strategy pack” recipe</strong> that tentatively includes:</p>

<ul>
  <li>A ‘Plan’ tab on nodes</li>
  <li>A long text field for shared notes per node</li>
  <li>A formatted text field for storing interim content per node</li>
  <li>User reference fields for the Accountable, Consulted, and Informed parties (with the responsible user being the author)</li>
  <li>A View with at least one display that shows every node in a RACI matrix</li>
</ul>

<p>Consuming sites will be able to extend the content strategy pack with content moderation tweaks, and potentially editor enhancements for the two long text fields if the site’s editorial users find great utility from them.</p>

<p>These two recipes seem the most straightforward to accomplish as one developer within the next 6 months, given the moving target of the brand-new Starshot project. As I’ll discuss below, there are other features I’d like to bring to Starshot but may need more time to accomplish.</p>

<h3 id="decommission">Decommission</h3>

<p>As an article of good faith and support for the Drupal community, <strong>I pledge to decommission the frost project as soon as the Experience Builder initiative is a viable part of Starshot</strong>. Since frost putatively <em>competes</em> with Starshot, decommissioning it signals a confidence in the larger community’s ability to offer a superior product.</p>

<p>The decommissioning will occur in stages, in case there are consumers of frost that would otherwise be adversely affected:</p>

<ul>
  <li>At the time of XB viability, I will no longer provide new releases, including security releases</li>
  <li>3 months after, I will get rid of active releases on the project page</li>
  <li>At the six month mark I will amend the drupal.org project page and GitHub readme to reflect the decommissioned status</li>
  <li>At one year I may replace the frost demo site with a project debrief microsite</li>
  <li>In 2026 and thereafter I may close or remove pages/sites as long as doing so does not cause link rot</li>
</ul>

<p>I cannot commit to decommissioning frost any sooner than XB viability, since that is the key way that Starshot will be able to improve upon the excellence frost already offers.</p>

<h3 id="backfill-features">Backfill features</h3>

<p>frost has a few features that may not lend themselves to quick recipes:</p>

<ul>
  <li>A Paragraphs entity bundle (which may have to be replaced with another approach) to hold SEO fields that can be token-ed into metatag: Description, news keywords, nofollow, noindex, Social image, Title tag</li>
  <li>Metatag settings based on the Paragraphs bundle</li>
  <li>An SEO Views listing for nodes, taxonomy terms, and commerce products based on the Paragraphs bundle fields</li>
  <li>An easy module for sitewide Contact information that makes the info available as blocks and tokens</li>
</ul>

<p>I cannot pledge an exact timeframe for the above SEO and management features to become contrib projects geared for Starshot sites, but am optimistic that I can make them available to the community to improve SEO management for Starshot sites.</p>

<p>Of course, frost has a lot of other great features and functionality that would be wonderful to contribute to Starshot, but the vast difference in approaches means it would end up being brand-new work rather than adapting the prior art:</p>

<ul>
  <li>Automatic class and attribute fields</li>
  <li>Maximum configurability with minimal CSS and JS payload</li>
  <li>Interactive charts built from tablefields</li>
  <li>View and form mode optimizations to show the same content multiple useful ways</li>
  <li>Sensible image styles that prevent unnecessary breakpoint-based payload doubling</li>
  <li>A “kitchen sink” component guide default content page for reviewing and testing all components</li>
  <li>Small, baked-in features of the component library like card animations and media hotspots</li>
</ul>

<p>If there is community interest in pursuing any of those avenues in a Starshot context, I would be happy to accommodate.</p>

<h2 id="in-closing">In closing</h2>

<p>frost has been a wild ride and a learning experience for me. While I wish it had gotten more traction and community support, I’ll remain encouraged that its <em>spirit</em> if not its actual code will see a future in Starshot.</p>

<p>In these last few months before the decommissioning I will try to cherish each minor-version update and small tweak that comes along. Hopefully soon I’ll find the next big thing on which to focus my zealous attention. Watch this space!</p>
]]></content:encoded>
      </item>
    
      <item>
        <title>Unofficial Starshot strategy guide</title>
        <link>http://solveitonce.com/blog/unofficial-starshot-strategy-guide/</link>
        <pubDate>Fri, 31 May 2024 00:00:00 EST</pubDate>
        
          
          <dc:creator>Brad Czerniak</dc:creator>
        
        
        
          <category><![CDATA[Drupal]]></category>
        
          <category><![CDATA[Design]]></category>
        
        <guid isPermaLink="true">http://solveitonce.com/blog/unofficial-starshot-strategy-guide/</guid>
        <description><![CDATA[Steal this content! Everything on this site is under a CC0 license, so you
can copy/paste this without guilt.

As Gabor knows,
I came to offer my expertise to the Starshot initiative after complaining about Pitchburgh:
my pitch for frost was an entertaining would-be crowd-pleaser
that closely followed the submission guidelines and was entered before the original deadline. The same cannot be said for many of
the selected pitches. Had I known the selection criteria didn’t have much to do with the submission guidelines, maybe I wouldn’t have
put in so much time and energy.

But I didn’t complain about that for nearly a year. I only got salty when Dries announced his ambitious new ‘Starshot’ initiative:
a starter kit for Drupal bearing a striking resemblance to the existing project I pitched
less than a year ago that he’d rejected!

Rather than whine further, I’d instead like to parlay what I’ve learned from building a composable starter kit for Drupal (featuring
the best of contrib, good install-time configs, and useful default content) into sound advice for Starshot.

Table of contents


  Straining the metaphor
  Marketing    
      1. Positioning against Wordpress        
          Partners fill in the blanks
        
      
      2. Positioning against SaaS and enterprise
      3. Welcoming back returners
    
  
  Project management    
      Constraining scope
      Timeline management
    
  
  Features    
      Project browser
      Recipes
      Experience builder
      Key contrib modules
      Default content
    
  
  In closing


Straining the metaphor

If you take nothing else from this guide, please watch this video in the context of star/moon-shots (I recommend at 1.5x speed,
but you do you):


    
      
        
        
        
        
        

        
        
        
        

        
        
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

Starshot is effectively three things:


  A new Drupal-based product to stand next to Drupal core
  A marketing campaign to draw folks away from the competition
  An ambitious project with a short timeline


As Destin highights in the video, we can learn from the original moonshot, and ignoring the lessons the original engineers took
the time to compile may be to our peril. Communicating the realistic risks and roadblocks and getting feedback from anyone willing
to share will be key to mission success.

An aside when it comes to Artemis, what’s the plan if the Starship falls over?

Marketing

There are three aspects to marketing the “Drupal CMS” product that comes out of the Starshot initiative.

1. Positioning against Wordpress

Yes, of course there are other CMSes out there and the Drupal and Wordpress communities’ rivalry can best be described as friendly,
but it’s still competition for hearts and minds.

From what I’ve heard from clients, Drupal is perceived as more enterprise-y, and small organizations wonder if they’re big enough to
support a Drupal site. On the other hand, Wordpress seems very approachable but not necessarily great for scale.

That’s a good perception for folks to have, since it can be improved by making Drupal a little easier!

A turnkey officially-supported Drupal product can shift the perception. The strategy for (in a friendly manner!) shifting the narrative:


  Wordpress has spent the last 15 years digging themselves a hole, while Drupal has been building a pedestal. Wordpress has prioritized
rolling updates and legacy PHP support, and because of that is now stuck with “the loop” and other sub-optimal architectural decisions.
Drupal made tough choices to break backwards-compatibility, and is now a modern framework with a great prospect for longevity
  The new Drupal CMS has the same ease-of-setup as Wordpress, but gives you far more room to grow
  Drupal CMS’s Project Browser and Automatic Updates are features you know and love from Wordpress, but are implemented with an
eye to security and responsible codebase management
  It’s rare for a Drupal site to require paid plugins or themes the way Wordpress does, so with the ease-of-use updates in Drupal CMS it
could actually be cheaper to run a Drupal site than a Wordpress one


Much of the sales pitch for converting Wordpress could also apply to Backdrop folks. If the vast majority of a site build can be done
without touching code, the advantage of having a familiar old-fashioned API paradigm goes away pretty quick.

Partners fill in the blanks

Many hosting providers have offered one-click installs of Wordpress, Drupal, and lots of other web software for years. Their customers
choose Wordpress all the time and get rolling. Reaching out to hosting providers to get their one-click Drupal buttons ready for
Starshot could be a boost during Starshot’s launch publicity.

If wordpress.com (as opposed to wordpress.org) is still considered a thing, there could be some business upside for a certified Partner
willing to do Drupal CMS site hosting without all the hosting headaches — a niche Wordpress presently owns.

2. Positioning against SaaS and enterprise

Commercial site builders like Wix, Squarespace, Google Sites, and others are all convenient, but they tend to have some drawbacks:


  The styling and layout tools tend to put flexibility ahead of consistency, so the front-end code is a bloated mess, and pages can
accidentally have four or more fonts on one page
  You’re locked in to a relatively-low monthly fee for a basic site, but can end up with big bills if you need more features or traffic
  You can’t really export your site in any useful way. The site builder software has a stranglehold on your site



    Key point 1: With Drupal CMS you own your website: the content, the code, everything.
  

To an alarming extent this same approach applies to enterprise-grade CMS/DXP products like Adobe Experience Manager (AEM). Drupal has
always had the ownership and portability advantage in this space, but Drupal CMS’s competitive feature set amps up the selling power.

3. Welcoming back returners

Plenty of organizations have assessed their options for a CMS to use and turned away from Drupal after a frustrating early experience.
This is a large segment that can be recovered!

A version of Drupal that’s easy to use from the get-go and can be assessed by multiple committee members independently at the click of
a button can tip the decision in Drupal’s favor, since it is known to be robust, portable, secure, open source, and all the other
selling points that got it on the committee’s list in the first place.

Welcoming back folks who’ve had a bad first impression can be tough, but case studies like Domino’s Pizza
could be useful for showing how.

Project management

The handling of the Starshot initiative to date, as well as its announced scope and timeline, is what gives me the most pause about
the project.

The first two weeks of a 35-week extravaganza have now been figuring out the leadership structure, taking meetings with strategic
partners, etc. Frankly, that should have all been done before the initiative was announced. The lack of polish makes Starshot seem at
least somewhat haphazard.

But that lost time can be recaptured somewhat with sound decisions about scope and timeline.

Constraining scope

It is important, ideally sooner rather than later, to clamp down on scope creep by encouraging the contrib space to offer recipes
rather than holding out hope that tons of modules will be included in Drupal CMS by default.

So far I’ve seen these and many other suggestions of a range of features that Starshot could include:


  Decoupled this-or-that: No, just no. A decoupled site is two sites, so why would you make the project twice as complex? Plus,
there’s no reasonable way to choose a decoupled solution that would be preferred by everyone. And most “Ambitious site builders”
don’t care about how the sausage is made, but the idea that they could someday tack on a hybrid site setup via recipe that could
send its data to a platform app (or something) would more than satisfy the ‘decoupled’ checkbox
  ECA: The ECA suite of modules is the modern Drupal replacement for Rules. I’m a fan of it
and can see great use for it in all flavors of Drupal. But unless there’s at least one ruleset that 80%+ of websites would keep enabled
due to its usefulness, including ECA and a chosen-default modeller module (and its dependencies) would be too much. But there should
be lots of ECA-based recipes available for Drupal CMS on day one
  AI: Unless there’s a free model endpoint that’s willing to handle Drupal CMS users’ throughput without API auth indefinitely,
the necessary API-wrangling seems much better suited to the recipes space



    Key point 2: Going forward, the new version of the polite &quot;Good idea — maybe! We&apos;re still figuring out what will be included&quot; should be &quot;That is a great idea for a recipe we should have ready on Starshot launch day!&quot;
  

Contrib authors that are early to the recipe party may be well-rewarded with tons of installs and an influx of new community members.
Starshot and Recipes hinge on each other for success, so it’s good to get folks excited about authoring recipes early.

Timeline management

If the scope of the project can remain constrained, the key timeline consideration is that the 8-month deadline is for a stable first
version. “The perfect is the enemy of the good”, “great artists ship” — all those sayings.

Since much of the advertised feature-set for Drupal CMS revolves around new features that are themselves big strategic initiatives, there’s
a tension in the planning between:


  Getting the other initiatives done independently and bringing them together once ready
  Integrating the other initiatives early and flooding their issue queues


It is absolutely imperative to merge early, as the launch-time success of Starshot hinges on users trying out Drupal not having a frustrating
experience.


    Key point 3: Merge in Recipes and Project Browser as early as possible. It will take time to make the site-builder experience smooth.
  

Along with merging early, freezes and gates are the other things to firm up for the remaining timeline:


  For the companion initiatives, a feature freeze just a month or two from now may be necessary
  For modules seeking inclusion, a stable release gate might be five months from now
  Experience Builder is going to need a lot of runway, as it’s probably the most ambitious part of the project



    Key point 4: For scope and timeline, assume recipes and project browser will be stable, but Experience Builder will launch in alpha/beta condition
  

Features

The phenaproxima/starshot-prototype repo is already showing promise toward many of the
same decisions as frost, with a lot of the remaining work being from the initiatives.

Project browser

For ambitious site builders trying to set up a Drupal site without a PHP background, choosing contrib modules and themes is bound to be a
matter of trial and error.

While not impossible, uninstalling modules in Drupal 8+ takes a real backseat to installing them, and that imbalance will become noticeable
when installing modules with overlapping functionality and varying levels of quality to choose a winner. Seasoned developers will dump their
local database before trying something risky (among many tactics), but that’s not stated as a feature to be added to the admin UI via Starshot,
so a smooth install and uninstall process for trying out contrib code is key.


    Key point 5: Project browser and the overall &apos;Extend&apos; system needs to guide newer site-builders in the right direction.
  

Perhaps, given the big mix of contrib modules available and the speed with which someone can get themselves in trouble, a focus on curated recipes
(which themselves can trigger module installation) over the ability to install contrib modules and themes from the admin UI, would be a bigger
driver of success for new site-builders. That’s not to say Project Browser isn’t a key feature — it definitely is — but recipes are probably a
safer and faster starting point.

Recipes

A good Drupal site architecture is a balancing act:


  A site with an “Accounting article” content type and 5 other subtly-different article types is too many types when one type with a term
reference field would be better
  But a site with one content type that has a dropdown for making each node act like a page, an article, or an event ends up putting a ton
of logic in one template instead of having 3 templates


A similar principle applies to field naming/reuse and plenty of other abstractions.

Ideally, Starshot will ship with Page, Article, and Event, and the base fields for the types will be included. With those architectural
baselines in place, recipe authors will have a rubric (and ideally accompanying guideline documentation) for making new entity types and
node bundles, field reuse between bundles, field naming, and other things that are easy to get wrong for first-timers.


    Key point 6: Let&apos;s take this opportunity to make community standards for node types and field naming + reuse.
  

This foundation work is useful for recipes because many recipes could extend the built-in types; for instance, a recipe with the contrib and
config to make the event content type (node bundle!) have an “Add to calendar” button based on its fields. If there’s one recipe like that
and everybody agrees it works great, then no worries! But if there’s multiple overlapping recipes and each cannot really be ‘uninstalled’ in a
meaningful fashion, even slightly diverging entity/field standards could make sites big messes of slightly-different fields and stuff.

And that’s a big risk when it comes to recipes: if you can install them but not really uninstall them, folks who are setting up new sites and
trying things out could get into trouble quickly. The community has got to try out as many recipes as possible in as many realistic scenarios
as possible as soon as possible, because that’s the only way we’re going to iron out the things that would frustrate new users.


    Key point 7: To reiterate key point 3, we gotta be thoroughly testing recipes for new users&apos; sake.
  

Experience builder

Wordpress has had Gutenberg as its default block editor since 2018, with it having full-site-editing capability since 2021. Meanwhile, Drupal
has been in CKEditor-land forever, with only contrib support for more advanced editors and components. Yes, Drupal Layout Builder has been
around for 5-ish years in experimental form and has been a viable stable core content-entry experience for a year or two, but I wouldn’t consider
it a runaway success. It gets the job done and is growing on me, but it’s not industry-leading.

Drupal desperately needs a page editing experience that is what-you-see-is-what-you-get…ish. It has to allow for easy responsive layouts,
on-brand theming and typesetting, and the interface should allow for content authors to turn a limited set of knobs and dials, while admins
should be able to tweak all kinds of stuff.


    Key point 8: Experience Builder must pass the Comic Sans test — a regular author should not be able to set off-brand content styling, but an admin should.
  

A smooth, easy-to-use interface just for the content area (ie. focusing on improving Layout Builder instead of going for full full-site-editing)
might be a better launch goal than the FSE aspect. The 3+ years from Gutenberg’s launch to Wordpress FSE could be taken as an indicator of the
difficulty of the new initiative.

Gutenberg is a great model for a page builder experience, whereas something like Acquia Site Studio is not. While a goal of Starshot is to allow
ambitious site builders to accomplish most everything from the admin UI in the browser, that doesn’t mean Site Studio’s clunky styling interface
belongs anywhere near Starshot.

Wordpress has a mechanism for editing CSS files in the theme interface if a site-builder wants to customize the styling a little bit. That
is a more comfortable way to set up styles (I cannot stress how clunky style-builder GUIs can be when you just want to write a little CSS). I’m
not advocating for a catch-all CSS file editor, especially considering single-directory components and front-end library management are a
competitive advantage of Drupal, but more trying to drive home that a GUI for setting element styles at the property: value; level would be
a bad idea.

That’s in contrast to being able to select background and font colors from a branded palette when placing a component block, which should be
unobtrusive and smooth to do.

Key contrib modules

I don’t think there’s a lot of project risk in picking which contrib modules to include in Drupal CMS, aside from the politics and scope
issues already mentioned, so this section is just a this works for frost, so I’d recommend them for Starshot blurb:

These contrib modules rule:


  Better exposed filters
  Config ignore
  Editoria11y
  Entity clone
  Entity reference display
  Honeypot
  Human decimal
  Media library edit
  Metatag
  Pathauto
  Redirect
  Similar by terms
  Simple sitemap
  Tablefield
  Views block filter block
  Webform


I went through a much longer list and even with a working starter kit I
still kept going, “Hmm, commerce would be better as a recipe.” Recipes are the key to a tight scope and user satisfaction!

Default content

This is the section where Brad has big opinions.

Frost ships with 22 pieces of default content, such as these:


  Home
  Search
  Events
  Events archive
  Contact us
  FAQs
  Blog
  Privacy Policy
  Accessibility Statement
  404 template
  Generic thank you page
  Component guide
  Style guide
  About us template
  Press
  Terms &amp;amp; Conditions


They mostly fall into three categories:


  Pages every site has, like Home and “About us”
  The boring stuff like Privacy policies, tag listings, etc.
  Placeholders for demonstrating article/event serialization


What’s great about default content for Home and About is that you can:


  Lay out a decent page-level information architecture for those type of pages
  Use that IA to include instructions here and there for making the page their own
  Demonstrate some of the cool out-of-the-box features from the component system


But what I love even more is reusable default content. Most sites are going to need a Privacy policy and Terms of use and all the other
boring pages that often get forgotten until the week of launch. If Drupal CMS can improve on the model for boring included default content
that frost has attempted, it could make a real difference in web creators’ lives. Please steal this idea and run with it, Starshotters


    Key point 9: Seriously, take frost&apos;s default content and include it in Starshot.
  

In closing

So that’s it! There are challenges ahead and some key factors for the success of the project, but every reason to be (cautiously)
optimistic. Let’s all give Starshot our zealous energy.


    
  

I definitely wanted to put more detail in this post into various features — like, wouldn’t it be great if the theme that ships with
Drupal CMS embraced
a utility CSS library like this one?
Alas, I only have so many late nights for writing!

If you’re working on some part of Starshot and think I could lend my expertise in some way, please don’t hesitate
to reach out to brad@solveitonce.com. Alternatively, if you think I missed the mark somewhere, I will happily
inline quote (and attribute it if you want) your feedback into this post if you reach out.


    Key point 10: Thank you for your time.
  

]]></description>
        <content:encoded><![CDATA[<p><strong class="color--third font-size--1p25em">Steal this content! Everything on this site is under a CC0 license, so you
can copy/paste this without guilt.</strong></p>

<p><a href="https://www.linkedin.com/posts/ghojtsy_drupalcon-portland-recap-activity-7196905403413102593-8pbu?utm_source=share&amp;utm_medium=member_desktop">As Gabor knows</a>,
I came to offer my expertise to the Starshot initiative after complaining about Pitchburgh:
<a href="https://www.frostdrupal.com/page/pitch-burgh-frost-drupal-2023">my pitch for frost</a> was an entertaining would-be crowd-pleaser
that closely followed the submission guidelines and was entered before the <em>original</em> deadline. The same cannot be said for many of
the selected pitches. Had I known the selection criteria didn’t have much to do with the submission guidelines, maybe I wouldn’t have
put in so much time and energy.</p>

<p>But I didn’t complain about that for nearly a year. I only got salty when Dries announced his ambitious new ‘Starshot’ initiative:
a starter kit for Drupal bearing a striking resemblance to the <a href="https://www.drupal.org/project/frost">existing project</a> I pitched
less than a year ago that he’d rejected!</p>

<p>Rather than whine further, I’d instead like to parlay what I’ve learned from building a composable starter kit for Drupal (featuring
the best of contrib, good install-time configs, and useful default content) into <strong>sound advice for Starshot</strong>.</p>

<h2 class="no_toc" id="table-of-contents">Table of contents</h2>

<ol id="markdown-toc">
  <li><a href="#straining-the-metaphor" id="markdown-toc-straining-the-metaphor">Straining the metaphor</a></li>
  <li><a href="#marketing" id="markdown-toc-marketing">Marketing</a>    <ol>
      <li><a href="#1-positioning-against-wordpress" id="markdown-toc-1-positioning-against-wordpress">1. Positioning against Wordpress</a>        <ol>
          <li><a href="#partners-fill-in-the-blanks" id="markdown-toc-partners-fill-in-the-blanks">Partners fill in the blanks</a></li>
        </ol>
      </li>
      <li><a href="#2-positioning-against-saas-and-enterprise" id="markdown-toc-2-positioning-against-saas-and-enterprise">2. Positioning against SaaS and enterprise</a></li>
      <li><a href="#3-welcoming-back-returners" id="markdown-toc-3-welcoming-back-returners">3. Welcoming back returners</a></li>
    </ol>
  </li>
  <li><a href="#project-management" id="markdown-toc-project-management">Project management</a>    <ol>
      <li><a href="#constraining-scope" id="markdown-toc-constraining-scope">Constraining scope</a></li>
      <li><a href="#timeline-management" id="markdown-toc-timeline-management">Timeline management</a></li>
    </ol>
  </li>
  <li><a href="#features" id="markdown-toc-features">Features</a>    <ol>
      <li><a href="#project-browser" id="markdown-toc-project-browser">Project browser</a></li>
      <li><a href="#recipes" id="markdown-toc-recipes">Recipes</a></li>
      <li><a href="#experience-builder" id="markdown-toc-experience-builder">Experience builder</a></li>
      <li><a href="#key-contrib-modules" id="markdown-toc-key-contrib-modules">Key contrib modules</a></li>
      <li><a href="#default-content" id="markdown-toc-default-content">Default content</a></li>
    </ol>
  </li>
  <li><a href="#in-closing" id="markdown-toc-in-closing">In closing</a></li>
</ol>

<h2 id="straining-the-metaphor">Straining the metaphor</h2>

<p>If you take nothing else from this guide, please watch this video in the context of star/moon-shots (I recommend at 1.5x speed,
but you do you):</p>

<figure class="figure figure--youtube js--youtube include include--molecule include--molecule--youtube
    " data-youtube="OoJsPvmFixU" data-title="I Was SCARED To Say This To NASA... (But I said it anyway) - Smarter Every Day 293">
    <a href="https://www.youtube.com/watch?v=OoJsPvmFixU">
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
        
        

        
        
        
        

        
        
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/youtube/OoJsPvmFixU.jpg.webp" type="image/webp" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/youtube/OoJsPvmFixU.jpg" alt="I Was SCARED To Say This To NASA... (But I said it anyway) - Smarter Every Day 293" loading="lazy" height="360" width="480" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/youtube/OoJsPvmFixU.jpg" alt="I Was SCARED To Say This To NASA... (But I said it anyway) - Smarter Every Day 293" loading="lazy" />
      </noscript>
    </a>
    
  </figure>

<p><a href="https://www.drupal.org/starshot">Starshot</a> is effectively three things:</p>

<ol>
  <li>A new Drupal-based product to stand next to Drupal core</li>
  <li>A marketing campaign to draw folks away from the competition</li>
  <li>An ambitious project with a short timeline</li>
</ol>

<p>As Destin highights in the video, <strong>we can learn from the original moonshot</strong>, and ignoring the lessons the original engineers took
the time to compile may be to our peril. Communicating the realistic risks and roadblocks and getting feedback from anyone willing
to share will be key to mission success.</p>

<p>An aside when it comes to Artemis, <strong>what’s the plan if the Starship falls over?</strong></p>

<h2 id="marketing">Marketing</h2>

<p>There are three aspects to marketing the “Drupal CMS” product that comes out of the Starshot initiative.</p>

<h3 id="1-positioning-against-wordpress">1. Positioning against Wordpress</h3>

<p>Yes, of course there are other CMSes out there and the Drupal and Wordpress communities’ rivalry can best be described as <em>friendly</em>,
but it’s still competition for hearts and minds.</p>

<p>From what I’ve heard from clients, Drupal is perceived as more enterprise-y, and small organizations wonder if they’re big enough to
support a Drupal site. On the other hand, Wordpress seems very approachable but not necessarily great for scale.</p>

<p>That’s a good perception for folks to have, since it can be improved by making Drupal a little easier!</p>

<p>A turnkey officially-supported Drupal product can shift the perception. The strategy for (in a friendly manner!) shifting the narrative:</p>

<ul>
  <li>Wordpress has spent the last 15 years digging themselves a hole, while Drupal has been building a pedestal. Wordpress has prioritized
rolling updates and legacy PHP support, and because of that is now stuck with “the loop” and other sub-optimal architectural decisions.
Drupal made tough choices to break backwards-compatibility, and is now a modern framework with a great prospect for longevity</li>
  <li>The new Drupal CMS has the same ease-of-setup as Wordpress, but gives you far more room to grow</li>
  <li>Drupal CMS’s <strong>Project Browser</strong> and <strong>Automatic Updates</strong> are features you know and love from Wordpress, but are implemented with an
eye to security and responsible codebase management</li>
  <li>It’s rare for a Drupal site to require paid plugins or themes the way Wordpress does, so with the ease-of-use updates in Drupal CMS it
could actually be cheaper to run a Drupal site than a Wordpress one</li>
</ul>

<p>Much of the sales pitch for converting Wordpress could also apply to Backdrop folks. If the vast majority of a site build can be done
without touching code, the advantage of having a familiar old-fashioned API paradigm goes away pretty quick.</p>

<h4 id="partners-fill-in-the-blanks">Partners fill in the blanks</h4>

<p>Many hosting providers have offered one-click installs of Wordpress, Drupal, and lots of other web software for years. Their customers
choose Wordpress all the time and get rolling. Reaching out to hosting providers to get their one-click Drupal buttons ready for
Starshot could be a boost during Starshot’s launch publicity.</p>

<p>If wordpress.com (as opposed to wordpress.org) is still considered a thing, there could be some business upside for a certified Partner
willing to do Drupal CMS site hosting without all the hosting headaches — a niche Wordpress presently owns.</p>

<h3 id="2-positioning-against-saas-and-enterprise">2. Positioning against SaaS and enterprise</h3>

<p>Commercial site builders like Wix, Squarespace, Google Sites, and others are all convenient, but they tend to have some drawbacks:</p>

<ul>
  <li>The styling and layout tools tend to put flexibility ahead of consistency, so the front-end code is a bloated mess, and pages can
accidentally have four or more fonts on one page</li>
  <li>You’re locked in to a relatively-low monthly fee for a basic site, but can end up with big bills if you need more features or traffic</li>
  <li>You can’t really export your site in any useful way. The site builder software has a stranglehold on your site</li>
</ul>

<div class="alert include include--module include--molecule--alert position--relative
    
    
    alert--status" id="alert--key-point-1-with-drupal-cms..." role="alert">
    <p><strong>Key point 1</strong>: With Drupal CMS you <em>own</em> your website: the content, the code, everything.</p>
  </div>

<p>To an alarming extent this same approach applies to enterprise-grade CMS/DXP products like Adobe Experience Manager (AEM). Drupal has
always had the ownership and portability advantage in this space, but Drupal CMS’s competitive feature set amps up the selling power.</p>

<h3 id="3-welcoming-back-returners">3. Welcoming back returners</h3>

<p>Plenty of organizations have assessed their options for a CMS to use and turned away from Drupal after a frustrating early experience.
<strong>This is a large segment that can be recovered</strong>!</p>

<p>A version of Drupal that’s easy to use from the get-go and can be assessed by multiple committee members independently at the click of
a button can tip the decision in Drupal’s favor, since it is known to be robust, portable, secure, open source, and all the other
selling points that got it on the committee’s list in the first place.</p>

<p>Welcoming back folks who’ve had a bad first impression can be tough, but case studies like <a href="https://bettermarketing.pub/how-dominos-revitalized-its-failing-brand-77e9dec19ac3">Domino’s Pizza</a>
could be useful for showing how.</p>

<h2 id="project-management">Project management</h2>

<p>The handling of the Starshot initiative to date, as well as its announced scope and timeline, is what gives me the most pause about
the project.</p>

<p>The first two weeks of a 35-week extravaganza have now been figuring out the leadership structure, taking meetings with strategic
partners, etc. Frankly, that should have all been done before the initiative was announced. The lack of polish makes Starshot seem at
least somewhat haphazard.</p>

<p>But that lost time can be recaptured somewhat with sound decisions about scope and timeline.</p>

<h3 id="constraining-scope">Constraining scope</h3>

<p>It is important, ideally sooner rather than later, to clamp down on scope creep by encouraging the contrib space to offer recipes
rather than holding out hope that tons of modules will be included in Drupal CMS by default.</p>

<p>So far I’ve seen these and many other suggestions of a range of features that Starshot could include:</p>

<ul>
  <li><strong>Decoupled this-or-that</strong>: No, just no. A decoupled site is two sites, so why would you make the project twice as complex? Plus,
there’s no reasonable way to choose a decoupled solution that would be preferred by everyone. And most “Ambitious site builders”
don’t care about how the sausage is made, but the idea that they could someday tack on a <em>hybrid</em> site setup via recipe that could
send its data to a platform app (or something) would more than satisfy the ‘decoupled’ checkbox</li>
  <li><strong>ECA</strong>: The <a href="https://www.drupal.org/project/eca">ECA suite of modules</a> is the modern Drupal replacement for Rules. I’m a fan of it
and can see great use for it in all flavors of Drupal. But unless there’s at least one ruleset that 80%+ of websites would keep enabled
due to its usefulness, including ECA <em>and</em> a chosen-default modeller module (and its dependencies) would be too much. But there should
be lots of ECA-based recipes available for Drupal CMS <strong>on day one</strong></li>
  <li><strong>AI</strong>: Unless there’s a free model endpoint that’s willing to handle Drupal CMS users’ throughput without API auth indefinitely,
the necessary API-wrangling seems much better suited to the recipes space</li>
</ul>

<div class="alert include include--module include--molecule--alert position--relative
    
    
    alert--status" id="alert--key-point-2-going-forward-t..." role="alert">
    <p><strong>Key point 2</strong>: Going forward, the new version of the polite "Good idea — maybe! We're still figuring out what will be included" should be "That is a great idea for a recipe we should have ready on Starshot launch day!"</p>
  </div>

<p>Contrib authors that are early to the recipe party may be well-rewarded with tons of installs and an influx of new community members.
Starshot and Recipes hinge on each other for success, so it’s good to get folks excited about authoring recipes early.</p>

<h3 id="timeline-management">Timeline management</h3>

<p>If the scope of the project can remain constrained, the key timeline consideration is that the 8-month deadline is for a stable first
version. “The perfect is the enemy of the good”, “great artists ship” — all those sayings.</p>

<p>Since much of the advertised feature-set for Drupal CMS revolves around new features that are themselves big strategic initiatives, there’s
a tension in the planning between:</p>

<ol>
  <li>Getting the other initiatives done independently and bringing them together once ready</li>
  <li>Integrating the other initiatives early and flooding their issue queues</li>
</ol>

<p>It is absolutely imperative to merge early, as the launch-time success of Starshot hinges on users trying out Drupal not having a frustrating
experience.</p>

<div class="alert include include--module include--molecule--alert position--relative
    
    
    alert--status" id="alert--key-point-3-merge-in-recipe..." role="alert">
    <p><strong>Key point 3</strong>: Merge in Recipes and Project Browser as early as possible. It will take time to make the site-builder experience smooth.</p>
  </div>

<p>Along with merging early, <em>freezes</em> and <em>gates</em> are the other things to firm up for the remaining timeline:</p>

<ul>
  <li>For the companion initiatives, a <strong>feature freeze</strong> just a month or two from now may be necessary</li>
  <li>For modules seeking inclusion, a <strong>stable release gate</strong> might be five months from now</li>
  <li>Experience Builder is going to need a lot of runway, as it’s probably the most ambitious part of the project</li>
</ul>

<div class="alert include include--module include--molecule--alert position--relative
    
    
    alert--status" id="alert--key-point-4-for-scope-and-t..." role="alert">
    <p><strong>Key point 4</strong>: For scope and timeline, assume recipes and project browser will be stable, but Experience Builder will launch in alpha/beta condition</p>
  </div>

<h2 id="features">Features</h2>

<p>The <a href="https://github.com/phenaproxima/starshot-prototype">phenaproxima/starshot-prototype repo</a> is already showing promise toward many of the
same decisions as <a href="https://github.com/solve-it-once/frost">frost</a>, with a lot of the remaining work being from the initiatives.</p>

<h3 id="project-browser">Project browser</h3>

<p>For ambitious site builders trying to set up a Drupal site without a PHP background, choosing contrib modules and themes is bound to be a
matter of trial and error.</p>

<p>While not impossible, uninstalling modules in Drupal 8+ takes a real backseat to installing them, and that imbalance will become noticeable
when installing modules with overlapping functionality and varying levels of quality to choose a winner. Seasoned developers will dump their
local database before trying something risky (among many tactics), but that’s not stated as a feature to be added to the admin UI via Starshot,
so a smooth install <em>and</em> uninstall process for trying out contrib code is key.</p>

<div class="alert include include--module include--molecule--alert position--relative
    
    
    alert--status" id="alert--key-point-5-project-browser..." role="alert">
    <p><strong>Key point 5</strong>: Project browser and the overall 'Extend' system needs to guide newer site-builders in the right direction.</p>
  </div>

<p>Perhaps, given the big mix of contrib modules available and the speed with which someone can get themselves in trouble, a focus on curated recipes
(which themselves can trigger module installation) over the ability to install contrib modules and themes from the admin UI, would be a bigger
driver of success for new site-builders. That’s not to say Project Browser isn’t a key feature — it definitely is — but recipes are probably a
safer and faster starting point.</p>

<h3 id="recipes">Recipes</h3>

<p>A good Drupal site architecture is a <em>balancing act</em>:</p>

<ul>
  <li>A site with an “Accounting article” content type and 5 other subtly-different article types is too many types when one type with a term
reference field would be better</li>
  <li>But a site with one content type that has a dropdown for making each node act like a page, an article, or an event ends up putting a ton
of logic in one template instead of having 3 templates</li>
</ul>

<p><a href="https://solveitonce.com/blog/is-this-the-hard-part/">A similar principle applies to field naming/reuse</a> and plenty of other abstractions.</p>

<p>Ideally, Starshot will ship with Page, Article, and Event, and the base fields for the types will be included. With those architectural
baselines in place, recipe authors will have a rubric (and ideally accompanying guideline documentation) for making new entity types and
node bundles, field reuse between bundles, field naming, and other things that are easy to get wrong for first-timers.</p>

<div class="alert include include--module include--molecule--alert position--relative
    
    
    alert--status" id="alert--key-point-6-let-s-take-this..." role="alert">
    <p><strong>Key point 6</strong>: Let's take this opportunity to make community standards for node types and field naming + reuse.</p>
  </div>

<p>This foundation work is useful for recipes because many recipes could extend the built-in types; for instance, a recipe with the contrib and
config to make the event content type (node bundle!) have an “Add to calendar” button based on its fields. If there’s one recipe like that
and everybody agrees it works great, then no worries! But if there’s multiple overlapping recipes and each cannot really be ‘uninstalled’ in a
meaningful fashion, even slightly diverging entity/field standards could make sites big messes of slightly-different fields and stuff.</p>

<p>And that’s a big risk when it comes to recipes: if you can install them but not <em>really</em> uninstall them, folks who are setting up new sites and
trying things out could <strong>get into trouble quickly</strong>. The community has got to try out as many recipes as possible in as many realistic scenarios
as possible as soon as possible, because that’s the only way we’re going to iron out the things that would frustrate new users.</p>

<div class="alert include include--module include--molecule--alert position--relative
    
    
    alert--status" id="alert--key-point-7-to-reiterate-ke..." role="alert">
    <p><strong>Key point 7</strong>: To reiterate key point 3, we gotta be thoroughly testing recipes for new users' sake.</p>
  </div>

<h3 id="experience-builder">Experience builder</h3>

<p>Wordpress has had Gutenberg as its default block editor since 2018, with it having full-site-editing capability since 2021. Meanwhile, Drupal
has been in CKEditor-land forever, with only contrib support for more advanced editors and components. Yes, Drupal Layout Builder has been
around for 5-ish years in experimental form and has been a viable stable core content-entry experience for a year or two, but I wouldn’t consider
it a runaway success. It gets the job done and is growing on me, but it’s not industry-leading.</p>

<p>Drupal <strong>desperately needs</strong> a page editing experience that is what-you-see-is-what-you-get…ish. It has to allow for easy responsive layouts,
on-brand theming and typesetting, and the interface should allow for content authors to turn a limited set of knobs and dials, while admins
should be able to tweak all kinds of stuff.</p>

<div class="alert include include--module include--molecule--alert position--relative
    
    
    alert--status" id="alert--key-point-8-experience-buil..." role="alert">
    <p style="font-family: 'Comic Sans MS', script;"><strong>Key point 8</strong>: Experience Builder must pass the Comic Sans test — a regular author should not be able to set off-brand content styling, but an admin should.</p>
  </div>

<p>A smooth, easy-to-use interface just for the content area (ie. focusing on improving Layout Builder instead of going for full full-site-editing)
might be a better launch goal than the FSE aspect. The 3+ years from Gutenberg’s launch to Wordpress FSE could be taken as an indicator of the
difficulty of the new initiative.</p>

<p>Gutenberg is a great model for a page builder experience, whereas something like Acquia Site Studio is not. While a goal of Starshot is to allow
ambitious site builders to accomplish most everything from the admin UI in the browser, that doesn’t mean Site Studio’s clunky styling interface
belongs anywhere near Starshot.</p>

<p>Wordpress has a mechanism for editing CSS files in the theme interface if a site-builder wants to customize the styling a little bit. That
is a more comfortable way to set up styles (I cannot stress how clunky style-builder GUIs can be when you just want to write a little CSS). I’m
not advocating for a catch-all CSS file editor, especially considering single-directory components and front-end library management are a
competitive advantage of Drupal, but more trying to drive home that a GUI for setting element styles at the <code class="language-plaintext highlighter-rouge">property: value;</code> level would be
a bad idea.</p>

<p>That’s in contrast to being able to select background and font colors from a branded palette when placing a component block, which should be
unobtrusive and smooth to do.</p>

<h3 id="key-contrib-modules">Key contrib modules</h3>

<p>I don’t think there’s a lot of project risk in picking which contrib modules to include in Drupal CMS, aside from the politics and scope
issues already mentioned, so this section is just a <em>this works for frost, so I’d recommend them for Starshot</em> blurb:</p>

<p>These contrib modules rule:</p>

<ul>
  <li><a href="https://www.drupal.org/project/better_exposed_filters">Better exposed filters</a></li>
  <li><a href="https://www.drupal.org/project/config_ignore">Config ignore</a></li>
  <li><a href="https://www.drupal.org/project/editoria11y">Editoria11y</a></li>
  <li><a href="https://www.drupal.org/project/entity_clone">Entity clone</a></li>
  <li><a href="https://www.drupal.org/project/entity_reference_display">Entity reference display</a></li>
  <li><a href="https://www.drupal.org/project/honeypot">Honeypot</a></li>
  <li><a href="https://www.drupal.org/project/human_decimal">Human decimal</a></li>
  <li><a href="https://www.drupal.org/project/media_library_edit">Media library edit</a></li>
  <li><a href="https://www.drupal.org/project/metatag">Metatag</a></li>
  <li><a href="https://www.drupal.org/project/pathauto">Pathauto</a></li>
  <li><a href="https://www.drupal.org/project/redirect">Redirect</a></li>
  <li><a href="https://www.drupal.org/project/similarterms">Similar by terms</a></li>
  <li><a href="https://www.drupal.org/project/simple_sitemap">Simple sitemap</a></li>
  <li><a href="https://www.drupal.org/project/tablefield">Tablefield</a></li>
  <li><a href="https://www.drupal.org/project/views_block_filter_block">Views block filter block</a></li>
  <li><a href="https://www.drupal.org/project/webform">Webform</a></li>
</ul>

<p>I went through <a href="https://github.com/solve-it-once/frost/blob/master/composer.json">a much longer list</a> and even with a working starter kit I
still kept going, “Hmm, commerce would be better as a recipe.” Recipes are the key to a tight scope <strong>and user satisfaction</strong>!</p>

<h3 id="default-content">Default content</h3>

<p>This is the section where <strong>Brad has big opinions</strong>.</p>

<p>Frost ships with 22 pieces of default content, such as these:</p>

<ul>
  <li><a href="https://www.frostdrupal.com/page/home">Home</a></li>
  <li><a href="https://www.frostdrupal.com/search">Search</a></li>
  <li><a href="https://www.frostdrupal.com/event">Events</a></li>
  <li><a href="https://www.frostdrupal.com/event/archive">Events archive</a></li>
  <li><a href="https://www.frostdrupal.com/contact-us">Contact us</a></li>
  <li><a href="https://www.frostdrupal.com/page/frequently-asked-questions">FAQs</a></li>
  <li><a href="https://www.frostdrupal.com/article">Blog</a></li>
  <li><a href="https://www.frostdrupal.com/page/privacy-policy">Privacy Policy</a></li>
  <li><a href="https://www.frostdrupal.com/page/accessibility-statement">Accessibility Statement</a></li>
  <li><a href="https://www.frostdrupal.com/page/404-not-found">404 template</a></li>
  <li><a href="https://www.frostdrupal.com/page/thank-you">Generic thank you page</a></li>
  <li><a href="https://www.frostdrupal.com/page/component-guide">Component guide</a></li>
  <li><a href="https://www.frostdrupal.com/admin/appearance/styleguide">Style guide</a></li>
  <li><a href="https://www.frostdrupal.com/page/about">About us template</a></li>
  <li><a href="https://www.frostdrupal.com/page/press">Press</a></li>
  <li><a href="https://www.frostdrupal.com/page/terms-conditions">Terms &amp; Conditions</a></li>
</ul>

<p>They mostly fall into three categories:</p>

<ol>
  <li>Pages every site has, like Home and “About us”</li>
  <li>The boring stuff like Privacy policies, tag listings, etc.</li>
  <li>Placeholders for demonstrating article/event serialization</li>
</ol>

<p>What’s great about default content for Home and About is that you can:</p>

<ul>
  <li>Lay out a decent page-level information architecture for those type of pages</li>
  <li>Use that IA to include instructions here and there for making the page their own</li>
  <li>Demonstrate some of the cool out-of-the-box features from the component system</li>
</ul>

<p><strong>But what I love even more is reusable default content</strong>. Most sites are going to need a Privacy policy and Terms of use and all the other
boring pages that often get forgotten until the week of launch. If Drupal CMS can improve on the model for boring included default content
that frost has attempted, it could make a real difference in web creators’ lives. <strong>Please steal this idea and run with it, Starshotters</strong></p>

<div class="alert include include--module include--molecule--alert position--relative
    
    
    alert--status" id="alert--key-point-9-seriously-take-..." role="alert">
    <p><strong>Key point 9</strong>: Seriously, take frost's default content and include it in Starshot.</p>
  </div>

<h2 id="in-closing">In closing</h2>

<p>So that’s it! There are challenges ahead and some key factors for the success of the project, but every reason to be (cautiously)
optimistic. Let’s all give Starshot our zealous energy.</p>

<figure class="figure figure--icon ">
    <svg xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 12 16"><path fill-rule="evenodd" d="M8.727 3C7.091 3 6.001 4.65 6.001 4.65S4.909 3 3.273 3C1.636 3 0 4.1 0 6.3 0 9.6 6 14 6 14s6-4.4 6-7.7C12 4.1 10.364 3 8.727 3z" /></svg>
  </figure>

<p>I definitely wanted to put more detail in this post into various features — like, wouldn’t it be great if the theme that ships with
Drupal CMS embraced
<a href="https://github.com/solve-it-once/frost/tree/master/docroot/themes/custom/frost_theme/css/utility">a utility CSS library like this one</a>?
Alas, I only have so many late nights for writing!</p>

<p>If you’re working on some part of Starshot and think I could lend my expertise in some way, please don’t hesitate
to <a href="mailto:brad@solveitonce.com">reach out to brad@solveitonce.com</a>. Alternatively, if you think I missed the mark somewhere, I will happily
inline quote (and attribute it if you want) your feedback into this post if you reach out.</p>

<div class="alert include include--module include--molecule--alert position--relative
    
    
    alert--status" id="alert--key-point-10-thank-you-for-..." role="alert">
    <p><strong>Key point 10</strong>: Thank you for your time.</p>
  </div>

]]></content:encoded>
      </item>
    
      <item>
        <title>Thriving!</title>
        <link>http://solveitonce.com/blog/thriving/</link>
        <pubDate>Sun, 19 Nov 2023 00:00:00 EST</pubDate>
        
          
          <dc:creator>Brad Czerniak</dc:creator>
        
        
        
          <category><![CDATA[Meta]]></category>
        
          <category><![CDATA[Updates]]></category>
        
        <guid isPermaLink="true">http://solveitonce.com/blog/thriving/</guid>
        <description><![CDATA[This blog has been a bit quiet since June. Today I had to submit an annual update for Solve it once LLC to the State
of Michigan and a brief update on the Michigan Drupal organization to Open Collective, so it seemed like a good time to
also keep you up-to-date on what so1ve has been up to recently.

It’s a lot!

In October we surpassed 5000 billable hours to clients, and early in November we confirmed that 2023 will be the fourth
consecutive year of revenue growth. These aren’t really the metrics I use to define success, but it’s nice to know the business
is healthy nonetheless.

Runner up!

In the early Summer I went back to Tactis for a while to help out with getting the new
Prince George’s County, Maryland site ready for launch.

I’d already pitched in quite a bit for this project:


  Migration from a legacy system using file exports and screen scraping
  Elaborate Acquia Pipelines work for cloud hosting, including automated accessibility testing
  Drupal Groups integration and patching for Drupal 10
  Help implementing the new design system using Acquia Site Studio
  AJAX-based menu solution for the giant navigation structure
  Custom drush commands and queue workers to easily batch updates


After it launched, the site was almost immediately nominated for an Acquia Engage award.
Ultimately, the award for “Leaders of the Pack - Public Sector” went to another Tactis project with overlapping team members,
the new Drug Enforcement Agency site. Congratulations to the DEA development team; I’m proud to work with folks doing great
things in the public sector.

Getting into the Fortune 500

No, not Solve it once. We’re still a few dollars short of making any Fortune Magazine lists, but now we’re working with
big companies! This was one of the last segments I had been targeting, since we’ve already done significant work with nonprofits,
small businesses, higher education institutions, government at multiple levels, libraries, and B2B, among others.

In July I started contracting with Principal Financial Group and have mostly helped out with projects at the intersection
of Drupal and web components:


  Contributing code and documentation to the web-component-based design system
  Pitching in to the Drupal starter kit team’s codebase to work with components via Layout Builder, webform, and other Drupal elements
  Playing a big part building the first live small site to use the new system while running on Drupal 10


This past week I deployed out Drupal 10 upgrades, single sign-on (SSO) updates, and other features for three different sites
for associated brands, all using a new deployment process with redundant success checks and integration with corporate controls.
What was most notable about these updates and the deployment was how not notable they were: the sites deployed without
any hiccups. Often no news is great news.

Every team at Principal is a joy to work with, and I’m looking forward to many more fruitful projects with them.

Blast from the past

It took a bit more than 3 years, but I’m back doing support work for my previous employer, Symmetri Marketing Group,
on a contractor basis this time. It’s great to catch up with a lot of familiar faces, and also a joy to see how many of
the projects I had contributed to from 2016-2020 have evolved.

The Autumn of our Drupal 10 upgrades

Whether for Tactis, Principal, Symmetri, or another support client, this Fall has been very Drupal-10-upgrade heavy:


  4 upgrades and one new site for Principal
  6 upgrades for Symmetri
  Help getting ready for PGC’s upgrade with Tactis
  1 upgrade for Human Element
  Discussions and prep with other clients


As you may know, so1ve’s frost install profile has been on Drupal 10 since March, and the experience
getting an install profile upgraded relatively early in the version’s lifecycle was great practice for rapidly upgrading
double-digit numbers of sites in the last couple of months.

All of the Drupal 10 upgrades have been smooth so far, with the custom parts all being along the same lines:


  Learning what Composer error messages mean rather than what they say
  Swapping composer dependencies without official Drupal 10 releases for Merge Requests using custom ‘repositories’ via drupal.org GitLab
  Changing out a few *.info.yml syntax changes, especially in custom themes
  Including any required and removed core-to-contrib dependencies, like RDF, quickedit, bartik, classy, and stable
  Changing out deprecated and removed function-based calls for OOP calls using services. When possible, those updates inside classes can use Dependency Injection
  Getting nervous when a site uses Advanced CSS/JS Aggregation, as JSMin can cause a lot of problems for a Drupal 10 site


Many of the sites also went to PHP 8.2 at the same time, and the biggest issue for that is dynamically-declared methods and properties.
There’s a strong correlation between codebases that use dynamic class elements and codebases that are a big mess to work
with and refactor, so I’d recommend estimating a bit extra padding on PHP 8.2 update projects where errors have been found.

What’s next?

Since June I’ve been working more than full-time to contribute meaningfully to my short-term, full-time contracts, while
also supporting my existing client base after hours. I plan to continue doing the same, and may have openings for projects
and support in the new year.

If you’re in the market for a website or already have a Drupal 8/9/10 site and are looking for an inexpensive and flexible
developer to support your platform, don’t hesitate to reach out via email to brad@solveitonce.com.
]]></description>
        <content:encoded><![CDATA[<p>This blog has been a bit quiet since June. Today I had to submit an annual update for Solve it once LLC to the State
of Michigan and a brief update on the Michigan Drupal organization to Open Collective, so it seemed like a good time to
also keep you up-to-date on what so1ve has been up to recently.</p>

<p>It’s a lot!</p>

<p>In October we surpassed 5000 billable hours to clients, and early in November we confirmed that 2023 will be the fourth
consecutive year of revenue growth. These aren’t really the metrics I use to define success, but it’s nice to know the business
is healthy nonetheless.</p>

<h2 id="runner-up">Runner up!</h2>

<p>In the early Summer I went back to <a href="https://www.tactis.com/">Tactis</a> for a while to help out with getting the new
<a href="https://www.princegeorgescountymd.gov/">Prince George’s County, Maryland</a> site ready for launch.</p>

<p>I’d already pitched in quite a bit for this project:</p>

<ul>
  <li>Migration from a legacy system using file exports and screen scraping</li>
  <li>Elaborate Acquia Pipelines work for cloud hosting, including automated accessibility testing</li>
  <li>Drupal Groups integration and patching for Drupal 10</li>
  <li>Help implementing the new design system using Acquia Site Studio</li>
  <li>AJAX-based menu solution for the giant navigation structure</li>
  <li>Custom drush commands and queue workers to easily batch updates</li>
</ul>

<p>After it launched, the site was almost immediately <a href="https://www.acquia.com/blog/introducing-2023-acquia-engage-awards-finalists">nominated for an Acquia Engage award</a>.
Ultimately, the award for “Leaders of the Pack - Public Sector” went to another Tactis project with overlapping team members,
the new Drug Enforcement Agency site. Congratulations to the DEA development team; I’m proud to work with folks doing great
things in the public sector.</p>

<h2 id="getting-into-the-fortune-500">Getting into the Fortune 500</h2>

<p>No, not Solve it once. We’re still a few dollars short of making any Fortune Magazine lists, but now we’re working with
big companies! This was one of the last segments I had been targeting, since we’ve already done significant work with nonprofits,
small businesses, higher education institutions, government at multiple levels, libraries, and B2B, among others.</p>

<p>In July I started contracting with Principal Financial Group and have mostly helped out with projects at the intersection
of Drupal and web components:</p>

<ul>
  <li>Contributing code and documentation to the web-component-based design system</li>
  <li>Pitching in to the Drupal starter kit team’s codebase to work with components via Layout Builder, webform, and other Drupal elements</li>
  <li>Playing a big part building the first live small site to use the new system while running on Drupal 10</li>
</ul>

<p>This past week I deployed out Drupal 10 upgrades, single sign-on (SSO) updates, and other features for three different sites
for associated brands, all using a new deployment process with redundant success checks and integration with corporate controls.
What was most notable about these updates and the deployment was how <em>not</em> notable they were: the sites deployed without
any hiccups. Often no news is great news.</p>

<p>Every team at Principal is a joy to work with, and I’m looking forward to many more fruitful projects with them.</p>

<h2 id="blast-from-the-past">Blast from the past</h2>

<p>It took a bit more than 3 years, but I’m back doing support work for my previous employer, <a href="https://symmetrimarketing.com/">Symmetri Marketing Group</a>,
on a contractor basis this time. It’s great to catch up with a lot of familiar faces, and also a joy to see how many of
the projects I had contributed to from 2016-2020 have evolved.</p>

<h2 id="the-autumn-of-our-drupal-10-upgrades">The Autumn of our Drupal 10 upgrades</h2>

<p>Whether for Tactis, Principal, Symmetri, or another support client, this Fall has been very Drupal-10-upgrade heavy:</p>

<ul>
  <li>4 upgrades and one new site for Principal</li>
  <li>6 upgrades for Symmetri</li>
  <li>Help getting ready for PGC’s upgrade with Tactis</li>
  <li>1 upgrade for Human Element</li>
  <li>Discussions and prep with other clients</li>
</ul>

<p>As you may know, so1ve’s <a href="https://frostdrupal.com/">frost install profile</a> has been on Drupal 10 since March, and the experience
getting an install profile upgraded relatively early in the version’s lifecycle was great practice for rapidly upgrading
double-digit numbers of sites in the last couple of months.</p>

<p>All of the Drupal 10 upgrades have been smooth so far, with the custom parts all being along the same lines:</p>

<ul>
  <li>Learning what Composer error messages <em>mean</em> rather than what they say</li>
  <li>Swapping composer dependencies without official Drupal 10 releases for <em>Merge Requests</em> using custom ‘repositories’ via drupal.org GitLab</li>
  <li>Changing out a few <code class="language-plaintext highlighter-rouge">*.info.yml</code> syntax changes, especially in custom themes</li>
  <li>Including any required and removed core-to-contrib dependencies, like RDF, quickedit, bartik, classy, and stable</li>
  <li>Changing out deprecated and removed function-based calls for OOP calls using services. When possible, those updates inside classes can use Dependency Injection</li>
  <li>Getting nervous when a site uses Advanced CSS/JS Aggregation, as JSMin can cause a lot of problems for a Drupal 10 site</li>
</ul>

<p>Many of the sites also went to PHP 8.2 at the same time, and the biggest issue for that is <strong>dynamically-declared methods and properties</strong>.
There’s a strong correlation between codebases that use dynamic class elements and codebases that are a big mess to work
with and refactor, so I’d recommend estimating a bit extra padding on PHP 8.2 update projects where errors have been found.</p>

<h2 id="whats-next">What’s next?</h2>

<p>Since June I’ve been working more than full-time to contribute meaningfully to my short-term, full-time contracts, while
also supporting my existing client base after hours. I plan to continue doing the same, and may have openings for projects
and support in the new year.</p>

<p>If you’re in the market for a website or already have a Drupal 8/9/10 site and are looking for an inexpensive and flexible
developer to support your platform, don’t hesitate to <a href="mailto:brad@solveitonce.com">reach out via email to brad@solveitonce.com</a>.</p>
]]></content:encoded>
      </item>
    
      <item>
        <title>frost design handoff</title>
        <link>http://solveitonce.com/blog/frost-design-handoff/</link>
        <pubDate>Tue, 13 Jun 2023 00:00:00 EST</pubDate>
        
          
          <dc:creator>Brad Czerniak</dc:creator>
        
        
        
          <category><![CDATA[Drupal]]></category>
        
          <category><![CDATA[Design]]></category>
        
        <guid isPermaLink="true">http://solveitonce.com/blog/frost-design-handoff/</guid>
        <description><![CDATA[Steal this content! Everything on this site is under a CC0 license, so you
can copy/paste this handoff without guilt.

Hello designer friend (BTW, did you know
so1ve is looking for talented freelance designers?)!

There are some nuances to designing for frost specifically, and to some extent Drupal in
general, that tuning into can help you design in a way that makes the developers happy and keeps the project moving quickly.
Don’t worry, though — there’s still plenty of room for creativity.

Before we jump into the design stuff, you may be wondering, “Why are we using this frost thing rather than something else?”
That’s a good question, and effectively it comes down to this: frost is a huge head start for making websites that can
later be extended to manage huge amounts of content.

The frost system came from turning a bunch of designs by a bunch of designers into component-based websites, reusing what
worked from the previous site each time, until the system seemed to work for any design. The setup may not be precisely
what you’re used to, but it works really well and you might end up really happy with how easy it is to customize.

We’ll start off easy and breezy, just send along an SVG logo or two, but quickly this handoff article becomes a deep
dive of all the possible components you may encounter on your design journey. When you’re deep in the atomic component trees,
you are hereby empowered to remember that you can plant any darned forest you want. This frost system allows you to
click-and-drag your way to websites that other systems simply cannot match.

If you’re not accustomed to trying out a site early in the design process, a frost site is a great time to buck that trend.
All the principles in this guide can be explored directly from a frost demo site, if your developer is up to the task of
setting one up.

Table of contents


  First, where to reference
  Second, brand assets
  Third, base styles    
      Fonts
      Colors        
          Here’s white/black/greys:
          And the medium shades of the three brand colors:
          And the light shades:
          And the dark shades:
          Here’s the theme accent color:
        
      
      Delivery
      Everything else
    
  
  Fourth, component party!    
      Tags in the style guide
      Reusable components        
          Sectioning            
              Stripe: Atomic
              Layout                
                  Column
                
              
              Stripe collection
            
          
          Storytelling            
              Accordion
              Block
              Blockquote
              Cards                
                  Card
                  Card: Percent
                
              
              Content listing
              Heading
              iframe
              Link
              Media                
                  Hotspot
                
              
              Media listing
              Message
              Product listing
              Rich text
              Spacer
              Table
              Term listing
              User listing
              View
              Webform
            
          
        
      
    
  
  Fifth, wrapper
  Sixth, page mockups    
      Three heroes        
          Fallback default and ‘system’ pages
          Per-bundle pre-configured heroes
          Stripe: Atomic heroes
        
      
    
  
  Wrapping up


First, where to reference

Soon we’ll have a Figma starter for frost sites,
which hopefully will be a big boost. In the mean time, these links have useful info for referencing much of what we’re discussing
in this post:


  frost component guide — demos of most components, with some helpful descriptions
  frost style guide — the base styles applied to Drupal’s built-in user interface elements
  Example ‘system’ page — a ‘boring’ page, which is a great template target
  settings.css — one little file that holds all the base styles


Second, brand assets

Especially at the start, just two logo files — one for the header and an inverted one for the footer — is enough for testing
development versions of the new site. But there are plenty of other assets to cut and send to your friendly neighborhood
developer:


  
    Brand image asset details
    
      
        Image
        Format
        Dimensions
        Notes
      
    
    
      
        logo.svg
        SVG
        64x64, approx.
        
          If possible, provide the logo as a real SVG file (rather than a JPEG/PNG embedded in an SVG wrapper). The header
          layout will constrain the image&apos;s size, but scaling it to be nearly the size it should appear on the site can
          be a page load performance boost. 64-100 pixels for the height is a good target, with the width being more flexible
          (for instance it could be 240-ish pixels wide if the image contains both the mark and text).
        
      
      
        footer-logo.svg
        SVG
        64x64, approx.
        
          Even if the header and footer will eventually have the same color scheme and the same logo, it&apos;s fun to make the
          &quot;evil twin&quot; version of the logo. This inverted version is intended for rev. 1 of the footer, and could be repurposed
          down the road.
        
      
      
        favicon.ico
        ICO
        64x64
        
          This appears in the browser&apos;s tab. 64x64 is probably big enough. The file must have square dimensions. Most often
          you&apos;ll want the logo mark over transparency, but a solid background is also possible. Very simple brand expression
          is the name of the game here.
        
      
      
        apple-touch-icon.png
        PNG
        512x512
        
          Icon used when installing the site to your desktop or home screen. In order to avoid providing a ton of slightly-varied
          versions of the same asset, ship the big 512x512 version with just the logo mark, a solid color background, and
          at least a little padding all the way around the logo.
        
      
      
        bg_hero_default.jpg
        JPEG
        1920x1080
        
          On system and other pages where a custom hero isn&apos;t set up, this image can be used as a default hero background
          if desired. It should be either dark with a mask for white text, or light for dark text. If you&apos;d prefer a solid
          color or CSS gradient background for default heroes, just let the developer know. Making a default hero image
          might be a good design exercise anyway.
        
      
      
        social_default_1200x630.jpg
        JPEG
        1200x630
        
          Social sharing image for Facebook/LinkedIn/Twitter. The template for making the image
          is available as an XCF for GIMP,
          and online converters to PSD are easy to come by.
        
      
    
  


Along with the brand assets above, now might be a good time to source backgrounds for various stripes in the default content
(more on stripes later):


    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

When the developer installs frost, the section backgrounds are stock photographs of icebergs with semi-transparent white
masks. Unless you’re making a site about icebergs, the default section backgrounds should probably be changed. However,
this piece can be deferred until content and page design, later in this post.

Third, base styles

The base styles in the settings.css file
define reusable variables for both implementing a consistent design, as well as to help the front-end developers out with
repetitive tasks. Overall, you can get an idea of the contexts for how the base styles are used from this site’s moodboard.

Fonts

For the most part you just need to pick two fonts, with the notes below helping clarify the format and how they’re used:


  Primary font — body copy and other defaults
  Secondary font — headings h1 and h2 by default


First in the file are @font-face declarations, which is how we import web-compatible font files. For frost and pretty
much any modern site, we strongly prefer variable fonts for the smaller number of files and fine-tuning
ability — you can tweak the font weight to be fractions between semi-bold and bold, for instance, which is not something
you can do with classic fonts.

The baked-in design system is set up for two main typefaces: one for headings (mostly) and another for body copy and everything
else. If the site is going to show a lot of code or other monospaced text, a third web font would be added, though the monospace
stack uses &apos;courier new&apos;, courier, monospace which will work in a pinch.

(Note more for the developer but still useful…) If the brand is centered on a single font, you can remove the @font-face
declaration for the second font, but rather than deleting the --font-family--secondary custom property or any of its usages,
it’s probably a better long-term decision to just duplicate the primary stack to the secondary variable.

One last font concept: the default frost setup has a sans-serif for --font-family--primary and a websafe stack following
the custom font. Similarly, --font-family--secondary is a serif with a websafe serif stack. When in doubt, replace the
name of the custom font, but leave the websafe stack for fallbacks. If you know what you’re doing you could switch the
websafe stacks to better match the custom faces (swapping Times New Roman out for Georgia, for instance), but that can be
considered a micro-optimization.

Colors

The frost design system leans heavily on the color scheme setup, so please try to stick to what we have here, at least
at first, as that’s one of the biggest ways to keep the front-end development scope in check.

Up front, we have white, ‘black’, and three shades of grey, plus three shades of each brand color (medium, light, and dark).
As a bonus there’s a fourth medium-lightness accent color available:

Here’s white/black/greys:

We can add more greys if needed to style components, for instance, but these would be the greyscale options available when
choosing background and text colors in the content-editing interface.


  
    
      #222
    
  
  
    
      #555
    
  
  
    
      #aaa
    
  
  
    
      #f7f7f7
    
  
  
    
      #fff
    
  


One notable thing is that our black is #222 rather than #000. This comes from Iam Storm Taylor’s advice,
and we recommend going further and putting some brand colors in your ‘black’ hex code!

And the medium shades of the three brand colors:

The medium shades should have a lightness around 50% (40-60% is a good range). The ‘main’ color should be the most blue
of the brand colors, even if it’s not the brand’s main color in the branding sense. This choice comes down to making links
look as blue and underlined by default as possible.


  
    
      #007599
    
  
  
    
      #E32416
    
  
  
    
      #00838a
    
  


And the light shades:

For WCAG contrast compliance specifically, the light shades should be perhaps 90% lightness or higher. Often this requires
bringing more white into the mix, effectively pastel-ing the colors in the process. The light shades need not be pastel,
but it seems those shades end up being the most versatile for contrast.


  
    
      #ccf4ff
    
  
  
    
      #ffcfcc
    
  
  
    
      #ccfcff
    
  


And the dark shades:

The dark shades could be a bit lighter than 10% lightness, but like the lightness choice for the light shades, the darker
the dark shades the more contrast-compliant combinations will be available to use.


  
    
      #002733
    
  
  
    
      #331716
    
  
  
    
      #003033
    
  


Any one of the dark shades might be a good candidate for the faux-black, too.

Here’s the theme accent color:

By default the accent color is used for visited link coloration and a couple other one-off component elements. If your brand
scheme contains a not-super-important purple, this is a good place for it. Otherwise, whichever brand color is least important
of the top four is good as an accent.


  
    
      #6100a7
    
  


Delivery

In the developers’ ideal world, you’d deliver the colors just like how they appear in settings.css:

:root {
  /* Main theme colors. */
  --color--black: #222;
  --color--grey-dark: #555;
  --color--grey: #aaa;
  --color--grey-light: #f7f7f7;
  --color--white: #fff;
  --color--main: #007DA3; /* This should be a 6-char hex with uppercase letters. */
  --color--main-dark: #002733;
  --color--main-light: #ccf4ff;
  --color--second: #e32416;
  --color--second-dark: #331716;
  --color--second-light: #ffcfcc;
  --color--third: #007e85;
  --color--third-dark: #003033;
  --color--third-light: #ccfcff;
  --color--accent: #6100a7;
}


The exact format isn’t super important, though. Just so long as there’s three brand colors with three shades apiece.
Most developers can translate between RGB, HSL, hex codes, or other color formats, so as long as you’re not giving Pantone
names or something you’re probably in good shape.

You can see in the code sample above that the --color--main should be a 6-character hex code with uppercase letters. This
quirk is to facilitate an automatic color scheme for the interactive charts and graphs (see the table section of the storytelling
components). If you’d prefer to hard-code the color scheme for charts and graphs instead, provide your developer with
a list of at least 10 hex codes that comply with the Highcharts color settings,
like:

[
  &quot;#2caffe&quot;,
  &quot;#544fc5&quot;,
  &quot;#00e272&quot;,
  &quot;#fe6a35&quot;,
  &quot;#6b8abc&quot;,
  &quot;#d568fb&quot;,
  &quot;#2ee0ca&quot;,
  &quot;#fa4b42&quot;,
  &quot;#feb56a&quot;,
  &quot;#91e8e12&quot;
]


This is purely optional, as the auto-generated colors are usually pretty good, and those colors only matter if the site
plans to use the charts and graphs prominently.

Everything else

The remaining default styles can be the difference between a ‘flat’ aesthetic and something with a lot of depth and playfulness.
Various pieces of the theme, by default, use the borders, shadows, and transitions, so tweaking these to match the brand
feel early on can make the site feel entirely different from the starting defaults:


  --border--default— default is 1px solid but you could pick thicker and/or switch to dotted or dashed for a custom feel
  --border-radius--default — 2px is default, which is a subtle rounding. 0 is square, 1em is quite round, and 25% is circular
  --box-shadow--default — default is 0 0 3px rgba(0, 0, 0, .5), which is a tiny, spread black shadow straight down
  --layout--content-area — default is 1280px, which you should only change if you have a good reason (narrowing it to as little as 900px is more workable than widening)
  --line-height--default — default is 1.425. This should be a unitless number between 1.2 and 2.5 for legible body copy
  --line-height--heading: it’s 1 by default, but something from 0.9 to 1.4 might work for your headings
  --spacing--single — set to 0.625rem and should probably remain that way, as it makes a single spacer 10px tall
  --text-shadow--default — default is 0 0 2px rgba(0, 0, 0, .5), which is even subtler than the box shadow. Text shadow is used sparingly by default
  --transition--default — default is all .3s ease-in. For performance you may want to pick just background-color rather than ‘all’, and maybe a different easing function if you have a sensitive eye. 0.3s is a good balance of perception without delay


As you can see for some of the notes, the default value is dialed into “best practices”, so in many cases the values would
only change by a small amount. If you’re working over a developer’s shoulder on a scrum team, these are things you two could
dial in after the bigger decisions are settled.

Fourth, component party!

Now we’re cooking with gas.

frost is all about Atomic Design, so be prepared to think through the
smallest-level ‘atoms’ first, and then put those atoms together to create the full experience. The more we stick to that
concept, the better both our code and the design system will be!

Tags in the style guide

If you look at the frost style guide you’ll see there’s a lot of
HTML tag type stuff that isn’t likely to need changing:


  Users are most comfortable with hyperlinks that are blue, underlined, or both. There’s room for creativity, but that’s the best starting point
  Bold text should be bold. Changing the &amp;lt;strong&amp;gt; styling to italicized or underline or another style could have unintended consequences
  Similarly, changing the &amp;lt;em&amp;gt; styling from italicized to something else could be accidentally bad


On the other hand, there’s a lot of room for creativity when it comes to:


  Horizontal rules, which could look however you’d like as long as they divide two blocks of text
  Forms and all the form controls
  Blockquotes
  Buttons and CTA button links
  Lists, mostly their indents/hangs and markers
  Tables, though keeping them simple might save trouble
  Default headings for levels h1-h6
  Pagers
  Progress bars
  Breadcrumbs


There’s some overlap between the tag-level and Drupal core components in this section and the reusable components below.
For the most part, defining how a tag-level style looks first can be helpful from a technical perspective, since any
component that uses a default tag but doesn’t look like a default tag has to override it. Not setting correct defaults
early can result in duplicated override code, so let’s get the atoms figured out first.

Reusable components

The components in the frost content-authoring toolkit come in a few different flavors, so we’ll subdivide them here and
go into way more detail than you asked for. That way you’ll have something to reference for the why of various design
decisions.

Sectioning

The sectioning components hold the storytelling components below, with Stripes (there’s one stripe type, ‘atomic’, included
by default in frost, but others can be added) being big containers with lots of options, layouts putting one or more columns
side-by-side, and stripe collections used to make tabs or even the dreaded slideshows.

Stripe: Atomic

The cornerstone of the design system; an infinitely-flexible section container.

When you’re on the edit screen, in the content tab, you enter the components that should live inside the stripe container:


    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

Then, in the settings tab, you can style the stripe to have a personality, while still meshing with the site’s brand:


    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

As you can see, a stripe has lots of available settings, with some self-explanatory and others that could use a little
clarification:


  Background color — Theme colors you can set. If you use a background image, please set a color that similar to the
darkness of the image being used. Also make sure the text color contrasts with the set background color
  Background image — Reusable images that appear as the background
  Background image alignment (horizontal) — A focal point horizontally. Most useful for ensuring you show the area
of interest when the screen narrows
  Background image alignment (vertical) — Focal point vertically in image. Usually good centered, but should be set
to ‘top’ when the background image contains people in a medium shot so you don’t cut off the top of their head(s)
  Background repeat — If you use a tiny image, you can tile it as a pattern. Be sure to change the background size if tiling
  Background repeat — Jk. Repeat, get it?
  Background attachment — Whether the background should stick to the page or act like it’s behind the page like parallax scrolling
  Background sizing — Usually fill the whole area. Can also do tricky things
  Background Video — Reusable video file that lives on top of the background color and image, but underneath the stripe’s content
  Full width — Eliminate the maximum content area width, and have the stripe go all the way to the screen edges on big screens
  Hide background image on mobile — If the background image is ‘busy’, hide it on narrow screens, falling back to the solid background color
  Tab title — If this stripe is used in a stripe collection, type what the tab should say here
  Text alignment — Left, right, center, justify. Please never use justify. Since layout columns have text aligned
left by default, aligning stripes center by default gives the most effective use of space when all the components are
used in combination
  Text color — Light or dark. Please match it to the background color you choose (the one that matches the darkness of any background images used)
  Unpad — Remove the top and bottom padding from the stripe so it’s short and has less breathing room


A stripe, by default, has 20px horizontal padding to give your thumb a place to scroll up and down without accidentally
tapping links and stuff. It also has 100px vertical padding (for desktop, it’s 60px for mobile) for pleasant and up-market
whitespace breathing room. The padding can be removed on a per-stripe basis using the Unpad checkbox described above
when you want to dial in less than the default amount of vertical padding. If you’d prefer a different amount of padding
on stripes by default, proportional to other spacing throughout the site, the developer could tweak the following line in
utility--layout.css:

.layout--stripe {
  padding: calc(10 * var(--spacing--single)) calc(2 * var(--spacing--single));
}


As noted in the list of settings above, you can also override the --layout--content-area width for a particular stripe,
in the event you want to show some really wide foreground content on big screens.

Layout

Layouts in frost are a little bit different/better than other site-building systems, in the following ways:


  Each layout component is a single row of columns. Below “portrait tablet” size, the columns stack vertically for responsiveness
  You don’t choose a two-column or three-column or whatever layout, you just pick layout and then add the columns you want.
If you want your two-column layout to be a three-column later, you don’t have to rebuild it, just add the next column
  (More of a developer note) Rather than Layout Builder in Drupal, layouts in frost are themselves components, so you
can place layouts anywhere you can place other components, and put layouts in layouts in layouts if your designs need it
  Rather than a grid system, the columns are proportional to each other. One medium and two small columns gets you to a 50%-25%-25% row
  Empty columns can be used without issue, and will automatically disappear on narrow screens when the columns stack
  If you have a series of layouts that had an image in one column and text in the other, and you wanted them to alternate
visually on desktop but be in the same order when stacked on mobile, the ‘Reverse’ checkbox makes that super easy
  Each column has a bunch of dials and switches for spacing, which we’ll get into next





    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

Column

Columns have a lot of options that let you dial in their desired appearance and do some tricky things:


  Animate — Unchecked by default, but check it to use the chosen animation below
  Animation type — Any of the reveal animations from animate.css
  Background color — Usually transparent, but can be a solid color where wanted
  Border color — Can be set to any of the theme colors
  Border radius — Whether the corners should be square, slightly rounded, or fully rounded. Can be used even without a border
  Border width — Anywhere from the “No border” default to 4px solid (or other values with developer help)
  Box shadow — Applies the site default drop shadow as set in the “Base settings” section way up this page
  Margin (horizontal) — Space between this column and its neighbors
  Margin (horizontal) collapse — When you want space on desktop by not on mobile
  Padding (horizontal) — Interior space for columns containing text (usually). Important note: in frost, horizontal
space is usually configurable, while vertical space is set with a combination of “Vertical alignment” and spacer components.
This makes more and more sense the more you use this philosophy
  Padding (horizontal) collapse — This is the “why doesn’t this block of text line up vertically on mobile?” checkbox
  Text alignment — Left, right, center, or justify. Each column can have its own settings, for tricky layouts
  Text color — Like stripes, the options here are light or dark, for contrast with the background color. Don’t worry:
if you want a heading or some rich text to be a brand color, we’ll show that option in the storytelling section
  Vertical alignment — Defaults to ‘center’, though ‘top’ is another common one. Oftentimes you want a text column
to be aligned to the top of the row, but the image to its side vertically centered. There are less-used options in the
dropdown to align the column’s contents to the bottom or to have them spaced out in the column’s vertical area
  Width — Proportional sizes, so you can make any fraction/percent layout you need (within reason). Every column starts
life as a ‘small (1)’ but can be promoted to bigger sizes as needed


Stripe collection

Reuses the stripe concept to allow content creators to make tabs (and slideshows with a small amount of development work.
We couldn’t include slideshows in the frost system in good conscience, as we’re still wondering
should we use a carousel? ).

The tab controls can certainly be re-styled to match your brand’s aesthetic, noting that the tabs in the Stripe collection
component share HTML classes with system tabs, so for consistency it’s best if all tabs on the site look the same.

For content entry especially, there are two big notes to keep in mind for using a Stripe collection to do tabs:


  If you’re making a lot of tabs on the site, it’s worthwhile to get comfortable promoting components to the Paragraphs library
  Each tab needs a tab title set in the ‘Settings’ for the individual stripe


Overall, things like on-page tabs and slideshows are interesting UI elements, but should likely be used sparingly and with
a clear purpose in mind.

Storytelling

The storytelling components are more at the atom/molecule level for the most part, compared to the sectioning components
which could be considered more organism-ish. Demos and detail are available at the frost component guide
so the notes here focus primarily on design needs.

Accordion

Accordions are ‘expandos’ for initially showing a title that explains what the expanded content box contains. A user can
toggle the accordion open/closed via click/tap or keyboard/other controls from assistive technologies.


    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

Many design systems mandate accordions be placed in groups, and often use JavaScript to ensure only one accordion is open
at a time. frost eschews this, in favor of letting the user toggle whichever elements they want. It’s the most versatile
and simple approach.

Design notes:


  Accordion titles in frost, by default, are plain text, with no icon or other indicator. Icons or rich text would require
extra development
  The body of regular accordions is a rich text WYSIWYG. An accordion using components as the body would be extra development.
Not to speak out of turn, but any project that requires really involved disclosure elements may be abusing those elements’
typical purpose
  The frost component system has accordions as well as the aforementioned “Stripe collection” tabs, with both filling
the role of a disclosure element: showing a little bit of information that a user can then choose to toggle open for
more information. Unless there’s a compelling unanticipated reason to add more or replace the existing components, project
designs should probably stick to just two disclosure element types
  Content editors can set any given accordion to be expanded by default from the settings tab. Note that browsers may
also expand the accordions if, for example, a search engine links the user and the result text is inside the accordion
  There’s something of a debate about whether the control+indicator for openness/closedness should be on the left or right.
In frost we went with the right, making the choice largely to facilitate scanning the titles easily. Since the entire
title section can be clicked to toggle the state (and the cursor lets desktop users know this), a user need not move
their mouse a lot to click the control, unless they really want to
  Similarly, there’s room for refinement when it comes to the indicator. HTML &amp;lt;details&amp;gt; elements are typically styled
in the browser by default with a “disclosure triangle” icon, with many design systems preferring a chevron. In frost
we’ve gone with a plus when closed and a minus when open, as these symbols represent more/less and are less ambiguous
about state than the direction a chevron or triangle is pointing


All that said, you have the freedom to design the accordions to look (and work, insofar as scope and developer talent allows)
however you’d like, especially as it meshes with the project’s brand.

Block

System, custom, and dynamic blocks. For the most part these blocks being placed will each be styled according to their varied
contents (see the frost component guide for the
likely culprits).

At least two of the coolest custom blocks that can be placed contain social icons, so determining what the social icons
(which use Simple Icons under the hood) should look like in general could be a boost for the
blocks, as well as the same block(s) possibly being used in the footer:


  The icon itself can have the fills/strokes styled to white or any other solid color. It’s potentially possible to do
a gradient or other effect, too
  It’s possible for the fill/stroke of a particular icon to be that brand’s preferred color, though setting up the styles
for lots of icons of varying colors could become a large part of the front-end scope
  Each icon is wrapped in an &amp;lt;a&amp;gt; tag to link it to the respective social site, and that tag can be styled to contrast
the chosen fill/stroke of the icon proper. By default the wrapping link has a black background and appears as a circle
due to equal height+width and fully-rounded corners. It should be trivial to change the background color, active/hover/focus
state styles, padding, and other styling, to switch to more-square containers, etc.
  The path of least resistance is to keep the icons themselves white, and pick a solid background color that works for
all icons to be used
  While it’s possible to switch icon libraries to something like fontawesome, that could present scope issues if your
project has lots of front-end customizations. So, if the simple-icons GMail icon, for instance, looks too much like
the Medium.com ‘M’ and not enough like an email envelope, please consider swapping it out for the simple-icons
“Invoice Ninja” or “Microsoft Outlook” icons before mandating a substantial swap or addition of icon library. This
email icon issue is odd, because all the other icons are for brands, while email is more of a concept(?), not to mention
that the mailto: icon is likely to be under-used, so it might be easiest to just remove it entirely if you plan to use
social blocks. A more generalized icon library with a few brands mixed in, like fontawesome, would give you multiple
good options to represent email, but may not have representations of every desired brand, so it’s a trade-off for sure


Blockquote

Rich text as a pull-quote:


    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

The blockquote component’s Settings have toggles, each enabled by default, to insert stylized double-quotation marks before
and after the contents of the rich text, respectively. These settings can instead be hidden or removed if you prefer a different
style for pull quotes.

Design notes:


  The quote, owing to being a rich text WYSIWYG, can contain all kinds of bold, italic, heading, code, and other markup.
In practice blockquote are used for quotes, though, so it may be most pragmatic to ignore lots of formatting
  The double-quote affectations can be set from either of the fonts chosen in the “Base styles” section. If neither of
those typefaces has quotes to your liking, a websafe font like Georgia might be a good pick. Otherwise, it will be a
tiny bit extra front-end development to use images instead. One reason to stick with fonts is that it’s easier and more
reliable to re-size them responsively, and of course it requires loading fewer front-end images/assets so there’s the
performance angle to consider, too
  If you decide to go another direction for blockquotes, like the common thick-left-border plus background style, collaborate
with your developer about whether the border and/or the background should be configurable by content authors
  Overall, blockquotes tend to have a font-size a bit bigger than regular body text, and frequently use italicized text
as well. That’s the common pattern, but is not a requirement per se


Cards

A side-by-side layout of cards that don’t represent other site content.

The “don’t represent other site content” part is important here, as there are ‘listing’ components described below for representing
content, media, products, tags/terms, or users, as well as the Views component for showing listings of those types of content
and more. That’s not to say that a card can’t be used to tease and link to an article on the site, as an example, but
if content authors are doing that frequently then they should probably discuss a better way to solve a particular content
problem with the dev team.

The ‘Cards’ (plural with an ‘s’) component holds one or more Card (or Card: Percent) components. The Cards container has
one setting, letting you choose if the cards it holds should be stacked vertical, shown side-by-side, or in a carousel.

For the most part, there’s not much to style at the Cards container level, unless the native horizontal scroll-snap-based
carousel should instead use a JavaScript library, which of course would be some additional amount of front-end development.

Card

An individual card has four fields:


  Image (optional, reusable)
  Title
  Text
  Link (URL and link text are both configurable)


Cards typically have a set-it-and-forget-it style site-wide, often inheriting things like the default amount of corner-rounding
and box-shadow from the base styles. Like all components, though, individual cards can have individual settings, so 99%
of cards could have a transparent/white background, but one card could be set to have a pink background. It depends on
your site’s needs, but the absence of these settings by default is intended to promote consistency across cards.

Card: Percent

This additional card type is used to highlight a top-line number, with optional animation. When a number is important for
telling your story, either this type of card or a table with chart/graph is a good way to convey the info.


    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

Card: Percent has three content fields by default:


  Number for the number itself. It can be integer or decimal, and the animation script will deal with it just fine
  Explanatory text as the body of the card
  Link as an optional way to send people toward details for a statistic, for instance


Additionally, there are two available settings for a percent card:


  Prefix so you could put a $ in front of the number and the animation will still work
  Suffix for a % or something like that, also not affected by the animation


Some design and functionality notes:


  At install-time the animation is set to always occur. It should be mostly trivial to add a toggle allowing a content
author to turn animation on and off per card
  The animation counts up from zero in increments that should cause the animation to complete in about 2.5 seconds. If
you intend to show how small a number is (A “We’ve reduced this metric from big to small” story), that will be another
thing to talk to your developer about. The alternative would be to turn the small into a large by saying “We’ve reduced
this metric by a staggering 144%” instead
  All five configurable fields can be styled separately, and technically the Card: Percent can be styled to appear different
from other card types. This most comes into play if you want the number itself to be big and bold, but the prefix/suffix
to be smaller and lower-contrast


Content listing

A content listing, like other components below that end in the word ‘listing’ (and to some extent like Cards), lets
you choose one or more pieces of content, put them in any order you deem appropriate, and display them as:


  Teasers, where the image, byline, title, teaser text, and “Read more” link appear card-like
  Small, which is configurable of course, but is usually just the title in a bordered box


The teaser/small representations of content on the site (articles, events, pages) can be displayed the same ways as cards
and other listings:


  Stacked vertical column
  Side-by-side (out of the box it’s 3 wide then wraps, but could be set to 2, 4, etc.)
  Carousel



    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

Each content type could have a different appearance if desired, but let’s just talk through some overall notes:


  The entire teaser is clickable/tappable to go to that content’s page, and desktop users get a pointer cursor and a hover
style to go with it. Out of the box it’s a slight background darkening, but you may want the teaser image to zoom a
little bit or something else more pronounced
  There’s likely a benefit in your site’s design system, like the concept of a ‘card’, to make all ‘teaser’ (and ‘small’
if used) representations share design cues/metaphors. While an article and a user are two different things, both can
have an image, a prominent label, some intro text, and a CTA link, so containing those elements and giving them some
aesthetic consistency could serve to make users familiar with what teasers do on the site (ie. link to the full page)
  Listing components differ from cards in that each individual teaser cannot be readily set to, for instance, have its
own signature background color or other atomic styling choice. This is certainly possible if you need to do it, but
it may be a bit clunky for authors
  Like the Cards container, there’s not much to design for the Content listing component itself, outside of introducing
a JavaScript library for the carousels. The big design lift is deciding what the ‘teaser’ metaphor should look like
  You can see in the screenshot above that the “teaser text” can be styled to be bigger or smaller, depending on how long
the text is. This isn’t required, but may keep things in-check and pleasant. There is a risk of the teaser text becoming
inaccessibly small, though, and you’re most likely to hear about this issue from your SEO specialist, who will get notified
of the issue through Google Search Console


Heading

The heading component gives a plain text box for the contents of &amp;lt;h1&amp;gt;-&amp;lt;h6&amp;gt; (plus a “Regular text” option for when
you need some text to look like a heading without messing with the document outline), with plenty of styling options:


  Appear as heading level so you can create a good document outline but also visually communicate however you want
  Font weight, hopefully used sparingly, so in a pinch you can have an &amp;lt;h2&amp;gt; that differs from others and catches
the eye
  Icon for design systems where headings are sometimes/always also represented with a visual
  Text color so you can use the brand colors in stripes with different backgrounds, display more variety in text, etc.
  Text transform to avoid the icky situation where authors are forced to enter their text in 
all-caps just to match a design. If you enter the text in natural case and then use the text-transform option,
you have easier options if a user complains that the site is yelling at them. Not so much if you enter the content with
a weird casing strategy


As insinuated above, the key role headings play for users of all abilities plus search engines is to create a hierarchical
“document outline”. It’s not uncommon for designers, though, to create a style guide or moodboard with 4-6 heading levels,
and then in practice use them where they look best visually rather than where they’re appropriate in the hierarchy. The
frost heading component lets you use the appropriate heading level and the set the heading to look like a different level,
but… that should be avoided if possible.

Here are some guidelines for how headings are used in frost (and lots of other Drupal/other sites), which will hopefully
be useful for creating the headings’ type scale:


  Ignoring the alternate history we could have had based on earlier drafts of HTML5 where you’d have been able to contain
various heading groups on a single page, in this timeline it’s standard practice for a page to only have one h1
tag, and for that tag to be the page title
  I’ll repeat this later in the guide, too: a quick and easy way to tell if a page design (aside from the home page, which
is allowed to not appear the same as ‘interior’ pages) is a good citizen of the internet is if the pretty URL path,
the title in the browser tab, the label for the page in the main nav (if present), and the visible on-page h1 title
all match. There can be a little deviation, but matching all of those things makes navigating the site and knowing where
you are a lot easier
  Similar to the point above, with little deviation, all h1 page titles should be consistent in size, location, and overall
appearance from page to page. Spoiler alert for the page design section later in this post: I strongly recommend every
page design have as consistent of a hero as possible, with only “Landing Pages” introducing more visual interest in the
hero in the form of background images and such
  Every stripe/section’s first text should be an &amp;lt;h2&amp;gt; tag in the markup order, even if that h2 is in a layout column
  Teaser titles in listing components should be &amp;lt;h3&amp;gt;, given the usages of h1 and h2 described above
  Regular &amp;lt;h3&amp;gt; can then be used in conjunction with teaser titles. One example of when this would be common is if you
have a stripe with an &amp;lt;h2&amp;gt; followed by a two-column layout. Each column might have an &amp;lt;h3&amp;gt; describing the contents
of the column in the context of the document outline. Heading levels h4-h6 end up being less commonly used, but are
still important to style appropriately


iframe

Frankly, &amp;lt;iframe&amp;gt;s kind of suck. A content author can place them, and are presented with the usual details to fill out:


  The URL of the page to show in the iframe
  A title describing the page in the frame, which is especially useful for folks using assistive technologies
  Height and width to show the iframe, noting that the iframe will end up being responsive, so the height and width are
the maximum on desktop


Design notes:


  For some third-party services there’s a benefit to using an iframe-resizer JavaScript library to calculate the height.
This is something to discuss with your friendly neighborhood developer. The bones for making that work are already in
place for frost, but may take a little bit of time to get dialed in
  Depending on what you’re going for, you may want all iframes to have a medium-grey border so you know the confines of
the frame, or you may want to pretend like the frame blends into the page. It should be pretty easy to add a checkbox
to the component settings if you need this configurable per iframe
  Everyone is likely to be happier if you don’t count on iframes for anything important


Link

There are lots of links aside from the link component: cards, teasers, media, and any part of the site that uses a WYSIWYG
can all have links. With WYSIWYGs the link is in its natural habitat: some highlighted text in the middle of a paragraph
that links out to somewhere else.

The link component can show a standalone text link in the same style as a link within a paragraph of text, though that
particular function may be of limited usefulness. Where the link component shines is in its ability to let you easily place
call-to-action (CTA) buttons.

The link component has a field for entering one or more links, plus two settings:


  Button background color to set which brand color the button should be
  Show links as buttons which toggles between text link and button-styled link


Design notes:


  The link buttons inherit the default button styles for the site, so having a consistent aesthetic is a plus here. Some
of the key aesthetic differentiators for buttons between design systems: proportion of horizontal to vertical padding,
border roundedness, font family+size+weight, and presence of borders, shadows, gradients, and other affectations
  While it’s entirely possible to make the hover/active/focus states of different-colored buttons distinct from one another,
and even to make the secondary states configurable with a dropdown, the lowest-scope, most consistent, highest performance,
and most maintainable design choice is to have all buttons transition to the same hover/active/focus state, regardless
of their starting background color
  Lots of sites using frost (or its forebears) have had designs containing “ghost buttons”, where the background is transparent
and the color is instead applied to the button text and the border surrounding it. Various UX professionals have told
me this is something of a design anti-pattern, so while it’s something I end up adding in somewhat frequently, it’s
not something I want to include by default because it appears to encourage ghost button usage


Media

The media component is a wrapper for showing Drupal core media: audio, document, image, video, and remote video (such as
YouTube).

Design notes:


  One mistake site architects sometimes make is over-loading the media items themselves. An image media entity should
only hold the image itself, plus metadata about the image like its file format, size, alt text, and perhaps some attribution.
The media component can then hold fields that apply to any media, and which could vary between usages, like the caption
  The media component renders the media in an HTML &amp;lt;figure&amp;gt;
element, which has an optional caption. I’ve found in practice that it’s easy and reliable to just set the caption to
be slightly-smaller-than-body text, but there’s design freedom to make the caption appearance a bit more elaborate
  Any media can be linked, though that typically does not change the media’s appearance
  The media component is most used for images. Any image on the site (not just this component) is resized and saved into
the next-generation WEBP format automatically, so creating extra-large ‘retina’ assets doesn’t usually make a difference.
Images that should have a lot of fidelity on retina screens should likely be created as vector graphics (SVG), with
photographs and other bitmapped images benefiting less from the added pixel density
  The last feature available to media at install-time is hotspots, which we’ll cover separately in the next section


Hotspot

Hotspots are a fun addition to the media component that let you place responsive dots that show a tooltip when hovered or
clicked.


    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

Design notes:


  The indicators for hotspots should be small, so as not to obscure too much of the media they’re on top of
  The indicators have a plus that rotates to resemble an ‘x’ when the tooltip is open. This need not be the way the designs
remain, but is a decent starting point
  There may be a benefit to setting the hotspot indicators in a loud color. A more subdued tone may make these interactive
elements blend into the media they’re covering
  The tooltips can be styled as well. This is a place where big changes could lose a developer an afternoon, but swapping
the background color or something could make it a nicer branded experience
  The hotspots, in order to be flexible and responsive, get placed a percentage width and height from the upper left-hand
corner of the media. Usually your first guess is pretty good, but in practice you end up having to tweak the numbers


Media listing

The Media listing works like a lot of the other listing components, but this time with images and stuff. The default behavior
is to show a square-cropped thumbnail of the selected media in a side-by-side grid. Clicking on a media item opens it in
a lightbox on the page.

Design notes:


  Square cropping images works great for photos with centered focal points, but could be less great for things like a
grid of logos. You may want to get the developer to switch the “Image Style” used for the media’s display mode to instead
use an image style that only scales the source image, rather than square cropping. The result would be a little less…
tidy, but would maintain fidelity of the source image
  This component can be extended pretty easily if you want galleries, slideshows, and other ways of showing a bunch of
media. Of course, any enhancement like that would be a scope increase, but cool media display modes is the kind of stuff
front-end developers wake up for


Message

The message component shares styles with the Drupal system on-screen messages/alerts. For some use cases it might make sense
to style the two things separately, but overall folks seem happiest when both have the same styles.


    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

The component has a WYSIWYG for the contents of the message, plus one setting:


  Severity, which lets you assign the message as a status, warning, or error


There are a few nuances to both the system messages and message component:


  Out of the box it’s a light color background with a darker shade for the text and border. All the corners are square
rather than rounded: so rounding the corners is an easy way to punch them up
  Message components as dismissible, and stay dismissed if a user closes them, so anything that should persist on the
page should probably not be in a message component
  Since the defaults here use color text, any links in the message body as set to inherit the current color. This isn’t
a strict requirement, but makes styling between instances of frost a touch easier
  Since the message body is a rich text WYSIWYG, designs of the component might benefit from exploring what is does,
and should look like when somebody puts way too much information with way too much formatting inside of one of those
things


Product listing

A Product listing works just like a Content/Term/User listing, but shows products from the site’s pre-installed ‘Commerce’
section. If your site doesn’t use frost’s e-commerce functionality, you can safely ignore this component.

If you are using frost for e-commerce, the notes about Teasers in the Content listing section above apply to product
teasers as well. Product teasers can be set up to show the price and “Buy now” CTA button instead of the article teaser
info like byline, since who authored a product page and when is a lot less important than how much the product costs.

Like the other listing components, a Product listing can be shown stacked, side-by-side, or as a simple carousel. If you
intend to have a few product carousels on the site, this is a place where you’ll want to specify a JavaScript carousel library.

Rich text

Finally, an easy one! The Rich text component gives you a WYSIWYG CKEditor for easily writing some everyday HTML.


    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

The WYSIWYG has a decent number of bells and whistles to accomplish your usual formatting needs, but out of the box tries
to limit the number of formatting buttons somewhat. This is meant to encourage authors to use the components instead, when
the components have an advantage over a WYSIWYG. This is true for things like headings and media.

The Rich text component has some settings that can apply to all the text entered in the WYSIWYG:


  Font size, in the event you want some text on the page larger or smaller than the body text default
  Font weight, for making especially-thin or especially-bold text sections, though this depends on using a variable
font as recommended earlier in the post
  Text color, which is the full list of brand colors. Stripes and layout columns let you pick dark or white text but
not the full brand palette. If you really need green text somewhere on a page, this is the dropdown for you
  Text columns, for setting some text in 2,3, or 4 columns on desktop. Text on the web isn’t especially friendly when
set in newspaper-like columns, so this is an option to be used rarely to make a little section of text pop while taking
up less vertical space, rather than a technique to be used everywhere on the site
  Text transform, which works just like the same option on headings. If you anticipate having a block of all-caps
text, this dropdown is a good way to accomplish that without typing everything in all-caps


Here are a couple extra notes for handling the overlap between things the WYSIWYG can do, compared to things the component
system can:


  Drupal has this concept called “Text formats &amp;amp; editors” that lets you set up multiple WYSIWYGs with different buttons.
In frost we have the default “Filtered HTML” editor with a limited number of buttons. The “Full HTML” format has an
editor with all the buttons, including the irresponsible ones
  If you make a layout and put rich text in one column and an image (Media) in another, the columns always end up separate.
Sometimes you want text to wrap around an image using old-school floats instead. This can be done by inserting an image
into a WYSIWYG. If the overall design is going to have a lot of wrapped images like this, that’s something to flag early
so the developer can prepare
  I’ve found that, if a developer is a big advocate for WYSIWYG editors and wants to put all the content editing features
in CKEditor rather than breaking out components another way, authors and users are probably going to have a bad time.
When in doubt, component it out


Spacer

Spacers are versatile ways of introducing vertical whitespace between other components in a configurable and responsive way.

Design notes:


  As discussed in the earlier ‘Layout’ section, frost leans on horizontal spacing being set by columns and other component
settings. This opens up spacers to be used specifically for extra vertical spacing
  Spacers can be set to 1x, 2x, 4x, 8x, 16x, and 32x, with the three biggest sizes being responsive: on small screens
they’re half their desktop height. In practice, we’ve found that small spacers should stay the same size on mobile, but
larger vertical spacers should be shorter on mobile. Unless there’s a good reason to change this up, I’d recommend giving
this setup a shot before changing it
  Spacers can be stacked without issue in most places, so if you need a 30px vertical space you can place a 1x and a 2x
as a stack. If there’s a good reason for spacing on the site to use lots of 30px (or other somewhat-arbitrary size),
it might make sense early on to tweak --spacing--single or augment other CSS values so stacks aren’t necessary
  The driving force behind having spacer components stems from something that happened in QA all the time before we had
them in our toolbox: most of the designers’ notes about how the implementation differed from the original mocks tended
to be small differences in vertical spacing. With spacer components we can tweak vertical spacing without writing a
bunch more CSS of increasing specificity during the QA phase
  Another advantage here is that we can increase the space between components at any time, just to ensure the breathing
room between, for instance, a paragraph of text and a CTA button, feels rhythmic and comfortable, even if it differs
from the original design


Table

Before clicking into the settings tab of the Table component and seeing the weird junk tables can do out of the box, there
are a few main things to touch on when it comes to tables:


  It’s been around 15 years since it’s been in any way acceptable to use HTML &amp;lt;table&amp;gt;s for page layout, so hopefully
it’s not surprising that the table component here is set up specifically for storing and displaying table data only
  In order to comply with accessibility requirements and be a good internet citizen, any table design must have a brief,
descriptive caption above the table, then a header row where the prominently-styled cells describe what’s in their column
  The tablefield module, which frost uses for this component, has extension modules that allow for things like HTML markup
in cells and setting up colspan and rowspan (HTML’s way of merging cells). These modules are turned off, though, because
those feature could be seen as encouraging the kind of table-misuse behaviors I was just talking about. If you have
a legitimate edge case for using those features, you developer can enable them


The component has a streamlined way of entering table data, plus the table caption and other info. If you have a lot of
data, the “Import from CSV” feature will come in handy.

As far as settings go, the table itself isn’t set up to be modified at all. However, the interactive charts and graphs
have some options:


  The chart can have a Chart title that’s distinct from the table caption, to describe what the chart shows
  You can choose between a few chart types, though you only can show one chart per table: vertical bar, horizontal
bar, pie, line, and stacked
  There’s a checkbox to Replace table with graph, which visually hides the source data table in favor of the chart
  Since the x-axis label is most often the text in the top left cell of the table, there’s a Y Axis label field for
describing the scale of the data


As noted in the color section of the base styles way earlier in this post, the charts and graphs use an auto-generated
color scheme based on the --color--main hex code that’s usually pretty appropriate for the site theme. You can provide
the developer with your own hex codes instead, if you want full control over the chart colors.

Otherwise, here are some design keys regarding both tables and the charts:


  The charts are generated by the Highcharts library. While Highcharts has an API and styling selectors, I’d recommend
avoiding trying to customize the charts much, if at all, beyond picking a color scheme. It’s a real here by dragons
part of the frontend codebase
  While you can design the data tables any way you like, I’ve found over the years that, since tables aren’t usually used
all that much and the markup is kind of complex, simple table designs make everyone happier, including end-users
  The table component has a wrapper &amp;lt;div&amp;gt; that shows the table in the horizontal scroll box on narrow tablets and mobile
devices. Other responsive table strategies are available, but that’s the one currently in place, so without increasing
scope you have that going for you. If you’re using lots of tables and need a more streamlined approach, that’s another
thing to discuss with your developer as early as possible
  Tables are great for what they’re good for, but… if you’re using lots of tables and charts and graphs it may be a
sign that either you’re a data-driven site, or that you’re mis-using the feature. Something to look out for


Term listing

Gonna level with you: the Term listing component exists mostly to fill out the list, rather than being something anyone
might use with any regularity. Taxonomy terms like ‘tags’ in frost have Names/titles, short body text, a field for a teaser
image, and all the things you’d need to render them as teasers, so…

Yeah, you can make listings of tags as teasers and make the stacks, side-by-side, or carousels. Clicking a teaser takes
you to that tag’s listing page, which itself is a little bit of content followed by side-by-side teasers of tagged content.

The advice in the “Content listing” component section about coming up with a sort-of-generalized ‘teaser’ style comes into
play here, since a well-designed teaser style means this component will just work, even if you didn’t do anything specific
to design for it.

User listing

Ditto all the stuff from the “Term listing” component section above for the user listing. If your teasers look good, you
get robust little lists of users for free.

Unlike the term listing, though, there’s a common-enough use case for user listings to highlight that it might make sense
to account for a user listing (and user teasers) in your designs:

If you have an About page that lists your company leadership or overall staff, a user listing can help automate keeping
it updated. Each user can manage their own little profile with a biography and portrait and the like (and administrators
can also manage those profiles). If those profiles should be publicly-viewable, and especially if the staff also author
content like blog posts, user listings and profiles and stuff can be a great way to keep your users clicking through pages
that interest them.

View

Views in Drupal are flexible displays that can be context-aware, so you can make a blog listing that auto-updates when
new content is added, or make a custom interface for your search page. frost comes out of the box with a bunch of useful
Views displays that we’ll cover in a separate post, but overall Views embedded via this component will reuse other component
styles, like:


  Field with label
  Teaser
  Table
  Stack/side-by-side/carousel layout
  Pager
  Form
  …and others


Some quick design notes, given that Views show other components:


  If a Views listing has an ‘exposed’ form for refining and filtering the results, that form will be collapsed by default
and available via a toggle button on mobile. This allows for less scrolling and confusion when landing on a listing
page on a phone. This is true for all Views except the main search display, which shows the form by default instead
  The frost Views kit comes with Views you may want to place in your designs: 3 related teasers side-by-side, 3 recent
teasers side-by-side that can be narrowed to a particular content type to match
  If you’d like to do something clever to show relevant content to users, discussing Views’ power with your developer
will almost certainly be a fruitful conversation


Webform

The webform module lets you build flexible forms that get stored on the website and can also be forwarded to admins via
email or sent via API to other services.

A big source of confusion among people who aren’t full-time professional Drupal developers is that there are lots of
forms on Drupal sites that aren’t webforms. Many of those forms can be easily modified and redesigned away from their
default appearance and behavior, but doing so isn’t as quick and easy as making contact forms and stuff with webform.

Additionally, even developers fall into a trap I recommend you avoid: since making webforms is so easy for most anybody,
it’s tempting to build out web-app-like functionality using webform, and then do things with ‘handlers’ to perform actions
and generate content. This approach works until it doesn’t, as the more you load up webform the more you have to wrestle
against it.

Some design notes:


  Like overall Drupal fields (which I may find a place to discuss either in this huge post or elsewhere), forms should
start with an overall style: what does a simple textfield look like? Typically you want a label on top, perhaps a light
grey placeholder that indicates what kind of input to put in the field (though this can be counterintuitive for users,
and some designers misuse the placeholder functionality), and a one-row text box with some padding and a border that
can be rounded and all that jazz. And then the form field should likely have some space between it and the next field
  From the general style for any form field, you can then style individual fields as shown in the webform demo of the
frost component guide. Things like radios, checkboxes, date pickers,
and more are all technically style-able, even if in some cases the default is familiar, usable, and accessible to the
most users. Getting really involved when it comes to form styling is a way to increase frontend development scope, but
is also a way to make a site feel truly custom
  If you’re planning to use what’s called the “Float label pattern” when the field label is crammed inside the form field
until the user focuses on it… don’t. It’s bad, it’s a lot of frontend dev work, and nobody will be happy about
it, including many end-users
  A great way to differentiate a form’s appearance, even if things like radio buttons and checkboxes use browser defaults,
is to get creative with how &amp;lt;fieldset&amp;gt;s look. In frost the fieldset’s legend is bold and centered, carrying along
the old-fashioned browser style of the legend intersecting the fieldset’s top border, but there are lots of directions
you could go, just so long as it’s a box with some legend text that contains form fields related to that descriptive
legend


Otherwise, since the webform component is used to insert a form anywhere you want on the page, the design really comes down
to how you want forms to look on the site.

Fifth, wrapper

Most sites (that aren’t hand-coded page-by-page) tend to have a similar design concept, and frost is no exception:
the content area is set up to be editable, while the header, footer, and sometimes a wrapper or sidebar are elements
designed once to match the brand and don’t change much page-to-page. This might seem obvious, but overall it means you
can go in any direction you want for the header and footer, even if content authors mess up your aesthetic a bit in the
in-between parts.


    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

Of course, the setup that frost ships with isn’t a terrible start:


  Header starts with the optional ability to show site-wide alerts, like “We’ll be closed for the fourth of July holiday”
  Main header has the logo/branding, main menu, and a search icon toggle
  Footer has columns for branding and contact info, a secondary menu, and site social icons
  After the main footer is a shorter section for the copyright statement, terms and privacy policy links, etc.
  After the footer and sticky to the bottom of the viewport until you close it is a very general, lightweight cookie prompt


These can all be added, removed, tweaked, and massaged to make a header and footer that direct users to the right places
and best convey your site’s brand.

The frost project is working on easy-to-add dropdown and mega menus for the main navigation, but those features aren’t available
quite yet, so while you may need those features, technically they will require your developer to make them happen.

One great way to keep scope in check for the header is to follow the out-of-the-box philosophy for mobile devices:


    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

The main header section can be thought of as two parts:


  The logo/branding block
  A big box holding the main nav, search, and other stuff on desktop, that turns into a sliding ‘tray’ on mobile


The tray gets toggled by a hamburger icon. When the tray is opened, there’s a slick little animation that turns the hamburger
into an ‘x’ visually, which is a neat little detail.

What’s useful about this philosophical approach is that you’re not juggling a bunch of different items’ visibility or putting
in duplicate blocks or anything, just to accommodate the visual differences between the desktop and mobile designs. You’re
just going, “Everything that’s not the logo will be in the hamburger tray, in roughly the same order they appear on desktop,
albeit vertically”.

I’ll once again stress that you don’t have to follow this guidance about header philosophy, but doing so is helpful
to manage development scope and overall complexity. It’s also pretty good at the whole omnichannel buzzword, where looking
at the site on mobile resembles the desktop experience enough that users feel more like they’re on the same site. Some designs
deviate enough between desktop and mobile to feel more like two different sites, which some would say is a missed opportunity.

There’s a lot that can be said about header and footer design, but rather than making this post even longer, I’ll leave
you with one design note, based on a problem I encountered on two recent designs:


  The copyright statement should be on its own line (with links to the privacy policy and terms), full stop. It is weird
to put the copyright statement in a column of the footer, and your design with an abbreviated copyright statement to
make the text fit in a column will absolutely lose out to any legal advisor’s guidance, so just keep the copyright
statement in the same place as every other website ever


Sixth, page mockups

In case this book of a design handoff blog post hasn’t made it obvious, us developers thrive on precise written comminication.
You can endear yourself to developers by annotating your designs with things that aren’t otherwise obvious, or things that
are especially important to you so they have the tools they need to get it right.

Right, so bringing together all the components with the header and footer to make various page-level designs is pretty common
for getting client approval. With all the words above, you can feel confident you’ve nailed all the constituent parts, so
all that’s left if putting the toy bricks together.

Key notes:


  Unless the client firmly demands mobile comps (and the estimate reflects the risk to scope this almost always presents),
it’s probably in everyone’s best interest to only do desktop page mocks. In frost responsiveness of the layouts
and components comes along logically and for free, so you’ll likely only have to tweak a few things here and there.
Designing for mobile specifically usually results in big headaches between expectation and reality, as the designs take
more creative liberties than is likely advisable in systems design
  Every page should have a hero containing the page title as an &amp;lt;h1&amp;gt;, even if the heroes differ somewhat in appearance
between different page types
  You can throw any combination of storytelling components with any amount of spacing into whichever layouts make the
most sense, with the biggest consideration being the appropriate heading levels as illustrated in the heading component
section
  I’ve found that using the stripes to alternate between backgrounds for thematic sections (see the frost demo privacy policy
for an example) is a great way to organize content while providing visual interest and breathing room. When other colors
or images aren’t quite right, alternating between white and light grey for background gets the job done well


Three heroes

One of the coolest parts of frost is a beautifully-coded block
that automatically picks the right hero to insert on the page for you. The following three sections describe the kinds of
heroes you’ll encounter and have to design for.

Fallback default and ‘system’ pages

The first hero, and the one that’s the least flexible, is the one that appears on ‘system’ pages:


    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

On pages like the user login, user register, and if you create standalone pages for things like webforms or views, or anything
else where you’re not going to an edit screen and moving components around, the only piece of information we reliably have
is the page title, so the content of the hero is just the page title.

However, the following notes apply:


  If so desired, the hero’s vertical padding could be smaller on system pages, and other styling can be applied to just
heroes on system pages
  The system ships with a CSS class applied to the system heroes that gives it the default background image mentioned
in the second section (Assets) of this novel. If you’d rather use a solid background color or a different image, that
can be done easily, and it will apply to all non-overridden system page heroes
  While it would take developer time per page, some system pages can have distinct override styles, like a different background
image or something like that. Ideally this would be done sparingly, and please resist the temptation to put any content
other than the page title in any system page hero design, as that will make the developer very sad


Per-bundle pre-configured heroes

Each type of content: article, event, page, tag, product, user, and more (any ‘entity’ bundle that has its own page) can
be set up with what’s called a “view mode” or “display mode” named hero that, when present in the site’s configuration,
will replace the “system page” hero style above.


    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

The illustration above shows how the hero for an event appears. An ambitious site builder (or more likely the developer
you know and love) can build out the layout from the admin UI, the same way they build out the rest of the page or the teaser:


    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

The hero for a piece of content is a good place to put fields that contain bite-sized and at-a-glance info, like an event’s
location and date, an article’s byline, and in many cases the teaser image or social share image for that content (which
leverages the psychological principle of priming: you see the image on a social media site or the teaser on a listing
page, click the link, then see the same image and go “That’s the same image, I’ve landed in the right place, I’m going to
think of this content any time I see that image or ones like it,” at least somewhat non-cynically).

What’s great about these heroes for things like events, articles, products, and tags is that as a content author you want
to focus on making compelling content, rather than custom designing a hero every time you want to write a press release,
so with this default setup you have something that looks good and is effective at communicating necessary information in
a consistent way from page to similar page.

But this is frost, so of course there’s going to be a more flexible and customizable option involving components…

Stripe: Atomic heroes

The last hero type, the ultimate override in the beautifully-coded hero block, and by far the coolest hero type, is just
using a stripe like all the others:


    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

Anything you can do with an atomic stripe, and any component you can place elsewhere on the site, you can technically
place in a stripe hero:


    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

This means you can easily make heroes that have:


  Background images
  Background videos
  Big spacers
  Layouts with multiple columns
  Additional text, media, and components
  Easy-to-edit CTA button links


With great power comes great responsibility, though, so please heed these notes:


  Every hero must contain the page title in an &amp;lt;h1&amp;gt; tag, and the h1 should probably look like all the other h1 titles
on the site, which goes in line with the thing I said about priming in the previous section. The user is getting familiar
with what different things look like on the site, so making the hero look consistent helps the user understand the site
  You can kind of ignore the previous bullet on the home page specifically. Users expect more of a “This is what
we do” tagline in the home page hero. That tagline should have relevant keywords and should have a prominent appearance,
and its tag should absolutely be an &amp;lt;h1&amp;gt;, but it doesn’t necessarily have to look like all the other site h1s
  In testing you’ll probably find that busy heroes don’t perform as well as simple, direct ones
  As with any stripe, the background color/image should contrast with the chosen text color


And… that’s all I have to say about that. You survived!

Wrapping up

That was a lot of stuff. Thanks for sticking around!

The big things to take away from this article, aside from the specific notes, are:


  When in doubt, design the smallest pieces first, as they’re then used in combination in larger components
  Since the system ships with reasonable defaults, not everything has to be designed or developed in one fell swoop.
    If your team is comfortable with it, you can deliver a Minimum Viable Product for the design, then tack on more components
    and page designs as you go
  There’s nothing that specifically stops you from designing how you always have, with the developer(s) doing the adapting
    of the mock-ups into base styles and components, but perhaps something in this handoff gave you an idea for tweaking
    the process or deliverables
  Any component, any style, can be adapted to suit your needs with just a little added development, so take the defaults
    as a jumping-off point. If the project has a small budget/scope, perhaps err on the side of the defaults, but for an
    ambitious experience you can dial in the brand and aesthetic
  Hopefully the places where I said “you should probably stick to such-and-such” make sense as being ways to maintain
    the integrity of the system and keep scope in check, rather than getting in the way of creative freedom or making all
    sites designed this way look same-y. You can break away from almost any of these guidelines as long as you and the team
    are okay with the scope implications


We hope you have as much fun designing for frost as we do developing with it!

And of course, if you run into any snags or want to hire Brad for a few hours to iron something out, please don’t hesitate
to reach out to brad@solveitonce.com.
]]></description>
        <content:encoded><![CDATA[<p><strong class="color--third font-size--1p25em">Steal this content! Everything on this site is under a CC0 license, so you
can copy/paste this handoff without guilt.</strong></p>

<p>Hello designer friend <span class="color--grey font-size--p875em">(BTW, did you know
<a href="https://solveitonce.com/careers/freelance-designer/">so1ve is looking for talented freelance designers</a>?)</span>!</p>

<p>There are some nuances to designing for <a href="https://www.frostdrupal.com/">frost</a> specifically, and to some extent Drupal in
general, that tuning into can help you design in a way that makes the developers happy and keeps the project moving quickly.
Don’t worry, though — there’s still plenty of room for creativity.</p>

<p>Before we jump into the design stuff, you may be wondering, “Why are we using this frost thing rather than something else?”
That’s a good question, and effectively it comes down to this: frost is a <strong>huge head start</strong> for making websites that can
later be extended to manage huge amounts of content.</p>

<p>The frost system came from turning a bunch of designs by a bunch of designers into component-based websites, reusing what
worked from the previous site each time, until the system seemed to work for any design. The setup may not be precisely
what you’re used to, but it works really well and you might end up really happy with how easy it is to customize.</p>

<p><strong>We’ll start off easy and breezy, just send along an SVG logo or two</strong>, but quickly this handoff article becomes a deep
dive of all the possible components you may encounter on your design journey. When you’re deep in the atomic component trees,
<em>you are hereby empowered</em> to remember that you can plant any darned forest you want. <strong>This frost system allows you to
click-and-drag your way to websites that other systems simply cannot match</strong>.</p>

<p>If you’re not accustomed to trying out a site early in the design process, <strong>a frost site is a great time to buck that trend</strong>.
All the principles in this guide can be explored directly from a frost demo site, if your developer is up to the task of
setting one up.</p>

<h2 class="no_toc" id="table-of-contents">Table of contents</h2>

<ol id="markdown-toc">
  <li><a href="#first-where-to-reference" id="markdown-toc-first-where-to-reference">First, where to reference</a></li>
  <li><a href="#second-brand-assets" id="markdown-toc-second-brand-assets">Second, brand assets</a></li>
  <li><a href="#third-base-styles" id="markdown-toc-third-base-styles">Third, base styles</a>    <ol>
      <li><a href="#fonts" id="markdown-toc-fonts">Fonts</a></li>
      <li><a href="#colors" id="markdown-toc-colors">Colors</a>        <ol>
          <li><a href="#heres-whiteblackgreys" id="markdown-toc-heres-whiteblackgreys">Here’s white/black/greys:</a></li>
          <li><a href="#and-the-medium-shades-of-the-three-brand-colors" id="markdown-toc-and-the-medium-shades-of-the-three-brand-colors">And the medium shades of the three brand colors:</a></li>
          <li><a href="#and-the-light-shades" id="markdown-toc-and-the-light-shades">And the light shades:</a></li>
          <li><a href="#and-the-dark-shades" id="markdown-toc-and-the-dark-shades">And the dark shades:</a></li>
          <li><a href="#heres-the-theme-accent-color" id="markdown-toc-heres-the-theme-accent-color">Here’s the theme accent color:</a></li>
        </ol>
      </li>
      <li><a href="#delivery" id="markdown-toc-delivery">Delivery</a></li>
      <li><a href="#everything-else" id="markdown-toc-everything-else">Everything else</a></li>
    </ol>
  </li>
  <li><a href="#fourth-component-party" id="markdown-toc-fourth-component-party">Fourth, component party!</a>    <ol>
      <li><a href="#tags-in-the-style-guide" id="markdown-toc-tags-in-the-style-guide">Tags in the style guide</a></li>
      <li><a href="#reusable-components" id="markdown-toc-reusable-components">Reusable components</a>        <ol>
          <li><a href="#sectioning" id="markdown-toc-sectioning">Sectioning</a>            <ol>
              <li><a href="#stripe-atomic" id="markdown-toc-stripe-atomic">Stripe: Atomic</a></li>
              <li><a href="#layout" id="markdown-toc-layout">Layout</a>                <ol>
                  <li><a href="#column" id="markdown-toc-column">Column</a></li>
                </ol>
              </li>
              <li><a href="#stripe-collection" id="markdown-toc-stripe-collection">Stripe collection</a></li>
            </ol>
          </li>
          <li><a href="#storytelling" id="markdown-toc-storytelling">Storytelling</a>            <ol>
              <li><a href="#accordion" id="markdown-toc-accordion">Accordion</a></li>
              <li><a href="#block" id="markdown-toc-block">Block</a></li>
              <li><a href="#blockquote" id="markdown-toc-blockquote">Blockquote</a></li>
              <li><a href="#cards" id="markdown-toc-cards">Cards</a>                <ol>
                  <li><a href="#card" id="markdown-toc-card">Card</a></li>
                  <li><a href="#card-percent" id="markdown-toc-card-percent">Card: Percent</a></li>
                </ol>
              </li>
              <li><a href="#content-listing" id="markdown-toc-content-listing">Content listing</a></li>
              <li><a href="#heading" id="markdown-toc-heading">Heading</a></li>
              <li><a href="#iframe" id="markdown-toc-iframe">iframe</a></li>
              <li><a href="#link" id="markdown-toc-link">Link</a></li>
              <li><a href="#media" id="markdown-toc-media">Media</a>                <ol>
                  <li><a href="#hotspot" id="markdown-toc-hotspot">Hotspot</a></li>
                </ol>
              </li>
              <li><a href="#media-listing" id="markdown-toc-media-listing">Media listing</a></li>
              <li><a href="#message" id="markdown-toc-message">Message</a></li>
              <li><a href="#product-listing" id="markdown-toc-product-listing">Product listing</a></li>
              <li><a href="#rich-text" id="markdown-toc-rich-text">Rich text</a></li>
              <li><a href="#spacer" id="markdown-toc-spacer">Spacer</a></li>
              <li><a href="#table" id="markdown-toc-table">Table</a></li>
              <li><a href="#term-listing" id="markdown-toc-term-listing">Term listing</a></li>
              <li><a href="#user-listing" id="markdown-toc-user-listing">User listing</a></li>
              <li><a href="#view" id="markdown-toc-view">View</a></li>
              <li><a href="#webform" id="markdown-toc-webform">Webform</a></li>
            </ol>
          </li>
        </ol>
      </li>
    </ol>
  </li>
  <li><a href="#fifth-wrapper" id="markdown-toc-fifth-wrapper">Fifth, wrapper</a></li>
  <li><a href="#sixth-page-mockups" id="markdown-toc-sixth-page-mockups">Sixth, page mockups</a>    <ol>
      <li><a href="#three-heroes" id="markdown-toc-three-heroes">Three heroes</a>        <ol>
          <li><a href="#fallback-default-and-system-pages" id="markdown-toc-fallback-default-and-system-pages">Fallback default and ‘system’ pages</a></li>
          <li><a href="#per-bundle-pre-configured-heroes" id="markdown-toc-per-bundle-pre-configured-heroes">Per-bundle pre-configured heroes</a></li>
          <li><a href="#stripe-atomic-heroes" id="markdown-toc-stripe-atomic-heroes">Stripe: Atomic heroes</a></li>
        </ol>
      </li>
    </ol>
  </li>
  <li><a href="#wrapping-up" id="markdown-toc-wrapping-up">Wrapping up</a></li>
</ol>

<h2 id="first-where-to-reference">First, where to reference</h2>

<p><a href="https://github.com/orgs/solve-it-once/projects/2?pane=issue&amp;itemId=8041402">Soon we’ll have a Figma starter for frost sites</a>,
which hopefully will be a big boost. In the mean time, these links have useful info for referencing much of what we’re discussing
in this post:</p>

<ul>
  <li><a href="https://www.frostdrupal.com/page/component-guide">frost component guide</a> — demos of most components, with some helpful descriptions</li>
  <li><a href="https://www.frostdrupal.com/admin/appearance/styleguide">frost style guide</a> — the base styles applied to Drupal’s built-in user interface elements</li>
  <li><a href="https://www.frostdrupal.com/user/login">Example ‘system’ page</a> — a ‘boring’ page, which is a great template target</li>
  <li><a href="https://github.com/solve-it-once/frost/blob/master/docroot/themes/custom/frost_theme/css/settings.css">settings.css</a> — one little file that holds all the base styles</li>
</ul>

<h2 id="second-brand-assets">Second, brand assets</h2>

<p>Especially at the start, just two logo files — one for the header and an inverted one for the footer — is enough for testing
development versions of the new site. But there are plenty of other assets to cut and send to your friendly neighborhood
developer:</p>

<div class="table--wrapper">
  <table>
    <caption>Brand image asset details</caption>
    <thead>
      <tr>
        <th>Image</th>
        <th>Format</th>
        <th>Dimensions</th>
        <th>Notes</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><a href="https://github.com/solve-it-once/frost/blob/master/docroot/themes/custom/frost_theme/logo.svg">logo.svg</a></td>
        <td>SVG</td>
        <td>64x64, approx.</td>
        <td>
          If possible, provide the logo as a real SVG file (rather than a JPEG/PNG embedded in an SVG wrapper). The header
          layout will constrain the image's size, but scaling it to be nearly the size it should appear on the site can
          be a page load performance boost. 64-100 pixels for the height is a good target, with the width being more flexible
          (for instance it could be 240-ish pixels wide if the image contains both the mark and text).
        </td>
      </tr>
      <tr>
        <td><a href="https://github.com/solve-it-once/frost/blob/master/docroot/themes/custom/frost_theme/images/footer-logo.svg">footer-logo.svg</a></td>
        <td>SVG</td>
        <td>64x64, approx.</td>
        <td>
          Even if the header and footer will eventually have the same color scheme and the same logo, it's fun to make the
          "evil twin" version of the logo. This inverted version is intended for rev. 1 of the footer, and could be repurposed
          down the road.
        </td>
      </tr>
      <tr>
        <td><a href="https://github.com/solve-it-once/frost/blob/master/docroot/themes/custom/frost_theme/favicon.ico">favicon.ico</a></td>
        <td>ICO</td>
        <td>64x64</td>
        <td>
          This appears in the browser's tab. 64x64 is probably big enough. The file must have square dimensions. Most often
          you'll want the logo mark over transparency, but a solid background is also possible. Very simple brand expression
          is the name of the game here.
        </td>
      </tr>
      <tr>
        <td><a href="https://github.com/solve-it-once/frost/blob/master/docroot/themes/custom/frost_theme/apple-touch-icon.png">apple-touch-icon.png</a></td>
        <td>PNG</td>
        <td>512x512</td>
        <td>
          Icon used when installing the site to your desktop or home screen. In order to avoid providing a ton of slightly-varied
          versions of the same asset, ship the big 512x512 version with just the logo mark, a solid color background, and
          at least a little padding all the way around the logo.
        </td>
      </tr>
      <tr>
        <td><a href="https://github.com/solve-it-once/frost/blob/master/docroot/themes/custom/frost_theme/images/bg_hero_default.jpg">bg_hero_default.jpg</a></td>
        <td>JPEG</td>
        <td>1920x1080</td>
        <td>
          On system and other pages where a custom hero isn't set up, this image can be used as a default hero background
          if desired. It should be either dark with a mask for white text, or light for dark text. If you'd prefer a solid
          color or CSS gradient background for default heroes, just let the developer know. Making a default hero image
          might be a good design exercise anyway.
        </td>
      </tr>
      <tr>
        <td><a href="https://github.com/solve-it-once/frost/blob/master/docroot/themes/custom/frost_theme/images/social_default_1200x630.jpg">social_default_1200x630.jpg</a></td>
        <td>JPEG</td>
        <td>1200x630</td>
        <td>
          Social sharing image for Facebook/LinkedIn/Twitter. The template for making the image
          <a href="https://github.com/solve-it-once/frost/blob/master/docroot/themes/custom/frost_theme/images/social_template.xcf">is available as an XCF for GIMP</a>,
          and online converters to PSD are easy to come by.
        </td>
      </tr>
    </tbody>
  </table>
</div>

<p>Along with the brand assets above, now might be a good time to source backgrounds for various stripes in the default content
(more on stripes later):</p>

<figure class="figure figure--image figure--image--frost-default-stripe-backgrounds-png box-shadow--lifted-edges">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_default_stripe_backgrounds.png.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_default_stripe_backgrounds.png.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/frost_default_stripe_backgrounds.png" alt="Screenshot showing part of a frost page, where two section backgrounds are light-masked icebergs" loading="lazy" height="1683" width="1439" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/frost_default_stripe_backgrounds.png" alt="Screenshot showing part of a frost page, where two section backgrounds are light-masked icebergs" loading="lazy" />
      </noscript>
    
    
  </figure>

<p>When the developer installs frost, the section backgrounds are stock photographs of icebergs with semi-transparent white
masks. Unless you’re making a site about icebergs, the default section backgrounds should probably be changed. However,
this piece can be deferred until content and page design, later in this post.</p>

<h2 id="third-base-styles">Third, base styles</h2>

<p>The base styles in the <a href="https://github.com/solve-it-once/frost/blob/master/docroot/themes/custom/frost_theme/css/settings.css">settings.css file</a>
define reusable variables for both implementing a consistent design, as well as to help the front-end developers out with
repetitive tasks. Overall, you can get an idea of the contexts for how the base styles are used from <a href="https://solveitonce.com/docs/design/moodboard/">this site’s moodboard</a>.</p>

<h3 id="fonts">Fonts</h3>

<p>For the most part you just need to pick two fonts, with the notes below helping clarify the format and how they’re used:</p>

<ol>
  <li><strong>Primary font</strong> — body copy and other defaults</li>
  <li><span class="font-family--secondary font-size--1p25em"><strong>Secondary font</strong> — headings h1 and h2 by default</span></li>
</ol>

<p>First in the file are <code class="language-plaintext highlighter-rouge">@font-face</code> declarations, which is how we import web-compatible font files. For frost and pretty
much any modern site, we strongly prefer <a href="https://v-fonts.com/">variable fonts</a> for the smaller number of files and fine-tuning
ability — you can tweak the font weight to be fractions between semi-bold and bold, for instance, which is not something
you can do with classic fonts.</p>

<p>The baked-in design system is set up for two main typefaces: one for headings (mostly) and another for body copy and everything
else. If the site is going to show a lot of code or other monospaced text, a third web font would be added, though the monospace
stack uses <code class="language-plaintext highlighter-rouge">'courier new', courier, monospace</code> which will work in a pinch.</p>

<p>(Note more for the developer but still useful…) If the brand is centered on a single font, you can remove the <code class="language-plaintext highlighter-rouge">@font-face</code>
declaration for the second font, but rather than deleting the <code class="language-plaintext highlighter-rouge">--font-family--secondary</code> custom property or any of its usages,
it’s probably a better long-term decision to just duplicate the primary stack to the secondary variable.</p>

<p>One last font concept: the default frost setup has a sans-serif for <code class="language-plaintext highlighter-rouge">--font-family--primary</code> and a websafe stack following
the custom font. Similarly, <code class="language-plaintext highlighter-rouge">--font-family--secondary</code> is a serif with a websafe serif stack. When in doubt, replace the
name of the custom font, but leave the websafe stack for fallbacks. If you know what you’re doing you could switch the
websafe stacks to better match the custom faces (swapping Times New Roman out for Georgia, for instance), but that can be
considered a <em>micro</em>-optimization.</p>

<h3 id="colors">Colors</h3>

<p>The <strong>frost design system leans heavily</strong> on the color scheme setup, so <em>please try to stick to what we have here</em>, at least
at first, as that’s one of the biggest ways to keep the front-end development scope in check.</p>

<p>Up front, we have white, ‘black’, and three shades of grey, plus three shades of each brand color (medium, light, and dark).
As a bonus there’s a fourth medium-lightness accent color available:</p>

<h4 id="heres-whiteblackgreys">Here’s white/black/greys:</h4>

<p>We can add more greys if needed to style components, for instance, but these would be the greyscale options available when
choosing background and text colors in the content-editing interface.</p>

<ul class="list-style--none layout--multiple--horizontal">
  <li class="flex--1">
    <div class="palette background-color--black color--white font-family--monospace text-align--center display--flex
          flex-direction--column justify-content--center">
      #222
    </div>
  </li>
  <li class="flex--1">
    <div class="palette background-color--grey-dark color--white font-family--monospace text-align--center display--flex
          flex-direction--column justify-content--center">
      #555
    </div>
  </li>
  <li class="flex--1">
    <div class="palette background-color--grey color--white font-family--monospace text-align--center display--flex
          flex-direction--column justify-content--center">
      #aaa
    </div>
  </li>
  <li class="flex--1">
    <div class="palette background-color--grey-light color--black font-family--monospace text-align--center display--flex
          flex-direction--column justify-content--center">
      #f7f7f7
    </div>
  </li>
  <li class="flex--1">
    <div class="palette background-color--white color--black font-family--monospace text-align--center display--flex
          flex-direction--column justify-content--center border--1px-solid">
      #fff
    </div>
  </li>
</ul>

<p>One notable thing is that our black is <code class="language-plaintext highlighter-rouge">#222</code> rather than <code class="language-plaintext highlighter-rouge">#000</code>. This comes from <a href="https://ianstormtaylor.com/design-tip-never-use-black/">Iam Storm Taylor’s advice</a>,
and we recommend going further and putting some brand colors in your ‘black’ hex code!</p>

<h4 id="and-the-medium-shades-of-the-three-brand-colors">And the medium shades of the three brand colors:</h4>

<p>The medium shades should have a lightness around 50% (40-60% is a good range). The ‘main’ color should be the most blue
of the brand colors, even if it’s not the brand’s main color in the branding sense. This choice comes down to making links
look as blue and underlined by default as possible.</p>

<ul class="list-style--none layout--multiple--horizontal">
  <li class="flex--1">
    <div class="palette background-color--main color--white font-family--monospace text-align--center display--flex
          flex-direction--column justify-content--center">
      #007599
    </div>
  </li>
  <li class="flex--1">
    <div class="palette background-color--second color--white font-family--monospace text-align--center display--flex
          flex-direction--column justify-content--center">
      #E32416
    </div>
  </li>
  <li class="flex--1">
    <div class="palette background-color--third color--white font-family--monospace text-align--center display--flex
          flex-direction--column justify-content--center">
      #00838a
    </div>
  </li>
</ul>

<h4 id="and-the-light-shades">And the light shades:</h4>

<p>For WCAG contrast compliance specifically, the light shades should be perhaps 90% lightness or higher. Often this requires
bringing more white into the mix, effectively pastel-ing the colors in the process. The light shades need not be pastel,
but it seems those shades end up being the most versatile for contrast.</p>

<ul class="list-style--none layout--multiple--horizontal">
  <li class="flex--1">
    <div class="palette background-color--main-light font-family--monospace text-align--center display--flex
          flex-direction--column justify-content--center">
      #ccf4ff
    </div>
  </li>
  <li class="flex--1">
    <div class="palette background-color--second-light font-family--monospace text-align--center display--flex
          flex-direction--column justify-content--center">
      #ffcfcc
    </div>
  </li>
  <li class="flex--1">
    <div class="palette background-color--third-light font-family--monospace text-align--center display--flex
          flex-direction--column justify-content--center">
      #ccfcff
    </div>
  </li>
</ul>

<h4 id="and-the-dark-shades">And the dark shades:</h4>

<p>The dark shades could be a bit lighter than 10% lightness, but like the lightness choice for the light shades, the darker
the dark shades the more contrast-compliant combinations will be available to use.</p>

<ul class="list-style--none layout--multiple--horizontal">
  <li class="flex--1">
    <div class="palette background-color--main-dark color--white font-family--monospace text-align--center display--flex
          flex-direction--column justify-content--center">
      #002733
    </div>
  </li>
  <li class="flex--1">
    <div class="palette background-color--second-dark color--white font-family--monospace text-align--center display--flex
          flex-direction--column justify-content--center">
      #331716
    </div>
  </li>
  <li class="flex--1">
    <div class="palette background-color--third-dark color--white font-family--monospace text-align--center display--flex
          flex-direction--column justify-content--center">
      #003033
    </div>
  </li>
</ul>

<p>Any one of the dark shades might be a good candidate for the faux-black, too.</p>

<h4 id="heres-the-theme-accent-color">Here’s the theme accent color:</h4>

<p>By default the accent color is used for visited link coloration and a couple other one-off component elements. If your brand
scheme contains a not-super-important purple, this is a good place for it. Otherwise, whichever brand color is least important
of the top four is good as an accent.</p>

<ul class="list-style--none layout--multiple--horizontal">
  <li class="flex--1">
    <div class="palette background-color--accent color--white font-family--monospace text-align--center display--flex
          flex-direction--column justify-content--center">
      #6100a7
    </div>
  </li>
</ul>

<h3 id="delivery">Delivery</h3>

<p>In the developers’ ideal world, you’d deliver the colors just like how they appear in settings.css:</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">:root</span> <span class="p">{</span>
  <span class="c">/* Main theme colors. */</span>
  <span class="py">--color--black</span><span class="p">:</span> <span class="m">#222</span><span class="p">;</span>
  <span class="py">--color--grey-dark</span><span class="p">:</span> <span class="m">#555</span><span class="p">;</span>
  <span class="py">--color--grey</span><span class="p">:</span> <span class="m">#aaa</span><span class="p">;</span>
  <span class="py">--color--grey-light</span><span class="p">:</span> <span class="m">#f7f7f7</span><span class="p">;</span>
  <span class="py">--color--white</span><span class="p">:</span> <span class="m">#fff</span><span class="p">;</span>
  <span class="py">--color--main</span><span class="p">:</span> <span class="m">#007DA3</span><span class="p">;</span> <span class="c">/* This should be a 6-char hex with uppercase letters. */</span>
  <span class="py">--color--main-dark</span><span class="p">:</span> <span class="m">#002733</span><span class="p">;</span>
  <span class="py">--color--main-light</span><span class="p">:</span> <span class="m">#ccf4ff</span><span class="p">;</span>
  <span class="py">--color--second</span><span class="p">:</span> <span class="m">#e32416</span><span class="p">;</span>
  <span class="py">--color--second-dark</span><span class="p">:</span> <span class="m">#331716</span><span class="p">;</span>
  <span class="py">--color--second-light</span><span class="p">:</span> <span class="m">#ffcfcc</span><span class="p">;</span>
  <span class="py">--color--third</span><span class="p">:</span> <span class="m">#007e85</span><span class="p">;</span>
  <span class="py">--color--third-dark</span><span class="p">:</span> <span class="m">#003033</span><span class="p">;</span>
  <span class="py">--color--third-light</span><span class="p">:</span> <span class="m">#ccfcff</span><span class="p">;</span>
  <span class="py">--color--accent</span><span class="p">:</span> <span class="m">#6100a7</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The exact format isn’t super important, though. Just so long as there’s <strong>three brand colors</strong> with <em>three shades apiece</em>.
Most developers can translate between RGB, HSL, hex codes, or other color formats, so as long as you’re not giving Pantone
names or something you’re probably in good shape.</p>

<p>You can see in the code sample above that the <code class="language-plaintext highlighter-rouge">--color--main</code> should be a 6-character hex code with uppercase letters. This
quirk is to facilitate an automatic color scheme for the interactive charts and graphs (see the table section of the storytelling
components). If you’d prefer to hard-code the color scheme for charts and graphs instead, provide your developer with
<a href="https://api.highcharts.com/highcharts/colors">a list of at least 10 hex codes that comply with the Highcharts color settings</a>,
like:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="w">
  </span><span class="s2">"#2caffe"</span><span class="p">,</span><span class="w">
  </span><span class="s2">"#544fc5"</span><span class="p">,</span><span class="w">
  </span><span class="s2">"#00e272"</span><span class="p">,</span><span class="w">
  </span><span class="s2">"#fe6a35"</span><span class="p">,</span><span class="w">
  </span><span class="s2">"#6b8abc"</span><span class="p">,</span><span class="w">
  </span><span class="s2">"#d568fb"</span><span class="p">,</span><span class="w">
  </span><span class="s2">"#2ee0ca"</span><span class="p">,</span><span class="w">
  </span><span class="s2">"#fa4b42"</span><span class="p">,</span><span class="w">
  </span><span class="s2">"#feb56a"</span><span class="p">,</span><span class="w">
  </span><span class="s2">"#91e8e12"</span><span class="w">
</span><span class="p">]</span><span class="w">
</span></code></pre></div></div>

<p>This is purely optional, as the auto-generated colors are usually pretty good, and those colors only matter if the site
plans to use the charts and graphs prominently.</p>

<h3 id="everything-else">Everything else</h3>

<p>The remaining default styles can be the difference between a ‘flat’ aesthetic and something with a lot of depth and playfulness.
Various pieces of the theme, by default, use the borders, shadows, and transitions, so tweaking these to match the brand
feel early on can make the site feel entirely different from the starting defaults:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">--border--default</code>— default is <code class="language-plaintext highlighter-rouge">1px solid</code> but you could pick thicker and/or switch to dotted or dashed for a custom feel</li>
  <li><code class="language-plaintext highlighter-rouge">--border-radius--default</code> — 2px is default, which is a subtle rounding. 0 is square, 1em is quite round, and 25% is circular</li>
  <li><code class="language-plaintext highlighter-rouge">--box-shadow--default</code> — default is <code class="language-plaintext highlighter-rouge">0 0 3px rgba(0, 0, 0, .5)</code>, which is a tiny, spread black shadow straight down</li>
  <li><code class="language-plaintext highlighter-rouge">--layout--content-area</code> — default is <code class="language-plaintext highlighter-rouge">1280px</code>, which you should only change if you have a good reason (narrowing it to as little as 900px is more workable than widening)</li>
  <li><code class="language-plaintext highlighter-rouge">--line-height--default</code> — default is <code class="language-plaintext highlighter-rouge">1.425</code>. This should be a unitless number between 1.2 and 2.5 for legible body copy</li>
  <li><code class="language-plaintext highlighter-rouge">--line-height--heading</code>: it’s <code class="language-plaintext highlighter-rouge">1</code> by default, but something from 0.9 to 1.4 might work for your headings</li>
  <li><code class="language-plaintext highlighter-rouge">--spacing--single</code> — set to <code class="language-plaintext highlighter-rouge">0.625rem</code> and should probably remain that way, as it makes a single spacer 10px tall</li>
  <li><code class="language-plaintext highlighter-rouge">--text-shadow--default</code> — default is <code class="language-plaintext highlighter-rouge">0 0 2px rgba(0, 0, 0, .5)</code>, which is even subtler than the box shadow. Text shadow is used sparingly by default</li>
  <li><code class="language-plaintext highlighter-rouge">--transition--default</code> — default is <code class="language-plaintext highlighter-rouge">all .3s ease-in</code>. For performance you may want to pick just background-color rather than ‘all’, and maybe a different easing function if you have a sensitive eye. 0.3s is a good balance of perception without delay</li>
</ul>

<p>As you can see for some of the notes, the default value is dialed into “best practices”, so in many cases the values would
only change by a small amount. If you’re working over a developer’s shoulder on a scrum team, these are things you two could
dial in after the bigger decisions are settled.</p>

<h2 id="fourth-component-party">Fourth, component party!</h2>

<p>Now we’re cooking with gas.</p>

<p>frost is all about <a href="https://atomicdesign.bradfrost.com/chapter-2/">Atomic Design</a>, so be prepared to think through the
smallest-level ‘atoms’ first, and then put those atoms together to create the full experience. The more we stick to that
concept, the better both our code and the design system will be!</p>

<h3 id="tags-in-the-style-guide">Tags in the style guide</h3>

<p>If you look at the <a href="https://www.frostdrupal.com/admin/appearance/styleguide">frost style guide</a> you’ll see there’s a lot of
HTML tag type stuff that isn’t likely to need changing:</p>

<ul>
  <li>Users are most comfortable with hyperlinks that are blue, underlined, or both. There’s room for creativity, but that’s the best starting point</li>
  <li>Bold text should be bold. Changing the <code class="language-plaintext highlighter-rouge">&lt;strong&gt;</code> styling to italicized or underline or another style could have unintended consequences</li>
  <li>Similarly, changing the <code class="language-plaintext highlighter-rouge">&lt;em&gt;</code> styling from italicized to something else could be accidentally bad</li>
</ul>

<p>On the other hand, there’s a lot of room for creativity when it comes to:</p>

<ul>
  <li>Horizontal rules, which could look however you’d like as long as they divide two blocks of text</li>
  <li>Forms and all the form controls</li>
  <li>Blockquotes</li>
  <li>Buttons and CTA button links</li>
  <li>Lists, mostly their indents/hangs and markers</li>
  <li>Tables, though keeping them simple might save trouble</li>
  <li>Default headings for levels h1-h6</li>
  <li>Pagers</li>
  <li>Progress bars</li>
  <li>Breadcrumbs</li>
</ul>

<p>There’s some overlap between the tag-level and Drupal core components in this section and the reusable components below.
For the most part, defining how a tag-level style looks <em>first</em> can be helpful from a technical perspective, since any
component that uses a default tag but doesn’t look like a default tag has to override it. <strong>Not setting correct defaults
early can result in duplicated override code</strong>, so let’s get the atoms figured out first.</p>

<h3 id="reusable-components">Reusable components</h3>

<p>The components in the frost content-authoring toolkit come in a few different flavors, so we’ll subdivide them here and
go into way more detail than you asked for. That way you’ll have something to reference for the <em>why</em> of various design
decisions.</p>

<h4 id="sectioning">Sectioning</h4>

<p>The sectioning components hold the storytelling components below, with <strong>Stripes</strong> (there’s one stripe type, ‘atomic’, included
by default in frost, but others can be added) being big containers with lots of options, layouts putting one or more columns
side-by-side, and stripe <em>collections</em> used to make tabs or even the <span class="color--second">dreaded</span> slideshows.</p>

<h5 id="stripe-atomic">Stripe: Atomic</h5>

<p>The <em>cornerstone</em> of the design system; an infinitely-flexible section container.</p>

<p>When you’re on the edit screen, in the content tab, you enter the components that should live inside the stripe container:</p>

<figure class="figure figure--image figure--image--frost-stripe-atomic-content-png box-shadow--lifted-edges">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_stripe-atomic-content.png.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_stripe-atomic-content.png.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/frost_stripe-atomic-content.png" alt="Screenshot showing the editor experience for content on an atomic stripe" loading="lazy" height="758" width="1334" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/frost_stripe-atomic-content.png" alt="Screenshot showing the editor experience for content on an atomic stripe" loading="lazy" />
      </noscript>
    
    
  </figure>

<p>Then, in the <em>settings</em> tab, you can style the stripe to have a personality, while still meshing with the site’s brand:</p>

<figure class="figure figure--image figure--image--frost-stripe-atomic-settings-png box-shadow--lifted-edges">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_stripe-atomic-settings.png.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_stripe-atomic-settings.png.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/frost_stripe-atomic-settings.png" alt="Screenshot showing the editor experience for settings on an atomic stripe" loading="lazy" height="1872" width="1317" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/frost_stripe-atomic-settings.png" alt="Screenshot showing the editor experience for settings on an atomic stripe" loading="lazy" />
      </noscript>
    
    
  </figure>

<p>As you can see, a stripe has lots of available settings, with some self-explanatory and others that could use a little
clarification:</p>

<ul>
  <li><strong>Background color</strong> — Theme colors you can set. If you use a background image, please set a color that similar to the
darkness of the image being used. Also make sure the text color contrasts with the set background color</li>
  <li><strong>Background image</strong> — Reusable images that appear as the background</li>
  <li><strong>Background image alignment (horizontal)</strong> — A focal point horizontally. Most useful for ensuring you show the area
of interest when the screen narrows</li>
  <li><strong>Background image alignment (vertical)</strong> — Focal point vertically in image. Usually good centered, but should be set
to ‘top’ when the background image contains people in a medium shot so you don’t cut off the top of their head(s)</li>
  <li><strong>Background repeat</strong> — If you use a tiny image, you can tile it as a pattern. Be sure to change the background size if tiling</li>
  <li><strong>Background repeat</strong> — Jk. Repeat, get it?</li>
  <li><strong>Background attachment</strong> — Whether the background should stick to the page or act like it’s behind the page like parallax scrolling</li>
  <li><strong>Background sizing</strong> — Usually fill the whole area. Can also do tricky things</li>
  <li><strong>Background Video</strong> — Reusable video file that lives on top of the background color and image, but underneath the stripe’s content</li>
  <li><strong>Full width</strong> — Eliminate the maximum content area width, and have the stripe go all the way to the screen edges on big screens</li>
  <li><strong>Hide background image on mobile</strong> — If the background image is ‘busy’, hide it on narrow screens, falling back to the solid background color</li>
  <li><strong>Tab title</strong> — If this stripe is used in a stripe collection, type what the tab should say here</li>
  <li><strong>Text alignment</strong> — Left, right, center, justify. Please never use justify. Since layout columns have text aligned
left by default, aligning stripes center by default gives the most effective use of space when all the components are
used in combination</li>
  <li><strong>Text color</strong> — Light or dark. Please match it to the background color you choose (the one that matches the darkness of any background images used)</li>
  <li><strong>Unpad</strong> — Remove the top and bottom padding from the stripe so it’s short and has less breathing room</li>
</ul>

<p>A stripe, by default, has 20px horizontal padding to give your thumb a place to scroll up and down without accidentally
tapping links and stuff. It also has 100px vertical padding (for desktop, it’s 60px for mobile) for pleasant and up-market
whitespace breathing room. The padding can be removed on a per-stripe basis using the <strong>Unpad</strong> checkbox described above
when you want to dial in less than the default amount of vertical padding. If you’d prefer a different amount of padding
on stripes by default, proportional to other spacing throughout the site, the developer could tweak the following line in
<code class="language-plaintext highlighter-rouge">utility--layout.css</code>:</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.layout--stripe</span> <span class="p">{</span>
  <span class="nl">padding</span><span class="p">:</span> <span class="n">calc</span><span class="p">(</span><span class="m">10</span> <span class="err">*</span> <span class="n">var</span><span class="p">(</span><span class="n">--spacing--single</span><span class="p">))</span> <span class="n">calc</span><span class="p">(</span><span class="m">2</span> <span class="err">*</span> <span class="n">var</span><span class="p">(</span><span class="n">--spacing--single</span><span class="p">));</span>
<span class="p">}</span>
</code></pre></div></div>

<p>As noted in the list of settings above, you can also override the <code class="language-plaintext highlighter-rouge">--layout--content-area</code> width for a particular stripe,
in the event you want to show some really wide foreground content on big screens.</p>

<h5 id="layout">Layout</h5>

<p><strong>Layouts in frost are a little bit different/better than other site-building systems</strong>, in the following ways:</p>

<ul>
  <li>Each layout component is a single row of columns. Below “portrait tablet” size, the columns stack vertically for responsiveness</li>
  <li>You don’t choose a two-column or three-column or whatever layout, you just pick layout and then add the columns you want.
If you want your two-column layout to be a three-column later, you don’t have to rebuild it, just add the next column</li>
  <li>(More of a developer note) Rather than Layout Builder in Drupal, layouts in frost are themselves components, so you
can place layouts anywhere you can place other components, and put layouts in layouts in layouts if your designs need it</li>
  <li>Rather than a grid system, the columns are proportional to each other. One medium and two small columns gets you to a 50%-25%-25% row</li>
  <li>Empty columns can be used without issue, and will automatically disappear on narrow screens when the columns stack</li>
  <li>If you have a series of layouts that had an image in one column and text in the other, and you wanted them to alternate
visually on desktop but be in the same order when stacked on mobile, the ‘Reverse’ checkbox makes that super easy</li>
  <li>Each column has a bunch of dials and switches for spacing, which we’ll get into next</li>
</ul>

<div class="spacer padding-vertical--4 "></div>

<figure class="figure figure--image figure--image--frost-layout-overview-png box-shadow--lifted-edges">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_layout-overview.png.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_layout-overview.png.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/frost_layout-overview.png" alt="Screenshot showing the editor experience for a frost layout example" loading="lazy" height="1564" width="668" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/frost_layout-overview.png" alt="Screenshot showing the editor experience for a frost layout example" loading="lazy" />
      </noscript>
    
    
  </figure>

<h6 id="column">Column</h6>

<p>Columns have a lot of options that let you dial in their desired appearance and do some tricky things:</p>

<ul>
  <li><strong>Animate</strong> — Unchecked by default, but check it to use the chosen animation below</li>
  <li><strong>Animation type</strong> — Any of the reveal animations from <a href="https://animate.style/">animate.css</a></li>
  <li><strong>Background color</strong> — Usually transparent, but can be a solid color where wanted</li>
  <li><strong>Border color</strong> — Can be set to any of the theme colors</li>
  <li><strong>Border radius</strong> — Whether the corners should be square, slightly rounded, or fully rounded. Can be used even without a border</li>
  <li><strong>Border width</strong> — Anywhere from the “No border” default to <code class="language-plaintext highlighter-rouge">4px solid</code> (or other values with developer help)</li>
  <li><strong>Box shadow</strong> — Applies the site default drop shadow as set in the “Base settings” section way up this page</li>
  <li><strong>Margin (horizontal)</strong> — Space between this column and its neighbors</li>
  <li><strong>Margin (horizontal) collapse</strong> — When you want space on desktop by not on mobile</li>
  <li><strong>Padding (horizontal)</strong> — Interior space for columns containing text (usually). <strong>Important note: in frost, horizontal
space is usually configurable, while vertical space is set with a combination of “Vertical alignment” and spacer components.
This makes more and more sense the more you use this philosophy</strong></li>
  <li><strong>Padding (horizontal) collapse</strong> — This is the “why doesn’t this block of text line up vertically on mobile?” checkbox</li>
  <li><strong>Text alignment</strong> — Left, right, center, or justify. Each column can have its own settings, for tricky layouts</li>
  <li><strong>Text color</strong> — Like stripes, the options here are light or dark, for contrast with the background color. Don’t worry:
if you want a heading or some rich text to be a brand color, we’ll show that option in the storytelling section</li>
  <li><strong>Vertical alignment</strong> — Defaults to ‘center’, though ‘top’ is another common one. Oftentimes you want a text column
to be aligned to the top of the row, but the image to its side vertically centered. There are less-used options in the
dropdown to align the column’s contents to the bottom or to have them spaced out in the column’s vertical area</li>
  <li><strong>Width</strong> — Proportional sizes, so you can make any fraction/percent layout you need (within reason). Every column starts
life as a ‘small (1)’ but can be promoted to bigger sizes as needed</li>
</ul>

<h5 id="stripe-collection">Stripe collection</h5>

<p>Reuses the stripe concept to allow content creators to make tabs (and slideshows with a small amount of development work.
We couldn’t include slideshows in the frost system in good conscience, as we’re still wondering
<a href="https://shouldiuseacarousel.com/">should we use a carousel?</a> ).</p>

<p>The tab controls can certainly be re-styled to match your brand’s aesthetic, noting that the tabs in the Stripe collection
component share HTML classes with system tabs, so for consistency it’s best if all tabs on the site look the same.</p>

<p>For content entry especially, there are two big notes to keep in mind for using a Stripe collection to do tabs:</p>

<ol>
  <li>If you’re making a lot of tabs on the site, it’s worthwhile to get comfortable promoting components to the Paragraphs library</li>
  <li>Each tab needs a tab title set in the ‘Settings’ for the individual stripe</li>
</ol>

<p>Overall, things like on-page tabs and slideshows are interesting UI elements, but should likely be used sparingly and with
a clear purpose in mind.</p>

<h4 id="storytelling">Storytelling</h4>

<p>The storytelling components are more at the atom/molecule level for the most part, compared to the sectioning components
which could be considered more organism-ish. Demos and detail are available at the <a href="https://www.frostdrupal.com/page/component-guide">frost component guide</a>
so the notes here focus primarily on design needs.</p>

<h5 id="accordion">Accordion</h5>

<p>Accordions are ‘expandos’ for initially showing a title that explains what the expanded content box contains. A user can
toggle the accordion open/closed via click/tap or keyboard/other controls from assistive technologies.</p>

<figure class="figure figure--image figure--image--frost-accordion-demo-png box-shadow--lifted-edges">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_accordion-demo.png.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_accordion-demo.png.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/frost_accordion-demo.png" alt="Screenshot showing three example accordions" loading="lazy" height="325" width="639" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/frost_accordion-demo.png" alt="Screenshot showing three example accordions" loading="lazy" />
      </noscript>
    
    
  </figure>

<p>Many design systems mandate accordions be placed in groups, and often use JavaScript to ensure only one accordion is open
at a time. frost eschews this, in favor of letting the user toggle whichever elements they want. It’s the most versatile
and simple approach.</p>

<p>Design notes:</p>

<ul>
  <li>Accordion titles in frost, by default, are plain text, with no icon or other indicator. Icons or rich text would require
extra development</li>
  <li>The body of regular accordions is a rich text WYSIWYG. An accordion using components as the body would be extra development.
Not to speak out of turn, but any project that requires really <em>involved</em> disclosure elements may be abusing those elements’
typical purpose</li>
  <li>The frost component system has accordions as well as the aforementioned “Stripe collection” tabs, with both filling
the role of a <em>disclosure</em> element: showing a little bit of information that a user can then choose to toggle open for
more information. Unless there’s a compelling unanticipated reason to add more or replace the existing components, project
designs should probably stick to just two disclosure element types</li>
  <li>Content editors can set any given accordion to be expanded by default from the settings tab. Note that browsers may
also expand the accordions if, for example, a search engine links the user and the result text is inside the accordion</li>
  <li>There’s something of a debate about whether the control+indicator for openness/closedness should be on the left or right.
In frost we went with the right, making the choice largely to facilitate scanning the titles easily. Since the entire
title section can be clicked to toggle the state (and the cursor lets desktop users know this), a user need not move
their mouse a lot to click the control, unless they really want to</li>
  <li>Similarly, there’s room for refinement when it comes to the indicator. HTML <code class="language-plaintext highlighter-rouge">&lt;details&gt;</code> elements are typically styled
in the browser by default with a “disclosure triangle” icon, with many design systems preferring a chevron. In frost
we’ve gone with a plus when closed and a minus when open, as these symbols represent more/less and are less ambiguous
about state than the direction a chevron or triangle is pointing</li>
</ul>

<p>All that said, you have the freedom to design the accordions to look (and work, insofar as scope and developer talent allows)
however you’d like, especially as it meshes with the project’s brand.</p>

<h5 id="block">Block</h5>

<p>System, custom, and dynamic blocks. For the most part these blocks being placed will each be styled according to their varied
contents (see the <a href="https://www.frostdrupal.com/page/component-guide#paragraph-heading-152">frost component guide</a> for the
likely culprits).</p>

<p>At least two of the coolest custom blocks that can be placed contain <strong>social icons</strong>, so determining what the social icons
(which use <a href="https://simpleicons.org/">Simple Icons</a> under the hood) should look like <em>in general</em> could be a boost for the
blocks, as well as the same block(s) possibly being used in the footer:</p>

<ul>
  <li>The icon itself can have the fills/strokes styled to white or any other solid color. It’s potentially possible to do
a gradient or other effect, too</li>
  <li>It’s possible for the fill/stroke of a particular icon to be that brand’s preferred color, though setting up the styles
for lots of icons of varying colors could become a large part of the front-end scope</li>
  <li>Each icon is wrapped in an <code class="language-plaintext highlighter-rouge">&lt;a&gt;</code> tag to link it to the respective social site, and that tag can be styled to contrast
the chosen fill/stroke of the icon proper. By default the wrapping link has a black background and appears as a circle
due to equal height+width and fully-rounded corners. It should be trivial to change the background color, active/hover/focus
state styles, padding, and other styling, to switch to more-square containers, etc.</li>
  <li>The path of least resistance is to keep the icons themselves white, and pick a solid background color that works for
all icons to be used</li>
  <li>While it’s <em>possible</em> to switch icon libraries to something like fontawesome, that could present scope issues if your
project has lots of front-end customizations. So, if the simple-icons GMail icon, for instance, looks too much like
the Medium.com ‘M’ and not enough like an email envelope, please consider swapping it out for the simple-icons
“Invoice Ninja” or “Microsoft Outlook” icons before mandating a substantial swap or addition of icon library. This
email icon issue is odd, because all the other icons are for brands, while email is more of a <em>concept</em>(?), not to mention
that the mailto: icon is likely to be under-used, so it might be easiest to just remove it entirely if you plan to use
social blocks. A more generalized icon library with a few brands mixed in, like fontawesome, would give you multiple
good options to represent email, but may not have representations of every desired <em>brand</em>, so it’s a trade-off for sure</li>
</ul>

<h5 id="blockquote">Blockquote</h5>

<p>Rich text as a pull-quote:</p>

<figure class="figure figure--image figure--image--frost-blockquote-demo-png box-shadow--lifted-edges">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_blockquote-demo.png.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_blockquote-demo.png.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/frost_blockquote-demo.png" alt="Screenshot showing an example blockquote" loading="lazy" height="199" width="639" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/frost_blockquote-demo.png" alt="Screenshot showing an example blockquote" loading="lazy" />
      </noscript>
    
    
  </figure>

<p>The blockquote component’s Settings have toggles, each enabled by default, to insert stylized double-quotation marks before
and after the contents of the rich text, respectively. These settings can instead be hidden or removed if you prefer a different
style for pull quotes.</p>

<p>Design notes:</p>

<ul>
  <li>The quote, owing to being a rich text WYSIWYG, can contain all kinds of bold, italic, heading, code, and other markup.
In practice blockquote are used for quotes, though, so it may be most pragmatic to ignore lots of formatting</li>
  <li>The double-quote affectations can be set from either of the fonts chosen in the “Base styles” section. If neither of
those typefaces has quotes to your liking, a websafe font like Georgia might be a good pick. Otherwise, it will be a
tiny bit extra front-end development to use images instead. One reason to stick with fonts is that it’s easier and more
reliable to re-size them responsively, and of course it requires loading fewer front-end images/assets so there’s the
performance angle to consider, too</li>
  <li>If you decide to go another direction for blockquotes, like the common thick-left-border plus background style, collaborate
with your developer about whether the border and/or the background should be configurable by content authors</li>
  <li>Overall, blockquotes tend to have a font-size a bit bigger than regular body text, and frequently use italicized text
as well. That’s the common pattern, but is not a requirement <em>per se</em></li>
</ul>

<h5 id="cards">Cards</h5>

<p>A side-by-side layout of cards that don’t represent other site content.</p>

<p>The “don’t represent other site content” part is important here, as there are ‘listing’ components described below for representing
content, media, products, tags/terms, or users, as well as the Views component for showing listings of those types of content
and more. That’s not to say that a card <em>can’t</em> be used to tease and link to an article on the site, as an example, but
if content authors are doing that frequently then they should probably discuss a better way to solve a particular content
problem with the dev team.</p>

<p>The ‘Cards’ (plural with an ‘s’) component holds one or more Card (or <code class="language-plaintext highlighter-rouge">Card: Percent</code>) components. The Cards container has
one setting, <strong>letting you choose if the cards it holds should be stacked vertical, shown side-by-side, or in a carousel</strong>.</p>

<p>For the most part, there’s not much to style at the Cards container level, unless the native horizontal scroll-snap-based
carousel should instead use a JavaScript library, which of course would be some additional amount of front-end development.</p>

<h6 id="card">Card</h6>

<p>An individual card has four fields:</p>

<ul>
  <li>Image (optional, reusable)</li>
  <li>Title</li>
  <li>Text</li>
  <li>Link (URL and link text are both configurable)</li>
</ul>

<p>Cards typically have a set-it-and-forget-it style site-wide, often inheriting things like the default amount of corner-rounding
and box-shadow from the base styles. Like all components, though, individual cards <em>can</em> have individual settings, so 99%
of cards could have a transparent/white background, but one card could be set to have a pink background. It depends on
your site’s needs, but the absence of these settings by default is intended to promote consistency across cards.</p>

<h6 id="card-percent">Card: Percent</h6>

<p>This additional card type is used to highlight a top-line number, with optional animation. When a number is important for
telling your story, either this type of card or a table with chart/graph is a good way to convey the info.</p>

<figure class="figure figure--image figure--image--frost-cards-demo-png box-shadow--lifted-edges">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_cards-demo.png.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_cards-demo.png.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/frost_cards-demo.png" alt="Screenshot showing example cards" loading="lazy" height="421" width="687" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/frost_cards-demo.png" alt="Screenshot showing example cards" loading="lazy" />
      </noscript>
    
    
  </figure>

<p><strong>Card: Percent</strong> has three content fields by default:</p>

<ul>
  <li><strong>Number</strong> for the number itself. It can be integer or decimal, and the animation script will deal with it just fine</li>
  <li><strong>Explanatory text</strong> as the body of the card</li>
  <li><strong>Link</strong> as an optional way to send people toward details for a statistic, for instance</li>
</ul>

<p>Additionally, there are two available settings for a percent card:</p>

<ul>
  <li><strong>Prefix</strong> so you could put a <code class="language-plaintext highlighter-rouge">$</code> in front of the number and the animation will still work</li>
  <li><strong>Suffix</strong> for a <code class="language-plaintext highlighter-rouge">%</code> or something like that, also not affected by the animation</li>
</ul>

<p>Some design and functionality notes:</p>

<ul>
  <li>At install-time the animation is set to always occur. It should be mostly trivial to add a toggle allowing a content
author to turn animation on and off per card</li>
  <li>The animation counts up from zero in increments that should cause the animation to complete in about 2.5 seconds. If
you intend to show how small a number is (A “We’ve reduced this metric from big to small” story), that will be another
thing to talk to your developer about. The alternative would be to turn the small into a large by saying “We’ve reduced
this metric by a staggering 144%” instead</li>
  <li>All five configurable fields can be styled separately, and technically the <code class="language-plaintext highlighter-rouge">Card: Percent</code> can be styled to appear different
from other card types. This most comes into play if you want the number itself to be big and bold, but the prefix/suffix
to be smaller and lower-contrast</li>
</ul>

<h5 id="content-listing">Content listing</h5>

<p>A <strong>content listing</strong>, like other components below that end in the word ‘listing’ (and to some extent like Cards), lets
you choose one or more pieces of content, put them in any order you deem appropriate, and display them as:</p>

<ul>
  <li><strong>Teasers</strong>, where the image, byline, title, teaser text, and “Read more” link appear card-like</li>
  <li><strong>Small</strong>, which is configurable of course, but is usually just the title in a bordered box</li>
</ul>

<p>The teaser/small representations of content on the site (articles, events, pages) can be displayed the same ways as cards
and other listings:</p>

<ul>
  <li>Stacked vertical column</li>
  <li>Side-by-side (out of the box it’s 3 wide then wraps, but could be set to 2, 4, etc.)</li>
  <li>Carousel</li>
</ul>

<figure class="figure figure--image figure--image--frost-teasers-side-by-side-png box-shadow--lifted-edges">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_teasers_side-by-side.png.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_teasers_side-by-side.png.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/frost_teasers_side-by-side.png" alt="Screenshot showing three article teasers side-by-side" loading="lazy" height="516" width="1272" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/frost_teasers_side-by-side.png" alt="Screenshot showing three article teasers side-by-side" loading="lazy" />
      </noscript>
    
    
  </figure>

<p>Each content type could have a different appearance if desired, but let’s just talk through some overall notes:</p>

<ul>
  <li>The entire teaser is clickable/tappable to go to that content’s page, and desktop users get a pointer cursor and a hover
style to go with it. Out of the box it’s a slight background darkening, but you may want the teaser image to zoom a
little bit or something else more pronounced</li>
  <li>There’s likely a benefit in your site’s design system, like the concept of a ‘card’, to make all ‘teaser’ (and ‘small’
if used) representations share design cues/metaphors. While an article and a user are two different things, both can
have an image, a prominent label, some intro text, and a CTA link, so containing those elements and giving them some
aesthetic consistency could serve to make users familiar with what teasers do on the site (ie. link to the full page)</li>
  <li>Listing components differ from cards in that each individual teaser cannot be readily set to, for instance, have its
own signature background color or other atomic styling choice. This is certainly <em>possible</em> if you need to do it, but
it may be a bit clunky for authors</li>
  <li>Like the <strong>Cards container</strong>, there’s not much to design for the Content listing component itself, outside of introducing
a JavaScript library for the carousels. The big design lift is deciding what the ‘teaser’ metaphor should look like</li>
  <li>You can see in the screenshot above that the “teaser text” can be styled to be bigger or smaller, depending on how long
the text is. This isn’t required, but may keep things in-check and pleasant. There is a risk of the teaser text becoming
inaccessibly small, though, and you’re most likely to hear about this issue from your SEO specialist, who will get notified
of the issue through Google Search Console</li>
</ul>

<h5 id="heading">Heading</h5>

<p>The heading component gives a <strong>plain</strong> text box for the contents of <code class="language-plaintext highlighter-rouge">&lt;h1&gt;</code>-<code class="language-plaintext highlighter-rouge">&lt;h6&gt;</code> (plus a “Regular text” option for when
you need some text to look like a heading without messing with the document outline), with plenty of styling options:</p>

<ul>
  <li><strong>Appear as heading level</strong> so you can create a good document outline but also visually communicate however you want</li>
  <li><strong>Font weight</strong>, hopefully used sparingly, so in a pinch you can have an <code class="language-plaintext highlighter-rouge">&lt;h2&gt;</code> that differs from others and catches
the eye</li>
  <li><strong>Icon</strong> for design systems where headings are sometimes/always also represented with a visual</li>
  <li><strong>Text color</strong> so you can use the brand colors in stripes with different backgrounds, display more variety in text, etc.</li>
  <li><strong>Text transform</strong> to avoid the icky situation where authors are forced to enter their text in <span class="text-transform--uppercase">
all-caps</span> just to match a design. If you enter the text in natural case and then use the <code class="language-plaintext highlighter-rouge">text-transform</code> option,
you have easier options if a user complains that the site is yelling at them. Not so much if you enter the content with
a weird casing strategy</li>
</ul>

<p>As insinuated above, the key role headings play for users of all abilities plus search engines is to <strong>create a hierarchical
“document outline”</strong>. It’s not uncommon for designers, though, to create a style guide or moodboard with 4-6 heading levels,
and then in practice use them where they look best visually rather than where they’re appropriate in the hierarchy. The
frost heading component lets you use the appropriate heading level and the set the heading to look like a different level,
but… <em>that should be avoided if possible</em>.</p>

<p>Here are some guidelines for how headings are used in frost (and lots of other Drupal/other sites), which will hopefully
be useful for creating the headings’ type scale:</p>

<ul>
  <li>Ignoring the alternate history we could have had based on earlier drafts of HTML5 where you’d have been able to contain
various heading groups on a single page, <strong>in this timeline it’s standard practice for a page to only have <em>one</em> h1
tag, and for that tag to be the page title</strong></li>
  <li>I’ll repeat this later in the guide, too: a quick and easy way to tell if a page design (aside from the home page, which
is allowed to not appear the same as ‘interior’ pages) is a good citizen of the internet is if the pretty URL path,
the title in the browser tab, the label for the page in the main nav (if present), and the visible on-page h1 title
all match. There can be a little deviation, but matching all of those things makes navigating the site and knowing where
you are a lot easier</li>
  <li>Similar to the point above, with little deviation, all h1 page titles should be consistent in size, location, and overall
appearance from page to page. Spoiler alert for the page design section later in this post: I strongly recommend <em>every</em>
page design have as consistent of a hero as possible, with only “Landing Pages” introducing more visual interest in the
hero in the form of background images and such</li>
  <li>Every stripe/section’s first text should be an <code class="language-plaintext highlighter-rouge">&lt;h2&gt;</code> tag in the markup order, even if that h2 is in a layout column</li>
  <li>Teaser titles in listing components should be <code class="language-plaintext highlighter-rouge">&lt;h3&gt;</code>, given the usages of h1 and h2 described above</li>
  <li>Regular <code class="language-plaintext highlighter-rouge">&lt;h3&gt;</code> can then be used in conjunction with teaser titles. One example of when this would be common is if you
have a stripe with an <code class="language-plaintext highlighter-rouge">&lt;h2&gt;</code> followed by a two-column layout. Each column might have an <code class="language-plaintext highlighter-rouge">&lt;h3&gt;</code> describing the contents
of the column in the context of the document outline. Heading levels h4-h6 end up being less commonly used, but are
still important to style appropriately</li>
</ul>

<h5 id="iframe">iframe</h5>

<p>Frankly, <code class="language-plaintext highlighter-rouge">&lt;iframe&gt;</code>s kind of suck. A content author can place them, and are presented with the usual details to fill out:</p>

<ul>
  <li>The URL of the page to show in the iframe</li>
  <li>A title describing the page in the frame, which is especially useful for folks using assistive technologies</li>
  <li>Height and width to show the iframe, noting that the iframe will end up being responsive, so the height and width are
the maximum on desktop</li>
</ul>

<p>Design notes:</p>

<ul>
  <li>For some third-party services there’s a benefit to using an iframe-resizer JavaScript library to calculate the height.
This is something to discuss with your friendly neighborhood developer. The bones for making that work are already in
place for frost, but may take a little bit of time to get dialed in</li>
  <li>Depending on what you’re going for, you may want all iframes to have a medium-grey border so you know the confines of
the frame, or you may want to pretend like the frame blends into the page. It should be pretty easy to add a checkbox
to the component settings if you need this configurable per iframe</li>
  <li><strong>Everyone is likely to be happier if you don’t count on iframes for anything important</strong></li>
</ul>

<h5 id="link">Link</h5>

<p>There are lots of links aside from the link component: cards, teasers, media, and any part of the site that uses a WYSIWYG
can all have links. With WYSIWYGs the link is in its natural habitat: some highlighted text in the middle of a paragraph
that links out to somewhere else.</p>

<p>The link component <em>can</em> show a standalone text link in the same style as a link within a paragraph of text, though that
particular function may be of limited usefulness. Where the link component shines is in its ability to let you easily place
call-to-action (CTA) buttons.</p>

<p>The link component has a field for entering one or more links, plus two settings:</p>

<ul>
  <li><strong>Button background color</strong> to set which brand color the button should be</li>
  <li><strong>Show links as buttons</strong> which toggles between text link and button-styled link</li>
</ul>

<p>Design notes:</p>

<ul>
  <li>The link buttons inherit the default button styles for the site, so having a consistent aesthetic is a plus here. Some
of the key aesthetic differentiators for buttons between design systems: proportion of horizontal to vertical padding,
border roundedness, font family+size+weight, and presence of borders, shadows, gradients, and other affectations</li>
  <li>While it’s entirely possible to make the hover/active/focus states of different-colored buttons distinct from one another,
and even to make the secondary states configurable with a dropdown, <strong>the lowest-scope, most consistent, highest performance,
and most maintainable design choice</strong> is to have all buttons transition to the same hover/active/focus state, regardless
of their starting background color</li>
  <li>Lots of sites using frost (or its forebears) have had designs containing “ghost buttons”, where the background is transparent
and the color is instead applied to the button text and the border surrounding it. Various UX professionals have told
me this is something of a design anti-pattern, so while it’s something I end up adding in somewhat frequently, it’s
not something I want to include by default because it appears to encourage ghost button usage</li>
</ul>

<h5 id="media">Media</h5>

<p>The media component is a wrapper for showing Drupal core media: audio, document, image, video, and remote video (such as
YouTube).</p>

<p>Design notes:</p>

<ul>
  <li>One mistake site architects sometimes make is over-loading the media items themselves. An image media <em>entity</em> should
only hold the image itself, plus metadata about the image like its file format, size, alt text, and perhaps some attribution.
The media component can then hold fields that apply to any media, and which could vary between usages, like the caption</li>
  <li>The media component renders the media in an HTML <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figure"><code class="language-plaintext highlighter-rouge">&lt;figure&gt;</code></a>
element, which has an optional caption. I’ve found in practice that it’s easy and reliable to just set the caption to
be slightly-smaller-than-body text, but there’s design freedom to make the caption appearance a bit more elaborate</li>
  <li>Any media can be linked, though that typically does not change the media’s appearance</li>
  <li>The media component is most used for images. Any image on the site (not just this component) is resized and saved into
the next-generation WEBP format automatically, so creating extra-large ‘retina’ assets doesn’t usually make a difference.
Images that should have a lot of fidelity on retina screens should likely be created as vector graphics (SVG), with
photographs and other bitmapped images benefiting less from the added pixel density</li>
  <li>The last feature available to media at install-time is <strong>hotspots</strong>, which we’ll cover separately in the next section</li>
</ul>

<h6 id="hotspot">Hotspot</h6>

<p>Hotspots are a fun addition to the media component that let you place responsive dots that show a tooltip when hovered or
clicked.</p>

<figure class="figure figure--image figure--image--frost-hotspot-demo-png box-shadow--lifted-edges">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_hotspot-demo.png.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_hotspot-demo.png.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/frost_hotspot-demo.png" alt="Screenshot showing a hotspot's tooltip when hovered" loading="lazy" height="296" width="416" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/frost_hotspot-demo.png" alt="Screenshot showing a hotspot's tooltip when hovered" loading="lazy" />
      </noscript>
    
    
  </figure>

<p>Design notes:</p>

<ul>
  <li>The indicators for hotspots should be small, so as not to obscure too much of the media they’re on top of</li>
  <li>The indicators have a plus that rotates to resemble an ‘x’ when the tooltip is open. This need not be the way the designs
remain, but is a decent starting point</li>
  <li>There may be a benefit to setting the hotspot indicators in a loud color. A more subdued tone may make these interactive
elements blend into the media they’re covering</li>
  <li>The tooltips can be styled as well. This is a place where big changes could lose a developer an afternoon, but swapping
the background color or something could make it a nicer branded experience</li>
  <li>The hotspots, in order to be flexible and responsive, get placed a percentage width and height from the upper left-hand
corner of the media. Usually your first guess is pretty good, but in practice you end up having to tweak the numbers</li>
</ul>

<h5 id="media-listing">Media listing</h5>

<p>The Media listing works like a lot of the other listing components, but this time with images and stuff. The default behavior
is to show a square-cropped thumbnail of the selected media in a side-by-side grid. Clicking on a media item opens it in
a lightbox on the page.</p>

<p>Design notes:</p>

<ul>
  <li>Square cropping images works great for photos with centered focal points, but could be less great for things like a
grid of logos. You may want to get the developer to switch the “Image Style” used for the media’s display mode to instead
use an image style that only scales the source image, rather than square cropping. The result would be a little less…
tidy, but would maintain fidelity of the source image</li>
  <li>This component can be extended pretty easily if you want galleries, slideshows, and other ways of showing a bunch of
media. Of course, any enhancement like that would be a scope increase, but cool media display modes is the kind of stuff
front-end developers wake up for</li>
</ul>

<h5 id="message">Message</h5>

<p>The message component shares styles with the Drupal system on-screen messages/alerts. For some use cases it might make sense
to style the two things separately, but overall folks seem happiest when both have the same styles.</p>

<figure class="figure figure--image figure--image--frost-message-demo-png box-shadow--lifted-edges">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_message-demo.png.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_message-demo.png.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/frost_message-demo.png" alt="Screenshot showing three system messages" loading="lazy" height="257" width="821" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/frost_message-demo.png" alt="Screenshot showing three system messages" loading="lazy" />
      </noscript>
    
    
  </figure>

<p>The component has a WYSIWYG for the contents of the message, plus one setting:</p>

<ul>
  <li><strong>Severity</strong>, which lets you assign the message as a status, warning, or error</li>
</ul>

<p>There are a few nuances to both the system messages and message component:</p>

<ul>
  <li>Out of the box it’s a light color background with a darker shade for the text and border. All the corners are square
rather than rounded: so rounding the corners is an easy way to punch them up</li>
  <li>Message components as dismissible, and stay dismissed if a user closes them, so anything that should persist on the
page should probably not be in a message component</li>
  <li>Since the defaults here use color text, any links in the message body as set to inherit the current color. This isn’t
a strict requirement, but makes styling between instances of frost a touch easier</li>
  <li>Since the message body is a rich text WYSIWYG, designs of the component <em>might</em> benefit from exploring what is does,
and <em>should</em> look like when somebody puts way too much information with way too much formatting inside of one of those
things</li>
</ul>

<h5 id="product-listing">Product listing</h5>

<p>A Product listing works just like a Content/Term/User listing, but shows products from the site’s pre-installed ‘Commerce’
section. If your site doesn’t use frost’s e-commerce functionality, you can safely ignore this component.</p>

<p>If you are using frost for e-commerce, the notes about Teasers in the <code class="language-plaintext highlighter-rouge">Content listing</code> section above apply to product
teasers as well. Product teasers can be set up to show the price and “Buy now” CTA button instead of the article teaser
info like byline, since who authored a product page and when is a lot less important than how much the product costs.</p>

<p>Like the other listing components, a Product listing can be shown stacked, side-by-side, or as a simple carousel. If you
intend to have a few product carousels on the site, this is a place where you’ll want to specify a JavaScript carousel library.</p>

<h5 id="rich-text">Rich text</h5>

<p>Finally, an easy one! The Rich text component gives you a WYSIWYG CKEditor for easily writing some everyday HTML.</p>

<figure class="figure figure--image figure--image--frost-wysiwyg-filtered-png box-shadow--lifted-edges">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_wysiwyg-filtered.png.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_wysiwyg-filtered.png.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/frost_wysiwyg-filtered.png" alt="Screenshot showing a basic CKEditor5 WYSIWYG setup in frost" loading="lazy" height="246" width="772" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/frost_wysiwyg-filtered.png" alt="Screenshot showing a basic CKEditor5 WYSIWYG setup in frost" loading="lazy" />
      </noscript>
    
    
  </figure>

<p>The WYSIWYG has a decent number of bells and whistles to accomplish your usual formatting needs, but out of the box tries
to limit the number of formatting buttons somewhat. This is meant to encourage authors to use the components instead, when
the components have an advantage over a WYSIWYG. This is true for things like headings and media.</p>

<p>The Rich text component has some settings that can apply to all the text entered in the WYSIWYG:</p>

<ul>
  <li><strong>Font size</strong>, in the event you want some text on the page larger or smaller than the body text default</li>
  <li><strong>Font weight</strong>, for making especially-thin or especially-bold text sections, though this depends on using a variable
font as recommended earlier in the post</li>
  <li><strong>Text color</strong>, which is the full list of brand colors. Stripes and layout columns let you pick dark or white text but
not the full brand palette. If you really need green text somewhere on a page, this is the dropdown for you</li>
  <li><strong>Text columns</strong>, for setting some text in 2,3, or 4 columns on desktop. Text on the web isn’t especially friendly when
set in newspaper-like columns, so this is an option to be used rarely to make a little section of text pop while taking
up less vertical space, rather than a technique to be used everywhere on the site</li>
  <li><strong>Text transform</strong>, which works just like the same option on headings. If you anticipate having a block of all-caps
text, this dropdown is a good way to accomplish that without typing everything in all-caps</li>
</ul>

<p>Here are a couple extra notes for handling the overlap between things the WYSIWYG can do, compared to things the component
system can:</p>

<ul>
  <li>Drupal has this concept called “Text formats &amp; editors” that lets you set up multiple WYSIWYGs with different buttons.
In frost we have the default “Filtered HTML” editor with a limited number of buttons. The “Full HTML” format has an
editor with all the buttons, including the irresponsible ones</li>
  <li>If you make a layout and put rich text in one column and an image (Media) in another, the columns always end up separate.
Sometimes you want text to wrap around an image using old-school floats instead. This can be done by inserting an image
into a WYSIWYG. If the overall design is going to have a lot of wrapped images like this, that’s something to flag early
so the developer can prepare</li>
  <li>I’ve found that, if a developer is a big advocate for WYSIWYG editors and wants to put all the content editing features
in CKEditor rather than breaking out components another way, authors and users are probably going to have a bad time.
<strong>When in doubt, component it out</strong></li>
</ul>

<h5 id="spacer">Spacer</h5>

<p>Spacers are versatile ways of introducing vertical whitespace between other components in a configurable and responsive way.</p>

<p>Design notes:</p>

<ul>
  <li>As discussed in the earlier ‘Layout’ section, frost leans on horizontal spacing being set by columns and other component
settings. This opens up spacers to be used specifically for extra <em>vertical</em> spacing</li>
  <li>Spacers can be set to 1x, 2x, 4x, 8x, 16x, and 32x, with the three biggest sizes being responsive: on small screens
they’re half their desktop height. In practice, we’ve found that small spacers should stay the same size on mobile, but
larger vertical spacers should be shorter on mobile. Unless there’s a good reason to change this up, I’d recommend giving
this setup a shot before changing it</li>
  <li>Spacers can be stacked without issue in most places, so if you need a 30px vertical space you can place a 1x and a 2x
as a stack. If there’s a good reason for spacing on the site to use lots of 30px (or other somewhat-arbitrary size),
it might make sense early on to tweak <code class="language-plaintext highlighter-rouge">--spacing--single</code> or augment other CSS values so stacks aren’t necessary</li>
  <li>The driving force behind having spacer components stems from something that happened in QA all the time before we had
them in our toolbox: most of the designers’ notes about how the implementation differed from the original mocks tended
to be small differences in vertical spacing. With spacer components we can tweak vertical spacing without writing a
bunch more CSS of increasing specificity during the QA phase</li>
  <li>Another advantage here is that we can increase the space between components at any time, just to ensure the breathing
room between, for instance, a paragraph of text and a CTA button, <em>feels rhythmic</em> and comfortable, even if it differs
from the original design</li>
</ul>

<h5 id="table">Table</h5>

<p>Before clicking into the settings tab of the Table component and seeing the weird junk tables can do out of the box, there
are a few main things to touch on when it comes to tables:</p>

<ul>
  <li>It’s been around 15 years since it’s been in any way acceptable to use HTML <code class="language-plaintext highlighter-rouge">&lt;table&gt;</code>s for page layout, so hopefully
it’s not surprising that the table component here is set up specifically for storing and displaying table data <em>only</em></li>
  <li>In order to comply with accessibility requirements and be a good internet citizen, <strong>any table design must have a brief,
descriptive caption above the table, then a header row where the prominently-styled cells describe what’s in their column</strong></li>
  <li>The tablefield module, which frost uses for this component, has extension modules that allow for things like HTML markup
in cells and setting up colspan and rowspan (HTML’s way of merging cells). These modules are turned off, though, because
those feature could be seen as encouraging the kind of table-misuse behaviors I was just talking about. If you have
a legitimate edge case for using those features, you developer can enable them</li>
</ul>

<p>The component has a streamlined way of entering table data, plus the table caption and other info. If you have a lot of
data, the “Import from CSV” feature will come in handy.</p>

<p>As far as settings go, the table itself isn’t set up to be modified at all. However, <strong>the interactive charts and graphs
have some options</strong>:</p>

<ul>
  <li>The chart can have a <strong>Chart title</strong> that’s distinct from the table caption, to describe what the chart shows</li>
  <li>You can choose between a few <strong>chart types</strong>, though you only can show one chart per table: vertical bar, horizontal
bar, pie, line, and stacked</li>
  <li>There’s a checkbox to <strong>Replace table with graph</strong>, which visually hides the source data table in favor of the chart</li>
  <li>Since the x-axis label is most often the text in the top left cell of the table, there’s a <strong>Y Axis label</strong> field for
describing the scale of the data</li>
</ul>

<p>As noted in the color section of the base styles <em>way</em> earlier in this post, the charts and graphs use an auto-generated
color scheme based on the <code class="language-plaintext highlighter-rouge">--color--main</code> hex code that’s usually pretty appropriate for the site theme. You can provide
the developer with your own hex codes instead, if you want full control over the chart colors.</p>

<p>Otherwise, here are some design keys regarding both tables and the charts:</p>

<ul>
  <li>The charts are generated by the Highcharts library. While Highcharts has an API and styling selectors, I’d recommend
<strong>avoiding trying to customize the charts much, if at all</strong>, beyond picking a color scheme. It’s a real <em>here by dragons</em>
part of the frontend codebase</li>
  <li>While you can design the data tables any way you like, I’ve found over the years that, since tables aren’t usually used
all that much and the markup is kind of complex, simple table designs make everyone happier, including end-users</li>
  <li>The table component has a wrapper <code class="language-plaintext highlighter-rouge">&lt;div&gt;</code> that shows the table in the horizontal scroll box on narrow tablets and mobile
devices. Other responsive table strategies are available, but that’s the one currently in place, so without increasing
scope you have that going for you. If you’re using lots of tables and need a more streamlined approach, that’s another
thing to discuss with your developer as early as possible</li>
  <li>Tables are great for what they’re good for, but… if you’re using lots of tables and charts and graphs it may be a
sign that either you’re a data-driven site, or that you’re mis-using the feature. Something to look out for</li>
</ul>

<h5 id="term-listing">Term listing</h5>

<p>Gonna level with you: the Term listing component exists mostly to fill out the list, rather than being something anyone
might use with any regularity. Taxonomy terms like ‘tags’ in frost have Names/titles, short body text, a field for a teaser
image, and all the things you’d need to render them as teasers, so…</p>

<p>Yeah, you can make listings of tags as teasers and make the stacks, side-by-side, or carousels. Clicking a teaser takes
you to that tag’s listing page, which itself is a little bit of content followed by side-by-side teasers of tagged content.</p>

<p>The advice in the “Content listing” component section about coming up with a sort-of-generalized ‘teaser’ style comes into
play here, since a well-designed teaser style means this component will <em>just work</em>, even if you didn’t do anything specific
to design for it.</p>

<h5 id="user-listing">User listing</h5>

<p>Ditto all the stuff from the “Term listing” component section above for the user listing. If your teasers look good, you
get robust little lists of users for free.</p>

<p>Unlike the term listing, though, there’s a common-enough use case for user listings to highlight that it might make sense
to account for a user listing (and user teasers) in your designs:</p>

<p>If you have an <strong>About page</strong> that lists your company leadership or overall staff, a user listing can help automate keeping
it updated. Each user can manage their own little profile with a biography and portrait and the like (and administrators
can also manage those profiles). If those profiles should be publicly-viewable, and especially if the staff also author
content like blog posts, user listings and profiles and stuff can be a great way to keep your users clicking through pages
that interest them.</p>

<h5 id="view">View</h5>

<p>Views in Drupal are flexible displays that can be context-aware, so you can make a blog listing that auto-updates when
new content is added, or make a custom interface for your search page. frost comes out of the box with a bunch of useful
Views displays that we’ll cover in a separate post, but overall Views embedded via this component will reuse other component
styles, like:</p>

<ul>
  <li>Field with label</li>
  <li>Teaser</li>
  <li>Table</li>
  <li>Stack/side-by-side/carousel layout</li>
  <li>Pager</li>
  <li>Form</li>
  <li>…and others</li>
</ul>

<p>Some quick design notes, given that Views show other components:</p>

<ul>
  <li>If a Views listing has an ‘exposed’ form for refining and filtering the results, that form will be collapsed by default
and <strong>available via a toggle button on mobile</strong>. This allows for less scrolling and confusion when landing on a listing
page on a phone. This is true for all Views except the main search display, which shows the form by default instead</li>
  <li>The frost Views kit comes with Views you may want to place in your designs: 3 related teasers side-by-side, 3 recent
teasers side-by-side that can be narrowed to a particular content type to match</li>
  <li>If you’d like to do something clever to show relevant content to users, discussing Views’ power with your developer
will almost certainly be a fruitful conversation</li>
</ul>

<h5 id="webform">Webform</h5>

<p>The webform module lets you build flexible forms that get stored on the website and can also be forwarded to admins via
email or sent via API to other services.</p>

<p><strong>A big source of confusion among people who aren’t full-time professional Drupal developers is</strong> that there are lots of
forms on Drupal sites that <em>aren’t</em> webforms. Many of those forms can be easily modified and redesigned away from their
default appearance and behavior, but doing so isn’t as quick and easy as making contact forms and stuff with webform.</p>

<p>Additionally, <strong>even developers fall into a trap I recommend you avoid</strong>: since making webforms is so easy for most anybody,
it’s tempting to build out web-app-like functionality using webform, and then do things with ‘handlers’ to perform actions
and generate content. This approach <strong>works until it doesn’t</strong>, as the more you load up webform the more you have to wrestle
against it.</p>

<p>Some design notes:</p>

<ul>
  <li>Like overall Drupal fields (which I may find a place to discuss either in this huge post or elsewhere), forms should
start with an overall style: what does a simple textfield look like? Typically you want a label on top, perhaps a light
grey placeholder that indicates what kind of input to put in the field (though this can be counterintuitive for users,
and some designers misuse the placeholder functionality), and a one-row text box with some padding and a border that
can be rounded and all that jazz. And then the form field should likely have some space between it and the next field</li>
  <li>From the general style for any form field, you can then style individual fields as shown in the webform demo of the
<a href="https://www.frostdrupal.com/page/component-guide">frost component guide</a>. Things like radios, checkboxes, date pickers,
and more are all technically style-able, even if in some cases the default is familiar, usable, and accessible to the
most users. Getting really involved when it comes to form styling is a way to increase frontend development scope, but
is also a way to make a site feel truly custom</li>
  <li>If you’re planning to use what’s called the “Float label pattern” when the field label is crammed inside the form field
until the user focuses on it… <strong>don’t</strong>. It’s bad, it’s a lot of frontend dev work, and nobody will be happy about
it, including many end-users</li>
  <li>A great way to differentiate a form’s appearance, even if things like radio buttons and checkboxes use browser defaults,
is to get creative with how <code class="language-plaintext highlighter-rouge">&lt;fieldset&gt;</code>s look. In frost the fieldset’s legend is bold and centered, carrying along
the old-fashioned browser style of the legend intersecting the fieldset’s top border, but there are lots of directions
you could go, just so long as it’s a box with some legend text that contains form fields related to that descriptive
legend</li>
</ul>

<p>Otherwise, since the webform component is used to insert a form anywhere you want on the page, the design really comes down
to how you want forms to look on the site.</p>

<h2 id="fifth-wrapper">Fifth, wrapper</h2>

<p>Most sites (that aren’t hand-coded page-by-page) tend to have a similar design concept, and frost is no exception:
<strong>the content area is set up to be editable, while the header, footer, and sometimes a wrapper or sidebar are elements
designed once to match the brand and don’t change much page-to-page</strong>. This might seem obvious, but overall it means you
can go in any direction you want for the header and footer, even if content authors mess up your aesthetic a bit in the
in-between parts.</p>

<figure class="figure figure--image figure--image--frost-header-footer-desktop-png box-shadow--lifted-edges">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_header-footer-desktop.png.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_header-footer-desktop.png.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/frost_header-footer-desktop.png" alt="Screenshot showing the header and footer of the frost demo site on desktop" loading="lazy" height="668" width="1269" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/frost_header-footer-desktop.png" alt="Screenshot showing the header and footer of the frost demo site on desktop" loading="lazy" />
      </noscript>
    
    
  </figure>

<p>Of course, the setup that frost ships with isn’t a terrible start:</p>

<ul>
  <li>Header starts with the optional ability to show site-wide alerts, like “We’ll be closed for the fourth of July holiday”</li>
  <li>Main header has the logo/branding, main menu, and a search icon toggle</li>
  <li>Footer has columns for branding and contact info, a secondary menu, and site social icons</li>
  <li>After the main footer is a shorter section for the copyright statement, terms and privacy policy links, etc.</li>
  <li>After the footer and sticky to the bottom of the viewport until you close it is a very general, lightweight cookie prompt</li>
</ul>

<p>These can all be added, removed, tweaked, and massaged to make a header and footer that direct users to the right places
and best convey your site’s brand.</p>

<p>The frost project is working on easy-to-add dropdown and mega menus for the main navigation, but those features aren’t available
quite yet, so while you may need those features, technically they will require your developer to make them happen.</p>

<p><strong>One great way to keep scope in check for the header</strong> is to follow the out-of-the-box philosophy for mobile devices:</p>

<figure class="figure figure--image figure--image--frost-mobile-tray-png box-shadow--lifted-edges">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_mobile-tray.png.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_mobile-tray.png.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/frost_mobile-tray.png" alt="Screenshot showing the mobile hamburger tray open in the frost demo" loading="lazy" height="745" width="496" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/frost_mobile-tray.png" alt="Screenshot showing the mobile hamburger tray open in the frost demo" loading="lazy" />
      </noscript>
    
    
  </figure>

<p>The main header section can be thought of as two parts:</p>

<ol>
  <li>The logo/branding block</li>
  <li>A big box holding the main nav, search, and other stuff on desktop, that turns into a sliding ‘tray’ on mobile</li>
</ol>

<p>The tray gets toggled by a hamburger icon. When the tray is opened, there’s a slick little animation that turns the hamburger
into an ‘x’ visually, which is a neat little detail.</p>

<p>What’s useful about this philosophical approach is that you’re not juggling a bunch of different items’ visibility or putting
in duplicate blocks or anything, just to accommodate the visual differences between the desktop and mobile designs. You’re
just going, “<strong>Everything that’s not the logo will be in the hamburger tray, in roughly the same order they appear on desktop,
albeit vertically</strong>”.</p>

<p>I’ll once again stress that <strong>you don’t <em>have to</em> follow this guidance about header philosophy</strong>, but doing so is helpful
to manage development scope and overall complexity. It’s also pretty good at the whole <em>omnichannel</em> buzzword, where looking
at the site on mobile resembles the desktop experience enough that users feel more like they’re on the same site. Some designs
deviate enough between desktop and mobile to feel more like two different sites, which some would say is a missed opportunity.</p>

<p>There’s a lot that can be said about header and footer design, but rather than making this post even <em>longer</em>, I’ll leave
you with <em>one</em> design note, based on a problem I encountered on two recent designs:</p>

<ul>
  <li>The copyright statement should be on its own line (with links to the privacy policy and terms), full stop. It is weird
to put the copyright statement in a column of the footer, and your design with an abbreviated copyright statement to
make the text fit in a column <strong>will absolutely lose out to any legal advisor’s guidance</strong>, so just keep the copyright
statement in the same place as every other website ever</li>
</ul>

<h2 id="sixth-page-mockups">Sixth, page mockups</h2>

<p>In case this book of a design handoff blog post hasn’t made it obvious, us developers thrive on precise written comminication.
You can endear yourself to developers by annotating your designs with things that aren’t otherwise obvious, or things that
are especially important to you so they have the tools they need to get it right.</p>

<p>Right, so bringing together all the components with the header and footer to make various page-level designs is pretty common
for getting client approval. With all the words above, you can feel confident you’ve nailed all the constituent parts, so
all that’s left if putting the toy bricks together.</p>

<p>Key notes:</p>

<ul>
  <li>Unless the client firmly demands mobile comps (and the estimate reflects the risk to scope this almost always presents),
<strong>it’s probably in everyone’s best interest to only do desktop page mocks</strong>. In frost responsiveness of the layouts
and components comes along logically and for free, so you’ll likely only have to tweak a few things here and there.
Designing for mobile specifically usually results in big headaches between expectation and reality, as the designs take
more creative liberties than is likely advisable in <em>systems design</em></li>
  <li>Every page should have a hero containing the page title as an <code class="language-plaintext highlighter-rouge">&lt;h1&gt;</code>, even if the heroes differ somewhat in appearance
between different page types</li>
  <li>You can throw any combination of storytelling components with any amount of spacing into whichever layouts make the
most sense, with the biggest consideration being the appropriate heading levels as illustrated in the heading component
section</li>
  <li>I’ve found that using the stripes to alternate between backgrounds for thematic sections (see <a href="https://www.frostdrupal.com/page/privacy-policy">the frost demo privacy policy</a>
for an example) is a great way to organize content while providing visual interest and breathing room. When other colors
or images aren’t quite right, alternating between white and light grey for background gets the job done well</li>
</ul>

<h3 id="three-heroes">Three heroes</h3>

<p>One of the coolest parts of frost is <a href="https://github.com/solve-it-once/frost/blob/master/docroot/modules/custom/frost_custom/src/Plugin/Block/HeroTitleBlock.php">a beautifully-coded block</a>
that automatically picks the right hero to insert on the page for you. The following three sections describe the kinds of
heroes you’ll encounter and have to design for.</p>

<h4 id="fallback-default-and-system-pages">Fallback default and ‘system’ pages</h4>

<p>The first hero, and the one that’s the least flexible, is the one that appears on ‘system’ pages:</p>

<figure class="figure figure--image figure--image--frost-hero-fallback-png box-shadow--lifted-edges">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_hero-fallback.png.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_hero-fallback.png.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/frost_hero-fallback.png" alt="Screenshot showing the plain fallback hero for system pages in frost" loading="lazy" height="608" width="1027" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/frost_hero-fallback.png" alt="Screenshot showing the plain fallback hero for system pages in frost" loading="lazy" />
      </noscript>
    
    
  </figure>

<p>On pages like the user login, user register, and if you create standalone pages for things like webforms or views, or anything
else where you’re not going to an edit screen and moving components around, the only piece of information we reliably have
is the page title, so the content of the hero is just the page title.</p>

<p>However, the following notes apply:</p>

<ul>
  <li>If so desired, the hero’s vertical padding could be smaller on system pages, and other styling can be applied to just
heroes on system pages</li>
  <li>The system ships with a CSS class applied to the system heroes that gives it the default background image mentioned
in the second section (Assets) of this novel. If you’d rather use a solid background color or a different image, that
can be done easily, and it will apply to all non-overridden system page heroes</li>
  <li>While it would take developer time per page, some system pages can have distinct override styles, like a different background
image or something like that. Ideally this would be done sparingly, and <strong>please resist the temptation to put any content
other than the page title in <em>any</em> system page hero design</strong>, as that will make the developer very sad</li>
</ul>

<h4 id="per-bundle-pre-configured-heroes">Per-bundle pre-configured heroes</h4>

<p>Each type of content: article, event, page, tag, product, user, and more (any ‘entity’ bundle that has its own page) can
be set up with what’s called a “view mode” or “display mode” <em>named</em> <strong>hero</strong> that, when present in the site’s configuration,
will replace the “system page” hero style above.</p>

<figure class="figure figure--image figure--image--frost-hero-bundle-event-png box-shadow--lifted-edges">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_hero-bundle-event.png.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_hero-bundle-event.png.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/frost_hero-bundle-event.png" alt="Screenshot showing the per-bundle hero for events in frost" loading="lazy" height="724" width="1216" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/frost_hero-bundle-event.png" alt="Screenshot showing the per-bundle hero for events in frost" loading="lazy" />
      </noscript>
    
    
  </figure>

<p>The illustration above shows how the hero for an event appears. An <em>ambitious site builder</em> (or more likely the developer
you know and love) can build out the layout from the admin UI, the same way they build out the rest of the page or the teaser:</p>

<figure class="figure figure--image figure--image--frost-hero-event-bundle-config-png box-shadow--lifted-edges">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_hero-event-bundle-config.png.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_hero-event-bundle-config.png.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/frost_hero-event-bundle-config.png" alt="Screenshot showing how the event hero is configured in the admin UI" loading="lazy" height="1183" width="1341" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/frost_hero-event-bundle-config.png" alt="Screenshot showing how the event hero is configured in the admin UI" loading="lazy" />
      </noscript>
    
    
  </figure>

<p>The hero for a piece of content is a good place to put fields that contain bite-sized and at-a-glance info, like an event’s
location and date, an article’s byline, and in many cases the teaser image or social share image for that content (which
leverages the psychological principle of <strong>priming</strong>: you see the image on a social media site or the teaser on a listing
page, click the link, then see the same image and go “That’s the same image, I’ve landed in the right place, I’m going to
think of this content any time I see that image or ones like it,” at least somewhat non-cynically).</p>

<p>What’s great about these heroes for things like events, articles, products, and tags is that as a content author you want
to focus on making compelling content, rather than custom designing a hero every time you want to write a press release,
so with this default setup you have something that looks good and is effective at communicating necessary information in
a consistent way from page to similar page.</p>

<p>But this is frost, so of course there’s going to be a more flexible and customizable option involving components…</p>

<h4 id="stripe-atomic-heroes">Stripe: Atomic heroes</h4>

<p>The last hero type, the ultimate override in the beautifully-coded hero block, and by far the coolest hero type, is just
using a stripe like all the others:</p>

<figure class="figure figure--image figure--image--frost-hero-stripe-atomic-png box-shadow--lifted-edges">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_hero-stripe-atomic.png.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_hero-stripe-atomic.png.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/frost_hero-stripe-atomic.png" alt="Screenshot showing a stripe hero on the component guide page of the frost demo site" loading="lazy" height="458" width="1304" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/frost_hero-stripe-atomic.png" alt="Screenshot showing a stripe hero on the component guide page of the frost demo site" loading="lazy" />
      </noscript>
    
    
  </figure>

<p>Anything you can do with an atomic stripe, and any component you can place elsewhere on the site, you can <em>technically</em>
place in a stripe hero:</p>

<figure class="figure figure--image figure--image--frost-hero-atomic-stripe-edit-png box-shadow--lifted-edges">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_hero-atomic-stripe-edit.png.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_hero-atomic-stripe-edit.png.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/frost_hero-atomic-stripe-edit.png" alt="Screenshot showing the editing experience for an atomic hero" loading="lazy" height="1090" width="1304" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/frost_hero-atomic-stripe-edit.png" alt="Screenshot showing the editing experience for an atomic hero" loading="lazy" />
      </noscript>
    
    
  </figure>

<p>This means you can easily make heroes that have:</p>

<ul>
  <li>Background images</li>
  <li>Background videos</li>
  <li>Big spacers</li>
  <li>Layouts with multiple columns</li>
  <li>Additional text, media, and components</li>
  <li>Easy-to-edit CTA button links</li>
</ul>

<p>With great power comes great responsibility, though, so please heed these notes:</p>

<ul>
  <li>Every hero must contain the page title in an <code class="language-plaintext highlighter-rouge">&lt;h1&gt;</code> tag, and the h1 should probably look like all the other h1 titles
on the site, which goes in line with the thing I said about priming in the previous section. The user is getting familiar
with what different things look like on the site, so making the hero look consistent helps the user understand the site</li>
  <li>You can <em>kind of</em> ignore the previous bullet on the <strong>home page specifically</strong>. Users expect more of a “This is what
we do” tagline in the home page hero. That tagline should have relevant keywords and should have a prominent appearance,
and its tag should absolutely be an <code class="language-plaintext highlighter-rouge">&lt;h1&gt;</code>, but it doesn’t necessarily have to look like all the other site h1s</li>
  <li>In testing you’ll probably find that <em>busy</em> heroes don’t perform as well as simple, direct ones</li>
  <li>As with any stripe, the background color/image should contrast with the chosen text color</li>
</ul>

<p>And… that’s all I have to say about that. You survived!</p>

<h2 id="wrapping-up">Wrapping up</h2>

<p>That was a lot of stuff. Thanks for sticking around!</p>

<p>The big things to take away from this article, aside from the specific notes, are:</p>

<ol>
  <li>When in doubt, design the smallest pieces first, as they’re then used in combination in larger components</li>
  <li>Since the system ships with reasonable defaults, not everything has to be designed or developed in one fell swoop.
    If your team is comfortable with it, you can deliver a Minimum Viable Product for the design, then tack on more components
    and page designs as you go</li>
  <li>There’s nothing that specifically stops you from designing how you always have, with the developer(s) doing the adapting
    of the mock-ups into base styles and components, but perhaps something in this handoff gave you an idea for tweaking
    the process or deliverables</li>
  <li>Any component, any style, can be adapted to suit your needs with just a little added development, so take the defaults
    as a jumping-off point. If the project has a small budget/scope, perhaps err on the side of the defaults, but for an
    ambitious experience you can dial in the brand and aesthetic</li>
  <li>Hopefully the places where I said “you should probably stick to such-and-such” make sense as being ways to maintain
    the integrity of the system and keep scope in check, rather than getting in the way of creative freedom or making all
    sites designed this way look same-y. You can break away from almost any of these guidelines as long as you and the team
    are okay with the scope implications</li>
</ol>

<p>We hope you have as much fun designing for frost as we do developing with it!</p>

<p>And of course, if you run into any snags or want to hire Brad for a few hours to iron something out, please don’t hesitate
to <a href="mailto:brad@solveitonce.com">reach out to brad@solveitonce.com</a>.</p>
]]></content:encoded>
      </item>
    
      <item>
        <title>.github org template</title>
        <link>http://solveitonce.com/blog/github-org-repo/</link>
        <pubDate>Mon, 22 May 2023 00:00:00 EST</pubDate>
        
          
          <dc:creator>Brad Czerniak</dc:creator>
        
        
        
          <category><![CDATA[git]]></category>
        
        <guid isPermaLink="true">http://solveitonce.com/blog/github-org-repo/</guid>
        <description><![CDATA[Today I wanted to focus on a quick win for anyone who uses GitHub: a template repository for doing a bunch of cool GitHub
things automatically.

tl;dr you can use solve-it-once/.github as a template repo to ensure your
GitHub organization (or individual account) has a default version of all the markdown and yaml files that GitHub uses in
its interface.


    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
      Either click the green drop-button as shown, or fork the repo to your organization
    
  

What .github has

First things first: .github can be the name of a special repository located within an account or organization, or it
can be the name of a directory in any repository that contains the same or similar files to those in the solve-it-once example.

If an org has a .github repository, the markdown and yaml files within it are the default policies and templates for the
whole organization. A .github/ directory within a particular repo in that org will override those defaults, so you can
have a different code of conduct for one project while all the others use the default, for instance.

All the files in solve-it-once/.github are worded as generically as possible,
so in many cases you don’t have to change a single thing… though you’re certainly welcome to!


  CODE_OF_CONDUCT.md — a generic version of the Contributor Covenant
  CONTRIBUTING.md — instructions and external links for making pull requests and other contribution activities
  FUNDING.yml — config to show a pay/tip link in the repo sidebar
  LICENSE — MIT license as the default when not overridden
  PULL_REQUEST_TEMPLATE.md — text with instructions/scaffolding for the text box when submitting a pull request
  SECURITY.md — a security policy and tracker document
  SUPPORT.md — instructions for seeking software support and reporting bugs, for non-developers
  readme.md — brief readme specific to the template repo, that can be deleted if you’d like
  ISSUE_TEMPLATE/ — folder of different kinds of text box defaults for submitting GitHub issues
  profile/README.md — profile text for your organization landing page. Can be customized for marketing purposes
  workflows/ — folder with an example: CodeQL analysis/scanning on any supported repo


How to make it your own

To include a .github repository in your account or organization:


  Navigate to https://github.com/solve-it-once/.github
  Click the green “Use this template” dropbutton (or fork the repository) and select “Create a new repository”. Follow the instructions to create the repo where you want it
  Edit line 47 of CODE_OF_CONDUCT.md to an appropriate email address
  Change the URL in FUNDING.yml or remove the file entirely
  (If necessary) Swap the default LICENSE from MIT to whichever you prefer
  Edit line 27 of SECURITY.md to an appropriate email address
  Most importantly edit profile/README.md so it’s not an ad for Solve it once (this is for your sake, not mine)


Of course, you can also tweak any of the other files as you desire, but those are the steps that will most appropriately
make this exercise worthwhile.

Alternative: directory in repo

You may already be familiar with .github directories in repositories, especially if you’ve used GitHub Actions that live
in a workflows folder.

The solve-it-once/.github repo can be used as a guide/template for a repo directory,
or — whether cloning the repo or downloading a release zip/tar file — can be copied and pasted into the root of your project.

The instructions for doing that are similar to the section above, with the following recommended changes:


  Ensure the .git/ directory, if present, is removed, as otherwise you could accidentally make the directory a submodule
  Get rid of the root readme.md and entire profile/ directory, as these do not apply to individual repositories
  You’ll likely also want to ditch the LICENSE, as the root of the repo itself should contain that file


Example: Provisio

Provisio Technology Solutions manages a lot of git projects on Patheon and Azure, but
somewhat-recently started maintaining (private) forks on the Provisio GitHub org
for redundancy, ability to navigate the code easier, and the Pull Request tooling for code reviews.

In the span of 20 minutes Solve it once was able to generate Provisio’s .github repo
using the template repo button, tweak the profile readme, and enhance the company’s marketing presence on GitHub, which
has the potential to open new avenues for clients to find them.

Any repository within the Provisio organization now falls back to the provided policy documents and templates, in case they
are not provided for an individual repo.

Hope this helps!

Still here? Check out solve-it-once/.github for a helpful free head-start.
]]></description>
        <content:encoded><![CDATA[<p>Today I wanted to focus on a quick win for anyone who uses GitHub: a template repository for doing a bunch of cool GitHub
things automatically.</p>

<p><strong>tl;dr</strong> you can use <a href="https://github.com/solve-it-once/.github">solve-it-once/.github</a> as a template repo to ensure your
GitHub organization (or individual account) has a default version of all the markdown and yaml files that GitHub uses in
its interface.</p>

<figure class="figure figure--image figure--image--solve-it-once-github-screencap-png ">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/solve-it-once_github_screencap.png.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/solve-it-once_github_screencap.png.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/solve-it-once_github_screencap.png" alt="Screenshot of solve-it-once/.github repo page" loading="lazy" height="1253" width="1252" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/solve-it-once_github_screencap.png" alt="Screenshot of solve-it-once/.github repo page" loading="lazy" />
      </noscript>
    
    
      <figcaption class="figcaption figure--image--figcaption position--relative z-index--1">Either click the green drop-button as shown, or fork the repo to your organization</figcaption>
    
  </figure>

<h2 id="what-github-has">What .github has</h2>

<p>First things first: <code class="language-plaintext highlighter-rouge">.github</code> can be the name of a special repository located within an account or organization, <em>or</em> it
can be the name of a directory in any repository that contains the same or similar files to those in the solve-it-once example.</p>

<p>If an org has a .github repository, the markdown and yaml files within it are the default policies and templates for the
whole organization. A <code class="language-plaintext highlighter-rouge">.github/</code> directory within a particular repo in that org will override those defaults, so you can
have a different code of conduct for one project while all the others use the default, for instance.</p>

<p>All the files in <a href="https://github.com/solve-it-once/.github">solve-it-once/.github</a> are worded as generically as possible,
so in many cases you don’t have to change a single thing… though you’re certainly welcome to!</p>

<ul>
  <li><strong>CODE_OF_CONDUCT.md</strong> — a generic version of the <a href="http://contributor-covenant.org/">Contributor Covenant</a></li>
  <li><strong>CONTRIBUTING.md</strong> — instructions and external links for making pull requests and other contribution activities</li>
  <li><strong>FUNDING.yml</strong> — config to show a pay/tip link in the repo sidebar</li>
  <li><strong>LICENSE</strong> — MIT license as the default when not overridden</li>
  <li><strong>PULL_REQUEST_TEMPLATE.md</strong> — text with instructions/scaffolding for the text box when submitting a pull request</li>
  <li><strong>SECURITY.md</strong> — a security policy and tracker document</li>
  <li><strong>SUPPORT.md</strong> — instructions for seeking software support and reporting bugs, for non-developers</li>
  <li><strong>readme.md</strong> — brief readme specific to the template repo, that can be deleted if you’d like</li>
  <li><strong>ISSUE_TEMPLATE/</strong> — folder of different kinds of text box defaults for submitting GitHub issues</li>
  <li><strong>profile/README.md</strong> — profile text for your organization landing page. Can be customized for marketing purposes</li>
  <li><strong>workflows/</strong> — folder with an example: CodeQL analysis/scanning on any supported repo</li>
</ul>

<h2 id="how-to-make-it-your-own">How to make it your own</h2>

<p>To include a .github repository in your account or organization:</p>

<ol>
  <li>Navigate to <a href="https://github.com/solve-it-once/.github">https://github.com/solve-it-once/.github</a></li>
  <li>Click the green “Use this template” dropbutton (or fork the repository) and select “Create a new repository”. Follow the instructions to create the repo where you want it</li>
  <li>Edit line 47 of CODE_OF_CONDUCT.md to an appropriate email address</li>
  <li>Change the URL in FUNDING.yml or remove the file entirely</li>
  <li>(If necessary) Swap the default LICENSE from MIT to whichever you prefer</li>
  <li>Edit line 27 of SECURITY.md to an appropriate email address</li>
  <li><strong>Most importantly</strong> edit profile/README.md so it’s not an ad for Solve it once (this is for your sake, not mine)</li>
</ol>

<p>Of course, you can also tweak any of the other files as you desire, but those are the steps that will most appropriately
make this exercise worthwhile.</p>

<h3 id="alternative-directory-in-repo">Alternative: directory in repo</h3>

<p>You may already be familiar with .github directories in repositories, especially if you’ve used GitHub Actions that live
in a workflows folder.</p>

<p>The <a href="https://github.com/solve-it-once/.github">solve-it-once/.github</a> repo can be used as a guide/template for a repo directory,
or — whether cloning the repo or downloading a release zip/tar file — can be copied and pasted into the root of your project.</p>

<p>The instructions for doing that are similar to the section above, with the following recommended changes:</p>

<ul>
  <li>Ensure the .git/ directory, if present, is removed, as otherwise you could accidentally make the directory a submodule</li>
  <li>Get rid of the root readme.md and entire profile/ directory, as these do not apply to individual repositories</li>
  <li>You’ll likely also want to ditch the LICENSE, as the root of the repo itself should contain that file</li>
</ul>

<h3 id="example-provisio">Example: Provisio</h3>

<p><a href="https://provisiosolutions.com/">Provisio Technology Solutions</a> manages a lot of git projects on Patheon and Azure, but
somewhat-recently started maintaining (private) forks on <a href="https://github.com/provisiosolutions">the Provisio GitHub org</a>
for redundancy, ability to navigate the code easier, and the Pull Request tooling for code reviews.</p>

<p>In the span of 20 minutes <em>Solve it once</em> was able to generate <a href="https://github.com/provisiosolutions/.github">Provisio’s .github repo</a>
using the template repo button, tweak the profile readme, and enhance the company’s marketing presence on GitHub, which
has the potential to open new avenues for clients to find them.</p>

<p>Any repository within the Provisio organization now falls back to the provided policy documents and templates, in case they
are not provided for an individual repo.</p>

<h2 id="hope-this-helps">Hope this helps!</h2>

<p>Still here? Check out <a href="https://github.com/solve-it-once/.github">solve-it-once/.github</a> for a helpful free head-start.</p>
]]></content:encoded>
      </item>
    
      <item>
        <title>AgileInterface: so1ve&apos;s approach to project management</title>
        <link>http://solveitonce.com/blog/so1ve-approach-agile-interface/</link>
        <pubDate>Sun, 16 Apr 2023 00:00:00 EST</pubDate>
        
          
          <dc:creator>Brad Czerniak</dc:creator>
        
        
        
          <category><![CDATA[Agile]]></category>
        
          <category><![CDATA[Project Management]]></category>
        
        <guid isPermaLink="true">http://solveitonce.com/blog/so1ve-approach-agile-interface/</guid>
        <description><![CDATA[If you’ve read my fairly scathing critique of many project management techniques and
the Agile manifesto (external link), you might wonder: What project management technique
does Solve it once use?

When the “cross-functional team” delivering services is mostly one guy, is a team-focused process really necessary?
Would an individual productivity approach like GTD fit better for Solve it once?

Maybe, but agile in its various forms is well-understood in the software industry and beyond, and in the incarnation
used at Solve it once can be thought of as an interface more than anything else.

How we define and focus agile

Ignoring capital-A Agile being somehow distinct from lowercase-a agile in various circles, we see our agile method as a
direct implementation of the values from the Agile manifesto:


  Individuals and interactions: things like processes and tools can be used to bludgeon people with bureaucracy, but
they can also facilitate useful communication. At so1ve the GitHub issue queue for a codebase is the tool, some light
automated kanban is the process, but overwhelmingly the tool and process are meant to facilitate communication rather
than put up fences. We want to facilitate open conversations with our clients, and have a clear place to talk about
the work being done
  Working software: this is absolutely essential to our whole offering. The idea is to have working software as quickly
as possible, and to deliver working software at the end of every cycle. By focusing on the software as the desired final
product rather than all the documents, drawings, and other trashcan-destined artifacts that other companies build into
their bloated processes (even ‘agile’ ones!), we can keep our eyes on your prize
  Customer collaboration: we value candor, open communication, and visibility into how our software gets made. Everybody
gets at least a little nervous about the unknown, so by not having any big secrets we’re hiding from clients we can
approach every situation together with calm resolve
  Responding to change: a key part of being responsive to change is having a flexible software architecture. On top
of that, a context for change is necessary to avoid free-for-all chaos. For a company that wants to deliver sophisticated
content-management system websites with a turnaround as quick as 2 weeks, coming up with a plan and not deviating too much from it
during those weeks is important. But sometimes plans do have to change, so we need to balance responsiveness and predictability


beta canon: the principles we embrace

Along with the core of the manifesto, Solve it once also environmentally applies many of the 12 principles held up along
the four alpha-canon value balances:


  Early and continuous delivery of valuable software: per “Working software” above, delivering software as the value-add
    early and often undergirds our entire strategy for success
  Welcome changing requirements: like many agile frameworks, we construe the welcoming of changing requirements in
    the context of our delivery timescale, as changing a requirement for the current sprint is more disruptive than changing
    one for the next sprint
  Deliver frequently: by settling on a two-week sprint cycle for both sales and delivery, we have a known and useful
    constraint that can be used to focus our effort. This timescale is a big factor into how responsive to change we are
    within a two-week cycle
  Business and development, together: not only do we embrace this internally, in that Brad (or additional team members
    on occasion) do client communication and then do the direct software development work requested, but we also welcome
    non-developer business folks on the client side to see the software and how it’s made, early and often. These are teachable
    moments, and sometimes businesspeople fall in love with software in the process
  Environment and trust: we count on our clients to trust us to do an expert job, and are fortunate to be able
    to set our own environments and use our own tools
  Face-to-face conversation: we reject this notion from the principles. While we’re willing to meet in person,
    or to (gasp!) turn our cameras on in video calls, our lived experience is that a combination of synchronous and asynchronous
    written communication is better than face-to-face
  Working software: it’s good that working software is mentioned so often in 16 quick lines of text, because it’s
    the most important thing for a software company
  Sustainability: both for maintaining an alluring price on our offering, and to ensure we can keep up the pace in
    the long term, sprints are capped at 50 hours of work, which is 25 hours per week. In short spurts this means Brad could
    handle two projects concurrently, while being able to do one sprint at a time most of the time with plenty of time left
    in the week to take walks in the park
  Technical excellence and good design: the Solve it once approach would not be possible without having a great
    software starting point. Making new sites from scratch is a far less viable thing to promise in two-week cycles
  Simplicity: having made software with all the bloat of waterfall and other processes, and having seen the sheer
    amount of attributes every project has in common, we are able to avoid the unnecessary complexity of other firms
  Self-organizing teams: for the most part, the self-organizing team is Brad. When a project requires a better eye
    for graphic design or an expert on SEO or another topic, we can bring somebody in for as long as they’re needed,
    but overall people equate to complexity, and that defeats our elegant simiplicity in delivering software
  Retrospectives: you can check the revision history of the content on this site to get an idea of how our internal
    approach evolves over time. For the most part, the feedback we seek the most comes from our clients


How our process differs from others

Especially in the Drupal development world, the two most apparent frameworks for delivery are Scrum
and waterfall, though waterfall is effectively the antithesis of agile. Another candidate is Xtreme Programming (XP), which
I’ll touch on briefly.

Similarities and differences to Scrum


  We tend to avoid daily stand-ups or scrums, except for short spurts where more than one developer is on a project and
we’re both working in overlapping parts of the codebase. When needed, we prefer stand-ups to be done via group chat
using a template, rather than video calls. We’re somewhat variable in the frequency of relaying progress information
to clients, but tend to summarize about a week’s worth of work into progress reports when more-pressing questions and
feedback are absent halfway through a sprint
  We embrace the main client contact as the “Product Owner” role, and may even refer to a client contact as the ‘PO’ informally.
One difference between our concept of a PO and more-formalized Scrum is that we don’t necessarily consider a PO the
voice of the end user, just the voice of software customer. The PO is mostly tasked with communicating new or changing
requirements in a timely manner, and reviewing work product. Otherwise, any responsibilities a Product Owner in Scrum
might have that would require training are handled instead by Solve it once for simplicity
  For the most part, the “Scrum Master” and developer is the same person on all projects, even those not handled by Brad
  For simplicity, sprint planning and refinement are largely the same meeting. Actual refinement often occurs outside
a group context, with the results of any asynchronous refinement presented during sprint planning
  Some sprints will have a defined meeting for doing a review/demo, while others may not. It depends on how involved the
client is during the process and the nature of the work being done during the sprint
  Retrospectives as meetings is largely only when requested by the client. Retros tend to be slow ways of getting
feedback, so seeking feedback from the client at their leisure can save billable hours for more productive things


Maybe a mile from Xtreme Programming


  We’re not entirely opposed to pair programming, especially for training new developers, but anything that can be done
by one developer rather than two will save everybody money
  Testing is useful, and we write tests when appropriate. For the most part, though, test-driven development seems to
add more overhead than the benefit a project gets from full coverage (caveat: unit coverage mostly, as integration
tests tend to be more valuable)
  Code reviews are encouraged when the team has more than one developer, which is rare at Solve it once. We’ve seen
a lot of success on subcontract project with Brad doing code reviews and merging the team’s pull requests


A typical sprint in non-development overhead

A simple analysis that must be considered in the context of long-term software quality is the ratio of time spent developing
software vs. anything that isn’t developing software. Clearly, tasks like setting up local environments, setting up infrastructure,
and other necessary blocking tasks can be argued to either side of that ratio, but what follows is a rough estimate of time
used for non-development in a 50-hour sprint using Solve it once’s method:


  Repository, hosting, and issue/board setup: 2 hours
  Sprint planning: 1 hour
  Refinement, asynchronous: 1 hour
  Review/demo, retro, other rituals/ceremonies: 1 hour


Assuming this reflects a typical sprint, that yields a ratio of ten to one development versus non-development tasks.
Most other project methodologies couldn’t get close to that, but Solve it once differs by focusing on simplicity and putting
developers in charge of decisions that affect the software.

Note that selecting and placing an image asset, which might ordinarily be considered non-development because the asset is
often used by a designer to fill an empty space in a design artifact, in the Solve it once model is considered productive
in the development category because the resulting image or video is getting directly added to working software, and
any work that touches the software rather than trashcan artifacts is development.

What is meant by an interface

Having now outlined the fairly standard agile process followed on sprints at Solve it once, it bears consideration that
perhaps this isn’t new or revolutionary, but just one company’s refinement of an utterly-refinable concept. However, even
this much structure seems an artifice when talking about a team that’s usually one guy.

After all, in most cases having a straightforward checklist of personal tasks and a first-in, first-out mentality will yield
similar results for the most part. Something more sophisticated like GTD might even be overkill.

What makes an agile approach with a lot of the process details considered ahead of time worth it is where Solve it once’s
work touches clients and contractors:


  With a defined two-week sprint containing a fixed number of hours, a dedicated client contact with set methods of communication,
    and agreed-upon progress reporting and a couple meetings as needed, the client has clear expectations for the process,
    not just the product
  A designer, copywriter, SEO specialist, or other consultant can instantly have visibility when coming onto a project,
    can know what they have to do and by when, and can be involved in either a cross-functional sense or treated as a blocking
    resource


It’s in this manner that details surrounding how tasks are formatted and estimated — whether tasks have user stories and
acceptance criteria and testing steps and t-shirt sizes or points or hours, and if they’re referenced in feature branch
names and commit messages — are wholly unimportant to anyone but the one or two people working in them, while the location,
number, status, and other outward-facing attributes of the tasks are important both internally and to third parties.

We care, I care, about the implementation details of the Solve it once process, and use retrospective feedback to refine
the process. But more importantly for more people, so1ve approaches our agile process as a way to communicate, focusing
the most effort where the process intersects clients and contractors.

Get your Drupal website from Solve it once today
]]></description>
        <content:encoded><![CDATA[<p>If you’ve read <a href="https://solveitonce.com/blog/developers-lead-projects/">my fairly scathing critique of many project management techniques</a> and
<a href="https://agilemanifesto.org/">the Agile manifesto (external link)</a>, you might wonder: <strong>What project management technique
does <em>Solve it once</em> use?</strong></p>

<p>When the “cross-functional team” delivering services is mostly one guy, is a team-focused process really necessary?
Would an individual productivity approach like <a href="https://gettingthingsdone.com/">GTD</a> fit better for <em>Solve it once</em>?</p>

<p>Maybe, but <strong>agile</strong> in its various forms is well-understood in the software industry and beyond, and in the incarnation
used at <em>Solve it once</em> can be thought of as an <em>interface</em> more than anything else.</p>

<h2 id="how-we-define-and-focus-agile">How we define and focus agile</h2>

<p>Ignoring capital-A Agile being somehow distinct from lowercase-a agile in various circles, we see our agile method as a
direct implementation of the values from <a href="https://agilemanifesto.org/">the Agile manifesto</a>:</p>

<ul>
  <li><strong>Individuals and interactions</strong>: things like processes and tools can be used to bludgeon people with bureaucracy, but
they can also facilitate useful communication. At <em>so1ve</em> the GitHub issue queue for a codebase is the tool, some light
automated kanban is the process, but overwhelmingly the tool and process are meant to <em>facilitate communication</em> rather
than put up fences. We want to facilitate open conversations with our clients, and have a clear place to talk about
the work being done</li>
  <li><strong>Working software</strong>: this is absolutely essential to our whole offering. The idea is to have working software as quickly
as possible, and to deliver working software at the end of every cycle. By focusing on the software as the desired final
product rather than all the documents, drawings, and other trashcan-destined artifacts that other companies build into
their bloated processes (even ‘agile’ ones!), we can keep our eyes on your prize</li>
  <li><strong>Customer collaboration</strong>: we value candor, open communication, and visibility into how our software gets made. Everybody
gets at least a little nervous about the unknown, so by not having any big secrets we’re hiding from clients we can
approach every situation together with calm resolve</li>
  <li><strong>Responding to change</strong>: a key part of being responsive to change is having a flexible software architecture. On top
of that, a <em>context</em> for change is necessary to avoid free-for-all chaos. For a company that wants to deliver sophisticated
content-management system websites with a turnaround as quick as 2 weeks, coming up with a plan and not deviating <em>too much from it</em>
during those weeks is important. But sometimes plans do have to change, so we need to balance responsiveness and predictability</li>
</ul>

<h3 id="beta-canon-the-principles-we-embrace">beta canon: the <a href="https://agilemanifesto.org/principles.html">principles</a> we embrace</h3>

<p>Along with the core of the manifesto, <em>Solve it once</em> also environmentally applies many of the 12 principles held up along
the four alpha-canon value balances:</p>

<ol>
  <li><strong>Early and continuous delivery of valuable software</strong>: per “Working software” above, delivering software as the value-add
    early and often undergirds our entire strategy for success</li>
  <li><strong>Welcome changing requirements</strong>: like many agile frameworks, we construe the welcoming of changing requirements in
    the context of our delivery timescale, as changing a requirement for the current sprint is more disruptive than changing
    one for the next sprint</li>
  <li><strong>Deliver frequently</strong>: by settling on a two-week sprint cycle for both sales and delivery, we have a known and useful
    constraint that can be used to focus our effort. This timescale is a big factor into how responsive to change we are
    <em>within</em> a two-week cycle</li>
  <li><strong>Business and development, together</strong>: not only do we embrace this internally, in that Brad (or additional team members
    on occasion) do client communication and then do the direct software development work requested, but we also welcome
    non-developer business folks on the client side to see the software and how it’s made, early and often. These are teachable
    moments, and sometimes businesspeople fall in love with software in the process</li>
  <li><strong>Environment and trust</strong>: we count on our clients to trust us to do an expert job, and are fortunate to be able
    to set our own environments and use our own tools</li>
  <li><strong>Face-to-face conversation</strong>: we reject this notion from the principles. While we’re <em>willing</em> to meet in person,
    or to (gasp!) turn our cameras on in video calls, our lived experience is that a combination of synchronous and asynchronous
    <strong>written communication is better than face-to-face</strong></li>
  <li><strong>Working software</strong>: it’s good that working software is mentioned so often in 16 quick lines of text, because it’s
    the most important thing for a software company</li>
  <li><strong>Sustainability</strong>: both for maintaining an alluring price on our offering, and to ensure we can keep up the pace in
    the long term, sprints are capped at 50 hours of work, which is 25 hours per week. In short spurts this means Brad could
    handle two projects concurrently, while being able to do one sprint at a time most of the time with plenty of time left
    in the week to take walks in the park</li>
  <li><strong>Technical excellence and good design</strong>: the <em>Solve it once</em> approach would not be possible without having a great
    software starting point. Making new sites from scratch is a far less viable thing to promise in two-week cycles</li>
  <li><strong>Simplicity</strong>: having made software with all the bloat of waterfall and other processes, and having seen the sheer
    amount of attributes every project has in common, we are able to avoid the unnecessary complexity of other firms</li>
  <li><strong>Self-organizing teams</strong>: for the most part, the self-organizing team is Brad. When a project requires a better eye
    for graphic design or an expert on SEO or another topic, we can bring somebody in for as long as they’re needed,
    but overall people equate to complexity, and that defeats our elegant simiplicity in delivering software</li>
  <li><strong>Retrospectives</strong>: you can check the revision history of the content on this site to get an idea of how our internal
    approach evolves over time. For the most part, the feedback we seek the most comes from our clients</li>
</ol>

<h2 id="how-our-process-differs-from-others">How our process differs from others</h2>

<p>Especially in the Drupal development world, the two most apparent frameworks for delivery are <a href="https://www.scrum.org/">Scrum</a>
and waterfall, though waterfall is effectively the antithesis of agile. Another candidate is Xtreme Programming (XP), which
I’ll touch on briefly.</p>

<h3 id="similarities-and-differences-to-scrum">Similarities and differences to Scrum</h3>

<ul>
  <li>We tend to avoid daily stand-ups or scrums, except for short spurts where more than one developer is on a project and
we’re both working in overlapping parts of the codebase. When needed, we prefer stand-ups to be done via group chat
using a template, rather than video calls. We’re somewhat variable in the frequency of relaying progress information
to clients, but tend to summarize about a week’s worth of work into progress reports when more-pressing questions and
feedback are absent halfway through a sprint</li>
  <li>We embrace the main client contact as the “Product Owner” role, and may even refer to a client contact as the ‘PO’ informally.
One difference between our concept of a PO and more-formalized Scrum is that we don’t necessarily consider a PO the
voice of the end user, just the voice of software customer. The PO is mostly tasked with communicating new or changing
requirements in a timely manner, and reviewing work product. Otherwise, any responsibilities a Product Owner in Scrum
might have that would require training are handled instead by <em>Solve it once</em> for simplicity</li>
  <li>For the most part, the “Scrum Master” and developer is the same person on all projects, even those not handled by Brad</li>
  <li>For simplicity, sprint planning and refinement are largely the same meeting. Actual refinement often occurs outside
a group context, with the results of any asynchronous refinement presented during sprint planning</li>
  <li>Some sprints will have a defined meeting for doing a review/demo, while others may not. It depends on how involved the
client is during the process and the nature of the work being done during the sprint</li>
  <li>Retrospectives as meetings is largely <strong>only when requested by the client</strong>. Retros tend to be slow ways of getting
feedback, so seeking feedback from the client at their leisure can save billable hours for more productive things</li>
</ul>

<h3 id="maybe-a-mile-from-xtreme-programming">Maybe a mile from Xtreme Programming</h3>

<ul>
  <li>We’re not entirely opposed to pair programming, especially for training new developers, but anything that can be done
by one developer rather than two will save everybody money</li>
  <li>Testing is useful, and we write tests when appropriate. For the most part, though, test-driven development seems to
add more overhead than the benefit a project gets from full coverage (caveat: unit coverage mostly, as integration
tests tend to be more valuable)</li>
  <li>Code reviews are encouraged when the team has more than one developer, which is rare at <em>Solve it once</em>. We’ve seen
a lot of success on subcontract project with Brad doing code reviews and merging the team’s pull requests</li>
</ul>

<h2 id="a-typical-sprint-in-non-development-overhead">A typical sprint in non-development overhead</h2>

<p>A simple analysis that must be considered in the context of long-term software quality is the ratio of <strong>time spent developing
software vs. anything that isn’t developing software</strong>. Clearly, tasks like setting up local environments, setting up infrastructure,
and other necessary blocking tasks can be argued to either side of that ratio, but what follows is a rough estimate of time
used for non-development in a 50-hour sprint using <em>Solve it once</em>’s method:</p>

<ul>
  <li>Repository, hosting, and issue/board setup: <strong>2 hours</strong></li>
  <li>Sprint planning: <strong>1 hour</strong></li>
  <li>Refinement, asynchronous: <strong>1 hour</strong></li>
  <li>Review/demo, retro, other rituals/ceremonies: <strong>1 hour</strong></li>
</ul>

<p>Assuming this reflects a typical sprint, that yields a ratio of <strong>ten to one</strong> development versus non-development tasks.
Most other project methodologies couldn’t get close to that, but <em>Solve it once</em> differs by focusing on simplicity and putting
developers in charge of decisions that affect the software.</p>

<p>Note that selecting and placing an image asset, which might ordinarily be considered non-development because the asset is
often used by a designer to fill an empty space in a design artifact, in the <em>Solve it once</em> model is considered productive
in the development category because the resulting image or video is getting directly added to <strong>working software</strong>, and
any work that touches the software rather than trashcan artifacts is development.</p>

<h2 id="what-is-meant-by-an-interface">What is meant by an <em>interface</em></h2>

<p>Having now outlined the fairly standard agile process followed on sprints at <em>Solve it once</em>, it bears consideration that
perhaps this isn’t new or revolutionary, but just one company’s refinement of an utterly-refinable concept. However, even
this much structure seems an artifice when talking about a team that’s usually one guy.</p>

<p>After all, in most cases having a straightforward checklist of personal tasks and a first-in, first-out mentality will yield
similar results for the most part. Something more sophisticated like GTD might even be overkill.</p>

<p>What makes an agile approach with a lot of the process details considered ahead of time worth it is where <em>Solve it once</em>’s
work touches clients and contractors:</p>

<ol>
  <li>With a defined two-week sprint containing a fixed number of hours, a dedicated client contact with set methods of communication,
    and agreed-upon progress reporting and a couple meetings as needed, the client has clear expectations for the process,
    not just the product</li>
  <li>A designer, copywriter, SEO specialist, or other consultant can instantly have visibility when coming onto a project,
    can know what they have to do and by when, and can be involved in either a cross-functional sense or treated as a blocking
    resource</li>
</ol>

<p>It’s in this manner that details surrounding how tasks are formatted and estimated — whether tasks have user stories and
acceptance criteria and testing steps and t-shirt sizes or points or hours, and if they’re referenced in feature branch
names and commit messages — are wholly unimportant to anyone but the one or two people working in them, while the location,
number, status, and other outward-facing attributes of the tasks are important both internally and to third parties.</p>

<p>We care, <em>I</em> care, about the implementation details of the <em>Solve it once</em> process, and use retrospective feedback to refine
the process. But more importantly for more people, <strong><em>so1ve</em> approaches our agile process as a way to communicate, focusing
the most effort where the process intersects clients and contractors</strong>.</p>

<p><a href="https://solveitonce.com/products/drupal-site/">Get your Drupal website from <em>Solve it once</em> today</a></p>
]]></content:encoded>
      </item>
    
      <item>
        <title>Introducing frost</title>
        <link>http://solveitonce.com/blog/introducing-frost/</link>
        <pubDate>Sat, 15 Apr 2023 00:00:00 EST</pubDate>
        
          
          <dc:creator>Brad Czerniak</dc:creator>
        
        
        
          <category><![CDATA[Meta]]></category>
        
          <category><![CDATA[Drupal]]></category>
        
        <guid isPermaLink="true">http://solveitonce.com/blog/introducing-frost/</guid>
        <description><![CDATA[It seems like there’s a few common pitfalls at the outset of a big web project:


  Underestimating front-end development time
  Forgetting about the boring pages, like the Privacy Policy
  Assuming the Content Management System can do more than it can by default


frost is a strong attempt to circumvent those pitfalls when making new sites in Drupal, so
projects can stay on track. Let’s take a look at some of its key features:


    
      
        
        
        
        
        

        
        
        
        

        
        
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

Fully-implemented front end

Just like popular site-building tools and ready-made themes for other systems, frost’s frost_theme has all the styles
and JavaScript snippets needed to launch a functional and beautiful website quickly.


    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

Out of the box this lets you quickly develop new components, yes, but also you don’t have to worry about:


  Mobile “Hamburger” menu and drawer
  Search bar
  Responsive layouts, even complex ones
  Teasers and cards for content listings
  Site footer with contact information and social icons
  Advanced components, such as tabbed interfaces and background videos anywhere


More than that, frost_theme will keep you productive.

.flex-direction--column {
  flex-direction: column;
}


If the utility class above makes sense to you – that the property name is first (hyphens included), then two hyphens,
then the value associated with the property – then clearly you know CSS well, and you also know 90% of the utility classes
in the theme by heart already!

Similarly, the JavaScript ‘partials’ directory has useful examples of how frost (and its JAMstack sibling, finished-starter)
handles behavior lifecycle:


  Once the DOM is ready for the script, the utilityInitializer() function runs the functions registered to it to make the component ready
  If new elements are added to the DOM, utilityInitializer()’s mutationObserver will get those components ready, too
  Clicks and other events are bubbled and filtered from the body, so the listener will pick up dynamically-added components


The boring pages: done!

On day one, just minutes after going through the installer, your new frost Drupal site has:


  Home
  Search
  Events
  Events archive
  Contact us
  FAQs
  Blog
  Privacy Policy
  Accessibility Statement
  404 template
  Generic thank you page
  Component guide
  Style guide
  About us template
  Press
  Terms &amp;amp; Conditions


Not only are most of these pages worded in a generic-enough manner that you may not have to tweak them at all, but they
also look pretty cool!


    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

At some point before or after launching your site, you’re bound to have to think about all those pages, plus XML sitemaps
and all the jazz every site needs to have. With frost you can worry a lot less.

Does what you want it to

If you’ve ever had the pleasure of having a website made for you, there may have been hiccups, like:


  Here’s your listing page of case studies with filters for categories. Pretty cool, huh? Oh, you want some intro text?
No problem. And regular page content below?! That would be an additional 8 development hours.


…or…


  The designs don’t have an accordion in a right column. To make that happen we’d have to refactor the frontend theme.
Well that would be a few thousand dollars over the original scope…


With frost you can put your accordions where you want, and your listing page can be customized to your heart’s content.


    
      
        
        
        
          
        

        
        
        
        
          
        

        
      
      
        
      
    
    
  

Also: free and easy

frost is based on Drupal, which is free and open source software.
You can clone or fork the code and have a working local version of the site ready
to go in minutes. If you’re not a PHP developer, though, you may want to hire Brad to set it up for you.
]]></description>
        <content:encoded><![CDATA[<p>It seems like there’s a few common pitfalls at the outset of a big web project:</p>

<ol>
  <li>Underestimating front-end development time</li>
  <li>Forgetting about the boring pages, like the Privacy Policy</li>
  <li>Assuming the Content Management System can do more than it can by default</li>
</ol>

<p><a href="https://frostdrupal.com/">frost</a> is a strong attempt to circumvent those pitfalls when making new sites in Drupal, so
projects can stay on track. Let’s take a look at some of its key features:</p>

<figure class="figure figure--youtube js--youtube include include--molecule include--molecule--youtube
    " data-youtube="bpi0KBzs23w" data-title="Introducing Frost (Drupal) by making wordpress.org: Free, open source atomic storytelling">
    <a href="https://www.youtube.com/watch?v=bpi0KBzs23w">
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
        
        

        
        
        
        

        
        
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/youtube/bpi0KBzs23w.jpg.webp" type="image/webp" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/youtube/bpi0KBzs23w.jpg" alt="Introducing Frost (Drupal) by making wordpress.org: Free, open source atomic storytelling" loading="lazy" height="360" width="480" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/youtube/bpi0KBzs23w.jpg" alt="Introducing Frost (Drupal) by making wordpress.org: Free, open source atomic storytelling" loading="lazy" />
      </noscript>
    </a>
    
  </figure>

<h2 id="fully-implemented-front-end">Fully-implemented front end</h2>

<p>Just like popular site-building tools and ready-made themes for other systems, frost’s <code class="language-plaintext highlighter-rouge">frost_theme</code> has all the styles
and JavaScript snippets needed to launch a functional and beautiful website quickly.</p>

<figure class="figure figure--image figure--image--frost-css-and-js-jpg box-shadow--lifted-edges">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_css-and-js.jpg.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_css-and-js.jpg.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/frost_css-and-js.jpg" alt="frost in PHPStorm, showing the CSS and JS structure" loading="lazy" height="1547" width="1275" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/frost_css-and-js.jpg" alt="frost in PHPStorm, showing the CSS and JS structure" loading="lazy" />
      </noscript>
    
    
  </figure>

<p>Out of the box this lets you quickly develop new components, yes, but also you don’t have to worry about:</p>

<ul>
  <li>Mobile “Hamburger” menu and drawer</li>
  <li>Search bar</li>
  <li>Responsive layouts, even complex ones</li>
  <li>Teasers and cards for content listings</li>
  <li>Site footer with contact information and social icons</li>
  <li>Advanced components, such as tabbed interfaces and background videos <em>anywhere</em></li>
</ul>

<p>More than that, frost_theme will <em>keep</em> you productive.</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.flex-direction--column</span> <span class="p">{</span>
  <span class="nl">flex-direction</span><span class="p">:</span> <span class="n">column</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>If the utility class above makes sense to you – that the property name is first (hyphens included), then two hyphens,
then the value associated with the property – then clearly you know CSS well, and you also know 90% of the utility classes
in the theme by heart already!</p>

<p>Similarly, the JavaScript ‘partials’ directory has useful examples of how frost (and its JAMstack sibling, finished-starter)
handles behavior lifecycle:</p>

<ol>
  <li>Once the DOM is ready for the script, the <code class="language-plaintext highlighter-rouge">utilityInitializer()</code> function runs the functions registered to it to make the component ready</li>
  <li>If new elements are added to the DOM, <code class="language-plaintext highlighter-rouge">utilityInitializer()</code>’s mutationObserver will get those components ready, too</li>
  <li>Clicks and other events are bubbled and filtered from the body, so the listener will pick up dynamically-added components</li>
</ol>

<h2 id="the-boring-pages-done">The boring pages: done!</h2>

<p>On day one, just minutes after going through the installer, your new frost Drupal site has:</p>

<ul>
  <li><a href="https://www.frostdrupal.com/page/home">Home</a></li>
  <li><a href="https://www.frostdrupal.com/search">Search</a></li>
  <li><a href="https://www.frostdrupal.com/event">Events</a></li>
  <li><a href="https://www.frostdrupal.com/event/archive">Events archive</a></li>
  <li><a href="https://www.frostdrupal.com/contact-us">Contact us</a></li>
  <li><a href="https://www.frostdrupal.com/page/frequently-asked-questions">FAQs</a></li>
  <li><a href="https://www.frostdrupal.com/article">Blog</a></li>
  <li><a href="https://www.frostdrupal.com/page/privacy-policy">Privacy Policy</a></li>
  <li><a href="https://www.frostdrupal.com/page/accessibility-statement">Accessibility Statement</a></li>
  <li><a href="https://www.frostdrupal.com/page/404-not-found">404 template</a></li>
  <li><a href="https://www.frostdrupal.com/page/thank-you">Generic thank you page</a></li>
  <li><a href="https://www.frostdrupal.com/page/component-guide">Component guide</a></li>
  <li><a href="https://www.frostdrupal.com/admin/appearance/styleguide">Style guide</a></li>
  <li><a href="https://www.frostdrupal.com/page/about">About us template</a></li>
  <li><a href="https://www.frostdrupal.com/page/press">Press</a></li>
  <li><a href="https://www.frostdrupal.com/page/terms-conditions">Terms &amp; Conditions</a></li>
</ul>

<p>Not only are most of these pages worded in a generic-enough manner that you may not have to tweak them at all, but they
also look pretty cool!</p>

<figure class="figure figure--image figure--image--frost-privacy-policy-jpg box-shadow--lifted-edges border--1px-solid">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_privacy-policy.jpg.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_privacy-policy.jpg.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/frost_privacy-policy.jpg" alt="Screenshot of the frost default Privacy Policy, with images and alternating stripes for interest" loading="lazy" height="1547" width="1345" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/frost_privacy-policy.jpg" alt="Screenshot of the frost default Privacy Policy, with images and alternating stripes for interest" loading="lazy" />
      </noscript>
    
    
  </figure>

<p>At some point before or after launching your site, you’re bound to have to think about all those pages, plus XML sitemaps
and all the jazz every site needs to have. With frost you can worry a lot less.</p>

<h2 id="does-what-you-want-it-to">Does what you want it to</h2>

<p>If you’ve ever had the pleasure of having a website made for you, there may have been hiccups, like:</p>

<blockquote>
  <p>Here’s your listing page of case studies with filters for categories. Pretty cool, huh? Oh, you want some intro text?
No problem. <strong>And</strong> regular page content below?! That would be an additional 8 development hours.</p>
</blockquote>

<p>…or…</p>

<blockquote>
  <p>The designs don’t have an accordion in a right column. To make that happen we’d have to refactor the frontend theme.
Well that would be a few thousand dollars over the original scope…</p>
</blockquote>

<p><strong>With frost</strong> you can put your accordions where you want, and your listing page can be customized to your heart’s content.</p>

<figure class="figure figure--image figure--image--frost-accordion-in-tab-jpg box-shadow--lifted-edges">
    
      <picture class="picture picture--lazy-load layout--hide--no-javascript" itemprop="image">
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_accordion-in-tab.jpg.webp" type="image/webp" />
        

        
        
        
        
          <source srcset="https://solveitonce.com/assets/images/required/s.webp" data-srcset="https://solveitonce.com/assets/images/frost_accordion-in-tab.jpg.avif" type="image/avif" />
        

        <img src="https://solveitonce.com/assets/images/required/s.gif" data-src="https://solveitonce.com/assets/images/frost_accordion-in-tab.jpg" alt="A set of tabs, with the visible tab containing an accordion, for demonstration purposes." loading="lazy" height="897" width="1337" />
      </picture>
      <noscript>
        <img src="https://solveitonce.com/assets/images/frost_accordion-in-tab.jpg" alt="A set of tabs, with the visible tab containing an accordion, for demonstration purposes." loading="lazy" />
      </noscript>
    
    
  </figure>

<h2 id="also-free-and-easy">Also: free and easy</h2>

<p><a href="https://frostdrupal.com/">frost</a> is based on Drupal, which is free and open source software.
<a href="https://github.com/solve-it-once/frost">You can clone or fork the code</a> and have a working local version of the site ready
to go in minutes. If you’re not a PHP developer, though, you may want to <a href="https://solveitonce.com/products/drupal-site">hire Brad to set it up for you</a>.</p>
]]></content:encoded>
      </item>
    
      <item>
        <title>Pie in the sky</title>
        <link>http://solveitonce.com/blog/pie-in-the-sky/</link>
        <pubDate>Thu, 13 Apr 2023 00:00:00 EST</pubDate>
        
          
          <dc:creator>Brad Czerniak</dc:creator>
        
        
        
          <category><![CDATA[Clients]]></category>
        
          <category><![CDATA[Project Management]]></category>
        
        <guid isPermaLink="true">http://solveitonce.com/blog/pie-in-the-sky/</guid>
        <description><![CDATA[A while back, in a team meeting with a subcontracting client, I distilled the idea of some of the value I feel I bring to
projects:


  If I’m on a client call and they say they want something Pie-in-the-sky, I’ll compromise them down to pie on the ground.


This is an imperfect metaphor, but I thought it might be fun to devote some written words to it.

A structural dysfunction

It’s common to designate a single internal point of contact for a client, often a dedicated Account Manager, and for the
client to designate a single point of contact on their end. This is helpful because there are boundaries and less confusion.

This arrangement leads to certain personalities being designated on the client side:


  The IT person who wants to second-guess the implementation
  The person who wants to be liked and not rock the boat, thereby drifting from their company’s goals
  The go-getter who replies within 5 minutes, so it’s a problem when it takes you 6 minutes to reply
  The idea person


The idea person keeps up with technology, broadly, and pitches in some idea of how ChatGPT might be leveraged in the project
to revolutionize the dry cleaning industry. These ideas are interesting, but aren’t happening this sprint or any others.

An idea person can be managed quite easily with two strategies in tandem:


  When an idea is clearly never going to see the light of day, capture the idea and put it in the backlog. Put appropriately-huge
    points estimates on the story, and try hard during refinement and sprint planning to avoid showing these tickets on
    the screen share
  For more-grounded ideas, discuss with the client contact the business need the idea addresses, then make a backlog
    ticket based on the business story. If necessary, repeat that the designers and dev team will be able to recommend the
    best technological solution to address the business need, and the client contact will be vital to this process. Refine
    stories like this quickly, and get them into an upcoming sprint as appropriate


It’s important not just that the client contact (idea person or otherwise) feels listened to, but that they truly are
listened to, and their business needs are captured in an actionable way. At the same time, an idea person will demolish
the notion of scope if you let them, so tactically under-emphasizing any project-threatening tasks is also important.

How to bring a pie back down to Earth

The back-and-forth for literal pie in the sky might go something like this:


  Client: “We want pie in the sky”
  Account: “So… a pie that’s hovering in a fixed position above the ground? Or a pie plate with wings so it flies more like a plane?”
  Client: “Shoot, right, I should have been more specific. We want a small pie in a cardboard box that we can purchase
after the TSA line at the airport and bring on a flight to the Atlanta Delta hub. Our C suite has made this priority one”
  Account: “Ah, I see. It seems this pie must be equally useful both on the ground and in the air. Is there any consideration
for the pie on a boat or in a submarine?”
  Client: “That’s an interesting question. I’d really like it if the pie were boat-compatible, but it’s not a requirement
for this phase”
  Account: “Great, I will make note of that, thank you. Flavor-wise for this phase, what are we thinking? Apple? Lemon
meringue? Pecan? Chicken pot?”
  Client: “Now we’re talking! Our CEO is a big fan of cherry. I’m tempted to say we only need cherry sky-pies for this iteration”
  Account: “Perfect. I’ll get this written up, run it by the rest of the team, put some numbers and specifications to it,
and we’ll try to get this planned for work in the next four weeks”


Clearly the single flavor will turn into 5 or 6 by launch, and then after launch it will be apparent that customers only want
the apple ones. We can’t fix every problem on every project all the time, but we avoided inventing pie-hovering technology
unnecessarily, which should be considered a win.

Sometimes an idea really is just that the CEO likes cherry pie, or whatever that equivalent may be. Far more often, and
usually more productively, ideas come from business problems and business needs.

Grabbing your expertise back

As a freelancer, agency, consultant, or other service agent for a client, you face an internal struggle:


  If I say ‘yes’ to an idea I disagree with, I’ll get paid and will feel icky but be able to feed my family this month
  If I push back, the client might not like it, might not like me, and I’ll have to go back to waiting tables


It’s vital that you remember that the client hired you because you are good at doing things that they’re not as capable
at doing. Even if they don’t like people they’re paying talking back to them, it would be a mistake on their part not
to listen to your expertise and find a good compromise.

That’s why, when a client suggests an implementation detail, that should be a yellow flag for your team. “We want a flashing
marquee on the home page that says CALL NOW (800) 555-1234” is an emphatically bad idea for almost any company that wants
to look professional on the web, for instance.

The kernel of truth for the marquee ask is the business need: the company isn’t getting as many phone leads from their website
as hoped, and want to do something to improve that metric. This business need can be made into a user story, and a cross-functional
team of designers, marketers, and developers can devise a much more professional approach than a flashing marquee.

When possible, rename tickets that have client-provided implementation specifics to reflect the business need instead.
Everybody on your team except the Account Manager might naturally assume the implementation specific is already firmly
decided, and might move forward with it, even if nobody on the team thinks it’s a good idea. Being presented with a business
problem and coming up with a technological solution to it is a chance for your team to shine, and impress your client in
the process.
]]></description>
        <content:encoded><![CDATA[<p>A while back, in a team meeting with a subcontracting client, I distilled the idea of some of the value I feel I bring to
projects:</p>

<blockquote>
  <p>If I’m on a client call and they say they want something Pie-in-the-sky, I’ll compromise them down to pie on the ground.</p>
</blockquote>

<p>This is an imperfect metaphor, but I thought it might be fun to devote some written words to it.</p>

<h2 id="a-structural-dysfunction">A structural dysfunction</h2>

<p>It’s common to designate a single internal point of contact for a client, often a dedicated Account Manager, and for the
client to designate a single point of contact on their end. This is helpful because there are boundaries and less confusion.</p>

<p>This arrangement leads to certain <em>personalities</em> being designated on the client side:</p>

<ul>
  <li>The IT person who wants to second-guess the implementation</li>
  <li>The person who wants to be liked and not rock the boat, thereby drifting from their company’s goals</li>
  <li>The go-getter who replies within 5 minutes, so it’s a problem when it takes you 6 minutes to reply</li>
  <li>The idea person</li>
</ul>

<p>The idea person keeps up with technology, broadly, and pitches in some idea of how ChatGPT might be leveraged in the project
to revolutionize the dry cleaning industry. These ideas are interesting, but aren’t happening this sprint or any others.</p>

<p>An idea person can be managed quite easily with two strategies in tandem:</p>

<ol>
  <li>When an idea is clearly never going to see the light of day, capture the idea and put it in the backlog. Put appropriately-huge
    points estimates on the story, and try hard during refinement and sprint planning to avoid showing these tickets on
    the screen share</li>
  <li>For more-grounded ideas, discuss with the client contact the <strong>business need the idea addresses</strong>, then make a backlog
    ticket based on the business story. If necessary, repeat that the designers and dev team will be able to recommend the
    best technological solution to address the business need, and the client contact will be vital to this process. Refine
    stories like this quickly, and get them into an upcoming sprint as appropriate</li>
</ol>

<p>It’s important not just that the client contact (idea person or otherwise) <em>feels</em> listened to, but that they truly are
listened to, and their business needs are captured in an actionable way. At the same time, an idea person will demolish
the notion of scope if you let them, so tactically under-emphasizing any project-threatening tasks is also important.</p>

<h2 id="how-to-bring-a-pie-back-down-to-earth">How to bring a pie back down to Earth</h2>

<p>The back-and-forth for literal pie in the sky might go something like this:</p>

<ul>
  <li>Client: “We want pie in the sky”</li>
  <li>Account: “So… a pie that’s hovering in a fixed position above the ground? Or a pie plate with wings so it flies more like a plane?”</li>
  <li>Client: “Shoot, right, I should have been more specific. We want a small pie in a cardboard box that we can purchase
after the TSA line at the airport and bring on a flight to the Atlanta Delta hub. Our C suite has made this priority one”</li>
  <li>Account: “Ah, I see. It seems this pie must be equally useful both on the ground and in the air. Is there any consideration
for the pie on a boat or in a submarine?”</li>
  <li>Client: “That’s an interesting question. I’d really like it if the pie were boat-compatible, but it’s not a requirement
for this phase”</li>
  <li>Account: “Great, I will make note of that, thank you. Flavor-wise for this phase, what are we thinking? Apple? Lemon
meringue? Pecan? Chicken pot?”</li>
  <li>Client: “Now we’re talking! Our CEO is a big fan of cherry. I’m tempted to say we only need cherry sky-pies for this iteration”</li>
  <li>Account: “Perfect. I’ll get this written up, run it by the rest of the team, put some numbers and specifications to it,
and we’ll try to get this planned for work in the next four weeks”</li>
</ul>

<p>Clearly the single flavor will turn into 5 or 6 by launch, and then after launch it will be apparent that customers only want
the apple ones. We can’t fix every problem on every project all the time, but we avoided inventing pie-hovering technology
unnecessarily, which should be considered a win.</p>

<p>Sometimes an idea really is just that the CEO likes cherry pie, or whatever that equivalent may be. Far more often, and
usually more productively, ideas come from business problems and business needs.</p>

<h2 id="grabbing-your-expertise-back">Grabbing your expertise back</h2>

<p>As a freelancer, agency, consultant, or other service agent for a client, you face an internal struggle:</p>

<ul>
  <li>If I say ‘yes’ to an idea I disagree with, I’ll get paid and will feel icky but be able to feed my family this month</li>
  <li>If I push back, the client might not like it, might not like me, and I’ll have to go back to waiting tables</li>
</ul>

<p>It’s vital that you remember that the client hired you because you are good at doing things that they’re not as capable
at doing. Even if they don’t like people they’re paying talking back to them, it would be a mistake on <em>their</em> part not
to listen to your expertise and find a good compromise.</p>

<p>That’s why, when a client suggests an implementation detail, that should be a yellow flag for your team. “We want a flashing
marquee on the home page that says CALL NOW (800) 555-1234” is an emphatically bad idea for almost any company that wants
to look professional on the web, for instance.</p>

<p>The kernel of truth for the marquee ask is the business need: the company isn’t getting as many phone leads from their website
as hoped, and want to do <em>something</em> to improve that metric. This business need can be made into a user story, and a cross-functional
team of designers, marketers, and developers can devise a much more professional approach than a flashing marquee.</p>

<p>When possible, <strong>rename tickets that have client-provided implementation specifics to reflect the business need instead</strong>.
Everybody on your team except the Account Manager might naturally assume the implementation specific is already firmly
decided, and might move forward with it, even if nobody on the team thinks it’s a good idea. Being presented with a business
problem and coming up with a technological solution to it is a chance for your team to shine, and impress your client in
the process.</p>
]]></content:encoded>
      </item>
    
      <item>
        <title>Developers lead</title>
        <link>http://solveitonce.com/blog/developers-lead-projects/</link>
        <pubDate>Mon, 29 Aug 2022 00:00:00 EST</pubDate>
        
          
          <dc:creator>Brad Czerniak</dc:creator>
        
        
        
          <category><![CDATA[Agile]]></category>
        
          <category><![CDATA[Project Management]]></category>
        
        <guid isPermaLink="true">http://solveitonce.com/blog/developers-lead-projects/</guid>
        <description><![CDATA[A cynical developer might observe that, rather than relying on their expertise to ensure project success, web agencies
instead try to ignore developers ever faster as the company’s workflow evolves.

The code, markup, and assets — the website itself — are the key deliverables on a web project, so developers are naturally the critical path
on any project. Fighting this conclusion can only result in frustration. Eventually, by trial and error, any team will count
on a technical person as a project leader, whether formally or informally.

Waterfall by default

There’s a surefire way to blow up a project budget and say a lot of plausible-sounding words to justify charging tens of
thousands of dollars for a brochure website: pretend every new project is the first website ever made.

In this model, a waterfall methodology is natural:


  Discovery: charge a blended professional-services rate to have an underpaid junior account person gather a bunch
    of business information and create boilerplate documents repeating what was collected back as deliverables, like
    “competitive analysis” showing that other companies indeed have brands and websites, many with fonts, colors, and labels
    for their top main menu items. The output of this phase results in agreement that the agency should make a website
    exactly as outlined in the already-signed proposal, and a bunch of documents in various formats that nobody will ever
    look at again
  Architecture: a UX specialist will use a blank slate to burn billable hours making obvious wireframes, in the process
    neglecting to put required elements on the page. During presentation of the first round of wireframes, the client will
    point out that the sitemap doesn’t include a link to a “Contact us” page, or that the wires don’t show where the logo
    will go. This will be embarrassing for everyone in attendance, but the UX designer will cover for this by claiming they
    believed these things were too obvious to include, or, if the UX person is particularly bold, they’ll decide it’s not
    in the brand strategy to show the logo. These oversights will be corrected by the second round either way. In parallel,
    somebody throws the Discovery documents in the trash, as they’re no longer needed
  Design: predicated on the idea that any kind of ‘template’ means impure expression of the brand, every element,
    component, layout, and convention of the site’s design will be drawn from scratch, with subtly-different designs for
    every single known page on the site. Since so many other websites have blue, underlined links, it would be a branding
    disaster to make links on this new site either blue or underlined, and certainly not both! If the dev team is lucky,
    it is around the end of the first round of these designs that the lead developer on the project will be able to review
    the comps for the one and only time. The developer’s feedback will be considered as purely optional. Meanwhile, the
    wires can be safely trashed
  Development: following a few rounds of design revision that could eat up most of the project’s timeline and budget,
    the comps land on the dev team’s lap, and the mad dash to make up for lost time begins. The designs are definitely an
    unmitigated disaster, and implementing the poorly-documented new components will blow any notion of scope from the proposal
    right out of the water. This will be the dev team’s fault, and everyone outside the team will wonder how the developers
    stay employed when every project goes like this
  Testing, Launch, and after: a project manager with no qualification to test software will review the site internally,
    and the dev team will have to set the middle paragraph in a stack of three to 15px font to match the designs, despite
    that not making a lick of sense. It’s clear that the developers aren’t good at skinning sites from designs, rather than
    the designers being wildly incompetent to not update a random paragraph on just one page of the overall designs. When
    the site passes internal QA it then goes to the client — seeing cumulative months of work for the first time — for user
    acceptance testing, where they’ll immediately notice that middle paragraphs are the wrong size font and make a line
    in a spreadsheet to revert the QA fix. This will happen an alarming number of times during UAT, before finally launching
    the site and performing post-launch support


The company’s leadership will vaguely agree that doing some project retrospectives might help refine this process, though
in practice retros will happen haphazardly for maybe one out of every four projects. The meeting will run long, lots of notes
will be taken, and despite lots of actionable feedback, the process for the next project will not change from before.

Every year, company leadership will get together and review the waterfall process and move things around in an entirely
symbolic fashion. This process-refinement theater can continue indefinitely, as long as there’s enough resistance to trying
‘agile’.

Agilefall evolution

The waterfall process is an attrition machine, so turnover at a waterfall shop will undoubtedly be high enough that after
a few years somebody who’s worked at an agile shop will land in a position to make change, however incremental.

Attempt alpha

The first agile project for the waterfall company will be a waterfall project as always, but with daily check-in calls and
a “sprint retrospective” added to half the team’s calendar for two weeks after kickoff. This retro will last 5 minutes, and
the event invitation will not be updated to recur every two weeks, owing to how little useful info came out of the one and
only sprint retro.

At the end of this experiment, the company will fully revert to regular waterfall, except for the unstructured daily check-ins,
which will continue regardless of if they provide any real value. The check-in will be at an inconvenient time in the workday,
and the developers will be less productive for having to context-switch around the non-billable call. Management will love
the ‘visibility’, though.

Going forward, the waterfall company will talk up their ability to deliver projects using cutting-edge agile methodology.

Attempt beta

Years later, institutional forces or a demanding client will lead to a second attempt at an agile workflow. The same steps
from Attempt alpha will return, but this time the project manager has learned the error of their former ways.

Steps 1-3 from waterfall continue unabated, as Discovery, Architecture, and Design have always been smooth. When the project
gets to Development, though, the core agile principle from the manifesto of doing and changing whatever whenever comes
into play. Rather than sticking to the approved designs and scope from the signed proposal, all “wouldn’t it be cool if…”
emails from the client contact are treated as gospel.

Regardless of development team feedback, this waterfall-to-free-for-all process continues until the logged hours exceed
125% of the project’s estimate. At that point, company leadership informs the client that the project is over budget, blames
the developers for spinning their wheels, and formulates a plan to do about 15 more hours of work toward launching whatever
the site looks like. This is just the Minimum Viable Product of the first phase, after all, and the quirks can be smoothed
out post-launch in an iterative fashion.

The development team at this point meets and works from the bar, and leadership has no idea why people talk about Agile
as such a transformative thing, as it always seems to cause more problems than it solves.

Next, scrum by the book

The waterfall company still tells clients that they have an agile process, but continues to do projects the way they always
have. After at least two failed attempts at half-heartedly implementing agile, the initiative to make it stick has been
mostly abandoned.

That is, until a partnership opportunity with a much larger and more successful company lands in leadership’s lap. By this
time the company leadership believes everything is agile anyway, so the contractual agreement for the team to use the scrum
process of the larger company feels like a natural fit not even worth questioning.

The big new project catches the waterfall company off-guard:


  Sprint zero felt kind of like Discovery and Architecture, but with a lot more talk around refining stories from the
backlog and planning for the next couple sprints
  Account folks are freaking out that a client contact is invited to all kinds of stuff, and that a demo was planned for
two weeks after executing the contract
  The dev team is tickled, as even though they’re not calling the shots, they’re involved in the process and have a voice
  The new structure feels foreign to everyone, but there’s reason to be excited


This project will be successful compared to other projects in recent memory, but will not be a runaway, perfect success.
Even so, everyone at the waterfall company is now committed to a scrum approach on future projects.

Independent scrum without training wheels

Not long after the pilot partnership project, the agency formerly known as the waterfall shop will attempt to do a scrum
project entirely on their own, with their existing project managers learning a bit on the side, but mostly emulating what
they saw during the last project.

This will not go particularly well, but is effectively a step in the journey to get to a by-the-book scrum implmentation.
There will be a feeling, not always present in scrum projects, that the company is trying to do waterfall but cycling every
two weeks. The developers will have feedback into the embedded IA/UX and graphic design output, still considered optional,
and with varying degrees of success.

Another touchpoint for the dev team, and especially the tech lead, is refinement. All the non-technical staff can mostly
write up stories and organize tasks by epic, but when it comes to Acceptance Criteria, testing protocols, and dev handoff
notes, only a senior developer seems to deliver quality words in a timely manner.

One of the big benefits of embracing Scrum in its entirety, is in adapting to the needs of the company and the mutual preferences
of the team. As the company does more and more scrum projects, retro feedback surfaces something interesting:

In the “What went well” part of the board, a developer at first writes that the designer updated an item based on feedback,
and it led to much faster development and a more consistent product. In discussing this item during the retro, everyone
on the team was happy about this, and the action item was to be on the lookout for opportunities to seek feedback and apply
it.

This, and similar things, occur over time and across projects, and becomes a common thread of the parts of projects that
feel good. Even if it hasn’t clicked to everyone yet, they’ve discovered the core truth of website-making: developer leadership
greases the wheels.

Embracing technical leadership

The natural-feeling next step from identifying developers as the critical path and agents of smooth website-making might
be to have a developer take a leadership role in the scrum team in some manner or fashion. This may lead to mixed results,
though.

A good developer is fairly easy to come by. The skills required to read a task, analyze the existing system, and then write
well-formatted and often well-documented code to accomplish the desired result are taught at computer science programs at
universities and boot camps the world over. It’s not controversial to point out that soft skills like tactful communication
can often be lacking in these training programs.

An effective technical leader, then, needs:


  Mastery of full stack engineering
  Good written and verbal communication skills
  Patience, tact, levity
  Solid grasp of the project management strategy
  Ability to translate between code and English
  That intangible leadership quality, at least to some degree
  Systems thinking: ability to contextualize small tasks in context of a whole system


Developers with that blend of skills are far more difficult to come by than just a good coder, and even among thusly-talented
folks, character traits like tempers, stubbornness, and poor reactions to feedback can doom a technical leader. And perhaps
unfortunately, many natural leaders take an interest in coding, but wash out of being engineers and leave technical roles
or the industry entirely, before they’re ready to jump into a leadership role.

This is a tricky problem for organizations, as there will likely never be enough technology leadership for all the companies
and projects out there. There are two mitigations for this to keep in mind, though:


  If you have a good technology leader, leverage their expertise as much as you can, and do everything you can to retain
    their services for the long term
  If you cannot find or create a strong technology leader, find a good non-technical leader and charge them with seeking
    feedback from the dev team early and often. The leader should then follow up with designers and other implementation
    specialists to ensure the feedback is not ignored to the detriment of the project and the rest of team

]]></description>
        <content:encoded><![CDATA[<p>A <strong>cynical developer</strong> might observe that, rather than relying on their expertise to ensure project success, web agencies
instead try to ignore developers ever <em>faster</em> as the company’s workflow evolves.</p>

<p>The code, markup, and assets — the website itself — are the key deliverables on a web project, so <strong>developers are naturally the critical path</strong>
on any project. Fighting this conclusion can only result in frustration. Eventually, by trial and error, any team will count
on a technical person as a project leader, whether formally or informally.</p>

<h2 id="waterfall-by-default">Waterfall by default</h2>

<p>There’s a surefire way to blow up a project budget and say a lot of plausible-sounding words to justify charging tens of
thousands of dollars for a brochure website: <strong>pretend every new project is the first website ever made</strong>.</p>

<p>In this model, a waterfall methodology is natural:</p>

<ol>
  <li><strong>Discovery</strong>: charge a blended professional-services rate to have an underpaid junior account person gather a bunch
    of business information and create boilerplate documents repeating what was collected back as deliverables, like
    “competitive analysis” showing that other companies indeed have brands and websites, many with fonts, colors, and labels
    for their top main menu items. The output of this phase results in agreement that the agency should make a website
    exactly as outlined in the already-signed proposal, and a bunch of documents in various formats that nobody will ever
    look at again</li>
  <li><strong>Architecture</strong>: a UX specialist will use a blank slate to burn billable hours making obvious wireframes, in the process
    neglecting to put required elements on the page. During presentation of the first round of wireframes, the client will
    point out that the sitemap doesn’t include a link to a “Contact us” page, or that the wires don’t show where the logo
    will go. This will be embarrassing for everyone in attendance, but the UX designer will cover for this by claiming they
    believed these things were too obvious to include, or, if the UX person is particularly bold, they’ll decide it’s not
    in the brand strategy to show the logo. These oversights will be corrected by the second round either way. In parallel,
    somebody throws the Discovery documents in the trash, as they’re no longer needed</li>
  <li><strong>Design</strong>: predicated on the idea that any kind of ‘template’ means impure expression of the brand, every element,
    component, layout, and convention of the site’s design will be drawn from scratch, with subtly-different designs for
    every single known page on the site. Since so many other websites have blue, underlined links, it would be a branding
    <em>disaster</em> to make links on this new site either blue <em>or</em> underlined, and certainly not both! If the dev team is lucky,
    it is around the end of the first round of these designs that the lead developer on the project will be able to review
    the comps for the one and only time. The developer’s feedback will be considered as purely optional. Meanwhile, the
    wires can be safely trashed</li>
  <li><strong>Development</strong>: following a few rounds of design revision that could eat up most of the project’s timeline and budget,
    the comps land on the dev team’s lap, and the mad dash to make up for lost time begins. The designs are definitely an
    unmitigated disaster, and implementing the poorly-documented new components will blow any notion of scope from the proposal
    right out of the water. This will be the dev team’s fault, and everyone outside the team will wonder how the developers
    stay employed when every project goes like this</li>
  <li><strong>Testing, Launch, and after</strong>: a project manager with no qualification to test software will review the site internally,
    and the dev team will have to set the middle paragraph in a stack of three to 15px font to match the designs, despite
    that not making a lick of sense. It’s clear that the developers aren’t good at skinning sites from designs, rather than
    the designers being wildly incompetent to not update a random paragraph on just one page of the overall designs. When
    the site passes internal QA it then goes to the client — seeing cumulative months of work for the first time — for user
    acceptance testing, where they’ll <strong>immediately</strong> notice that middle paragraphs are the wrong size font and make a line
    in a spreadsheet to revert the QA fix. This will happen an alarming number of times during UAT, before finally launching
    the site and performing post-launch support</li>
</ol>

<p>The company’s leadership will vaguely agree that doing some project retrospectives might help refine this process, though
in practice retros will happen haphazardly for maybe one out of every four projects. The meeting will run long, lots of notes
will be taken, and despite lots of actionable feedback, the process for the next project will not change from before.</p>

<p>Every year, company leadership will get together and review the waterfall process and move things around in an entirely
symbolic fashion. This process-refinement theater can continue indefinitely, as long as there’s enough resistance to trying
‘agile’.</p>

<h2 id="agilefall-evolution">Agilefall evolution</h2>

<p>The waterfall process is an attrition machine, so turnover at a waterfall shop will undoubtedly be high enough that after
a few years somebody who’s worked at an agile shop will land in a position to make change, however incremental.</p>

<h3 id="attempt-alpha">Attempt alpha</h3>

<p>The first agile project for the waterfall company will be a waterfall project as always, but with daily check-in calls and
a “sprint retrospective” added to half the team’s calendar for two weeks after kickoff. This retro will last 5 minutes, and
the event invitation will not be updated to recur every two weeks, owing to how little useful info came out of the one and
only sprint retro.</p>

<p>At the end of this experiment, the company will fully revert to regular waterfall, except for the unstructured daily check-ins,
which will continue regardless of if they provide any real value. The check-in will be at an inconvenient time in the workday,
and the developers will be less productive for having to context-switch around the non-billable call. Management will love
the ‘visibility’, though.</p>

<p>Going forward, the waterfall company will talk up their ability to deliver projects using cutting-edge agile methodology.</p>

<h3 id="attempt-beta">Attempt beta</h3>

<p>Years later, institutional forces or a demanding client will lead to a second attempt at an agile workflow. The same steps
from Attempt alpha will return, but this time the project manager has learned the error of their former ways.</p>

<p>Steps 1-3 from waterfall continue unabated, as Discovery, Architecture, and Design have always been smooth. When the project
gets to Development, though, the core agile principle from the manifesto of <em>doing and changing whatever whenever</em> comes
into play. Rather than sticking to the approved designs and scope from the signed proposal, all “wouldn’t it be cool if…”
emails from the client contact are treated as gospel.</p>

<p>Regardless of development team feedback, this waterfall-to-free-for-all process continues until the logged hours exceed
125% of the project’s estimate. At that point, company leadership informs the client that the project is over budget, blames
the developers for spinning their wheels, and formulates a plan to do about 15 more hours of work toward launching whatever
the site looks like. This is just the Minimum Viable Product of the first phase, after all, and the quirks can be smoothed
out post-launch in an <em>iterative</em> fashion.</p>

<p>The development team at this point meets and works from the bar, and leadership has no idea why people talk about Agile
as such a transformative thing, as it always seems to cause more problems than it solves.</p>

<h2 id="next-scrum-by-the-book">Next, scrum by the book</h2>

<p>The waterfall company still tells clients that they have an agile process, but continues to do projects the way they always
have. After at least two failed attempts at half-heartedly implementing agile, the initiative to make it stick has been
mostly abandoned.</p>

<p>That is, until a partnership opportunity with a much larger and more successful company lands in leadership’s lap. By this
time the company leadership believes everything is agile anyway, so the contractual agreement for the team to use the scrum
process of the larger company feels like a natural fit not even worth questioning.</p>

<p>The big new project catches the waterfall company off-guard:</p>

<ul>
  <li>Sprint zero felt kind of like Discovery and Architecture, but with a lot more talk around refining stories from the
backlog and planning for the next couple sprints</li>
  <li>Account folks are freaking out that a client contact is invited to all kinds of stuff, and that a demo was planned for
two weeks after executing the contract</li>
  <li>The dev team is tickled, as even though they’re not calling the shots, they’re involved in the process and have a voice</li>
  <li>The new structure feels foreign to everyone, but there’s reason to be excited</li>
</ul>

<p>This project will be successful compared to other projects in recent memory, but will not be a runaway, perfect success.
Even so, everyone at the waterfall company is now committed to a scrum approach on future projects.</p>

<h3 id="independent-scrum-without-training-wheels">Independent scrum without training wheels</h3>

<p>Not long after the pilot partnership project, the agency formerly known as the waterfall shop will attempt to do a scrum
project entirely on their own, with their existing project managers learning a bit on the side, but mostly emulating what
they saw during the last project.</p>

<p>This will not go particularly well, but is effectively a step in the journey to get to a by-the-book scrum implmentation.
There will be a feeling, not always present in scrum projects, that the company is trying to do waterfall but cycling every
two weeks. The developers will have feedback into the embedded IA/UX and graphic design output, still considered optional,
and with varying degrees of success.</p>

<p>Another touchpoint for the dev team, and especially the tech lead, is refinement. All the non-technical staff can mostly
write up stories and organize tasks by epic, but when it comes to Acceptance Criteria, testing protocols, and dev handoff
notes, only a senior developer seems to deliver quality words in a timely manner.</p>

<p>One of the big benefits of embracing Scrum in its entirety, is in adapting to the needs of the company and the mutual preferences
of the team. As the company does more and more scrum projects, retro feedback surfaces something interesting:</p>

<p>In the “What went well” part of the board, a developer at first writes that the designer updated an item based on feedback,
and it led to much faster development and a more consistent product. In discussing this item during the retro, everyone
on the team was happy about this, and the action item was to be on the lookout for opportunities to seek feedback and apply
it.</p>

<p>This, and similar things, occur over time and across projects, and becomes a common thread of the parts of projects that
feel good. Even if it hasn’t clicked to everyone yet, they’ve discovered the core truth of website-making: developer leadership
greases the wheels.</p>

<h2 id="embracing-technical-leadership">Embracing technical leadership</h2>

<p>The natural-feeling next step from identifying developers as the critical path and agents of smooth website-making might
be to have a developer take a leadership role in the scrum team in some manner or fashion. <strong>This may lead to mixed results</strong>,
though.</p>

<p>A good developer is fairly easy to come by. The skills required to read a task, analyze the existing system, and then write
well-formatted and often well-documented code to accomplish the desired result are taught at computer science programs at
universities and boot camps the world over. It’s not controversial to point out that soft skills like tactful communication
can often be lacking in these training programs.</p>

<p>An effective technical leader, then, needs:</p>

<ul>
  <li>Mastery of full stack engineering</li>
  <li>Good written and verbal communication skills</li>
  <li>Patience, tact, levity</li>
  <li>Solid grasp of the project management strategy</li>
  <li>Ability to translate between code and English</li>
  <li>That intangible leadership quality, at least to some degree</li>
  <li>Systems thinking: ability to contextualize small tasks in context of a whole system</li>
</ul>

<p>Developers with that blend of skills are far more difficult to come by than just a good coder, and even among thusly-talented
folks, character traits like tempers, stubbornness, and poor reactions to feedback can doom a technical leader. And perhaps
unfortunately, many natural leaders take an interest in coding, but wash out of being engineers and leave technical roles
or the industry entirely, before they’re ready to jump into a leadership role.</p>

<p>This is a tricky problem for organizations, as there will likely never be enough technology leadership for all the companies
and projects out there. There are two mitigations for this to keep in mind, though:</p>

<ol>
  <li>If you have a good technology leader, leverage their expertise as much as you can, and do everything you can to retain
    their services for the long term</li>
  <li>If you cannot find or create a strong technology leader, find a good non-technical leader and charge them with seeking
    feedback from the dev team early and often. The leader should then follow up with designers and other implementation
    specialists to ensure the feedback is not ignored to the detriment of the project and the rest of team</li>
</ol>
]]></content:encoded>
      </item>
    
      <item>
        <title>How much more effort?</title>
        <link>http://solveitonce.com/blog/is-this-the-hard-part/</link>
        <pubDate>Sat, 27 Aug 2022 00:00:00 EST</pubDate>
        
          
          <dc:creator>Brad Czerniak</dc:creator>
        
        
        
          <category><![CDATA[Groupthink]]></category>
        
          <category><![CDATA[Agile]]></category>
        
          <category><![CDATA[Drupal]]></category>
        
          <category><![CDATA[Project Management]]></category>
        
        <guid isPermaLink="true">http://solveitonce.com/blog/is-this-the-hard-part/</guid>
        <description><![CDATA[It may be that I have odd luck as a contractor embedded on scrum teams, but more than once I’ve run into weird
group behaviors. Today, as the first post in what may become a series, I want to give an example of some interesting
groupthink, and provide a concrete pointer for how a quiet outsider can try to set their temporary team up for long-term
success.

Overall, this is a drawn-out story that ends with encouraging you to advocate for what you believe in, especially by communicating
effectively and asking the right questions.

A contrived example

It’s common on Drupal projects nowadays, especially when migrating from Drupal 7 to Drupal 8/9/10, to adopt a naming convention
for fields attached to particular entity types and/or bundles. For instance, if you had two node bundles, one called ‘article’
and another called ‘event’, you might set up the machine names of the fields on them in one of the following three-ish ways:


  
    Field machine names in various naming schemes
    
      
        Label
        Type
        Machine name, shared
        Machine name, shared and generalized
        Machine name, typed, article
        Machine name, typed, event
      
    
    
      
        Teaser text
        Formatted text, long
        field_teaser_text
        field_longtext_1
        field_article_teasertext
        field_event_teasertext
      
      
        Tags
        Entity reference
        field_tags
        field_termreference_1
        field_article_tags
        field_event_tags
      
      
        Published date
        Date
        field_date_published
        field_date_1
        field_article_date
        field_event_date
      
    
  


If you’ve worked on some projects of various sizes and at different points in their lifecycle, you’ll inevitably come to
the conclusion that the ‘shared’ naming scheme is the correct answer:


  The “shared and generalized” scheme feels like it could be useful, for instance if you had a bunch of content types
that all had many longtext fields. You could share the storage definitions and swap the labels, thereby reducing the
number of database tables somewhat. But if you have to reference these fields in templates and the like, it gets super confusing super fast
  The “shared and generalized” scheme isn’t actually shared, since field_termreference_1 might be tags on the article
but “event categories” on the event. If you wanted to put both types in a Views display with an exposed filter, you’d run into problems
  The ‘typed’ definitions make the non-shared problem worse. field_article_tags and field_event_tags could both be tags
from the same vocabulary, but the (redundant!) bundle namespacing means you will likely need per-bundle templates, plus
way more customized Views displays and buggy field/filter/sort plugins than if you went with shared field machine names
  Sadist/masochist software architects could combine typed and generalized schemes, though this doesn’t become truly painful
unless one type has a ton of fields of the same type


A violent psychopath

If you have indeed worked on a lot of projects, you’ll know that you often don’t have the luxury to decide on the machine
naming scheme, regardless of if you’re setting the project up at the beginning or jumping into a website with millions of pages.

Famously, John Woods once said “Always code as if the guy who ends up maintaining your code will be a violent psychopath
who knows where you live.” It’s unclear if Mr. Woods ever envisioned a violent psychopath embedded on a team with people
who truly believe their weird architectural decisions were the right call, and who incidentally speak a dialect of English
revolving around subdividing their lives around fortnights, but that’s probably what I’d fear most at retro.

If you inherit a codebase and are now responsible for maintaining it, you can choose to break from the former field machine-naming
scheme, as unless there’s some weird code enforcing it, there’s otherwise no penalty for switching. However, if you’re joining
a team that made a mistake years ago and have never had reason to change course, you’re likely gonna have to continue the
mistakes as long as you work with the team.

Except that things could be so much better

We all know that “because we’ve always done it that way” isn’t a great reason to do something, but we also know that change
for change’s sake may be the only thing worse. The trick for a team set in their ways is showing clear reasoning to change,
and helping them see the bright future that awaits them.

Also, if effort is involved in getting to a bright future, you might have to subvert the perverted swirl of scope, velocity,
backlog size, and other scrummy junk that can get in the way of sound decision-making.

In the case of this clearly-made-up example team that definitely listened to my advice, that meant coming up with a concrete
use case.

Show the why

The wilder part of the field_date_published example that jumps out to seasoned Drupal developers is that entities tend
to have a ‘created’ property that holds a UNIX timestamp. Properties aren’t quite as flexible as fields, or at least they
aren’t in the same way as fields, but they have the advantage of being more performant to query and built right in to
entities like nodes.

Around 10,000 articles had already been migrated in to the Drupal 9 version of the entirely-fictional hypothetical example
site, and the team was planning to import in over 100,000 events from a legacy system. Since article already had field_article_date
as architected on autopilot, changing course could require updating existing content and code, even if doing so were quick,
automatic, and not necessarily in the next sprint or two.

When to speak up

10,000 articles is a lot of articles, don’t get me wrong. But 100,000 events is, website-wise, a big chonking lot of content.
If the team retained the naming scheme and migrated the legacy published date into the new field_event_date field, that
would largely be decisive. This was a speak-now-or-forever-hold-your-peace inflection point.

If you have the courage of your convictions and any reason whatsoever to think the team will be receptive, now or earlier
is the right time to speak up. Maybe not right now, but if you can make your own backlog tickets do that first and stub
it with as much clear, relevant information as possible. Then, when you’re in refinement or sprint planning, it’s natural
to be like “Can we take a look at PROJ-256?” and use that as an in.

Another option, if the previous sprint contained an effort that would have been lighter had a fix been put in place, is
to raise the problem during a retro. This depends on how seriously your team takes retro feedback, as some teams work hard
to improve action items out of retros, whereas other teams treat retrospectives as a way to vent and not much else.

Or bring it up as something to discuss asynchronously on the team slack. It’s mostly a matter of fitting your approach to
your team’s culture.

Communicating effectively

For a small change that has a potentially big impact, there are three great communication styles that can be used in tandem:


  A bullet list of benefits
  A short narrative (in user story format if you must) of something that’s easy in the bright new future, but hard in the present
  An outline (as tech specs and acceptance criteria if your PM can be coaxed) of what’s needed to get to the future


A bullet list of benefits for migrating the published date from the legacy system into the ‘credted’ property instead of
a new field_event_date:


  Administrative and user-facing listings that combine articles and events will be accurate and easy to create
  There will be no confusion about what field_event_date is, since the published date is usually far less relevant for
events than the date the event itself starts and finishes
  Querying for the published date will be fast and won’t require any JOINs
  Templating articles and events and displaying bylines could be far simpler


This list applies to the fix, and could be made into a story or other kind of ticket, and with any luck the fix (and related
tasks) can be estimated to show how hard or easy it would be to port the article date field into the created property, and
the relative ease of putting a legacy timestamp into ‘created’ in the event migration, rather than messing with format_date
and all that (though the article migration might already have that done, so it’s not a slam dunk argument).

Two competing visions of the future, in short narrative form


  As an administrator user, when I navigate to Content &amp;gt; Advanced via the top admin bar, I expect to see a combined
listing (table) of all node types with applicable shared fields, sorted by default by published date descending.


The above brief user story serves largely as a thought experiment for a developer who’s encountered similar tickets before.
If everyone on the team is aware that namespaced fields make listings like this far more complicated than they’d otherwise
be, it may be an opportunity for someone to shout that this is a 13-point (or XL t-shirt) ticket, only for the team to
have a realistic conversation about its practices.

In the current situation, this is a big ticket with the potential to introduce a bunch of technical debt. In the bright
future, this would be a 3-pointer (Small t-shirt).

Is this the hard part?

When a team with a backlog, planned sprints, milestones and goals, and all that business stuff encounters a refactoring
task, there’s a natural inclination to bury it. Maintaining existing software, fixing bugs that the client hasn’t noticed,
documenting code and features, and other maintenance tasks clearly have value, but don’t move the project forward like a
typical feature story. In some cases the “this over that” of the Agile manifesto gives the appearance of a conflict when
it comes to more-thorough documentation or increased rigidity of specification, even if that’s not really what the manifesto
says.

Often, even when a task to fix a problem comes up, someone on the team can kill the effort just by pointing out that keeping
things the way they are requires no new work, while fixing the problem requires some amount of work. The team’s incentives
largely revolve around succeeding in the two-week cycle, so any new points in the current or near-future sprints feel like
a big risk, even if the effort benefits everybody in the longer term.

The narrative, and finding the best example, showing a story that’s a huge estimate with the software the way it currently
is, but a tiny estimate after refactoring, is the key way to demonstrate where the project’s difficulties lie.

The team discussion can then circle around:


  Why is this story so tough with the code as it is?
  If the difference between estimates is X points, is the estimate for the fix X or less? Would there be other estimates
in the future that would factor in X as well?
  Does the fix block any other stories?
  What are the risks and drawbacks of performing the fix?
  What happens if we do nothing?
  What do similar projects to ours do, that we might not otherwise know?
  Have we identified the hard part of this endeavor?
  Is this the hard part?


How much more effort?

The key thing to do when you’re suggesting a new effort and someone tries shutting it down because it inflates the scope,
is when they correctly point out that a fix or enhancement will require unanticipated effort, simply ask How much more effort?

Pointing out that something is more than nothing is obvious. If you let an unhelpful argument win the day, you’re almost
definitely going to be the person writing a custom Views filter plugin to handle unnecessarily-namespaced fields across node
types. Doing this will rightly feel like adding insult to injury, and hopefully will teach you to speak up when the team
wants to default toward laziness.

Teams are collaborative, and you can’t expect to win every single argument. However, if you don’t say anything when your
teammates counter your suggestions with simple, obvious arguments, you could be doing everyone a disservice.
]]></description>
        <content:encoded><![CDATA[<p>It may be that I have odd luck as a contractor embedded on scrum teams, but more than once I’ve run into weird
group behaviors. Today, as the first post in what may become a series, I want to give an example of some interesting
groupthink, and provide a concrete pointer for how a quiet outsider can try to set their temporary team up for long-term
success.</p>

<p>Overall, this is a drawn-out story that ends with encouraging you to advocate for what you believe in, especially by communicating
effectively and asking the right questions.</p>

<h2 id="a-contrived-example">A contrived example</h2>

<p>It’s common on Drupal projects nowadays, especially when migrating from Drupal 7 to Drupal 8/9/10, to adopt a naming convention
for fields attached to particular entity types and/or bundles. For instance, if you had two node bundles, one called ‘article’
and another called ‘event’, you might set up the machine names of the fields on them in one of the following three-ish ways:</p>

<div class="table--wrapper">
  <table>
    <caption>Field machine names in various naming schemes</caption>
    <thead>
      <tr>
        <th>Label</th>
        <th>Type</th>
        <th>Machine name, shared</th>
        <th>Machine name, shared and generalized</th>
        <th>Machine name, typed, article</th>
        <th>Machine name, typed, event</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Teaser text</td>
        <td>Formatted text, long</td>
        <td>field_teaser_text</td>
        <td>field_longtext_1</td>
        <td>field_article_teasertext</td>
        <td>field_event_teasertext</td>
      </tr>
      <tr>
        <td>Tags</td>
        <td>Entity reference</td>
        <td>field_tags</td>
        <td>field_termreference_1</td>
        <td>field_article_tags</td>
        <td>field_event_tags</td>
      </tr>
      <tr>
        <td>Published date</td>
        <td>Date</td>
        <td>field_date_published</td>
        <td>field_date_1</td>
        <td>field_article_date</td>
        <td>field_event_date</td>
      </tr>
    </tbody>
  </table>
</div>

<p>If you’ve worked on some projects of various sizes and at different points in their lifecycle, you’ll inevitably come to
the conclusion that <strong>the ‘shared’ naming scheme is the correct answer</strong>:</p>

<ul>
  <li>The “shared and generalized” scheme <em>feels</em> like it could be useful, for instance if you had a bunch of content types
that all had many longtext fields. You could share the storage definitions and swap the labels, thereby reducing the
number of database tables somewhat. But if you have to reference these fields in templates and the like, it gets <strong>super confusing super fast</strong></li>
  <li>The “shared and generalized” scheme isn’t <em>actually</em> shared, since <code class="language-plaintext highlighter-rouge">field_termreference_1</code> might be tags on the article
but “event categories” on the event. If you wanted to put both types in a Views display with an exposed filter, you’d run into problems</li>
  <li>The ‘typed’ definitions make the non-shared problem worse. <code class="language-plaintext highlighter-rouge">field_article_tags</code> and <code class="language-plaintext highlighter-rouge">field_event_tags</code> could both be tags
from the same vocabulary, but the (redundant!) bundle namespacing means you will likely need per-bundle templates, plus
way more customized Views displays and buggy field/filter/sort plugins than if you went with shared field machine names</li>
  <li>Sadist/masochist software architects could combine typed and generalized schemes, though this doesn’t become truly painful
unless one type has a ton of fields of the same type</li>
</ul>

<h3 id="a-violent-psychopath">A violent psychopath</h3>

<p>If you have indeed worked on a lot of projects, you’ll know that you often don’t have the luxury to decide on the machine
naming scheme, regardless of if you’re setting the project up at the beginning or jumping into a website with millions of pages.</p>

<p>Famously, John Woods once said “Always code as if the guy who ends up maintaining your code will be a violent psychopath
who knows where you live.” It’s unclear if Mr. Woods ever envisioned a violent psychopath embedded on a team with people
who truly believe their weird architectural decisions were the right call, and who incidentally speak a dialect of English
revolving around subdividing their lives around fortnights, but that’s probably what I’d fear most at retro.</p>

<p>If you inherit a codebase and are now responsible for maintaining it, you can choose to break from the former field machine-naming
scheme, as unless there’s some weird code enforcing it, there’s otherwise no penalty for switching. However, if you’re joining
a team that made a mistake years ago and have never had reason to change course, you’re likely gonna have to continue the
mistakes as long as you work with the team.</p>

<h3 id="except-that-things-could-be-so-much-better">Except that things could be so much better</h3>

<p>We all know that “because we’ve always done it that way” isn’t a great reason to do something, but we also know that change
for change’s sake may be the only thing worse. The trick for a team set in their ways is showing clear reasoning to change,
and helping them see the bright future that awaits them.</p>

<p>Also, if effort is involved in getting to a bright future, you might have to subvert the perverted swirl of scope, velocity,
backlog size, and other scrummy junk that can get in the way of sound decision-making.</p>

<p>In the case of this clearly-made-up example team that definitely listened to my advice, that meant coming up with a concrete
use case.</p>

<h3 id="show-the-why">Show the why</h3>

<p>The wilder part of the <code class="language-plaintext highlighter-rouge">field_date_published</code> example that jumps out to seasoned Drupal developers is that entities tend
to have a ‘created’ <em>property</em> that holds a UNIX timestamp. Properties aren’t quite as flexible as fields, or at least they
aren’t in the same <em>way</em> as fields, but they have the advantage of being more performant to query and built right in to
entities like nodes.</p>

<p>Around 10,000 articles had already been migrated in to the Drupal 9 version of the entirely-fictional hypothetical example
site, and the team was planning to import in over 100,000 events from a legacy system. Since article already had <code class="language-plaintext highlighter-rouge">field_article_date</code>
as architected on autopilot, changing course could require updating existing content and code, even if doing so were quick,
automatic, and not necessarily in the next sprint or two.</p>

<h2 id="when-to-speak-up">When to speak up</h2>

<p>10,000 articles is a lot of articles, don’t get me wrong. But 100,000 events is, website-wise, a big chonking lot of content.
If the team retained the naming scheme and migrated the legacy published date into the new <code class="language-plaintext highlighter-rouge">field_event_date</code> field, that
would largely be decisive. <strong>This was a speak-now-or-forever-hold-your-peace inflection point</strong>.</p>

<p>If you have the courage of your convictions and any reason whatsoever to think the team will be receptive, now or earlier
is the right time to speak up. Maybe not <em>right now</em>, but if you can make your own backlog tickets do that first and stub
it with as much clear, relevant information as possible. Then, when you’re in refinement or sprint planning, it’s natural
to be like “Can we take a look at PROJ-256?” and use that as an in.</p>

<p>Another option, if the previous sprint contained an effort that would have been lighter had a fix been put in place, is
to raise the problem during a retro. This depends on how seriously your team takes retro feedback, as some teams work hard
to improve action items out of retros, whereas other teams treat retrospectives as a way to vent and not much else.</p>

<p>Or bring it up as something to discuss asynchronously on the team slack. It’s mostly a matter of fitting your approach to
your team’s culture.</p>

<h2 id="communicating-effectively">Communicating effectively</h2>

<p>For a small change that has a potentially big impact, there are three great communication styles that can be used in tandem:</p>

<ol>
  <li>A bullet list of benefits</li>
  <li>A short narrative (in user story format if you must) of something that’s easy in the bright new future, but hard in the present</li>
  <li>An outline (as tech specs and acceptance criteria if your PM can be coaxed) of what’s needed to get to the future</li>
</ol>

<p>A bullet list of benefits for migrating the published date from the legacy system into the ‘credted’ property instead of
a new <code class="language-plaintext highlighter-rouge">field_event_date</code>:</p>

<ul>
  <li>Administrative and user-facing listings that combine articles and events will be accurate and easy to create</li>
  <li>There will be no confusion about what <code class="language-plaintext highlighter-rouge">field_event_date</code> is, since the published date is usually far less relevant for
events than the date the event itself starts and finishes</li>
  <li>Querying for the published date will be fast and won’t require any JOINs</li>
  <li>Templating articles and events and displaying bylines could be far simpler</li>
</ul>

<p>This list applies to the fix, and could be made into a story or other kind of ticket, and with any luck the fix (and related
tasks) can be estimated to show how hard or easy it would be to port the article date field into the created property, and
the relative ease of putting a legacy timestamp into ‘created’ in the event migration, rather than messing with <code class="language-plaintext highlighter-rouge">format_date</code>
and all that (though the article migration might already have that done, so it’s not a slam dunk argument).</p>

<h3 id="two-competing-visions-of-the-future-in-short-narrative-form">Two competing visions of the future, in short narrative form</h3>

<blockquote>
  <p><em>As an administrator user</em>, when I navigate to <code class="language-plaintext highlighter-rouge">Content &gt; Advanced</code> via the top admin bar, I expect to see a combined
listing (table) of all node types with applicable shared fields, sorted by default by published date descending.</p>
</blockquote>

<p>The above brief user story serves largely as a thought experiment for a developer who’s encountered similar tickets before.
If everyone on the team is aware that namespaced fields make listings like this far more complicated than they’d otherwise
be, it may be an opportunity for someone to shout that this is a 13-point (or XL t-shirt) ticket, only for the team to
have a realistic conversation about its practices.</p>

<p>In the current situation, this is a big ticket with the potential to introduce a bunch of technical debt. In the bright
future, this would be a 3-pointer (Small t-shirt).</p>

<h2 id="is-this-the-hard-part">Is this the hard part?</h2>

<p>When a team with a backlog, planned sprints, milestones and goals, and all that business stuff encounters a refactoring
task, there’s a natural inclination to bury it. Maintaining existing software, fixing bugs that the client hasn’t noticed,
documenting code and features, and other maintenance tasks clearly have value, but don’t move the project forward like a
typical feature story. In some cases the “this over that” of the Agile manifesto <em>gives the appearance</em> of a conflict when
it comes to more-thorough documentation or increased rigidity of specification, even if that’s not <em>really</em> what the manifesto
says.</p>

<p>Often, even when a task to fix a problem comes up, someone on the team can kill the effort just by pointing out that keeping
things the way they are requires no new work, while fixing the problem requires some amount of work. The team’s incentives
largely revolve around succeeding in the two-week cycle, so any new points in the current or near-future sprints feel like
a big risk, even if the effort benefits everybody in the longer term.</p>

<p>The narrative, and finding the best example, showing a story that’s a huge estimate with the software the way it currently
is, but a tiny estimate after refactoring, is the key way to demonstrate where the project’s difficulties lie.</p>

<p>The team discussion can then circle around:</p>

<ul>
  <li>Why is this story so tough with the code as it is?</li>
  <li>If the difference between estimates is <code class="language-plaintext highlighter-rouge">X</code> points, is the estimate for the fix <code class="language-plaintext highlighter-rouge">X</code> or less? Would there be other estimates
in the future that would factor in <code class="language-plaintext highlighter-rouge">X</code> as well?</li>
  <li>Does the fix block any other stories?</li>
  <li>What are the risks and drawbacks of performing the fix?</li>
  <li>What happens if we do nothing?</li>
  <li>What do similar projects to ours do, that we might not otherwise know?</li>
  <li>Have we identified the hard part of this endeavor?</li>
  <li>Is this the hard part?</li>
</ul>

<h2 id="how-much-more-effort">How much more effort?</h2>

<p>The <strong>key thing to do when you’re suggesting a new effort</strong> and someone tries shutting it down because it inflates the scope,
is when they correctly point out that a fix or enhancement will require unanticipated effort, simply ask <strong>How much more effort?</strong></p>

<p>Pointing out that something is more than nothing is obvious. If you let an unhelpful argument win the day, you’re almost
definitely going to be the person writing a custom Views filter plugin to handle unnecessarily-namespaced fields across node
types. Doing this will rightly feel like adding insult to injury, and hopefully will teach you to speak up when the team
wants to default toward laziness.</p>

<p>Teams are collaborative, and you can’t expect to win every single argument. However, if you don’t say anything when your
teammates counter your suggestions with simple, obvious arguments, you could be doing everyone a disservice.</p>
]]></content:encoded>
      </item>
    
      <item>
        <title>Welcome to the new Solve it once website</title>
        <link>http://solveitonce.com/blog/new-solve-it-once-website/</link>
        <pubDate>Thu, 25 Aug 2022 00:00:00 EST</pubDate>
        
          
          <dc:creator>Brad Czerniak</dc:creator>
        
        
        
          <category><![CDATA[Meta]]></category>
        
        <guid isPermaLink="true">http://solveitonce.com/blog/new-solve-it-once-website/</guid>
        <description><![CDATA[A website two years in the making

One thing they surely tell you about starting a business, but that is easy enough to ignore and forget, is that you can’t
know when you’ll be busy all of the sudden.

When client work and life get busy, the “business development” category can be delayed to the back burner the easiest. In
my case, that meant wanting to replace my perennial coming-soon page with a real website, but prioritizing paying clients
and family for over two years.

You can imagine what a relief this website launch is, then!

A quick catch-up

Solve it once was founded June 2, 2020, just days after COVID lockdowns were lifted in Michigan. I had been spending
Spring 2020 enjoying some much-needed time off (having quit my last full-time job of 7+ years in February):


  Hand-renovated my kitchen with drywall, flooring, cabinets, countertops, paint, and some new electrical and appliances
  Made a wedding website for Shelby and I
  Did some wedding planning and made cool invitations
  Used the wedding website codebase to make a maximalist JAMstack starter
  Took everything I’d learned about Drupal and turned it into what eventually became frost
  Jogged my way back to double-digit-miles weekly long runs
  Watched an unconscionable amount of Star Trek and YouTube
  Played Risk by email with multiple groups of friends
  Got a taste of freelancing prior to formally starting Solve it once


It turns out that I really like freelancing and working from home, so starting a business to do that felt like a no-brainer!

I was on a roll when it came to filing new entities with the State of Michigan, so in do-gooder fashion my friends and I
also founded lower barriers. Progress there can sometimes feel slow in comparison to all the
nine-to-five work, but we have a lot of fun getting on video calls and mustering through Robert’s Rules of Order.

The first two years

The details would probably be boring, so here are some bullet points:


  June/July 2020: Set up Google Drive and domains, made boilerplate, opened a bank account, parked socials, etc.
  July 2020 to February 2021: First three clients! It felt like a miracle that work was coming in
  February 2021 to September 2021: Focused on fourth client, New York Public Library. A dream come true
  September 2021 to February 2022: Caught back up with Pat Oja from Provisio and worked part-time clients
  February 2022 through July 2022: Worked full-time contract for Tactis, getting the opportunity to work on recognizable brands
  August 2022 to present: Spent a month making frost a reality and getting this website launched. Ready for your business!


Throughout it all, I’ve tried to provide some coaching and mentoring to motivated friends who wanted to get into web development,
which is very rewarding. And it’s especially great to have a standing weekly appointment with friends.

In those two years there have been some particularly interesting projects that could benefit from a blog post of their own.
That’s a big reason to subscribe to this blog (or the newsletter using the subscription form on the home page).

Drupal business, JAMstack website

The site you’re on right now is made with the Jekyll static site generator (using the aforementioned finished-starter template)
and hosted for free on GitHub Pages. It’s weird to focus mostly on Drupal sites and market them from the JAMstack site,
but it would be hypocritical not to practice what I preach about minimizing overhead and recurring costs for small businesses.

That hosting bill is taking a cut of your paycheck, so if you don’t need all the features and creature comforts of a CMS
like Drupal, and especially if you have the technical chops to write your own HTML, I heartily recommend using a simpler
site platform to keep costs down.

What I think is cool about the site

This site, being based on finished-starter, has all the features
of the template, plus new components for the homepage wall of logos among other nifty things.

Here are a few things you may not have immediately noticed that I think are cool:


  In the footer there’s a link to ‘Documentation’, which is a treasure trove of wild stuff you can borrow
  flat-rate Drupal websites and sprints. I don’t know if they will be popular, but I think it’s cool
  Speaking of, that’s lightweight snipcart e-commerce powering the products


Now that the site is a reality, I’m hoping to be able to put an afternoon here and there into subtle improvements. All the
more reason to come back and see what’s new!

Thank you

Thank you for visiting the site, for reading this post, and for considering so1ve for your next ambitious web project.
Please reach out and say hi!
]]></description>
        <content:encoded><![CDATA[<h2 id="a-website-two-years-in-the-making">A website two years in the making</h2>

<p>One thing they surely tell you about starting a business, but that is easy enough to ignore and forget, is that you can’t
know when you’ll be busy all of the sudden.</p>

<p>When client work and life get busy, the “business development” category can be delayed to the back burner the easiest. In
my case, that meant wanting to replace my perennial coming-soon page with a real website, but prioritizing paying clients
and family for over two years.</p>

<p>You can imagine what a relief this website launch is, then!</p>

<h2 id="a-quick-catch-up">A quick catch-up</h2>

<p>Solve it once was founded June 2, 2020, just days after COVID lockdowns were lifted in Michigan. I had been spending
Spring 2020 enjoying some much-needed time off (having quit my last full-time job of 7+ years in February):</p>

<ul>
  <li>Hand-renovated my kitchen with drywall, flooring, cabinets, countertops, paint, and some new electrical and appliances</li>
  <li>Made a <a href="https://shelbybrad.com/">wedding website for Shelby and I</a></li>
  <li>Did some wedding planning and made cool invitations</li>
  <li>Used the wedding website codebase to make a <a href="https://lowerbarriers.org/finished-starter">maximalist JAMstack starter</a></li>
  <li>Took everything I’d learned about Drupal and turned it into what eventually became <a href="https://www.frostdrupal.com/">frost</a></li>
  <li>Jogged my way back to double-digit-miles weekly long runs</li>
  <li>Watched an unconscionable amount of Star Trek and YouTube</li>
  <li>Played Risk by email with multiple groups of friends</li>
  <li>Got a taste of freelancing prior to formally starting Solve it once</li>
</ul>

<p>It turns out that I really like freelancing and working from home, so starting a business to do that felt like a no-brainer!</p>

<p>I was on a roll when it came to filing new entities with the State of Michigan, so in do-gooder fashion my friends and I
also founded <a href="https://lowerbarriers.org/">lower barriers</a>. Progress there can sometimes feel slow in comparison to all the
nine-to-five work, but we have a lot of fun getting on video calls and mustering through Robert’s Rules of Order.</p>

<h3 id="the-first-two-years">The first two years</h3>

<p>The details would probably be boring, so here are some bullet points:</p>

<ul>
  <li>June/July 2020: Set up Google Drive and domains, made boilerplate, opened a bank account, parked socials, etc.</li>
  <li>July 2020 to February 2021: First three clients! It felt like a miracle that work was coming in</li>
  <li>February 2021 to September 2021: Focused on fourth client, New York Public Library. A dream come true</li>
  <li>September 2021 to February 2022: Caught back up with Pat Oja from <a href="https://provisiosolutions.com/">Provisio</a> and worked part-time clients</li>
  <li>February 2022 through July 2022: Worked full-time contract for Tactis, getting the opportunity to work on recognizable brands</li>
  <li>August 2022 to present: Spent a month making frost a reality and getting this website launched. Ready for your business!</li>
</ul>

<p>Throughout it all, I’ve tried to provide some coaching and mentoring to motivated friends who wanted to get into web development,
which is very rewarding. And it’s especially great to have a standing weekly appointment with friends.</p>

<p>In those two years there have been some particularly interesting projects that could benefit from a blog post of their own.
That’s a big reason to subscribe to this blog (or the newsletter using the subscription form on the home page).</p>

<h2 id="drupal-business-jamstack-website">Drupal business, JAMstack website</h2>

<p>The site you’re on right now is made with the Jekyll static site generator (using the aforementioned finished-starter template)
and hosted for free on GitHub Pages. It’s weird to focus mostly on Drupal sites and market them from the JAMstack site,
but it would be hypocritical not to practice what I preach about minimizing overhead and recurring costs for small businesses.</p>

<p>That hosting bill is taking a cut of your paycheck, so if you don’t need all the features and creature comforts of a CMS
like Drupal, and especially if you have the technical chops to write your own HTML, I heartily recommend using a simpler
site platform to keep costs down.</p>

<h3 id="what-i-think-is-cool-about-the-site">What I think is cool about the site</h3>

<p>This site, being based on <a href="https://github.com/lowerbarriers/finished-starter">finished-starter</a>, has all the features
of the template, plus new components for the homepage wall of logos among other nifty things.</p>

<p>Here are a few things you may not have immediately noticed that I think are cool:</p>

<ul>
  <li>In the footer there’s a link to ‘Documentation’, which is a treasure trove of wild stuff you can borrow</li>
  <li><strong>flat-rate Drupal websites and sprints</strong>. I don’t know if they will be popular, but I think it’s cool</li>
  <li>Speaking of, that’s lightweight snipcart e-commerce powering the products</li>
</ul>

<p>Now that the site is a reality, I’m hoping to be able to put an afternoon here and there into subtle improvements. All the
more reason to come back and see what’s new!</p>

<h2 id="thank-you">Thank you</h2>

<p>Thank you for visiting the site, for reading this post, and for considering so1ve for your next ambitious web project.
Please reach out and say hi!</p>
]]></content:encoded>
      </item>
    
  
</channel>
</rss>
