<?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 | Drupal</title>
  <atom:link href="https://solveitonce.com/rss/drupal/" rel="self" type="application/rss+xml" />
  <link>https://solveitonce.com/rss/drupal/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>Steal this content! Everything on this site is under a CC0 license, so youcan copy/paste this without guilt.First, a bit of housekeeping: in April I took a permanent full-time job with Principal Financial Groupwhich 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 lowerThat’s not to say I’m out of the market entirely! If you have a project or wish to m</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>Steal this content! Everything on this site is under a CC0 license, so youcan 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-pleaserthat closely followed the submission guidelines and was entered before the original deadline. The same cannot be said for many ofthe selected pitches. Had I known the selection criteria didn’t have much to do with the submission guidelines, maybe I wouldn’t haveput in so much time and energy.But I didn’t complain about that</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>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>Steal this content! Everything on this site is under a CC0 license, so youcan copy/paste this handoff without guilt.Hello designer friend (BTW, did you knowso1ve is looking for talented freelance designers?)!There are some nuances to designing for frost specifically, and to some extent Drupal ingeneral, 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 somethi</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>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>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 defaultfrost is a strong attempt to circumvent those pitfalls when making new sites in Drupal, soprojects can stay on track. Let’s take a look at some of its key features:                                                                                                    Fully-implemented front endJust like popular site-building tools and ready-made t</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>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>It may be that I have odd luck as a contractor embedded on scrum teams, but more than once I’ve run into weirdgroup behaviors. Today, as the first post in what may become a series, I want to give an example of some interestinggroupthink, and provide a concrete pointer for how a quiet outsider can try to set their temporary team up for long-termsuccess.Overall, this is a drawn-out story that ends with encouraging you to advocate for what you believe in, especially by communicatingeffectively and asking the right questions.A contrived exampleIt’s common on Drupal projects nowadays, especially wh</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>
    
  
</channel>
</rss>
