Solve it once | Drupal https://solveitonce.com/rss/drupal/index.xml Solve it once, LLC makes better websites faster and for less money. Sun, 01 Dec 2024 19:26:52 GMT en hourly 1 [Jekyll](https://github.com/mojombo/jekyll) Star-frost (lovers) http://solveitonce.com/blog/star-frost/ Sun, 21 Jul 2024 00:00:00 EST Brad Czerniak http://solveitonce.com/blog/star-frost/ 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 Steal this content! Everything on this site is under a CC0 license, so you can copy/paste this without guilt.

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

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

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

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

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

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

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

so1ve’s Starshot commitment

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

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

Recipes

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

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

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

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

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

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

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

Decommission

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

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

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

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

Backfill features

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

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

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

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

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

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

In closing

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

In these last few months before the decommissioning I will try to cherish each minor-version update and small tweak that comes along. Hopefully soon I’ll find the next big thing on which to focus my zealous attention. Watch this space!

]]>
Unofficial Starshot strategy guide http://solveitonce.com/blog/unofficial-starshot-strategy-guide/ Fri, 31 May 2024 00:00:00 EST Brad Czerniak http://solveitonce.com/blog/unofficial-starshot-strategy-guide/ 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 Steal this content! Everything on this site is under a CC0 license, so you can copy/paste this without guilt.

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

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

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

Table of contents

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

Straining the metaphor

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

I Was SCARED To Say This To NASA... (But I said it anyway) - Smarter Every Day 293

Starshot is effectively three things:

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

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

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

Marketing

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

1. Positioning against Wordpress

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

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

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

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

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

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

Partners fill in the blanks

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

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

2. Positioning against SaaS and enterprise

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

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

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

3. Welcoming back returners

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

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

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

Project management

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

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

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

Constraining scope

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

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

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

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

Timeline management

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

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

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

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

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

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

Features

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

Project browser

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

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

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

Recipes

A good Drupal site architecture is a balancing act:

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

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

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

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

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

Experience builder

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

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

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

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

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

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

Key contrib modules

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

These contrib modules rule:

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

Default content

This is the section where Brad has big opinions.

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

They mostly fall into three categories:

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

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

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

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

In closing

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

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

If you’re working on some part of Starshot and think I could lend my expertise in some way, please don’t hesitate to reach out to [email protected]. 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.

]]>
frost design handoff http://solveitonce.com/blog/frost-design-handoff/ Tue, 13 Jun 2023 00:00:00 EST Brad Czerniak http://solveitonce.com/blog/frost-design-handoff/ 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 Steal this content! Everything on this site is under a CC0 license, so you can copy/paste this handoff without guilt.

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

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

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

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

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

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

Table of contents

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

First, where to reference

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

Second, brand assets

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

Brand image asset details
Image Format Dimensions Notes
logo.svg SVG 64x64, approx. If possible, provide the logo as a real SVG file (rather than a JPEG/PNG embedded in an SVG wrapper). The header layout will constrain the image's size, but scaling it to be nearly the size it should appear on the site can be a page load performance boost. 64-100 pixels for the height is a good target, with the width being more flexible (for instance it could be 240-ish pixels wide if the image contains both the mark and text).
footer-logo.svg SVG 64x64, approx. Even if the header and footer will eventually have the same color scheme and the same logo, it'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.
favicon.ico ICO 64x64 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.
apple-touch-icon.png PNG 512x512 Icon used when installing the site to your desktop or home screen. In order to avoid providing a ton of slightly-varied versions of the same asset, ship the big 512x512 version with just the logo mark, a solid color background, and at least a little padding all the way around the logo.
bg_hero_default.jpg JPEG 1920x1080 On system and other pages where a custom hero isn'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.
social_default_1200x630.jpg JPEG 1200x630 Social sharing image for Facebook/LinkedIn/Twitter. The template for making the image is available as an XCF for GIMP, and online converters to PSD are easy to come by.

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

Screenshot showing part of a frost page, where two section backgrounds are light-masked icebergs

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

Third, base styles

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

Fonts

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

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

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

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

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

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

Colors

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

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

Here’s white/black/greys:

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

  • #222
  • #555
  • #aaa
  • #f7f7f7
  • #fff

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

And the medium shades of the three brand colors:

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

  • #007599
  • #E32416
  • #00838a

And the light shades:

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

  • #ccf4ff
  • #ffcfcc
  • #ccfcff

And the dark shades:

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

  • #002733
  • #331716
  • #003033

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

Here’s the theme accent color:

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

  • #6100a7

Delivery

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

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

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

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

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

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

Everything else

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

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

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

Fourth, component party!

Now we’re cooking with gas.

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

Tags in the style guide

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

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

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

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

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

Reusable components

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

Sectioning

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

Stripe: Atomic

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

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

Screenshot showing the editor experience for content on an atomic stripe

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

Screenshot showing the editor experience for settings on an atomic stripe

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

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

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

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

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

Layout

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

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

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

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

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

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

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

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

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

Storytelling

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

Accordion

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

Screenshot showing three example accordions

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

Design notes:

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

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

Block

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

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

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

Rich text as a pull-quote:

Screenshot showing an example blockquote

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

Design notes:

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

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

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

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

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

Card

An individual card has four fields:

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

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

Card: Percent

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

Screenshot showing example cards

Card: Percent has three content fields by default:

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

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

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

Some design and functionality notes:

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

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

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

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

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

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

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

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

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

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

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

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

Frankly, <iframe>s kind of suck. A content author can place them, and are presented with the usual details to fill out:

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

Design notes:

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

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

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

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

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

Design notes:

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

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

Design notes:

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

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

Screenshot showing a hotspot's tooltip when hovered

Design notes:

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

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

Design notes:

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

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

Screenshot showing three system messages

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

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

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

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

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

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

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

Rich text

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

Screenshot showing a basic CKEditor5 WYSIWYG setup in frost

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

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

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

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

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

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

Design notes:

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

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

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

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

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

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

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

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

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

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

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

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

User listing

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

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

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

View

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

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

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

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

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

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

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

Some design notes:

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

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

Fifth, wrapper

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

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

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

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

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

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

Screenshot showing the mobile hamburger tray open in the frost demo

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

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

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

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

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

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

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

Sixth, page mockups

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

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

Key notes:

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

Three heroes

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

Fallback default and ‘system’ pages

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

Screenshot showing the plain fallback hero for system pages in frost

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

However, the following notes apply:

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

Per-bundle pre-configured heroes

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

Screenshot showing the per-bundle hero for events in frost

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

Screenshot showing how the event hero is configured in the admin UI

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

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

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

Stripe: Atomic heroes

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

Screenshot showing a stripe hero on the component guide page of the frost demo site

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

Screenshot showing the editing experience for an atomic hero

This means you can easily make heroes that have:

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

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

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

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

Wrapping up

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

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

  1. When in doubt, design the smallest pieces first, as they’re then used in combination in larger components
  2. 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
  3. 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
  4. 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
  5. Hopefully the places where I said “you should probably stick to such-and-such” make sense as being ways to maintain the integrity of the system and keep scope in check, rather than getting in the way of creative freedom or making all sites designed this way look same-y. You can break away from almost any of these guidelines as long as you and the team are okay with the scope implications

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

And of course, if you run into any snags or want to hire Brad for a few hours to iron something out, please don’t hesitate to reach out to [email protected].

]]>
Introducing frost http://solveitonce.com/blog/introducing-frost/ Sat, 15 Apr 2023 00:00:00 EST Brad Czerniak http://solveitonce.com/blog/introducing-frost/ 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 It seems like there’s a few common pitfalls at the outset of a big web project:

  1. Underestimating front-end development time
  2. Forgetting about the boring pages, like the Privacy Policy
  3. Assuming the Content Management System can do more than it can by default

frost is a strong attempt to circumvent those pitfalls when making new sites in Drupal, so projects can stay on track. Let’s take a look at some of its key features:

Introducing Frost (Drupal) by making wordpress.org: Free, open source atomic storytelling

Fully-implemented front end

Just like popular site-building tools and ready-made themes for other systems, frost’s frost_theme has all the styles and JavaScript snippets needed to launch a functional and beautiful website quickly.

frost in PHPStorm, showing the CSS and JS structure

Out of the box this lets you quickly develop new components, yes, but also you don’t have to worry about:

  • Mobile “Hamburger” menu and drawer
  • Search bar
  • Responsive layouts, even complex ones
  • Teasers and cards for content listings
  • Site footer with contact information and social icons
  • Advanced components, such as tabbed interfaces and background videos anywhere

More than that, frost_theme will keep you productive.

.flex-direction--column {
  flex-direction: column;
}

If the utility class above makes sense to you – that the property name is first (hyphens included), then two hyphens, then the value associated with the property – then clearly you know CSS well, and you also know 90% of the utility classes in the theme by heart already!

Similarly, the JavaScript ‘partials’ directory has useful examples of how frost (and its JAMstack sibling, finished-starter) handles behavior lifecycle:

  1. Once the DOM is ready for the script, the utilityInitializer() function runs the functions registered to it to make the component ready
  2. If new elements are added to the DOM, utilityInitializer()’s mutationObserver will get those components ready, too
  3. Clicks and other events are bubbled and filtered from the body, so the listener will pick up dynamically-added components

The boring pages: done!

On day one, just minutes after going through the installer, your new frost Drupal site has:

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!

Screenshot of the frost default Privacy Policy, with images and alternating stripes for interest

At some point before or after launching your site, you’re bound to have to think about all those pages, plus XML sitemaps and all the jazz every site needs to have. With frost you can worry a lot less.

Does what you want it to

If you’ve ever had the pleasure of having a website made for you, there may have been hiccups, like:

Here’s your listing page of case studies with filters for categories. Pretty cool, huh? Oh, you want some intro text? No problem. And regular page content below?! That would be an additional 8 development hours.

…or…

The designs don’t have an accordion in a right column. To make that happen we’d have to refactor the frontend theme. Well that would be a few thousand dollars over the original scope…

With frost you can put your accordions where you want, and your listing page can be customized to your heart’s content.

A set of tabs, with the visible tab containing an accordion, for demonstration purposes.

Also: free and easy

frost is based on Drupal, which is free and open source software. You can clone or fork the code and have a working local version of the site ready to go in minutes. If you’re not a PHP developer, though, you may want to hire Brad to set it up for you.

]]>
How much more effort? http://solveitonce.com/blog/is-this-the-hard-part/ Sat, 27 Aug 2022 00:00:00 EST Brad Czerniak http://solveitonce.com/blog/is-this-the-hard-part/ 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 It may be that I have odd luck as a contractor embedded on scrum teams, but more than once I’ve run into weird group behaviors. Today, as the first post in what may become a series, I want to give an example of some interesting groupthink, and provide a concrete pointer for how a quiet outsider can try to set their temporary team up for long-term success.

Overall, this is a drawn-out story that ends with encouraging you to advocate for what you believe in, especially by communicating effectively and asking the right questions.

A contrived example

It’s common on Drupal projects nowadays, especially when migrating from Drupal 7 to Drupal 8/9/10, to adopt a naming convention for fields attached to particular entity types and/or bundles. For instance, if you had two node bundles, one called ‘article’ and another called ‘event’, you might set up the machine names of the fields on them in one of the following three-ish ways:

Field machine names in various naming schemes
Label Type Machine name, shared Machine name, shared and generalized Machine name, typed, article Machine name, typed, event
Teaser text Formatted text, long field_teaser_text field_longtext_1 field_article_teasertext field_event_teasertext
Tags Entity reference field_tags field_termreference_1 field_article_tags field_event_tags
Published date Date field_date_published field_date_1 field_article_date field_event_date

If you’ve worked on some projects of various sizes and at different points in their lifecycle, you’ll inevitably come to the conclusion that the ‘shared’ naming scheme is the correct answer:

  • The “shared and generalized” scheme feels like it could be useful, for instance if you had a bunch of content types that all had many longtext fields. You could share the storage definitions and swap the labels, thereby reducing the number of database tables somewhat. But if you have to reference these fields in templates and the like, it gets super confusing super fast
  • The “shared and generalized” scheme isn’t actually shared, since field_termreference_1 might be tags on the article but “event categories” on the event. If you wanted to put both types in a Views display with an exposed filter, you’d run into problems
  • The ‘typed’ definitions make the non-shared problem worse. field_article_tags and field_event_tags could both be tags from the same vocabulary, but the (redundant!) bundle namespacing means you will likely need per-bundle templates, plus way more customized Views displays and buggy field/filter/sort plugins than if you went with shared field machine names
  • Sadist/masochist software architects could combine typed and generalized schemes, though this doesn’t become truly painful unless one type has a ton of fields of the same type

A violent psychopath

If you have indeed worked on a lot of projects, you’ll know that you often don’t have the luxury to decide on the machine naming scheme, regardless of if you’re setting the project up at the beginning or jumping into a website with millions of pages.

Famously, John Woods once said “Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.” It’s unclear if Mr. Woods ever envisioned a violent psychopath embedded on a team with people who truly believe their weird architectural decisions were the right call, and who incidentally speak a dialect of English revolving around subdividing their lives around fortnights, but that’s probably what I’d fear most at retro.

If you inherit a codebase and are now responsible for maintaining it, you can choose to break from the former field machine-naming scheme, as unless there’s some weird code enforcing it, there’s otherwise no penalty for switching. However, if you’re joining a team that made a mistake years ago and have never had reason to change course, you’re likely gonna have to continue the mistakes as long as you work with the team.

Except that things could be so much better

We all know that “because we’ve always done it that way” isn’t a great reason to do something, but we also know that change for change’s sake may be the only thing worse. The trick for a team set in their ways is showing clear reasoning to change, and helping them see the bright future that awaits them.

Also, if effort is involved in getting to a bright future, you might have to subvert the perverted swirl of scope, velocity, backlog size, and other scrummy junk that can get in the way of sound decision-making.

In the case of this clearly-made-up example team that definitely listened to my advice, that meant coming up with a concrete use case.

Show the why

The wilder part of the field_date_published example that jumps out to seasoned Drupal developers is that entities tend to have a ‘created’ property that holds a UNIX timestamp. Properties aren’t quite as flexible as fields, or at least they aren’t in the same way as fields, but they have the advantage of being more performant to query and built right in to entities like nodes.

Around 10,000 articles had already been migrated in to the Drupal 9 version of the entirely-fictional hypothetical example site, and the team was planning to import in over 100,000 events from a legacy system. Since article already had field_article_date as architected on autopilot, changing course could require updating existing content and code, even if doing so were quick, automatic, and not necessarily in the next sprint or two.

When to speak up

10,000 articles is a lot of articles, don’t get me wrong. But 100,000 events is, website-wise, a big chonking lot of content. If the team retained the naming scheme and migrated the legacy published date into the new field_event_date field, that would largely be decisive. This was a speak-now-or-forever-hold-your-peace inflection point.

If you have the courage of your convictions and any reason whatsoever to think the team will be receptive, now or earlier is the right time to speak up. Maybe not right now, but if you can make your own backlog tickets do that first and stub it with as much clear, relevant information as possible. Then, when you’re in refinement or sprint planning, it’s natural to be like “Can we take a look at PROJ-256?” and use that as an in.

Another option, if the previous sprint contained an effort that would have been lighter had a fix been put in place, is to raise the problem during a retro. This depends on how seriously your team takes retro feedback, as some teams work hard to improve action items out of retros, whereas other teams treat retrospectives as a way to vent and not much else.

Or bring it up as something to discuss asynchronously on the team slack. It’s mostly a matter of fitting your approach to your team’s culture.

Communicating effectively

For a small change that has a potentially big impact, there are three great communication styles that can be used in tandem:

  1. A bullet list of benefits
  2. 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
  3. An outline (as tech specs and acceptance criteria if your PM can be coaxed) of what’s needed to get to the future

A bullet list of benefits for migrating the published date from the legacy system into the ‘credted’ property instead of a new field_event_date:

  • Administrative and user-facing listings that combine articles and events will be accurate and easy to create
  • There will be no confusion about what field_event_date is, since the published date is usually far less relevant for events than the date the event itself starts and finishes
  • Querying for the published date will be fast and won’t require any JOINs
  • Templating articles and events and displaying bylines could be far simpler

This list applies to the fix, and could be made into a story or other kind of ticket, and with any luck the fix (and related tasks) can be estimated to show how hard or easy it would be to port the article date field into the created property, and the relative ease of putting a legacy timestamp into ‘created’ in the event migration, rather than messing with format_date and all that (though the article migration might already have that done, so it’s not a slam dunk argument).

Two competing visions of the future, in short narrative form

As an administrator user, when I navigate to Content > Advanced via the top admin bar, I expect to see a combined listing (table) of all node types with applicable shared fields, sorted by default by published date descending.

The above brief user story serves largely as a thought experiment for a developer who’s encountered similar tickets before. If everyone on the team is aware that namespaced fields make listings like this far more complicated than they’d otherwise be, it may be an opportunity for someone to shout that this is a 13-point (or XL t-shirt) ticket, only for the team to have a realistic conversation about its practices.

In the current situation, this is a big ticket with the potential to introduce a bunch of technical debt. In the bright future, this would be a 3-pointer (Small t-shirt).

Is this the hard part?

When a team with a backlog, planned sprints, milestones and goals, and all that business stuff encounters a refactoring task, there’s a natural inclination to bury it. Maintaining existing software, fixing bugs that the client hasn’t noticed, documenting code and features, and other maintenance tasks clearly have value, but don’t move the project forward like a typical feature story. In some cases the “this over that” of the Agile manifesto gives the appearance of a conflict when it comes to more-thorough documentation or increased rigidity of specification, even if that’s not really what the manifesto says.

Often, even when a task to fix a problem comes up, someone on the team can kill the effort just by pointing out that keeping things the way they are requires no new work, while fixing the problem requires some amount of work. The team’s incentives largely revolve around succeeding in the two-week cycle, so any new points in the current or near-future sprints feel like a big risk, even if the effort benefits everybody in the longer term.

The narrative, and finding the best example, showing a story that’s a huge estimate with the software the way it currently is, but a tiny estimate after refactoring, is the key way to demonstrate where the project’s difficulties lie.

The team discussion can then circle around:

  • Why is this story so tough with the code as it is?
  • If the difference between estimates is X points, is the estimate for the fix X or less? Would there be other estimates in the future that would factor in X as well?
  • Does the fix block any other stories?
  • What are the risks and drawbacks of performing the fix?
  • What happens if we do nothing?
  • What do similar projects to ours do, that we might not otherwise know?
  • Have we identified the hard part of this endeavor?
  • Is this the hard part?

How much more effort?

The key thing to do when you’re suggesting a new effort and someone tries shutting it down because it inflates the scope, is when they correctly point out that a fix or enhancement will require unanticipated effort, simply ask How much more effort?

Pointing out that something is more than nothing is obvious. If you let an unhelpful argument win the day, you’re almost definitely going to be the person writing a custom Views filter plugin to handle unnecessarily-namespaced fields across node types. Doing this will rightly feel like adding insult to injury, and hopefully will teach you to speak up when the team wants to default toward laziness.

Teams are collaborative, and you can’t expect to win every single argument. However, if you don’t say anything when your teammates counter your suggestions with simple, obvious arguments, you could be doing everyone a disservice.

]]>