Reach out to book a complimentary 20-minute call. Share your website, specific concerns, and book your no-obligation chat to ask me anything about your website.
WordPress gives you ownership, flexibility, and independence. You can update it yourself, grow into it over time, and work with any developer you choose — including someone other than me.
Reach out to book a complimentary 20-minute call. Share your website, specific concerns, and book your no-obligation chat to ask me anything about your website.
WordPress gives you ownership, flexibility, and independence. You can update it yourself, grow into it over time, and work with any developer you choose — including someone other than me.
Lately I’ve been trying out Studio, WordPress’s own local development app. Initially, just as an alternative to Local to see what it could do. I’ve found that Studio Code, the agentic AI built into it, has been surprisingly nice to use. Connected to WordPress-specific documentation, it feels more powerful and reliable than my trial run of that other WordPress experiment, Telex, which tends to unravel with successive requests (in my experience).
Using Studio Code on a few real-life client tasks this past week, my overall impression is positive: it’s intuitive and I really like being able to connect my IDE to this setup. However, while it’s good at creating a solution it is less good at choosing how a solution should be built in WordPress.
This is a BETA version, I’m sure the experience will become refined over time and with more usage.
Make me a theme!
Diving right into Studio Code on the heels of it’s launch (and with 100,000 free AI credits to start), I asked it to build me a new block theme based on an existing classic site, and gave it a full-page screenshot to work from.
In just a few minutes it had spun up a new site and a custom block theme. “Wow!,” I thought with just a twinge of existential dread, “This is going to save me so much time!”
But then I looked at how it decided to build. Behind the pretty design curtain was a hardcoded stylesheet of colors, font sizes, spacing values, and core block tweaks that had no global definitions. Rather than using theme.json, or executing designs in core blocks on the page, Studio Code had created something with a classic junior-developer mindset – built literally to the spec but without any consideration for long-term maintainability or natural changes in content over time.
Taking apart what AI built and putting it back together the “right” way, I wondered if being more specific in my prompts about how to build this theme would improve the result. But also, shouldn’t it already sort of know that hardcoding everything is “wrong”? Or, at least, that it shouldn’t be the default?
As I rejiggered the theme, I gave Studio Code a short, specific task to explain why a style wasn’t appearing, using CSS I’d already written and tested elsewhere. I shared the code snippet (add a border-bottom on the current page’s link in the main navigation).
Studio Code found the relevant code in my theme, checked the frontend and reported that the class it needed — .current-menu-item — wasn’t being applied. Which it then decided to interpret as an error. It called the missing class the “real bug” and promptly dove into architecting a solution.
As it iterated, showing me a log that proved it was working very hard, it found the reason why the class didn’t exist on the front-end: the nav links weren’t wired to real WordPress Page objects. WordPress only auto-adds .current-menu-item when a nav link references a real post ID. The menu links were hardcoded URLs because Studio Code had created a visual match to my initial design, but not the actual pages indicated.
But, again, this was a choice made by Studio Code to put placeholder links in the menu rather than create a menu of pages. That’s not something I would do when building a site out and it didn’t occur to me that anyone else (or any agentic presence) would create a menu this way either.
From this “bug”, it determined that the next step was to create a new PHP function: a filter that manually compared each link’s URL to the current request and tags it as “current” allowing my class to work.
But that solve was also a totally unnecessary fix (that cost me whole $1.97 in AI credits). The better answer would have been going into the editor and reconnecting each nav item to its actual Page. The new function solved a perceived failure that was actually just WordPress working as intended. If I was using Studio Code as a non-developer, I wouldn’t have known the difference.
Studio Code didn’t tell me it was about to add a custom function, and it never surfaced that an alternative fix was rebuilding the nav links, not working around their absence. Solving-the-symptom and solving-the-cause looked identical to the tool (because it’s predictive, not consciously trouble-shooting).
I expected that Studio Code would have the context around how WordPress works to approach the initial request differently. But, that just reinforces the value of my own experience with WordPress over 20 years. I know where to look when funky issues occur. To Studio Code (aka. The Hammer), everything is a nail.
Status:
Investment: 100,000 AI credits
Used: 19,727 credits
Level of completion: Complete but also wrong
Production-readiness: Not ready
Probabilistic decision-making
“Combobulating…”
Part of why I didn’t catch these misdirected efforts in the moment: Studio Code (and other AI pals) display a running log while they work. They are disarmingly busy with file searches, checks, little status lines, and occasional bits of personality. To a human, that reads like someone narrating their process, and we extend that the same trust we’d extend a colleague who’s talking through their steps out loud. A person doing that is usually also self-correcting as they go, so hearing the narration is itself a signal that the work is on track.
Alas, ’tis but an illusion. The log is a UX pattern, not a transparency window. It tells you the tool is doing something, even when that’s just diving down another rabbit-hole.
Web designers aren’t out of a job (yet)
What Studio Code produced worked but it didn’t reliably reach for the WordPress mechanism that would allow for a more functional, thoughtful structure. Like the Mechanical Turk that appeared to play chess autonomously, it’s a fun rush to the finish line but unless you can run through multiple passes and specifically steer it (ouch, the AI credits!), it’s not quite a replacement for the knowledgable human within.
I can review what Studio Code and AI tools produce and decide whether to accept it or push back on the process. For the parts I need technical help with – building utility plugins and custom blocks – Studio Code is still a genuinely handy tool. I fix what I think it should have done differently, or, as I like to say, make it more better.
For people who don’t have a background in building websites, or knowledge of what to ask for, what gets produced is likely to create issues: accessibility failures, a plugin or theme that’s hard to maintain over time, and usability problems for anyone else who has to work with what they made.
In some ways, this reminds me of the evolution of desktop publishing. Once people could create in Microsoft Word, design opened up to everyone. There were fewer barriers to entry – which in my opinion is always good. It also introduced a lot of “bad” design, simply because people weren’t trained in the field. Comic Sans, all caps, off-brand colors, whimsical clip art, centered or fully justified text – these are the classic faux pas that make professional designers cringe. But ugly can be beautiful too. Look at thrift store paintings and found art, both of which have their own dedicated connoisseurs. What’s beautiful is that people want to express themselves, in all kinds of ways. When you don’t know the rules, there are no rules (which is something you also have to discover on your own after you learn all of the rules)!
So if people want to prompt their way through a website design, that’s not a bad thing. Maybe it becomes a kind of web design renaissance – people generating on the fly and just having fun with it.
But… as a web developer, there is a place where those rules do matter, when you are making something for public use and not just for your own amusement. So, don’t forget to review the code and push back on those assumptions.
If you have a website, it’s likely that your media library has accumulated some unoptimized files.
I recently did an audit for a small nonprofit that had been running their WordPress site for about ten years. What we found was an overstuffed digital attic: huge PNG images, videos eating up hundreds of megabytes of server space, old PDFs nobody had accessed in years, and zip archives that probably shouldn’t have been uploaded in the first place.
Up to 90% of digital data is not used. We collect. We store. We create and then don’t use. Data is the atomic structure of digital. Words, music, images, films, videos, software. It all ends up as data. Most data is like single use, throwaway plastic. What sort of society accepts 90% waste?
That’s the law of space (and time): the more space you have, the more junk you will fill it up with. Adding storage is always easier than deleting what you no longer need. But there are real costs to this seemingly infinite, intangible digital space: to your site performance, to your hosting bill, and to the environment.
Back in my day…
If you built websites in the dial-up era, you already know this story. But, let’s wax nostalgic for a minute:
File size wasn’t an abstract concern in the early days of the web. A 200 KB image on a 56k modem cost you 60-seconds and a beep boop … and your image loaded incrementally.
Choosing the wrong file format, or skipping optimization, could mean the difference between a site that worked and a page full of broken image icons.
We had three formats to choose from (and we had to walk 3 miles in the snow to get to school every day):
BitMap and GIF (Graphics Interchange Format) – were the first graphics formats supported by HTML. GIF was perfect for simple graphics, logos, quick animations, and those blinking “under construction” banners that were everywhere on the early web. Capped at 256 web-safe colors. Photographs had to be dithered if saved as a GIF and the results were always pixelated.
The JPEG (Joint Photographic Experts Group) became the standard in 1992 and was a revelation for photographic images, introducing lossy compression that could squeeze a photo down to a fraction of its size. You chose your compression level deliberately, previewing the quality tradeoff before you committed.
PNG (Portable Network Graphics) – developed as a patent-free alternative to GIF with better quality and more colors.
Screens added another layer of constraint. Many monitors ran at 800 x 600 pixels (smaller than today’s phone screens in raw pixel count). If you sized an image incorrectly, it could overflow the screen, get clipped, or be resampled poorly. We weren’t just picking a format, we were working within a strict pixel budget.
Screen resolutions improved. Broadband arrived and storage got cheap. Suddenly, the limitations we had been working with evaporated and file size stopped feeling like anyone’s problem. The costs of our unoptimized media have became cumulative and hidden rather than showing up as a spinning progress bar.
Even if you live in a 5G world, speed matters
Broadband and fast wifi are easy to take for granted when you’re working at a desk with a new machine and a reliable connection. But we should not assume that’s the default experience of our website’s visitors.
Many people access the internet on pay-as-you-go mobile plans where every megabyte of data has a real dollar cost. Others are on older devices, slower connections, or both. The person managing your site and the person visiting it are often living in very different bandwidth realities, and designing only for the former is making a big assumption.
Page speed has direct SEO implications
Core Web Vitals are a Google ranking signal, and large images are one of the most common causes of poor scores. Mobile users on cellular connections still feel oversized images.
More data uses more energy
Files stored on a website live on servers that run 24/7, drawing electricity and generating heat that requires additional energy to cool. An old, unlinked file is still occupying storage and contributing a small share of the site’s overall resource use.
Multiply that across millions of unmaintained sites and cloud storage services and it’s part of why data centers in the US currently consume 4–5% of total national electricity, a figure that could reach as high as 17% by 2030 – thanks AI.
The big picture on file sizes
Before looking at fixes, let’s get a sense of the scale involved:
Unit
Size
What it feels like
1 KB
1,024 bytes
A short plain-text email
100 KB
~100,000 bytes
A well-optimized web image
1 – 2 MB
~1 million bytes
An unoptimized JPEG or PNG, ~1 min of MP3
5 – 10 MB
~5–10 million bytes
A larger PDF on your website
1 GB
~1 billion bytes
~200 smartphone photos, ~4 min of 4K video
Many websites I work with have been around for a few years and they are often host 10 GB or more of data. Most of that is content no one ever sees or even remembers uploading.
Is PNG making a comeback?
At first glance, PNG looks like a reasonable default; it supports transparency, it’s lossless, and it handles crisp interface elements well. These days, everything exports as a PNG — it’s the standard format for apps like Canva and Figma, screenshots, and even iOS images.
A lot of what gets uploaded to websites may not even see the inside of a photo editing tool. AI-generated PNG images go straight from the slop-machine to your website as 7MB graphics, form submitted images shunted right back up to the cloud with a single click.We take it straight to the web now, baby!
PNG may have the best PR team on the web but it’s the single biggest source of unnecessary file bloat I see in images on websites.
Remember, PNG is designed for flat-color graphics: logos, icons, illustrations with hard edges. Use it for photographs or gradient-heavy images and you can end up with files 3 to 10 times larger than necessary, with no visible quality difference.
Please, stop with the PNG files.
Use a modern image format
Format
Best for
Notes
WebP (yay!)
Photos, artwork
Best option, smallest file size at good quality
JPEG
Photos, artwork
Widely supported, solid fallback
PNG
Logos, flat graphics only
Avoid for photos, it’s HUGE
SVG
Logos, simple graphics
Ideal for logos, tiny and infinitely scalable
The target for most web images is around 100 KB (or less), aim for a hard ceiling of around 300 – 500 KB for large hero images. If an image is over 1 MB, it almost certainly needs to be optimized before upload.
When should we optimize? Before we upload!
The best time to optimize is before the file goes into WordPress (or your CMS of choice). This may feel like an extra step but it’s faster than fixing things later, and let’s be real, you probably won’t fix things later.
For individual images:Affinity Photo is now free. It’s a full-featured image editor (Canva acquired it in 2024) available for both Mac and Windows.
For batch processing images: Affinity Photo has a batch job feature (File > New Batch Job) that lets you point it at a folder, set your output format and dimensions, and convert everything at once.
On Mac, ImageOptim is another excellent free option. Drag any image or folder into the app and it compresses files in place. The Windows version requires a paid license.
Replacing existing images in WordPress
If you’ve already got oversized images live on your site, you don’t need to hunt down every page they appear on. The Enable Media Replace plugin lets you swap a file directly in the media library and automatically updates all references site-wide.
Optimizing media already in your library
SmushIt is popular but I’m personally not a fan; the configuration and dashboard is harder for clients and there’s too many paid upgrades here. Check this blog post on Dev.to for Smush Alternatives for WordPress.
Converter for Media is a nice one not mentioned but it may require some extra config by your web host and/or developer. It does a great job converting to WebP format!
Dorian Gray enjoying his attic. The painting is by Ivan Albright and can be seen at The Art Institute of Chicago.
What else is lurking in your digital attic, I mean, media library?
Images are usually the first priority, but a full media audit looks at all of the other stuff you’ve squirreled away:
Videos hosted directly in WordPress should be moved to YouTube or Vimeo and embedded instead. Video files can quickly exceed 100 MB. That’s not what your web hosting is designed for.
PDFs and documents that aren’t actively linked from a public page don’t belong in the media library. Move them to a public Google Drive folder and link from there if needed.
Zip archives almost never belong in a media library. If you see them, they’re almost certainly safe to delete.
Sort images by file size and look for anything over 500 KB. PNGs are usually the culprit.
A note on “unattached” media: because of how some WordPress themes handle images, unattached doesn’t always mean unused. Download a file before deleting it if you’re not sure.
Better digital habits start today
Like all good habits, the hardest part of a media audit isn’t the cleanup, it’s preventing the same accumulation from happening again.
Start including these habits into your digital workflow:
Check file size before uploading.
Don’t upload that PNG.
Run a batch conversion on folders of new images before upload, especially if you’re dealing with bulk image submissions.
Schedule a media library review quarterly or annually. It doesn’t take long once the initial cleanup is done.
A well-maintained media library isn’t just tidier, it’s faster for your visitors, cheaper to host, and a small but real contribution to running a leaner, greener operation overall.
Your website. When’s the last time you really looked at it? It gets updated when something breaks, redesigned when a competitor’s looks better, and handed off to whoever seems to know what they’re doing at the time.
Recently, I’ve conducted a few website audits and spoken with business owners about their newly launched websites. The issues I’ve encountered range from black-hat SEO techniques to poor relationships with existing developers and 100% of the time – accessibility issues that can only be chalked up to “did not care”. Your website is an important piece of your business. It helps you to establish your brand, build authority, and market your services. And, it makes you money.
A new website is often a large investment for a small business, somewhere between roof repairs and a new car. But, when you do it “right” your website will pay for itself. Just like researching cars and roofers, it pays to look closely at what people are promising and getting a feel for what a working relationship looks like. A good developer asks you the questions you don’t know to ask. If someone is overselling, not hearing your concerns, or never turning the questions back on you — you might get a deal, but I can almost guarantee you’ll be going through this whole process again sooner than you’d like.
I wanted to create a missing manual to help you know what questions to ask, get a rough sense of what things might cost, and to better understand what parts of the project you should own.
You should own your website
This sounds obvious. Unfortunately, it isn’t.
Some web platforms (and some developers) build your site in a way that makes it difficult or impossible to leave. If you ever want to change developers or hosting, you could lose your content, your design, and years of SEO progress.
Before you sign anything, ask:
Who owns the domain? Your domain (yourcompany.com) should be registered in your name, in an account you control, not your developer’s account.
Who controls the hosting? You should be able to move your site to a different host if you need to.
Can I export my content? Some website builders have no export function (Wix and SquareSpace for example). A migration to a more robust platform later could mean rebuilding every page.
Is this an open platform? WordPress is open-source. Your files, your database, your content – it’s all portable. Proprietary builders are usually not. They take care of the hosting and application updates for a fee but there is no easy way to migrate away from them if you need to at a later date. If the proprietary service stops working or shuts down, there goes your website.
A developer who says “don’t worry, I’ll handle all of that” without giving you access or ownership documentation should be a hard pass. It’s your website and you should always have login credentials to your own domain, hosting account, and website backend.
Sprinkling keywords like garlic salt over your generic content is not SEO
Search engine optimization is structural, it’s built into how a site is planned and coded.
Every well-built website should have a solid SEO foundation baked in from the start. That includes:
SEO strategy that is informed by content strategy and research (i.e., a plan for how content is structured and connected)
Unique page titles and meta descriptions for every page
Proper heading and page structure
Clean, human-readable URLs
Schema markup – structured data that helps search engines understand your business, location, and services
Optimized site performance (media, scripts, caching)
Don’t forget to allow search engines to crawl your site (if WordPress) and submit your sitemap to Google
SEO: one-time setup vs. ongoing work
Ongoing SEO is a different conversation from the one-time foundational work I outlined above. Keyword tracking, competitor research, content strategy, blog writing, technical audits, local citation management – this can be time-intensive work whose value compounds over time when done consistently. It can also be oversold and if Search Engine Optimization isn’t what you do every day, it can be hard to identify when a specific result is being over-promised.
A lot of businesses get locked into monthly SEO retainers without a clear picture of what’s actually being done or what results to expect. “We submit to directories and monitor your rankings” for $300 a month is often very little work. Before signing anything, ask for a specific list of monthly deliverables and how results will be measured. If the answer is vague, well, it’s probably not worth it.
Retainers for ongoing SEO work typically run $500–$1,500 per month for most businesses, depending on how competitive your market is. That’s a big investment, it should come with accountability.
Worth asking: Are my business name, address, and phone number consistent everywhere, on my website, my Google Business Profile, and online directories? Inconsistent information is one of the most common local SEO problems, and one of the most fixable.
Accessibility is a project requirement
And I will use metaphor, because we all love those, and talk about making muffins for your niece’s birthday party. And on your way there, your mom said, these were supposed to be blueberry muffins. And you forgot that, and you start to force blueberries into the muffins and they are gross.
They are not really the same as blueberry muffins; they are not melted and delicious. It’s not a good experience. By definition yes, it’s a blueberry muffin, and yes, you may have an accessible system, but it is not a good system.
Considering accessibility in your website project is simply the right thing to do. It’s mostly only hard and expensive when it’s an afterthought. Consider a public building:
According to the ADA standards for Accessible Design, “Architectural barriers are physical elements of a building that prevent movement or access for people with disabilities. For example, if the only way to get to the entrance of a business is by using stairs, those stairs are a barrier for wheelchair users.”
So, what does accessibility look like for websites and virtual spaces? People with disabilities must be able to perceive, operate, understand, and enjoy a robust experience of your content.
Making your website accessible to people with disabilities has the supplemental benefit of improving the online experience for all people – perhaps experiencing situational disabilities like bright sunlight on a screen, a broken arm, or needing glasses to read. Making your website accessible is also good for SEO. And if none of that moves you, accessibility is a legal consideration, and lawsuits targeting small business websites have been on the rise.
Signs of a site with accessibility problems:
Low color contrast between text and background
Images with no descriptive text
Links that say “click here” or “read more” with no surrounding context
No way to skip repetitive navigation when using a keyboard
Image alt text or link labels stuffed with keywords instead of actual descriptions
Navigation that relies on JavaScript
Has an accessibility overlay. These are third-party widgets that claim to “fix” accessibility automatically. They don’t. Overlays patch surface-level issues while leaving the underlying problems in place, and they can actually interfere with the assistive technology people are already using. They exist to sell a product, not to make your site accessible. Relying on one can make your website a larger target for legal action, not a smaller one. Don’t use an accessibility overlay.
Ironically, the web is actually accessible by default and Web Content Accessibility Guidelines (WCAG) were first compiled in January 1995. Each year, WebAIM (Web Accessibility In Mind) publishes a report on the accessibility of the top 1 million home pages. In 2026, 95.9% of home pages had detected WCAG 2 failures.
A developer who dismisses accessibility as unnecessary is another hard pass.
Content is strategy, not filler
A lot of websites have content created for SEO “reasons” – pages packed with marketing phrases no one reads, that don’t answer real questions, and won’t help anyone make a decision.
Good website content:
Speaks directly to the person reading it
Answers the questions your customers have
Is organized around what users need, not your internal org chart
If a site is full of keyword phrases that don’t read naturally or that no one is actually searching for, or a blog with generic posts disconnected from your core services, that’s what I like to gently refer to as a “missed opportunity”. There’s no sustainable benefit to this short-sighted approach, and over time it costs you credibility.
Search engines have always been able to glean context. They are not only looking for keyword matches, but checking whether the surrounding content actually supports them. They’re getting better at understanding entities and at identifying low-quality content. When an AI Overview answers a question at the top of the results page, thin content gets passed over twice: once by the algorithm deciding what to cite, and once by the user who already got their answer.
Google has even patented the ability to generate a page on the fly when it can’t find a good enough result to send someone to. Whether or not that feature ever ships widely, the intent is clear: if your content isn’t genuinely useful, the search engine would rather write the answer itself than point people to you.
Red flag: A developer who never asks what questions your customers are trying to answer? Nope. If content isn’t part of the early development conversation, your site won’t be built to support it.
Two websites is one too many
If you have ever moved, rebranded, or switched developers, there is a chance more than one version of your site is still live. Maybe an old domain still resolves. Maybe a contractor set up a second site and never took it down.
Having two active domains splits your SEO authority. You could be competing against yourself without knowing it.
Ask your developer: Do I have more than one active domain? If so, is the old one properly redirecting to the new one?
So, how much is this going to cost?
It can still feel like the Wild West out there. You might see $500 or $15,000 for what sounds like the same thing. The price difference isn’t about the deliverable. Pricing is about whether the person building your site knows what questions to ask before they start, what to test before they launch, how to measure whether it’s working, and the level of ongoing support they offer.
Anyone can build a website. Not everyone will build one that is designed around what you need it to do, who it’s for, and what should happen when someone lands on it. Without that strategic planning, you’ve got a pretty presence, not a website that works for your business.
With that in mind, here’s a realistic (although still guess-timated) range for what different levels of development complexity might cost:
Simple brochure site — $2,500 – $5,000 Static pages, standard contact form, no dynamic content. A home page, an about page, a services overview, and a contact page. The content does not update often and nothing connects to anything else. May or may not have a blog – but it should be easy to scale up when needed.
Site with some custom functionality — $4,000 – $7,000 Adds a content management system so you can publish posts, case studies, or updates without touching code. Maybe some custom development work is included.
Fully custom professional site — $7,000 and up Some businesses have content that needs to work together, not just sit on separate pages. Designing this kind of site means figuring out the relationships between content before anything gets built. What connects to what? What information repeats across every service? What 3rd party services need to integrate? That design and planning work is what separates a site that scales well from one that becomes difficult to manage six months after launch.
National / international business website or e-commerce — $10,000 and up Booking systems, client portals, payment processing, membership functionality, online stores, anything that connects your site to an external system adds complexity in setup, testing, and ongoing maintenance. Every integration is a dependency that needs attention over time.
Keep in mind, a website is also a deductible business expense. A useful question before you get a quote isn’t just “how much will this cost?” It’s “what will this do for my business, and how will we know if it’s working?”
Pricing is hard
Pricing is always a learning process for business owners and web developers are not an exception. There’s no standard process or rate. Some developers charge by the hour, others quote a flat fee for the full project, and many use value-based pricing. All are legitimate pricing methods.
Flat project fees are easier to budget for. You know what you are paying upfront. The tradeoff is that scope needs to be clearly defined (and it often is not). If and when the project scale changes, the price usually does too. The challenge here is that the flat project fee is always going to be a guess. An informed guess based on past experience and initial conversations but still a guess. There are a lot of unknown unknowns that surface once you get to work and that can lead quickly to scope creep.
One way to handle this is to ask for a discovery phase: a low-commitment starting point where the developer gets a fuller picture of what the project actually involves before a full scope is written. A good discovery engagement ends with a clear option to continue or walk away. Either way, you come out of it with documented findings you can hand to the next developer if the relationship isn’t the right fit.
Hourly billing is more flexible, especially for ongoing work, smaller tasks, or projects where the full scope isn’t clear yet. It also tends to surface problems earlier, because you’re reviewing work in smaller increments rather than waiting for a fixed deliverable.
Rates vary by experience, specialty, and region. As a general reference point, experienced independent web professionals typically charge $85–$150 per hour. Agencies often charge more, with some of that covering account management and overhead.
Some developers (like me) offer a prepaid hour block or time bank. This is a set number of hours purchased at a slight discount, drawn down as needed. For ongoing support or small updates that don’t justify a full project quote, this can be a practical middle ground. It also gives you a low-stakes way to start a relationship before committing to a larger project.
Post-launch website costs
Just like any major purchase, a website comes with ongoing costs. Hosting, maintenance, and domain renewal are the three most common ones people forget to budget for.
Maintaining your new website
You’ve made it through your website project and have successfully launched your brand new website. Congrats!
Now that your site is live, it still needs ongoing attention. I like to compare your living website to a garden. It needs maintenance, pruning back old content, planting new content where it makes sense. And, technical site maintenance is what keeps your site secure, up to date, and recoverable if something goes wrong. Proprietary platforms like Squarespace and Wix handle much of the technical maintenance for you, which can be a selling point. The trade-off is flexibility and ownership, which is worth understanding before you choose a platform. In this case, we’ll talk about maintenance for a WordPress powered website:
What is typically included:
Platform and plugin updates. WordPress and its plugins release updates regularly. Skipping them creates security vulnerabilities. Someone needs to apply those updates, check that nothing broke, and keep backups current.
Backups. A good maintenance plan includes regular automated backups stored offsite. If something goes wrong like a bad update, a hack, an accidental deletion you can restore quickly.
Security monitoring. Websites are targeted by automated bots constantly. Monitoring catches problems before they become serious.
Uptime monitoring. If your site goes down, you want to know before a customer calls to tell you.
Basic support. Content updates or changes, quick questions answered. Ongoing technical help when you need it. Training if requested.
What maintenance does not usually include:
New pages or major design changes
SEO work or content strategy
Writing new posts or copy
Rebuilding something that breaks due to a major platform or plugin change
A basic WordPress maintenance plan from a reputable provider typically runs $40 – $100 per month. This can also vary by site complexity too. If you run an eCommerce website with hundreds of products, that’s more to maintain and troubleshoot. If you need more hands-on or custom support, budget more.
Website Hosting
Your website files live on a server. That server costs money. Hosting is billed separately from your developer’s fees and is usually paid annually.
Shared hosting (sites share server resources): $100 – $300/year. Adequate for most sites.
Managed WordPress hosting (faster, more secure, less to manage on your end): $200 – $600/year.
Not all hosts are equal. Cheap hosting is cheap for a reason: oversold servers, slower load times, minimal support, and security that gets less attention than it should. Page speed affects both user experience and search rankings, and a slow host is one of the hardest problems to diagnose after the fact because everything else looks fine. Paying a little more for a reputable host is, as the saying goes, a no-brainer1.
Your developer might host your site as part of their service, which can be convenient. Make sure you understand the terms. Can you take your site elsewhere if you part ways? Is the account in your name? Ask before you commit.
Renew your domain name with your registrar
Your domain name, yourcompany.com, is something you rent, not own. It needs to be renewed annually, usually for $15–$20+ a year. Miss the renewal window and your site goes down. Most domains have a grace period of around 30 days after expiration where you can renew at the normal price. After that, recovery gets expensive. Registrars typically charge a redemption fee that can run $50–$200 or more. Wait long enough and the domain goes to auction, where you may be bidding against someone who noticed it lapsed and wants it. Be sure to check your registrar’s specific terms. Your domain name registrar may also be your website host, but not always.
One of the most common panicked calls a web developer gets: “My website is gone, something is broken.” In many cases, the site is fine, the domain just lapsed because the renewal notice went to an old email address, or the credit card on file expired, or the client forgot which registrar they used when they first set everything up years ago.
Before your website project wraps, confirm: where is your domain registered, what email address is on the account, and is auto-renew turned on? Write it down somewhere safe – and test your login.
Service agreements: what is reasonable?
Most web professionals will ask you to sign an agreement before starting work. That is normal and protects both sides.
Reasonable:
A project agreement that outlines scope, timeline, payment schedule, and what happens if the scope changes
A maintenance agreement that is month-to-month or annual, with clear cancellation terms
Language that confirms your ownership of the domain and content regardless of what happens
Watch for:
Long-term contracts with no exit clause. A developer confident in their work does not need to lock you in for two or three years.
Automatic renewals with no advance notice. You should be notified before any contract renews, especially if pricing is changing.
Contracts that give the developer rights to your domain or content. Your domain and your content are yours, always.
Vague deliverables. If the agreement says “website design and development” with no further detail, you have no recourse if what is delivered is not what you expected. Scope should be specific.
A simple question to ask before signing: If I decide to leave, what happens? Can I take my website with me? If the answer is unclear, it is worth requiring that be defined in the terms before you commit.
What a good, ongoing client-developer relationship can look like
The best client-developer relationships don’t feel like a transaction every time you need something. At their best, they should feel like having someone who knows your site as well as you do and who will tell you when something needs attention before it becomes a problem.
That might mean:
A quarterly check-in to review traffic, rankings, and any issues
Proactive suggestions when something on the site needs attention
Help thinking through a new service page or seasonal content
Someone available when something breaks, without emergency rates
A good maintenance plan plus a few hours of support each month can go a long way.
Not sure where your site stands?
A website audit is a good place to start. I look at your site’s structure, SEO, accessibility, and content — and come back with a specific list of what’s working, what isn’t, and what to fix first.
I recently wrote about block variations and block styles, styles associated with a core block that appear when you add a block to your page or post. Common examples are button style variations like “Default,” “Outline,” or other block styles that may be included in your theme.
Introducing Section Styles
Section Styles are an extension of block styles and they work with any block that supports inner blocks (groups, columns, covers, etc). The main advantage and use case for Section Styles is that you can create curated design presets for entire “sections” of your pages. And, as with block styles, Section Styles are only loaded when the section exists resulting in better performance.
Helpful, curated design defaults for everyone
Section Styles provide helpful defaults and design consistency without limiting the user from making adjustments. Your section style might set heading colors to blue, but users can change individual headings through the block editor without any conflicts. This flexibility works because WordPress keeps CSS specificity low by “using :where() but prefixing it with :root. The result is selectors with 0-1-0 specificity.”
Section style or pattern?
Section Styles and Patterns serve different purposes.
Patterns provide complete content structures: the blocks, placeholder content, and initial layout. They’re great when you want to give users a starting point with a specific content arrangement. With Patterns, we also have the ability to make a design synced or partially synced with pattern overrides.
Section Styles are more open ended, separating content and style through visual treatments that work across different content structures. They’re especially useful when you want consistent styling options that users can apply to any content they’re building, without dictating the structure.
For example, you might have a “Feature Section” style that allows for a two-column layout with an image and text. But what if users want that same visual treatment (background color, heading style, button appearance) for a three-column layout? Or a stacked group with a different heading structure? Section styles let them apply visual design presets to any Group, Cover, or Columns block, regardless of what’s inside.
It’s possible to flesh (section styles) out to include styles for every element and block that WordPress supports, styling them when they are used within this block. It’s for this reason that these types of variations may best be used for container-type blocks, such as Group, Columns, and Cover.
You want to provide multiple visual options (light background, dark background, accent color) without creating separate patterns for every possible variation
Content structures may vary too much to use patterns, but you still want visual consistency
Users need flexibility to build their own layouts but don’t want to think about every little design choice
You want to update a visual treatment site-wide by editing one file rather than managing pattern instances
As of 6.0, WordPress automatically discovers any JSON files in this directory and registers them as available block styles. You don’t need to register them in functions.php or add any PHP code. Note that "version": 3 is required.
Each file contains a complete style definition. Here’s my working example:
The filename can be anything, though it’s helpful to prefix with ‘section-‘ for easy identification. Inside your JSON file, the title and slug should match. The title is what users see in the editor, and the slug is the internal identifier.
Ollie’s theme academy has an excellent how-to video to get you started, Creating a Section Style.
Unknown unknowns
I think that there are limitations to what is allowed in Section Style JSON but I’m having a hard time finding specific documentation around this.
Limitations that I am aware of (not necessarily complete or correct):
Section Styles are limited to styles – you can’t add settings here
You can style elements per Section Style, but you can’t style a block style variation of an element (ex. Button with the outline style) with the Section Style
Each Section Style needs it’s own separate JSON file inside the theme’s /styles/ directory
Spacing values DO work but blockGap – for gap spacing – does NOT work
Alignment and justification not available here
User’s block style adjustments will override the Section Style presets (by design, specificity here is low)
Preset values aren’t visible to the user (known issue) – so, even though there may be padding or colors in use, those aren’t displayed in the styles panel
If you know more, please comment!
JSON structure and syntax
WordPress supports shorthand or CSS variables in your section styles:
The shorthand is a bit easier to read and quicker to edit if you are using presets.
If you are using the css property to add custom CSS that theme.json doesn’t directly support, you will need to use full CSS (or full CSS variable) inside that string:
This is because the css property outputs raw CSS to your stylesheet, and WordPress doesn’t process shorthand syntax in these strings.
Adapting the section style of a parent theme
Child themes can add new section styles or override parent section styles.
To add a new style: Create a file with a unique slug in your child theme’s /styles/ directory. Both the parent’s styles and your new styles will be available.
To override a parent style: Create a new JSON file in your /styles/ directory using the same filename, title, and slug as the parent theme. Your child theme version will override the parent’s version entirely.
Sometimes, when you create a child theme, your custom palette may be applied in unexpected and ungainly ways to parent section styles (patterns as well) and you’ll want to refine these. An override is useful in this case but be aware that you’re completely replacing it, not just modifying parts of it.
Troubleshooting issues:
Mismatched filename and slug when overriding a parent section style
I started a new section-primary.json file in my /styles/ folder to override the parent section style. But I forgot to match the title and slug to the parent even through the filename DID match. As a result, neither the parent nor the child section style showed up. Double-check the obvious human errors like naming and syntax (ie. Try turning it off and then on again).
JSON syntax errors
Missing commas, extra commas, or unclosed brackets will break your entire style file. WordPress can’t parse invalid JSON, so the style simply won’t appear.
Incorrect property nesting
Some properties need specific nesting structures. For example, heading color must be nested inside a color object:
The theme.json reference on WordPress.org is helpful when you’re not sure about the correct structure for a property.
Limitations and appropriate control
The main caveat with section styling is that it is easy to get carried away and add too many style options for group blocks and columns. Here we need to practice restraint to not overwhelm users.
Section styles should control the container and set sensible defaults for common elements. Content editors should retain full control over the blocks they place inside. If you find yourself writing complex CSS to control every aspect of the inner content, you might be better off with a synced or partially-synced pattern.
Section Styles are a really cool tool for your Block Theme toolbox. If you’re not using them yet, what are you waiting for?
When you’re building a WordPress block theme, you’ll often want to customize how a core block looks beyond what the block editor allows. Maybe you want a cover block with diagonal clip-path edges, a featured image that scales on hover, or a fancy Heading style. Before you add a class to that block, consider using a Block Style Variation.
Benefits of block style variations
While we could add a class to a block’s “Advanced” settings and style that class under “Advanced CSS” or in a stylesheet, this requires content creators (and you) to remember your class name and how to use it. Block Style Variations are a big improvement, allowing site editors to choose and apply options visually from the block editor’s controls while keeping those styles performant and flexible.
As a web designer or theme creator, making design decisions easier for site editors is a good thing. Using block style variations also means you can load CSS conditionally (only when the block exists), a performance win.
How to register styles
JavaScript, PHP, or JSON
Fig. 1: Block styles aren’t reflected in visual controls.
I’ll skip the JavaScript (not my job) and look at the PHP and JSON methods.
Block Variationscan be registered via PHP within the theme or in a plugin. If portability of block variations is important to you or if you need to make sure that your block styles are independent from the theme (which could be changed), a plugin approach1 is best.
Block Stylesdon’t require registration. They are picked up by WordPress auto-magically when you include the JSON file in your theme’s /styles/ directory.
One downside with block variations and block styles is that settings don’t appear in the block controls (see Fig. 1).
If I select a style, like the Button style variation “Outline” – that style change is not reflected in the element style controls2 in the editor even though the attributes exist.
Wait, aren’t block variations and block styles sort of the same?
When should I create a block variation vs. a block style? The answer is almost always the same as the answer to another question: Can these changes be made through theme.json styles or CSS? If (theme.json), you should almost always create a custom block style (JSON).
Block Variations, via WordPress Developer Resources, Theme Handbook
Block Variations and Block Styles are sort of the same, but also a little bit different. Naming things is hard.
Consider the problem you are solving: if theme.json supports most of what you want to accomplish and/or if you want a style to be available to more than one core block, the JSON method might work best.
Carolina Nymark notes that if you want to register Block Styles with a JSON file, “this feature requires WordPress 6.6 and version 3 of theme.json.”
If you need to do things that mostly aren’t supported in theme.json, like add interactivity with JavaScript or use a lot of custom CSS, use the JavaScript or PHP method to register your block variations.
Registering block variations with PHP
Registering block variations3 in your functions.php file makes them available in the block editor’s style panel.
My example registers four clip-path variations for the Cover block and a scale-on-hover effect for both Cover and Featured Image blocks.
/** * Register block style variations */functionmytheme_register_block_styles() { $cover_styles =array('right-clip'=>__('Right Clip','mytheme'),'bottom-clip'=>__('Bottom Clip','mytheme'),'left-clip'=>__('Left Clip','mytheme'),'top-clip'=>__('Top Clip','mytheme'),'scale-on-hover'=>__('Scale on Hover','mytheme'), );foreach ( $cover_styles as $name => $label ) {register_block_style('core/cover',array('name'=>$name,'label'=>$label,)); }// Featured image variationregister_block_style('core/post-featured-image',array('name'=>'scale-on-hover','label'=> __('Scale on Hover','mytheme'),));}add_action('init','mytheme_register_block_styles');
The first function is plural, I’m registering several block styles for core/cover at once. I also want to add the “scale-on-hover” variation for the Post Featured Image block and the Cover block.
Even though I want to use the same style, “scale-on-hover”, for two core blocks – they have to be registered separately in PHP. If I was using the JSON method, I could make a style variation available across blocks using the blockTypes property.
Both of these block variations use CSS (clip-path, transition, transform) that isn’t supported in theme.json and would require some pretty long CSS strings so the PHP function seems the best approach.
Organizing CSS files
Create a /blocks/ directory in your theme to keep blocks and variation styles organized. For this example:
assets/css/blocks/cover-variations.css
assets/css/blocks/featured-image-variations.css
You can call the css files anything you want. We’ll reference this file name in the next section when we enqueue our block css.
TIP: If you just need to add a smidge of CSS (a few lines), you can include the styles directly in the register_block_style() function using the inline_style parameter. There’s a great tutorial by Mike McAlister on Ollie.com that shows you how to do this. Brian Coords has a similar example adding a checkmark variation to the ul element where registering the block style is a separate utility plugin.
I’ve decided that grouping related variations in a single CSS file makes sense and is more maintainable (for me) but you can also break your styles down into separate stylesheets for each variation, even for the same block.
Block variations and conditional CSS loading
This function conditionally enqueues your block variation stylesheets using WordPress’s wp_enqueue_block_style() function, which loads CSS only when the associated block variation is present on the page:
Combining multiple related variations in one CSS file (like my four clip-path variations for the Cover block) will mean that WordPress loads the entire file if any of those variations appear on the page even though they’re not actively used. But this is still a small file and performance impact should be minimal. This is kind of a personal choice, since all of these styles are for the Cover block variations, I don’t mind keeping them together.
Another way: block styles in JSON
Originally, /styles/ was used to define Global Style Variations for themes (like a light and dark mode). An advantage of this method is that JSON files within the /styles/ directory are auto-discovered by WordPress (as of 6.0), work across the blocks you specify, and don’t require a PHP function or JavaScript. For this to work:
“You have to place each custom block style in its own JSON file, or WordPress can not parse them correctly. Place the JSON file inside a folder in your theme called styles, or a subfolder to styles (ex. /styles/blocks/custom-style.json).”
If you have a simple block style, like a fancy, visual heading that uses a special font, this could be a good reason to use JSON. You can also tell WordPress that this style can apply to different blockTypes.
Call this file anything you want, place it in your theme’s /styles/ directory (or a sub-dir of styles) and your style will be available in the editor:
Magic! The core heading block now has a style variation, “Shadow Pop”.
How WordPress applies block styles
When you select a style variation in the block editor, WordPress adds a class to the block in the format .is-style-{variation-name}. For example, selecting the “Right Clip” variation on a Cover block produces this HTML:
You could use the full block class combined with the variation class (EX: .wp-block-cover.is-style-right-clip) but that’s probably only necessary if you actually run into specificity issues (which is unlikely, I think…).
WordPress detects your new class on the page and loads the associated stylesheet. If the page doesn’t use any of your style variations, that CSS file isn’t needed and doesn’t load.
Try block variations and block styles in your theme today!
Whether you register your block styles via PHP or through the Global Styles, you enhance your WordPress block theme in several ways:
Your theme stays lean because variation styles are broken down into small, load-as-needed files rather than one comprehensive stylesheet.
Pages now load faster since browsers only download that CSS when blocks are actually present on the page.
Users are happy because they can make effortless design changes without being afraid of doing it wrong.
Maintaining style variations will also be easier for you than remembering where you slapped those ad-hoc classes, wondering if they are still in use, and writing CSS in an external stylesheet or in the dreaded “Advanced CSS” panel.
But I still need to build custom blocks for clients. As a solo developer working with small businesses, I don’t have the bandwidth (or desire) to learn an entirely new technology stack. With Advanced Custom Fields (ACF) blocks, I can create fully functional custom blocks using the PHP and WordPress templating I already know.
Advanced Custom Fields (ACF®) is available for free through the WordPress plugin repository but you will need the Pro version to create custom ACF blocks.
Custom ACF blocks1 combine the flexibility of custom fields with the ease of building out content in the modern block editor interface. No need to write React components or deal with complex JavaScript build processes. Hooray!
ACF Custom Blocks: In a theme or in a plugin?
Custom ACF blocks can be plugins or built into your theme. If you are creating a plugin, you just need to register the block from your plugin file instead of functions.php.
Use a plugin when:
The block is site-specific functionality that should persist if you ever switch themes
You want to reuse the block across multiple sites
The block is complex enough to warrant its own updates and version control
I prefer to keep it in my theme when:
The block is built for that specific theme’s design system
It relies on theme-specific styles or CSS custom properties
I’m building a custom theme where the blocks are part of the overall design package
The client is unlikely to change themes
For my client work, I usually build blocks as part of the theme. But if I find myself rebuilding the same block type for multiple projects (like an FAQ accordion or a team member grid), that’s when I convert it to a plugin so I can reuse it. You can always move a block from theme to plugin later.
Setting up your block structure
With block themes, you should use a block.json metadata file2 rather than registering blocks entirely through PHP. This approach lets WordPress automatically handle asset loading and block registration, which means better performance and less manual code.
Your block will live in its own directory within your theme. For this example, I’ll walk through creating a text rotation block that cycles through different phrases with a typing animation effect, something a client might use for a dynamic homepage headline.
For a custom ACF block, you’ll need at minimum two files: a block.json file and a PHP template file.
block.json – This is where you define the block’s name, title, description, category, icon3, keywords, and any rendering settings.
render.php – You can name this file whatever you want (commonly something like block-name.php or template.php), but you need to reference it correctly in your block.json using the render property. I use the same names for all custom blocks, only the /custom-block-name/ folder changes – I just find it easier to set things up that way.
style.css – While you can enqueue styles globally, best practice for performance is to use the style property in block.json to load your block’s stylesheet only when the block is actually used on a page.
script.js – You can also add a JavaScript file if your block needs any frontend interactivity.
Here’s the directory structure I’m creating within my theme:
Each custom block – /text-rotate/ in this example – gets its own folder inside of /blocks/ with all its assets contained together. This keeps your theme organized and makes blocks portable if you need to move them to a different theme or turn them into a plugin later.
Let’s build a custom block
The block.json configuration
The block.json file defines your block’s metadata and tells WordPress where to find your assets:
{"$schema": "https://schemas.wp.org/wp/6.9/block.json","apiVersion": 3,"name": "acf/text-rotate","title": "Text Rotate","description": "Rotate words on the homepage","style": [ "file:./style.css" ],"script": [ "file:./script.js" ],"category": "text","icon": "carrot","keywords": ["rotate", "text slide"],"acf": {"mode":"preview","renderTemplate":"render.php" }}
You can also extend your ACF blocks by adding Block Supports to your block.json file. This allows editors access to core WordPress block attributes like spacing, alignment, or color.
Note: ACF Blocks V3 is now available but you have to manually enable this. This version makes the preview mode unnecessary, “…in ACF Blocks Version 3, the concept of modes no longer exists. Rather, your block will always be in “preview”, always showing what’s in your PHP render template in the block preview area. The block’s ACF fields show up in the sidebar, and also in a pop-out sidebar that has more space.”
Registering the Block
In your theme’s functions.php, you only need a few lines to register the block:
The __DIR__ constant points to your theme directory, and WordPress will automatically find and process the block.json file. No need to manually enqueue your CSS and JavaScript, WordPress handles that based on the block.json configuration.
Creating the ACF field group
Once your block is registered, create an ACF field group inside of WordPress:
Add a repeater field. I called mine: text_slide
Inside the repeater, add a text sub-field. Mine is: slide_it
Set the location rule to “Block is equal to Text Rotate (sub your block name)”
Create an ACF field group, add a repeater field.Create your sub-field for the repeater.Set your location rule to the block you registered.
The render template
Advanced Custom Fields use PHP templates (server-side rendering) rather than JavaScript for block rendering. This simplifies our workflow and may have some performance and SEO benefits over JavaScript.
Your render.php file outputs the block’s HTML. This is standard PHP that loops through your ACF fields:
The first part of this template handles block settings that users configure in the block editor’s sidebar. The className and align handling ensures your custom block respects the same settings that core WordPress blocks use.
WordPress passes these settings to your template in the $block array, which you escape with esc_attr() before output – standard practice for any dynamic data.
If you (like me) need a starter when working with PHP, the plugin ACF Theme Code is super helpful. There is a free version but it won’t work for repeaters.
Note: For a deeper explanation of WordPress security best practices, see the ACF security principles.
Styling the block
In our render.php template, input words start with the .is-hidden class applied. The CSS and JavaScript will handle revealing and animating them.
The CSS handles the positioning and visibility states for the rotating text:
.words-wrapper {display:inline-block;position:relative;min-width:150px;}.words-wrapper i {display:inline-block;position:absolute;white-space:nowrap;left:0;top:0;font-style:normal;}.words-wrapper i.is-visible {position:relative;opacity:1;}.words-wrapper i.is-hidden {opacity:0;visibility:hidden;}.headline.slide span {display:inline-block;margin:auto;}.headline.slide.words-wrapper {overflow:hidden;vertical-align:top;}/* Show first word in block editor */.editor-styles-wrapper.words-wrapper i:first-child {opacity:1;visibility:visible;}
All the <i> elements are absolutely positioned, stacking on top of each other. Only the visible one uses position: relative, which means only it affects the layout and takes up space.
I also wanted to be able to see the first word added to my repeater in the editor. Adding a rule that targets the .editor-styles-wrapper and the :first-child does this.
Let’s improve this CSS by adding an accessibility consideration for the media query prefers-reduced-motion4:
But wait – we hate those bossy !important declarations. How about we instead adjust the CSS specificity by adding the class .is-hidden and .is-visible:
This targets the first <i> regardless of which class JavaScript applies, matching the specificity without needing to force it with that self-important !important.
Adding the typing animation
The JavaScript creates a typing effect where each word types out character by character, pauses briefly, then deletes before moving to the next word:
The script stores the original text in a data-text attribute so it can be retyped on each loop iteration. The intervals are properly cleared to avoid memory leaks, and the modulo operator5 (%) wraps the index back to zero, ensuring the animation loops back to the first word after reaching the end.
Mistakes were made (learning is doing)
A few things tripped me up when building this ACF block:
Forgetting the file:./ prefix in block.json will cause WordPress to look for your assets in the wrong location. Always use the relative path prefix.
Not using block.json at all and trying to register everything in PHP. While this might work in classic themes, block themes expect the metadata file for proper asset handling.
Not clearing intervals in JavaScript animations. Always use clearInterval() to prevent memory leaks, especially in animations that run continuously.
Using Claude.ai for help: I did have to push back on Claude to reduce complexity. Providing guidance to AI before you start building anything is a good idea: don’t add complexity, check for accessibility, security and performance, avoid !important declarations, etc.
Troubleshooting common issues
Asset Loading Issues – CSS and JavaScript files loading on every page instead of only when the block is actually used. If you’re manually enqueuing assets in functions.php, they load globally. Use the style and script properties in block.json instead – WordPress will only load those files on pages where the block appears.
Block Preview Not Updating – Sometimes you make changes to your ACF fields or template, but the block preview in the editor doesn’t reflect them. This is usually a caching issue. Save the page, refresh the editor, or temporarily change the block’s mode from “preview” to “edit” in your block.json to force a refresh.
Field Group Not Connected – Your block won’t show any fields if the ACF field group isn’t properly assigned to it. In your field group settings, make sure the location rule is set to “Block” and matches your block’s name exactly (like acf/text-rotate). If you rename your block, you need to update the field group location too.
File Path Problems – Using relative paths incorrectly is a quick way to break things. In block.json, paths to your CSS and JavaScript files need the file: prefix and should be relative to the block.json file itself (like "style": ["file:./style.css"]). However, if you’re using ACF’s renderTemplate property, it’s just the filename.
Missing Escaping – Any time you’re outputting ACF field data or block attributes, escape it. Use esc_html() for text content, esc_attr() for HTML attributes, and esc_url() for URLs. Skipping this creates security vulnerabilities, especially if clients can input the data.
Block Not Appearing in Inserter – If your block doesn’t show up when you try to add it, check your block.json syntax. Also make sure your theme is actually registering the block directory. Remember, you need code in functions.php to tell WordPress where to find your blocks.
Benefits of the custom block approach for client projects
The combination of ACF’s visual field builder with block theme architecture gives you something powerful: blocks that are easy for clients to use but give you complete control over markup and styling.
For solo consultants working with small businesses, this is a big deal. You’re not just building the site, you’re building something clients can manage and maybe even enjoy working with!
In the first part of this block theme exploration, I looked at getting started with block theme development using the Create Block Theme plugin. This post picks up where we left off, focusing on building out page templates, enabling custom functionality through functions.php, and making custom style adjustments that can’t quite be handled in the site editor styles.
Setting up page template structure
Reviewing my template needs, the site requires two main page templates: one with a featured image and page title hero pattern and another for special pages like the homepage. Custom archive views are also necessary for specific category archive views and custom post types. I will need a single view for some of those with the ability to include custom blocks and ACF content.
The parent theme I’m using (Greyd) has with two basic templates for page content: “Pages” (the default) and “Page with Title.” But, because the default “Pages” template doesn’t have a page title at all, I needed to swap how these templates function.
Note: Your page title is an H1
When I added the title block to my page template in the previous post, I noticed it was an H2. That’s appropriate for post titles in loops, but for the main page title, it needs to be an H1 for proper heading hierarchy and accessibility. The fix was straightforward in the block editor. Opening up my page template, I selected the Post Title block and changed the heading level to H1 in the block settings.
There should only ever be one H1 heading on your page and this should be your page title. Headings do have a minor SEO value but their semantic function is more important: headings help organize your content and your H1 heading describes the main content on your page. Don’t use more than one H1 per page (even if everyone else is doing it).
Learning something new about spacing and layout behavior
Watch me learn something new – exploring block spacing settings.
Spacing in block themes can be confusing because there are multiple systems working simultaneously:
Block padding and margin: can be applied to individual blocks
Block spacing: controls the gap between blocks within a group
Layout spacing: a global settings that describes how inner blocks are spaced within a group or container
Go with the flow…
Working in the editor, I want to try to exert the least amount of control and get it to do the thing because it just feels more stable that way. If I have to futz around with design elements, that just becomes tedious.
Me
With block-level dimension settings, we can add all kinds of margin and padding and spacer blocks (still!) to effect a specific layout. However, I see a lot of developers and clients get stuck over-engineering a design solution. If you feel like you are fighting with block styles, take a deep breath and consider how flex and grid containers want to operate. Rather than applying lots of manual margin or padding adjustments to force a specific result, maybe you need to try a different block, or inspect the front-end to understand what is actually happening. Manual block-by-block adjustments are less maintainable and much more tedious to create.
To better understand spacing in WordPress, we can first take a look at the CSS Box Model. This describes how browsers will calculate space around every HTML element. Each element is in a “box” with four layers (from inside to outside). This is a conceptual box, not a visible box, but if you inspect your code you will see how margin, padding and gap spacing are highlighted within a “boxed” element or layout.
Content – the actual content inside your element box (EX: this could be a paragraph, heading, image, or a group)
Padding – space between the content and the edge of the box
Margin – space outside the border that separates this element from others
Gap spacing – the CSS gap property creates space between flex or grid elements
How spacing works in WordPress:
Padding expands the element itself (background colors and borders extend through the padding area)
Margin creates empty space between elements (background colors and borders do not extend into margin)
TIL– Block spacing in WordPress is not exactly the same as gap spacing. Block spacing adds space between child elements within a flex or grid container (gap spacing) AS WELL AS adding an equal amount of margin to the top of any default block-level elements inside the container (like a paragraph block).
If a container is display: flex; – like the Columns block – the block spacing control changes the default gap spacing between columns.
If an element is display: block; – like a paragraph – it will get the same amount of spacing as margin-block-start: var(--wp-preset-spacing-value); since gap won’t affect elements that aren’t using flex or grid.
Block spacing controls are also available to the theme in the site editor under layout settings. The block spacing setting here will determine the space between all of the blocks on all of your templates across the site.
In WordPress blocks, we’re manipulating these properties through the visual “dimensions” settings panel. Padding and margin affect the space inside and outside a box (or block), respectively. Block spacing affects the gaps between elements within that group or container block (group, columns, grid, cover block) and the margin-block-start for elements within those containers.
Thinking about it now, this does seem the most logical way to handle space equity among things that may have a different display modes – but it was not immediately obvious to me. I’m sure its documented, one of my fatal flaws is that I never read instructions first.
Breadcrumbs are added to templates using the Yoast Breadcrumb Block.
Looking at the current site design, I decided to add breadcrumbs to the Page Title Hero pattern rather than above the page content as it is on the current site. I’m using Yoast Breadcrumbs here but there are other plugins that can do this like SEOPress. The Yoast Breadcrumb block does not have any style options available in the editor so I will need to add some custom styles to a separate stylesheet or in the Advanced CSS panel.
I also want the breadcrumbs to left-align with other header elements, using the wide alignment shared by the navigation menu. This involves working with flex containers and understanding how the cover block centers its content. The cover block is a flex container that aligns items center by default. This was overriding my attempts to space elements using justify-content: space-between.
Adjusting the position of elements inside a cover block using custom css.
After experimenting with height settings and flex properties, I realized I needed to add a custom class to override the default align-items center property. Sometimes blocks can get you most of the way there, but for specific design requirements, you may still need to add custom CSS.
The design calls for an optional excerpt to appear below the page title in the hero pattern. WordPress doesn’t enable excerpts for pages by default, so I needed to add this functionality.
There’s no functions.php file included by default in my child theme but I can add one. I just need a basic file to add excerpt support for pages:
After adding this code and reloading the editor, I am able to add excerpts to pages through the page settings panel. I can also use the excerpt block on the Pages template and adjust the visual style in the editor. But – what if a page doesn’t have an excerpt?
Function tweak: conditional excerpt display
Having the excerpt field available was only half the solution. I wanted the excerpt to display only if it had been manually created, not auto-generated from page content. The excerpt block doesn’t have a built-in conditional setting for this.
*** Enable excerpt for pages - Only show excerpt if manually created*/functionthemename_block_filter_excerpt( $excerpt ) {if ( !has_excerpt() ) {return''; }return $excerpt;}add_filter( 'get_the_excerpt', 'themename_block_filter_excerpt' );
I asked Claude.ai for an assist. Initially, it produced an overly complex solution involving PHP template files, which would defeat the purpose of building a block theme. The second option it provided was much simpler: adding a filter to the excerpt content that returns an empty string if no manual excerpt exists.
The code checks if there’s content in the excerpt field, and only outputs it if content exists. This allows the excerpt to remain an optional element in the page template.
Working with custom CSS in block themes
For my next design challenge, I wanted to add a drop shadow to my page title. Since this is text over an image, I want to make sure it’s legible and has good contrast. WordPress has shadow support, but it applies box-shadow (to a block container) not text-shadow. My first instinct was to add this to the style.css file referenced in functions.php but that’s like sledge hammer when I just need a small, block-specific style, say, a tack hammer for this operation.
In the site editor, each block has an “Advanced > Additional CSS” field where you can add properties directly. Instead of writing a full selector in an external stylesheet, you just add the property and value:
text-shadow: 0 2px 7px rgba(0,0,0,0.5);
This approach is cleaner for one-off block styles. It keeps the styling close to the block it affects and previews immediately in the editor. Save the external stylesheet for the things that you can’t do in the editor at all.
Wrapping Up
This phase of development involved a lot of problem-solving around layout and spacing. Working with a classic theme migration with existing content and styles is a lot more complicated than I had anticipated…
Key lessons from this session:
Block themes offer flexibility through the visual interface, but there will still be times you need to reach for functions.php and custom CSS for specific functionality and fine-tuned control.
Functions.php in block themes should be minimal and focused on functionality you can’t achieve through theme.json or the block interface.
Block-level custom CSS is often preferable to external stylesheets for one-off “utility” styles.
Visual interfaces are powerful but have limitations. Understanding when to use theme.json, functions.php, and custom CSS is all part of the fun!
I’ll try to get back to the archive templates and custom post types next. Since these use a lot of custom fields – I may need to convert these to ACF field groups to blocks that can be used in the editor.
Even two years ago, I wasn’t completely confident that I could create everything needed in a block theme for a custom business website. Last year, I reversed my opinion: block themes are now a solid solution for even very complex sites. I don’t grasp all the complexity around Node.js development tools but I no longer feel that they are a prerequisite. With Advanced Custom Fields (Pro), and a good understanding of how the parts of a block theme work, great strides can be made.
I’ve been itching to migrate one particular legacy site over to a block theme to see just how great an impact to site performance there is. I’m also keen to spread the joy of blocks to clients. I anticipate that there will be an improvement to site usability and a confidence boost for content publishers with a block theme.
First question: Can/should I even attempt this?
Built in 2018 using Underscores (_S), this is one of my first fully custom PHP themes as a freelancer. The current website received an interim hybrid update in 2019 to take advantage of some block styles and settings – but not all settings are available so it’s hard to visualize how changes will actually look when published.
Before taking this site apart, I need to make sure critical functionality wouldn’t break. This particular site connects to a third-party chamber of commerce management tool and relies on some scripts and a template file to work. If I do need a PHP template down the road, I can still add that in the new block theme.
But there are some issues I know I have to tackle:
The site has extensive design customizations including animated text, hover effects, custom drop shadows, shapes, and icons. All of this will require custom styles that are beyond what the current site editor can generate. There’s also some content sprawl and complex navigation, but I think I will ignore this until I get past the design work and have a base theme in place (note to self: content work is out of scope, even though it begs for a gentle tidy).
There are several custom post types with overwrought PHP templates and lots of custom fields. I am hopeful these will be easier to manage visually in a block theme – we shall see!
Catalog the current site needs
The current site uses the Custom Post Type UI plugin to create five post types and custom taxonomies for each. These are easy to migrate to Advanced Custom Fields, which I want to do. ACF Pro lets me manage all my post types, taxonomies, and fields in one place. I might also use it to create some custom blocks, like for the text animation currently on the homepage which is already using custom fields.
Choosing a block theme: Start from scratch or use a parent theme?
Since most design and layout work happens with blocks on a page, I first need to decide whether starting with a premade theme is even necessary.
Rolling your own means you only build what you need. You don’t end up with templates and patterns for every possible scenario. But if you code from scratch, you have to manually update your theme.json whenever WordPress makes new block settings or styles available (that you may want access to).
So, in developer-speak: it depends. Understand what you want to accomplish first. There are pros and cons with each approach.
The minimum requirement to enable a block theme is a style.css, theme.json, and templates/index.html file. You don’t need any content here except for theme.json where you want to create a valid JSON object with schema reference and version number. Toss that in a folder, zip it up and upload to your site – start designing with the site editor! But, you can’t do everything in the site editor (yet). Enabling some of the settings and styles available to core blocks through theme.json will require some manual editing of that file.
Using a ready-made theme means you’ll get a head start with some useful presets and you get updates when the theme is updated – so choosing a well supported block theme or parent theme is very important. The downside is you will probably get a lot of templates and patterns you don’t actually need in the theme (I call these “patterns for all occasions”). Patterns may be helpful for non-designers to get a quick start on layout. Since I’m doing a custom design, I don’t find them particularly inspirational – and sometimes patterns in themes have weird structure like an overabundance of divs or vestigial spacer blocks.
I do like Twenty Twenty-Five. Very robust, but equally complex, this is a great choice for a simple site that needs adjustments you can do in the editor alone. With the extensive style customizations I need to do, it feels like I’ll have to fight with it too much.
My fallback theme favorite is Greyd from Greyd Suite. It’s not too opinionated, has excellent accessibility features built in (hello, great focus states), I know it’s getting solid support, and it feels more flexible than most “designed” themes. Ollie and some others are also popular and good options, but the design of these are too controlled for my taste.
Setting up the theme
I’m choosing to create a child theme of Greyd because I feel like it might give me a little speed in development.
To add my own custom fonts and color palettes, the Create Block Theme plugin makes everything easy.
First, I use Create Block Theme to generate my child. Next, I update my color palette and custom fonts in the child. When I write these changes to my child theme, I make sure to uncheck “write patterns” so I don’t end up with a bunch of patterns I don’t need synced within my theme. This save generates a new theme.json file with my customizations.
Next, I wanted to set up in the two main patterns: the header and the footer. In Greyd, there are multiple design patterns available, but to make my life easier, I just want to customize the Header and Footer defaults. That way, I don’t have to go back and update header and footer patterns on every single template. Default patterns are included, well, by default.
Hot Tip: Try to find the simplest solution to a problem before reaching for complexity.
Tackling the home page
The home page is almost entirely driven by custom fields, so I could have easily gotten stuck here. Instead, I decided to just sketch it in and come back to it later. I created the hero section with a featured call to action pattern and moved on.
When things stop working for no obvious reason
In the current design, images have drop shadows. This should be easy with the shadow style for images, right? For some reason it worked on standalone images but not on featured images in post loops. I could see the shadow in the editor but not on the frontend.
This is typical – you start with a fresh new site, the future is bright, and then things start going wrong. These things are universally true:
Your assumptions will be challenged
You will have to troubleshoot things that appear “broken”
You will have to troubleshoot your troubleshooting
You probably have a syntax error
I opened my theme.json file in my IDE (I use PHPStorm if you care about those things) and manually added the shadow presets to see if they’d get picked up. That worked for the image block but still not for post featured images in a query loop. This was a clue that the setting probably needed to be enabled for that specific core block under styles in theme.json.
Important note about editing theme.json
After saving external edits to a theme.json file, you have to go to the site editor and reload the page. This has to be an editor or template page, not just a regular WordPress page. Reloading updates the database, which updates the version of theme.json stored there, with your manual edits.
If you don’t do this and you keep making changes in the editor, your next “write to theme” command will make the site editor’s version of theme.json the version of record and your manual edits will be overwritten.
Note that this kind of back and forth between your IDE and the editor is really only workable at the beginning of a project. Over time it gets messy. My advice is to get your theme.json set up with the basics it needs, then work on styles in the editor – and use your style.css file if needed.
When the “Advanced CSS” editor doesn’t cut it
We’ll look at this more in future posts but you may need to use your style.css file if you’re doing fancy things like CSS animations, pseudo effects, or … trying to adjust link and focus styles. These can’t (yet) be managed through the editor.
Next time: Archive Views
I could sense I was about to get stuck on some more complex functionality on the home page, so I decided to take a break and move on to some other big pieces, like archive views.
The great advantage of working with block themes vs. classic themes is that you can build your designs visually through the WordPress site editor. However, there are times when WordPress meets a simple design need (for example, adding ::before and ::after quote marks to a blockquote) and makes a mountain of a molehill.
One helping tool here is the slightly obscure ability to add custom CSS directly to individual blocks via Additional CSS. While there are multiple places to include custom CSS in WordPress – adding a class to a block, using a separate stylesheet, or using the Customizer’s Additional CSS section – the block-level Additional CSS feature gives us a precision tool for specific block enhancements.
Who and what is Additional CSS for?
The Additional CSS feature in the WordPress block editor is designed for users with basic CSS knowledge who wish to customize a block appearance through the site editor, without modifying theme files. It replaces the CSS “customizer” feature in classic themes (although you can still access this if you really want to, at /wp-admin/customize.php).
The Additional CSS feature is mostly for manual overrides or one-off changes that the block editor and/or theme.json don’t support right now. Unlike theme customizations that affect your entire site, block-level CSS targets only the selected block instance, meaning it is only used when the block exists on a page or post.
Highlights:
No main selector needed in Additional CSS for blocks – WordPress applies your CSS to the selected block automatically
Use & for pseudo-elements and nested selectors – Use for targeting ::before, ::after, and child elements
Media queries may not work reliably (in my test) – Use theme-level CSS for responsive adjustments
Consider CSS functions – clamp(), min(), and max() can provide responsive behavior without media queries
Why use block-scoped CSS?
Using Additional CSS within a block offers several advantages over site-wide styling:
Safe experimentation: Test styling changes. Block-scoped CSS won’t break existing designs or affect other pages.
Performance optimization: Styles only load when the specific block type is present on a page, reducing unnecessary CSS overhead compared to loading all possible block styles globally.
How to find the additional CSS feature in WordPress
The Additional CSS option is located in the block editor but isn’t immediately visible.
Finding Additional CSS under “Advanced” in the style editor.
Open the WordPress site editor (Appearance > Editor)
Select any block in your template or design Look for the block settings panel on the right side of your screen
Scroll down to find the “Advanced” section
Click to expand the “Advanced” dropdown
You’ll see an “Additional CSS” textarea
The textarea is where you’ll write your custom CSS code for that specific block.
Aside: I’ll speak for all web designers and say we kinda hate how Additional CSS stuffs our programming language of choice into an obscure, hard to find box with no code formatting.
How to write CSS for individual blocks
The description for this tool tripped me up initially: “Add your own CSS to customize the appearance of the [specific] block. You do not need to include a CSS selector, just add the property and value.” There should be a link to a resource that has more detail here since, usually, if we want to add custom CSS, it’s because we want to do something more complex with nested styles and not just modify a base default.
The point is, don’t use a selector for the main block. WordPress automatically applies your styles to the selected block.
For example, if you want to style a blockquote, instead of writing:
/* this won't work */.wp-block-quote { color: red;}
You write:
/* yay! your quote is now a brilliant red color */color: red;
Working with pseudo-elements and nested selectors
For pseudo-elements like ::before and ::after, or to target child elements, use the & symbol to reference the current block and parent selector:
But, I was wrong. Although media queries are supported in the block editor, there may be some nuances and occasional issues where media queries behave inconsistently.
For now, if media queries inside block-level Additional CSS don’t behave as expected, it’s recommended to add those styles globally (in the theme Additional CSS or stylesheets) until native support is added.
Split the difference
After discovering this limitation, here’s the working approach:
Block Additional CSS (for base styles):
border: 0!important;quotes: "\201C""\201D""\2018""\2019";position: relative;margin-block: 1.5rem;&::before { content: '\201C'; font-size: min(max(4rem, 5vw), 8rem); font-family: Georgia, Times New Roman, Serif; color: #4271d750; position: absolute; top: -1.75rem; left: -1.25rem;}// add the closing quote mark after the last paragrph& :where(p:last-of-type)::after { content: '\201D';}
Use the global theme Additional CSS (Appearance > Customize > Additional CSS):
Where does additional CSS go when changes are saved?
Additional CSS added through the block editor – such as custom classes specified for individual blocks – is saved in the block’s attributes within the WordPress database.
The actual CSS code that styles these custom classes is not written to theme.json unless you manually include it OR use a helpful plugin like Create Block Theme to write changes to the theme.
The site editor now shows a version history of style changes made on the fly in the editor, allowing us to restore to a previous version if we make a mess of things.
Should you use Additional CSS in a block or in a theme?
I would think of Additional CSS as utility CSS, reserved for temporary or minimal style tweaks that don’t call for a new block variation.
A block theme needs the style.css, index.html, and theme.json files to be fully functional.
theme.json: Manage global and block-level styles and settings for a theme
style.css: Needed to register your theme. The only required part of the file header is the theme name.
index.php: This is your default page template using HTML with block markup.
Added features and functionality
Block variations: Create predefined style variations for blocks that can be selected by the user
Block patterns: Pre-designed block combinations that users can insert as starting points
Section styles: A built-in styling system for grouping and organizing blocks with consistent design patterns – kind of like a cross between a template part and a pattern
Custom blocks: When core WordPress blocks don’t meet specific functionality needs, you can create entirely new blocks with unique features, custom fields, or specialized layouts
Other stylesheets: Organize custom CSS in separate files (but still try to rely on defaults within theme.json, good design needs limitations after all)
functions.php: Not required for block themes, but you can include it for extra PHP functionality (e.g., registering block patterns or styles).
Without learning about how and why the site editor works the way it does, you’ll find it much harder to adapt a classic theme development approach to the block editor. Block themes can be incredibly flexible, but they do require a shift in approach.
Many ways to design and build
There’s no single way to do block themes “right” and you don’t have to employ a complex build process (I don’t). Start anywhere and experiment.
Additional CSS at the block level works well for styling specific blocks across your site without editing theme files. It’s ideal for making one-off changes to a core block appearance (like all quote blocks or all button blocks) that you can’t yet accomplish in theme.json or in the style editor. Scoping CSS to a specific block avoids generating monstrous global theme CSS since those styles will only be inlined if the block exists on a rendered page.
Have questions or thoughts? Please share your comments below!
You’re feeling productive and ready to analyze your website performance on Google Search Console. You click on the Pages report and suddenly feel like your website is having a total meltdown…
Take a deep breath. You haven’t broken the internet.
Most of those scary-looking “errors” in your Google Search Console Indexing report aren’t actually errors at all. They’re just Google being chatty about what it’s up to behind the scenes. Let’s decode this digital drama together.
What’s This Indexing Business All About?
Before we dive into the nitty-gritty, let’s define our terms. Indexing is basically Google’s way of deciding which pages deserve a spot in its massive digital filing cabinet. Just because you built a page doesn’t mean Google automatically files it away for searchers to find.
Think of Google like that friend who’s impossibly organized—they won’t keep everything you give them. If your content is thin, repetitive, or just plain unhelpful, Google might politely decline to add it to their collection. And honestly? That’s probably doing you a favor.
Crawling = Google’s robot (Googlebot) stops by to check out your page
Indexing = Google decides your page is worth keeping in search results
Google discovers your content through links—both from other sites and within your own. I often talk about “content relationships” when working with clients. How content is connected helps Google, and people, understand the context and relevance of your content.
You can help Google crawl your site by submitting an XML sitemap through Google Search Console or using the URL Inspection tool for individual pages. A sitemap tells search engines which pages and files you think are important on your site, and provides valuable information about these files like when they were last updated. It’s important to remember that, as mere mortals laying honey and nectar before the Great Googlebot, submitting a sitemap is only a hint. It doesn’t guarantee that Google will download the sitemap or use it for crawling URLs on the site.
Google might also visit your page but choose not to index it. That doesn’t mean you’ve done something wrong—it might mean you’ve done something right by not cluttering the web with duplicate content. For Google to actually prioritize your content, make sure your site isn’t blocked by robots.txt, loads properly, and offers useful, original content that’s well-connected through internal links.
Google’s Crawl Budget (Don’t Panic If You’re Small)
Crawl budget sounds super technical and important, but here’s the TL;DR version: if your site has fewer than 500 pages, you probably don’t need to worry about this. Google’s pretty good at crawling smaller sites efficiently.
If you do have a massive site, then yes, crawl budget matters. Think of it like Google’s daily energy allowance for your website. If you’re serving up thousands of thin, duplicate, or pointless pages, you’re basically making Google waste its time on junk instead of your good stuff.
Decoding Those “Scary” Status Messages
Let’s break down what Google is actually telling you (and why most of it isn’t cause for alarm):
“Crawled – currently not indexed”
What Google’s saying: “I looked at this page, but meh, I’m not filing it away right now.”
Why this happens:
Your content is thinner than a grocery store receipt
It’s too similar to other pages (Google’s already got this covered)
No other pages on your site link to it (Google thinks, “If you don’t care about it, why should I?”)
What to do:
Make the content more helpful and unique
Add some internal links to show it matters
Give it time—Google can be slow to warm up to new content
Possible red herring: This might not even be a problem.
“Discovered – currently not indexed”
Translation: “I know this page exists, but I haven’t gotten around to checking it out yet.”
This is like Google saying, “It’s on my to-do list!” Common reasons:
Your server was having a bad day when Google tried to visit
Google’s prioritizing other stuff on your site
Your site’s internal linking could use some work
The fix: Make sure your important pages are easy to find and your server isn’t taking coffee breaks when Googlebot comes knocking.
“Alternate page with proper canonical tag”
Google’s message: “I see what you did there with that canonical tag—nice work!”
This is actually Google giving you a high-five. You told Google which version of similar pages to prefer, and it listened. You might see this for:
Product pages with tracking parameters (yoursite.com/product?utm_source=email)
The dreaded 404. But wait—is it actually dreadful?
Sometimes yes: If you have typos in your sitemap or broken internal links, fix those.
Sometimes no: If these are genuinely deleted pages that you’re not bringing back, just let them be. Don’t redirect every dead page to your homepage—that’s like telling someone asking for directions to the bakery, “Just go to the town square, you’ll figure it out from there.”
“Duplicate without user-selected canonical”
What happened: Google found similar pages and picked a winner for itself, since you didn’t specify which one you preferred.
This is like letting Google reorganize your closet without asking your opinion first. It might work out fine, but wouldn’t you rather be in control?
The solution: Add canonical tags to tell Google which version you prefer.
“Excluded by ‘noindex’ tag”
Translation: “You specifically told me not to index this, so I didn’t.”
This isn’t an error—it’s Google following your instructions! You might use noindex on:
Thank you pages (nobody’s searching for those)
Login pages
Duplicate content you can’t get rid of but don’t want in search results
Just double-check you didn’t accidentally noindex something important.
What Actually Counts as a Real Problem?
Real errors usually involve:
Important pages that should be indexed but aren’t due to technical issues
Server problems (5xx errors)
Accidentally blocking valuable content with robots.txt
Broken URLs cluttering up your sitemap
Most other statuses? They’re just Google being transparent about its process.
The Right Way to Get Your Content Noticed by Google
Before we get to the action plan, let’s talk about how to properly submit your content to Google. There are good ways and… well, let’s just say there are ways that make SEO experts cringe.
Sitemaps: Your Website’s Table of Contents
Think of your XML sitemap as a helpful table of contents you hand to Google. It’s not a guarantee that everything will get indexed, but it’s like saying, “Hey Google, here are the pages I think are worth your time.”
How to do sitemaps right:
Submit your sitemap through Google Search Console (Index > Sitemaps)
Keep it updated automatically (most CMS platforms can do this)
Only include URLs you actually want indexed—no thank-you pages, no admin areas
Make sure every URL in your sitemap returns a 200 status code (not 404s or redirects)
Pro tip: If you’re using WordPress, plugins like Yoast or RankMath generate sitemaps automatically. Just don’t forget to submit the sitemap URL to Google Search Console!
The IndexNow Temptation (And Why You Should Probably Skip It)
You might have seen plugins promising instant indexing through something called IndexNow. IndexNow is a protocol that lets you ping search engines immediately when you publish or update content.
Sounds amazing, right? Well, just because we can, it doesn’t mean we should.
Reality check:
Google doesn’t officially support IndexNow (that’s more of a Bing thing)
These plugins often create more noise than signal
Google prefers discovering content naturally through crawling and sitemaps
Some plugins spam search engines with every tiny change, which can actually hurt your crawl budget
A better indexing strategy:
Internal links: Link to new pages from high-authority pages on your site.
XML sitemap: Keep it clean—no 404s, redirects, or noindex pages.
Use structured data: Help Google understand your content faster.
Fetch as Google (judiciously): Use the URL Inspection tool in GSC to submit truly important updates.
Content quality: Pages that are useful, unique, and well-linked get indexed faster. No plugin can fix weak content.
Exception: If you’re publishing time-sensitive news content, the manual “Request Indexing” feature in Google Search Console can be helpful. Just use it sparingly—Google gives you a limited number of requests.
Your Search Health Action Plan
Focus on what matters: Are your main service and product pages indexed? If yes, you’re probably fine.
Use the URL Inspection Tool: This gives you real-time info on individual pages and is way less overwhelming than staring at the full report.
Keep your sitemap clean: Only include URLs you actually want indexed. Think quality, not quantity.
Look for trends, not daily drama: Check your indexing report monthly, not daily. Google’s index fluctuates, and obsessing over every change will drive you bonkers.
Remember the golden rule: Google will always exclude some pages. That’s not a bug—it’s a feature.
The Bottom Line
Google Search Console isn’t trying to give you an anxiety attack—it’s just showing you what’s happening behind the curtain. The key is understanding that “not indexed” doesn’t automatically mean “broken.”
Let Google index your content on its own terms. Everything else? Don’t let it keep you up at night. Focus instead on creating valuable pages and a crawl-friendly site structure—that’s the real (long term) win.
Need some help with your website?
Need help cleaning up your Google Search Console issues or optimizing your site for better search performance? Let’s chat about how to get your most important pages the attention they deserve.
How you self-host fonts depends entirely on the type of WordPress theme you’re building. If you are creating a Block Theme – great news! You don’t have to read this article! WordPress now lets you add and manage custom fonts directly in the Site Editor under Styles → Typography.
However, if you’re working with a Hybrid Theme or a Classic Theme, you’ll need to do a little more hands-on work:
Download your fonts
Convert .TTF font files to .WOFF2 files
Load them cleanly through functions.php and theme.json
However you decide to build your theme (or non-WordPress website), you will want to make sure that you are optimizing the technical aspects of the site as well as it’s content. Including external fonts locally, within your theme, is an easy win.
Why is it important to self-host fonts?
Faster page loads
Better Core Web Vitals
Full control over privacy and design
Say Hello to Variable Fonts
Variable fonts allow for greater design control with optimized performance. Using a single, variable font file we can use CSS to adjust properties like font-stretch, font-style, and font-weight. But, including variable fonts can be a little tricky. If you’ve downloaded .ttf files for a variable font from Google Fonts and have gotten stuck because it’s not rendering correctly, it’s not just you. The devil is (so often) in the details.
In this example, I’m using a Hybrid Theme approach. Let’s walk through exactly how to self-host variable Google Fonts correctly — and how to fully support Gutenberg editor styles too.
Why .TTF Fonts Aren’t The Best Choice for the Web
First, .ttf (TrueType) fonts were never designed for the web:
They’re huge compared to .woff2 (30–50% bigger).
They don’t stream efficiently, slowing down first paint.
They carry extra metadata browsers don’t need.
Modern browsers love .woff2 because it’s lightweight and streamable. If you want fast fonts, you must convert your .ttf files.
How to Convert .TTF Files to .WOFF2
After testing several tools, the best converter I tried was Everything Fonts TTF to WOFF2 tool. It delivered clean, minimal .woff2 files — no bloated metadata, no weird rendering issues.
💡 Pro Tip: Make sure you’re converting variable.ttf files if you want full weight ranges (100–900), not just individual weights. While you can convert any .ttf font file, if it is not a true variable font, you won’t get all of the benefits. This process will not magically create a variable font for you.
Setting Up Local Font Hosting in Your WordPress Theme
You’ve selected the variable fonts that you want to use and you’ve download the files. Next, you’ll want to convert the .ttf files to .woff2 files, as mentioned above. I’ll be using REM and Nunito, both variable Google Fonts in this example. Here’s how you can now include your fonts in your WordPress theme:
1. Organize Your Fonts in Your Theme Folder
Store your converted fonts neatly inside your theme:
✅ Notice each fontFace block includes a local src path to the .woff2. ✅ The Block Editor and the frontend now both load the same fonts — no mismatch warnings.
Do You Still Need Static Fonts as Fallback?
For 99% of projects today? No.
All modern browsers — Chrome, Firefox, Safari, Edge — support .woff2 variable fonts. Adding static .woff2 or .ttf backups only bloats page weight.
Only consider static fallbacks if:
You have strict enterprise requirements for ancient browsers.
Your analytics show a significant number of IE11 or Android 5 users.
Otherwise, skip static fallbacks and stay light.
In Conclusion
Self-hosting fonts is a must for performance optimized WordPress web development. By converting fonts correctly and setting up theme.json the right way, you’ll get:
Faster loads
Stronger SEO
Better design control
When converting .ttf to .woff2, I liked Everything Fonts — it simply worked better than the others for me.
WordPress Block Themes Offer Performance and SEO Win for Small Business Owners
If you’ve been using WordPress for a while, you’ve likely witnessed some degree of transformation to your workflow. Wordpress, originally a simple blogging platform, has grown into a robust content management system capable of powering everything from personal blogs to enterprise websites. The Gutenberg Project that began in 2018 has evolved into a rich “site editor” experience in which anyone can build beautiful websites (relatively) easily. The site editor can dramatically improve your content creation workflow and provide more “no-code” flexibility to you as a site owner or content creator.
What Are WordPress Themes?
Themes are the foundation of your WordPress site’s visual identity. They define essential visual elements like your color palette, typography choices, and layouts for various content types. Your theme will establish the look and feel that makes your website uniquely yours, setting the tone for your brand’s online presence.
Classic themes: a traditional approach
How Classic Themes Work
For many years, WordPress themes followed a traditional development model. Before the block editor arrived on the scene, all theme templates and parts were written primarily in PHP, with supporting CSS and HTML. This technical foundation allowed developers to create dynamic, full-featured websites but came with significant limitations for non-developers.
If you wanted to make structural changes to your site—even something as seemingly simple as updating your logo or rearranging elements in your header—you typically needed to call a developer.
Page builder frameworks: power tools or performance pitfalls?
In response to these limitations, builder frameworks emerged as a popular solution. These tools promised the ability to build sophisticated websites through visual interfaces, liberating non-technical users from their dependence on developers. With the ability to click and drag elements onto your pages, creating complex layouts “without writing a single line of code” became possible (to a degree).
But, we all know that magic has a cost. Many builder frameworks:
Created “div sandwiches” (layers upon layers of nested divs) that resulted in messy, inefficient code. This could make your website harder to maintain and potentially slower to load – and make it harder for Google to get to your content.
Introduced accessibility issues by not using semantic HTML or not having testing methods in place for keyboard or voice controls. This not only affected users with disabilities but could also impact your SEO and legal compliance.
Added unnecessary features in an attempt to appeal to everyone, creating bloated sites with poor performance. These “kitchen sink” approaches often included dozens of features you’d never use but that still consumed resources.
Sat on top of core WordPress rather than integrating with it, adding extra processing layers that could slow down your site and complicate updates.
Block themes: the modern approach
Better No-Code Site Building
Block themes represent a fundamental shift in how WordPress sites are built and managed. Block themes embrace a visual, component-based approach that puts a lot of creative control back in the hands of content creators.
With WordPress block themes, you can build and customize your entire site directly in the Site Editor. The entire experience—from designing navigation menus to crafting templates for custom post types—leverages core WordPress blocks through an intuitive visual interface.
This democratization of web design means that you can experiment, iterate, and launch new designs quickly, with much more autonomy*.
*There are still considerations around accessibility and functionality that may require a custom block or plugin. Built-in checks in the editor are pretty good at alerting you to common issues such as poor contrast between text and background colors or skipped headings (when you view your page in outline mode).I do recommend the Accessibility Checker plugin by Equalize Digital to help you identify and fix accessibility errors.And, please – never, ever use an accessibility overlay.
How block themes make WordPress management easier for non-technical business owners
For small business owners, the traditional WordPress development cycle often meant expensive developer retainers or settling for a website that couldn’t evolve with your business. Block themes eliminate this frustration by putting you in control of your most important digital asset.
Greater control, less dependance on custom code
Using block themes enables you to incorporate sophisticated site elements that would typically require developer intervention in classic themes. Want to customize how search results appear on your site? You can do that. Need to create a more helpful and branded “404 Page Not Found” experience? That’s within your reach too. Considering a global update to your headers and footers across dozens or hundreds of pages? With block themes, these changes can be made quickly and consistently without writing or editing code.
The modern architecture of block themes delivers tangible performance benefits through more efficient code and smarter resource management. The conditional asset loading approach means your site only loads what it needs for each page, rather than burdening visitors with unnecessary resources. This translates to faster load times and a more responsive user experience—factors that influence everything from visitor satisfaction to search engine rankings.
Perhaps most importantly, working with a block themes represents an investment in future-proofing your digital presence. WordPress core development is clearly focused on expanding and enhancing the block architecture. By embracing this approach now, you position your website to seamlessly adopt new features and capabilities as they emerge.
WordPress Classic Theme Limitations
Even when using the block editor with classic themes:
Not all block properties will be available (unless specifically enabled)
There’s no front to backend visual parity: the page editor appears as a white page with black text, disconnected from your site’s design (unless you enable site editor styles and pursue a hybrid approach)
WordPress Block Theme Advantages
Block themes offer:
A seamless visual experience between editing content and the results you see on your live site
Enhanced design options for dynamic content (like the Query Loop block)
Automatic reflection of your design choices (fonts, colors, styles) in the editor and on the frontend of your website
More engaging, dynamic page layouts possible without developer assistance
Ability to load custom, branded patterns for use throughout your website for more consistent design even when you have multiple editors (to be fair, you can do this in classic themes also – block themes take it a bit further with the ability to create theme specific section styles and settings)
By reducing dependence on developer assistance for routine website updates, block themes can significantly lower the total cost of website ownership for small businesses, allowing you to allocate resources to other critical areas of your operation.
Performance comparison: block vs. classic
All WordPress sites, whether using a classic theme or a block theme will benefit from recent core updates. Performance improvements are more dramatic when you use a block theme.
Classic Themes Can Be Slow…
Rely heavily on PHP for rendering templates dynamically
Increase server-side processing time and database queries
Store changes via the WordPress Customizer or manual edits
Load large, comprehensive stylesheets and scripts regardless of what’s used on the page
Block Themes are Super Fast!
Use theme.json files and block-based templates
Store global styles in the database via a theme.json file
Employ conditional loading to include only assets needed for specific blocks
Reduce unnecessary database queries and server-side processing
SEO benefits of block themes
Block themes have several SEO advantages:
Speed and Technical SEO
Faster loading times positively impact search rankings
Cleaner code improves crawlability and indexing (this can vary depending on the theme you choose and what else you’ve got happening with plugins, etc)
Mobile Optimization
Inherently responsive (intrinsic) design aligns with Google’s mobile-first indexing
More uniform adaptation to various screen sizes – if you can include some clamp sizing rules for layout, fonts, and spacing in your theme.json file you’ll go far with core blocks!
Performance Enhancements
Reduced dependency on plugins and multiple stylesheets*
Style loading only when needed improves Core Web Vitals scores
Better user experience translates to improved search performance
*For reference, a migration I did a few years ago cut about 3,000 lines of custom CSS from the stylesheet – and that was a hybrid theme.
Should your small business switch to a block theme?
Short answer: If you’ve been considering a website update or rebrand in the next 6 months – YES, ask your developer about block themes.
Making the transition from classic to block themes is a significant decision. While both block and classic themes can perform well with proper optimization strategies like effective caching and image compression, block themes offer compelling advantages that are becoming increasingly difficult to ignore.
The significant performance gains alone would make a compelling case, but when combined with the potential for reduced design and development time and greater flexibility for content creators and site owners, the argument for block theme development becomes even stronger.
Block themes represent not only the future of WordPress, but its present reality. By adopting this approach now, you ensure your site can take full advantage of current capabilities while also being able to implement future improvements as they’re released.
Block By Block: How Small Business Websites Gain a Competitive Edge with Block Themes
Subscribe and you’ll get 1 email a week for 7 weeks that covers the competitive advantages of WordPress blocks and block themes as well as pro-tips to help you improve your current WordPress powered website.
Your website is a service, not a brochure or a product. As a service, your website should prioritize the tasks and information that your readers need most. Crafting a website with your readers in mind is more sustainable over time. It also translates to better search performance.
Setting expectations
Websites should be accessible, usable, and useful
People need to use your website to access important information and services. Website content that is accessible is designed to follow the P.O.U.R. guidelines:
Perceivable
Operable
Understandable
Robust
When designers, developers, and publishers consider accessibility from the beginning we can create a more inclusive digital experience. Content that is easy to scan and read enables more accurate translation, is easier to maintain, and is more findable.
Write content for people
People are busy and often distracted. Writing clear, easy to read copy helps them to “get” your content, do what they need to do, and move on with their lives. Sometimes this will result in shorter time on page, or “less engagement” in terms of Google Analytics. But, that’s not always bad! If you’ve helped people get to the content they need more quickly, you’ve created a more positive and successful web experience.
Using plain language can help you to avoid convoluted or cliché expressions. Simplifying the words you choose – for example, write “use” instead of “utilize” – will make your content more impactful and meaningful.
Use active verbs
Write shorter sentences
Avoid abbreviations
Avoid generic “click here” link text
People will skim and scan and that’s okay
The web is made of links
Links allow people and search engines to navigate your content. When crafting links, consider the following:
Action – What do people need to do?
Clarity – Links should look like links, ie. underlined
Visibility – Don’t hide essential elements (search, menu)
Promises – A link is a promise. Tell the reader what to expect.
Words – Choose the right words. Language is more powerful than images.
Research on usability indicates that when users fail to navigate correctly on their first attempt, their success rate tends to decrease. Making sure your links and navigation are clear and that content relationships are visible (through breadcrumbs for example), all help people understand and navigate the virtual space of your website.
Internal links also help search engines crawl (discover) and index (store in its database) the pages of your site. As Google states in its guide to how search works, “Some pages are known because Google has already crawled them before. Other pages are discovered when Google follows a link from a known page to a new page.”
Don’t be afraid of linking to external sites. The idea of “keeping” people on your site is not realistic. Links to high-quality, useful external sites can be helpful to your readers. That’s the job of well-crafted content; get people the information they need, when they need it.
Structure your content for readability
Web pages and documents with a clear structure and hierarchy are easy for people to understand. Typically, a person will scroll a page and scan the headings to get a sense of what the page is about.
In HTML, the markup language of a webpage, we have some core elements that create structure in our page:
Headings – H1, H2, H3, H4, H5, H6
Lists – <ul> is an unordered list, <ol> is an ordered, or numbered, list (this list is a <ul> element)
Blockquotes – more than a visual style, a <blockquote> is a different element from a paragraph, but it may include a paragraph
Paragraphs – the basic, essential element to display text content
Good page structure helps people scan content and find what they’re looking for more easily. It also helps Search Engines to understand your content. Page structure is a factor in technical search engine optimization (SEO) as well as usability and accessibility. Use your elements!
Using headings to define blocks of content
Headings organize and define blocks of content. They help all readers scan your page to understand the content and find the information they need. This includes sighted readers, readers using assistive technology, and search engines.
You should only use one H1 per page – this is usually your page title.
Don’t skip a heading level. Headings 1 through 6 are available to use but you might not need them all. Just make sure they appear in order (ascending, descending).
Don’t use headings just because you want your text to stand out visually.
Conclusion: Your audience is people – prioritize their needs and expectations
Keeping your audience in mind when developing content, optimizing for search, and testing for accessibility, will all ultimately help you develop a more successful web presence (one that can be found in search and is optimized for conversion).
Need help or have questions about content? I provide team training to help content publishes create useful, optimized, accessible content and make the most of their website tools. Feel free to reach out to me with any questions, I’m always happy to help.
Flashback to September 2022. Full Site Editing (FSE), introduced in 2020, extended the visual design capabilities of the WordPress block editor allowing anyone, regardless of their coding knowledge, to build templates and template parts directly in the WordPress editor. Full Site Editing elicited many Feelings(™) from designers and developers using WordPress who had established workflows and potentially complex development needs which the site editor was still a bit clunky with. The question of “who is this for?” was (and is) an ongoing discussion.
A freelance, self-taught web designer, I was mainly using the blank Underscores theme as my base, and feeling like maybe I had the hang of this web design thing. Googling how to do something in PHP was/is still a major part of my development process so the idea of being able to visually design themes was quite attractive. The web, after all, is fundamentally about the democratization of publishing, so, all signs pointed to “Yay!”.
But… the site editor (formerly known as Full Site Editing) is a completely new thing. Completely new things are hard.
Community and Collaboration
When Jonathan Bossenger posted a request for a block theme design on Twitter, I volunteered. Jonathan is a Developer Educator for WordPress and I had recently begun following his training modules on Learn WordPress. Learning from a legitimate “real” developer*, as opposed to fumbling through Stack Overflow posts, promised to be much more illuminating.
* As a web designer at the very front of the front-end, there’s a lot of things that I can understand conceptually but I just don’t have the skills to create from scratch.
Note to Designers
It’s especially informative for ANY designer to understand how a developer might read your designs and interpret them. If you are new-er to designing for the web, or even a seasoned pro, it’s super-beneficial to get involved in the building and thinking process rather than just delivering a design file and calling it a day.
Sendig theme styles outlined in the Sketch file.
Make Web Design Fun!
Jonathan graciously accepted my offer to design a theme for the block editor. Uh oh – now I have to design something that can withstand the critical gaze of #DesignTwitter!
Mostly, I wanted web design to be fun again. My approach was to do things that my standard client work would not be receptive to and have some fun with design challenges that would be more tricky for me to code.
It starts with a name…
I chose “Sendig” as my theme name because it sounded kind of cool and it’s also an anagram of the word “design”.
Aesthetically, I really enjoy Brutalist architecture and design. I like showing the structure of things as well as bringing back some vintage web conventions such as a visited link color. I spent some time reviewing the structure of the Figma* file for WordPress Twenty-Twenty Three theme** and patterened my Sketch file after that.
* Maybe I’ll learn Figma someday. For now, Sketch or Balsamiq are easier for me.
** WordPress has a Figma design library and many other resources through Make WordPress Design.
Can a free theme also be a teaching opportunity?
I was thinking, instead of Lorem Ipsum text, what if we included some hints about accessible design considerations within the text of the theme? Maybe a little learning mixed into the theme could help to keep accessibility in mind when creating a new website?
So, I probably have to change this to something from Web AIM or a more general source, but I chose to use some quotes from Steve Krug, author of the classic text “Don’t Make Me Think,” and a quote from Marcy Sutton’s recent accessibility training course, Testing Accessibility.
Headings in the design also describe their purpose; introducing a new section or topic and helping to create good page structure.
Design is Problem Solving
I wanted to do some design-y things that tend to be less applicable to my commercial work – such as aligning main content to the left rather than centering it by default or using “not typically considered beautiful” colors like mustard yellow (aka. Yellow Ochre for the painters). And, I wanted to do some fun CSS things like shapes, overlay/opacity, transform, and layering of elements in space.
I’ve created a few patterns that reference “classic” graphic design motifs like scattered images around a block of text. These patterns would be hard for me to create in the WordPress site editor (without relying on custom CSS and code) so I’m keen to see how they develop through this process.
Developing the Sendig Theme in Public: The First Twitch Session
After several months, the first Twitch development session took place on this auspicious day, May 9, 2023. Today was mostly set up and although Jonathan called it the “boring” part, it’s always informative to me to learn how other developers structure their process, what tools they use, and how they approach a project.
In that sense, I find developing to be closely related to painting. In practice, all painting is essentially abstract. When observing a structure or a landscape, what we see is broken down into colors, shapes, and light (or, components) as we understand how all the parts can fit together to compose a whole. In painting, an expression of feeling supersedes exactitude. Which, for better or worse, also tends to be my design approach (apologies in advance).
Live streaming this process highlights the thinking that underpins any project. There is no such thing as a perfect design to dev handoff (at least, not in my experience). Communication, collaboration, and ongoing inquiry are key. And, love it or hate it, we are all learning this new thing together, which is pretty cool!
I’m looking forward to continuing to follow this project on Twitch on Tuesdays and I hope you will to.
Bill Erickson shares a lot of useful info, snippets, and resources.
Just launched by Aurooba Ahmed, Thoughtful Block UI. The podcast, viewSource, with Aurooba Ahmed and Brian Coords is more advanced development and also highly recommended (most of it is beyond me but I still learn a thing or two).
Build Mode Live, an ongoing and open Zoom conversation each Friday morning (10am CST) hosted by Sam Munoz and Brian Gardner from WPEngine about the future of WordPress and the site editor.
Gutenberg Times, “All things WordPress Block Editor and Gutenberg Plugin”!
WP Café is a podcast that’s a bit more about the business aspects around theme development but also documents their transition into learning and using the block editor for client work.
MasterWP, not specific to block theming but a great learning resource: https://masterwp.com/
The good thing about looking back at early work, is seeing how much you’ve learned.
c. 2010, classic table layoutc. 2015 – first WordPress incarnation
I built the first website for the law firm of Despres, Schwartz, and Geoghegan, Ltd. around 2015. They needed a responsive website (migrating from a classic table layout) and WordPress seemed the right solution. I used my premium theme builder and created a simple website with a few pages and a blog.
After nearly ten years, the site desperately needed a rethink. Rebuilding in the site editor this year was an opportunity for me to explore (and learn) what might be possible in a block theme on a “real”1 website.
1 Some anti- block-theme sentiment spirals around block themes being fine for displaying simple content but not functional for the complexities of an actual website.
Create Block Theme Plugin
The Create Block Theme plugin is not required but it sure does make things easier. For example, creating a child theme (unclear if this is still as essential with block themes as with classic themes), including fonts in theme.json, or even just setting up a new “empty” theme with the basic structure and files you need to get started. When you generate your theme, it will create the theme folder in the site’s theme directory. You can also choose to export your theme.
Using this plugin I first created a child of the theme Beaumont by Anders Norén (because his designs are so great). At some point, I decided it wasn’t quite right – I didn’t really want any styling to exist, just the basic structure. I opted for something more stripped down, Blockbase. In this attempt, I didn’t create a child at first. I chose to create a style variation for the current theme thinking, “Let’s keep this simple – I’m just customizing styles and blocks, right?”
As many of us know, simple soon becomes complex. I experimented in changing my selected style variation to see what would happen if an editor did that. All of my customizations were lost, probably due to me not saving my changes.
Lesson #1: Always save your work
Save changes as you go!
We can make a whole lot of changes in the site editor very quickly and saving changes isn’t an obvious part of the flow (as it is when you are working directly in a file editor). A nice feature in Create Block Theme, which I discovered through doing things wrong, is that in addition to saving your theme at any point through the Create Block Theme dash, you can also write your user changes (to styles and templates) to the database while working in the site editor. The wrench icon opens to display your save options:
Save Changes saves everything to the theme.
Export zip exports your theme but you also want to be sure to “save changes” to your theme first or they won’t be included (learned this the hard way!)
Notifications are a little too discreet here. I’d like to see an alert or something that repeats the description of what to expect, like: “You may want to save your user changes to the theme first or they won’t be included in your exported theme.” A message when you change your variation would be nice too. If the site editor can note that changes have been made, but not saved, remind me. Especially for a new user or non-developer, contextual messaging about what happens next could help them from feeling frustrated that things appear broken “for no reason”.
Revision history in the site editor
We can view a list of changes and revert to a previous version using the revision history panel in Styles.
3rd (or 4th) time, the charm
I began again with a copy of Blockbase and got pretty far with my new theme until I read somewhere that it should be a child. Or, maybe I began second-guessing myself and thinking, “this should be a child,” in case the parent theme is updated. Once more, I returned to the beginning and created a child of Blockbase.
Some minor issues that happened at various points in development:
At one point, the social links block was missing the setting to change the link color on icons. I could change the block background and text color but not individual link icons.
The height unit for spacers stopped working. The values are displayed in the spacer block settings (em, rem, px, vh) but only the pixel value would change the height.
I’m not sure if those bugs are related to some glitch that may have happened during a save/write to theme files.
Major Mental Model Shift
The most challenging aspect of working to create a block theme, for me, was not relying on editing files directly. It felt a bit like I was working with blinders on, unable to see the actual code. I could work on theme.json initially in my code editor but after a certain point what happens in the code editor and what happens in the site editor starts to break down (as one might expect in a mirror universe). This is because what’s happening in the site editor is being written to the database, which is not the case when editing files outside of WordPress (I think).
Why can’t I just write CSS?
Add CSS – if you dare!
I don’t like the tiny little panel we get for custom CSS stuff. “Additional CSS” isn’t even exposed by default. It’s like, don’t you want me to write CSS anymore, WordPress? Where block themes are currently, and what theme.json can control, is pretty awesome. But, there ends up being a fair amount of CSS we designers and developers will want/need to add in a custom theme. Even a block theme. The few examples that occurred in this very basic site involved:
Custom bullet styles for unordered lists
Overwriting a form plugin gap and required field color in order to meet color contrast requirements
Creating a negative margin style so that an image could “overlap” a section
Adding a transition to buttons to ease the background color shift
Many styles to adjust the navigation block
Which brings me to the navigation block.
Navigation Block: Bane or Boon?
The great thing about the navigation block is that it has accessibility baked in. A parent item with children is a button element. Keyboard interaction is as expected. Yay! But … there’s a few things that are hard here:
I want the .current-menu-item li to have some style that shows what is current and active in the menu, like a bottom border.
If a page is a pseudo parent, for example, a static team page contains the custom post type team, I still want to highlight the parent page when viewing a single team member (post).
I also had this issue with the /blog/ page menu item when a single post was viewed. Even with a .current-menu-item style, I had to add another custom style for this to work on the archive view.
The mobile menu: there’s minimal and then there’s, um, the mobile menu for the navigation block. Compared to what we are used to, it’s too limited. I want to be able to show the word “Menu” and “Close” as well as the icons. I also want to be able to change alignment and styles here.
Your selected, primary navigation menu is synced: a good default but not obvious.
When adding the navigation block to the footer template part, I customized it not realizing that the navigation block was by default my “primary” navigation and synced with the header navigation.
Under the navigation settings, the title is simply “menu” and then menu items are listed. It wasn’t obvious that this is a specific default menu that would also be synced. If I click on the options menu, I can see that I am able to import classic menus or create new menus. If the selected menu name was also shown in the settings panel, not just the “Menu” label, we might infer multiple menus could be created and managed and that changes to a current menu would affect all instances of that menu.
Search Icon, wherefore art thou?
A search icon that opens up a search panel is ubiquitous in website designs. The search field is probably better UX but it’s not always going to work in those minimal header designs with a logo to the left and navigation to the right. My work around on this website was to use a modal block and, basically, fake it.
Working with Page Templates
As I neared the end of the rebuild I started to use Polypane for a look at responsive and accessibility issues. One thing immediately noted was that the Page Title was not in a landmark. That’s not good! I checked my page template and realized that the Page Title, which has a full-width cover image background, was indeed outside of the <main> content group.
The main group has a margin that doesn’t allow for full-width inside the template. On a page, you can include full-width blocks but not inside the template (I’m not sure why, to be honest). I referred to my usual _S (Underscores) theme structure within the body:
Since we can define the HTML element under the “advanced” settings of the group block, I added two more container groups to create the missing article and article header sections and grouped everything in a new <main> section. I then demoted the <main> content group to a general purpose div.
This is something that will vary by theme since the theme author decides the structure when they build their templates. It’s not something everyone would investigate. More explicit instructions could be useful, for both DIY folks and developers. Landmarks may not be top of mind for everyone when building out a template and even developers aren’t always aware of their importance to accessibility.
This setting is hidden under an advanced label. The name “advanced” would probably deter many content creators from even looking here.
Could there be a warning / “are you sure” message if a landmark is missing from a template?
The descriptions are a little vague, for example: “The <section> element should represent a standalone portion of the document that can’t be better represented by another element.”
Some examples or a link to learn more about each type of element could be useful, as we have for the HTML anchor option.
File under “Miscellaneous”
One thing that is necessary for larger sites is handling custom field data. I use Advanced Custom Fields (ACF) on many of my sites. I likely want my custom field content to appear dynamically in certain places and not just the page or post it is created on. Here’s where I start to encounter a knowledge chasm going from classic theme to block theme developer.
I am not a person who will be able to “learn JavaScript, deeply”. Learning new things is hard, which doesn’t mean I won’t try, but it’s really hardnot possible to keep up on everything and do it well. I am excited about the potential of the site editor and block themes. I’m a little sad to lose the control and autonomy I had with my _S based theme process.
There is a middle path (for now)
Hybrid themes afford someone like me a viable option for sites of any complexity. I kind of understand PHP now and I am able to manipulate it. With the inclusion of theme.json, some editor styles, and custom blocks I can leverage the more modern aspects of WordPress core. But, if I see an opportunity to go full-on block theme I definitely will.
Re: Block theme and site editor resistance
When I was first introduced to WordPress, I had been building websites using BBedit and Dreamweaver. I started by creating child themes but, not knowing any PHP, there were many things that I couldn’t do. Using a builder framework offered me much more design control and a speedier process (in theory). Gradually, I tried to improve my processes to follow what I considered to be “best practices” – relying on defaults, using semantic HTML, prioritizing accessibility in design. Using a builder began to feel confining because I didn’t want to just do it faster and increase my volume to make more “web product”. I wanted to craft the web experience more holistically and have a meaningful personal and professional investment in my work. Or, maybe I just like doing things the hard way.
Despite the recent advances of the site editor, builder frameworks are still a prevalent solution and the default editing capabilities of WordPress are often compared negatively. Most commonly, the developer complaint is that the block editor is great in theory but it’s still too new and not capable of the robust solutions (ie. control) we developers have in our established themes and plugins of choice. That always makes me think of the agency job I had 5 or 6 years ago where my manager vetoed the use of CSS Grid for the same reason. It’s been almost seven years, that’s super old in internet years? But, okay, I get it.
“Mostly in” on Block Theme Development
When web creators push back and say something is too new to use, often that means, “I’m not comfortable with this change and I’m worried about all the additional labor needed to understand this.” Once that knee-jerk “no” is out of our system, I think we can acknowledge that adapting to change is one of the strengths inherent in our practice. And, if that doesn’t inspire you, the block editor is here to stay. It’s on us to learn and understand more fully what is possible – and to work together to make it better.
Reflections on my first “An Event Apart” conference.
In every generation a Change-maker is born. She alone will stand against the forces of scope creep. She is the designer, developer, brand-builder, project manager, and client hand-holder.
But actually, she’s not alone. The full-stack myth may persist but what truly makes the individual powerful is their team. Consider Buffy the Vampire Slayer. Without her scooby-gang, she may not have saved the world quite as often and she definitely would have stayed dead that second time. A good leader empowers their team to be better, and recognizes that they can’t fight the powers of darkness alone.
Attending An Event Apart in Chicago this past August was kind of like being in the presence of a united group of superheroes. Each presenter built their talk on a shared foundation of research, humanism, inclusion, thoughtful design, and more research. As attendees listened (far, far away from our ruts of creativity-squelching projects and unrealistic time frames), we became equals. We were all Change-makers.
“Research saves money.” — Jeffrey Zeldman
Introduced by Eric Meyer as, “the Kirk to my Spock,”Jeffrey Zeldman opened with a major rebuttal to a giant assumption. His analysis of his own research-centric approach on a recent project offered a lot of insight to many of us who struggle with a demand for “magic” under the restrictions of small budgets and smaller timelines. Zeldman told the story of a recent client coming to him for a site refresh, checkbook at the ready.
“Stop, don’t give me all of your money. Just give me some of your money and let’s do some research,” said Jeffrey.
It may seem tempting to take the money and run with the problem as outlined by the client, (ie. “We just need a design refresh.”). In reality, working in this way is neither faster, nor easier, and will almost always result in confusion, disappointment, and the dreaded scope creep as everything that went unspoken in the kick-off call rears it’s bloated, assumption-ridden visage.
Research is the web’s version of, “Measure twice. Cut once.”
“Yeah,” you say, “but, that’s Jeffrey Zeldman. He can afford to do research. What about the little start-up web companies and the independent designer/developers out there? Do we really have time to do research? And user-testing? This sounds great but let’s be practical. We’ve got deadlines and projects are backed up. Clients will never go for it.”
We buckle under the pressure of “business” considerations (aka. the way we’ve always done things) and take on another “quick brochure-site redesign”. We do exactly what the client asks for without delving further into the problem.
How long did the project actually end up taking (did you exceed your budgeted time)? What happens in 2 or 3 years when the logo is updated or web design trends change? After several different “refreshes,” and twice as many development firms, the original website will become a Frankenstein. The only way forward will be a complete re-build from the ground up.
No one wins in this scenario. Without research, there is no meaningful design. Without meaningful design, we can’t be sure that we are solving the right problems.
Stop Being Boring
The commercial web has been around for a mere 20+ years, an insignificant amount of time, and yet it feels like we have already run out of ways to present our ideas. Wait a minute… are we really that boring?
Enter Rachel Andrew. With the publication of “Get Ready for CSS Grid Layout,” Rachel became the prophet for a new CSS spec that changes everything. Acknowledging that change can be hard, Rachel provided some excellent pro-grid arguments to make when you encounter objections. CSS Grid is currently at 68–72%95% browser support — this is one of the fastest adoption rates ever for any new CSS spec. That website you are working on today is meant to live on the web in the future. Use the technology that it can grow into today without doing any extra work – a few @supports rules and you are all good!
Should you use grid? The short and resounding answer is “YES”. CSS Grid is a revolution in web layout. Prepare to be amazed at how a few lines of code can open up a whole new realm of possibilities in web design.
When Jen Simmons steps up to the stage to close out Day 1 of An Event Apart Chicago, and says (essentially), “Okay, let’s stop this bootstrap-py navel gazing. Let’s look at something completely different,” the audience is rapt. “What about websites that refer to Bauhaus design concepts? How about aligning text from top to bottom or right to left? We can look at art and design from India or Japan.” We are frightened and entranced. We are grateful to hear our own nagging suspicions spoken aloud. The web, and by extension the world, can be anything we imagine.
What does the future look like?
Making assumptions is just something humans do in order to navigate a complex world in a more or less timely and productive fashion. However, assumptions do not save time when it comes to web development. When allowed to run amok, assumptions will always seek to override and impair its challenger — discovery.
Tasked with creating a shared language of symbols and interactions meant to assist other humans in their day to day activities, we can not simply go through the motions. What do real people need to do? How are they best able to do it? What issues might arise from a marketing decision to rename the login area to something more “original” or a designers minimalist proclivity to place 12px #7A7A7A copy on a #F5F5F5 background?
Accessibility is more than just being mobile friendly.
The future is not merely mobile, it is inclusive. Day two of An Event Apart explored the varied levels of human interaction within teams and with technology in greater depth.
Derek Featherstone spoke on the topic, “Where Accessibility Lives”. Imagine a hypothetical web team, faced with a number of complaints from users, that has to “determine if the issues (are) larger than a bug and require strategic decisions”. Derek suggested that rather than overwhelming ourselves (and our teams) trying to be “100% perfect and 0% done”, we can create a standard that “evolves to always get better”. We can be 100% done and 60–70% perfect and continue to make improvements. We “focus on better” by incorporating accessibility thinking into our processes and tools. We can then test our assumptions by reaching out to advocacy groups, colleges, and universities.
If basic human empathy is not enough to sway you, accessibility is now a Google ranking indicator and, actually, web accessibility is like a law and stuff. Since 2010, many public and private companies have been sued under the Americans with Disabilities act for failing to to meet Web Content Accessibility Guidelines.
A website is often viewed in context with a user’s real life.
In a related talk titled, “Design for Real Life,” Eric Meyer weighed the importance of understanding who our users are against the assumptions we might be making on their behalf. Is an automated “Happy Mother’s Day” email something that everyone wants to receive, does it elicit the same response in all people? People don’t access web content in a vacuum, life is full of stressors and “stress expands to fill available space”. All the more reason to challenge our assumptions about what users need and how they will complete a task. Eric impressed upon us that “when we shape information, we can alter the shape of lives”.
In applying design thinking throughout the lifespan of a project, we come to appreciate that “what we do to help other people, (ultimately) helps us.”
“Our work is done with other people, for other people.” — Brad Frost
The way forward must be to consider what we do in a more holistic and critical way. How do we help our clients and our organizations stand out? How do we optimize for the human experience? How do we work together?
In a recent meeting to kickoff a new project, a lead developer and project manager (from another company) assigned approximately one week to each aspect of the project: research — 1 to 2 weeks, wireframes — 1 week, design — 1 week, with 1 week between each for client feedback and changes. At the end of these 6 or so weeks, “production ready files” would be handed off to our development team. Which, I guess, we would then proceed to print on our Gutenberg printing press, placing fresh Web Pages under the windshield wipers of parked cars up and down Main Street, USA!
“Not my job.” — Everyone
The “handoff” between the designer and the developer is a bit of a running gag within each group (although the clueless party in the story changes depending on whether you talk to the designer or the developer). Brad Frost, in his presentation “Let’s Work Together,” showed a GIF of a delivery driver dumping a package over a fence and driving away. The driver was, naturally, the stand-in for the designer. It’s funny because it is largely true, but why is it this way? When did this divide occur?
There are assumptions ruling departments and agencies that separate the sales process from the wireframe and design period from the let’s-actually-build-this-thing phase. A successful project begins with thoughtful communication and research. Research is an opportunity to discard our assumptions, and to explore the wealth of knowledge and experience contained beyond our own design preferences and production habits.
Evolve into Better
Sure, we can do what is asked of us and no more. We can work in isolated silos and pretend we are “full-stack” superheroes — but aren’t we all better when we work together?
We grow when we challenge each other. It is our job to empower our teams to be better, to educate our clients on the value of research, and to be advocates for the people who will use the things we make.