Default ACF Flexible Content Fields

ACF Default Content Blocks

I had a recent request to set up some default Advance Custom Fields Flexible Content Fields for new posts. We often use FCF blocks for a lot of our page creation to allow for greater customization and flexibility. While this might seem like limiting some of that flexibility it comes with the benefit of streamlining things for your client.

Limiting the filter to only run on certain post types I can set up some default blocks and settings to make things easier and quicker to get up and running. This makes it easier on the client, and makes them happy. And a happy client, is a happy coder.

The ACF filter we’ll use is acf/load_value/name={$field_name}, read more on the ACF Docs. You need to set the name as the name of your flexible content blocks field name.

In this example I name mine content_blocks

add_filter( 'acf/load_value/name=content_blocks', 'default_fields', 10, 3 );
function default_fields( $value, $post_id, $field ) {

  // Only add default content for new posts
  if ( $value !== null ) {
    return $value;
  }

  // Only add default content for certain post types
  if ( ! in_array(
		get_post_type( $post_id ),
		array(
			@TODO Post Types
		) ) ) {
		return $value;
	}

  // Set up your initial post, then get the field id's of the settings you want to set
  // They look like: field_5b4e57efd0660_field_5b4e63e479d81
  // Add them after the acf_fc_layout
  $value = array(
    array(
      'acf_fc_layout' => 'name_of_layout',
      'field_5b4e57efd0660_field_5b4e63e479d81' => 'Default Value'
    ),
    array(
      'acf_fc_layout' => 'another_layout',
    )
  );

  return $value;
}

First we check the $value and make sure it’s set to null. If not than the post has already been created and we need to return early.

Next I check against the post type. There are a variety of checks you could do to make sure you’re only added default blocks where you want. You could check against the post template, post type, or even specific post ID’s.

Once you’re done checking you can setup the $value variable. The variable is an array, made up of arrays for each block you want to create.

The first value key pair you’ll need to set is the acf_fc_layout. This corresponds to the name of your layout in the flexible content field.

Any other fields that you want to set by default you need to first list the field key, and then your default value.

Finding Field Keys

You can find the field keys you need for this array in a couple of ways. You can go into your screen settings of the field group and toggle on the Field Keys

You can also go to a post that you have already created and want to use as default and output the $value variable. To do so you could add the following to your above filter:

echo ‘<pre>’;print_r($value); echo ‘</pre>’

Do this before you return early since the post has already been created. Then you’ll see an output of all the field keys and easily match them to the settings you want to set up as default.

However I prefer to use Kint for my debugging. Then you only have to add:

d($value);

Wrapping Up

ACF is full of extra filters for doing pretty much anything you can imagine. Check out the docs and support forums if you ever get stuck.

New Office & Desk

new office featured image

I’ve been working from home for almost a year we finally got around to setting up a better office. We have a three bedroom home and decided to swap the rooms we use as the office and the guest room. After a few years of living in a home you realize the initial decisions you made are not always the best.

We cleaned out what was our guest room and started with a clean slate to set up the best workspace. I also needed a new desk as the one I had been using was showing a lot of wear and tear.

For the desk I ended up getting an Ikea Kitchen Countertop, the BARKABODA. I got the 74x 1 1/2 inch desk which was plenty for what I needed. I used the same legs that I had on my previous desk. But I added a fifth to the middle of the back of the desk to provide extra support for the monitor stand. My monitor stand is the VIVO Dual LCD Monitor Desk Mount Stand. It has great mobility for the monitors and has the option to swivel them vertically if I have the need. The stand is very sturdy and I haven’t had any issues.

desk 2

I keep my 2017 MacBook Pro on a Giffin Desktop Stand to get the screen up for better visibility and airflow. Since I opted for the 256GB drive I got a USB-C Hard Drive Dock. The speed is great and works with my large IDE and SATA Drives that were in my old PC Tower.

I debating between getting a standing desk, or some sort of converter for a long time. I liked the look and size of the Barkaboda countertop and the price was much less than any standing desk that would be worth a damn. I opted instead to get a DeskCycle that fits right under the desk. I try to put in a couple hours a day on the cycle. I have found that when I’m reading documentation or trying to learn something difficult the cycling gets in the way.

Overall I’m happy with my new setup and look forward lots more productive work from home.

A Return to Television, sort of

skelton_switching

Almost a year has passed since I left the TV station and pursued Web Development work full time. Things are going great, but now I’m starting another journey that has led me back to television. I am now the TD for the Sacramento Kings games on NBC Sports California. For now I’m doing mostly the home games, but as the season goes on I’ll also work on the visitor shows.

I started training in December and I just finished my first game by myself so I guess that makes it official. I’m still doing all my web development work and just doing the home games for the Kings. TDing was always my favorite and doing live Sports is fast, exciting, nerve racking, but ultimately a lot of fun.

kings_basketball
Production Truck for NBCCA Kings Basketball

A big thanks to Ross for recommending me and everyone who helped along the way!

Books Read in 2017

2017 Shaped up to be a better reading year. Getting hooked to the Expanse and Red Rising series certainly helped. That and my new job allowed for a long vacation in December to get a lot of reading done.

The Well of Ascension – Brandon Sanderson

The impossible has been accomplished. The Lord Ruler — the man who claimed to be god incarnate and brutally ruled the world for a thousand years — has been vanquished. But Kelsier, the hero who masterminded that triumph, is dead too, and now the awesome task of building a new world has been left to his young protégé, Vin, the former street urchin who is now the most powerful Mistborn in the land, and to the idealistic young nobleman she loves.

As Kelsier’s protégé and slayer of the Lord Ruler she is now venerated by a budding new religion, a distinction that makes her intensely uncomfortable. Even more worrying, the mists have begun behaving strangely since the Lord Ruler died, and seem to harbor a strange vaporous entity that haunts her.

Stopping assassins may keep Vin’s Mistborn skills sharp, but it’s the least of her problems. Luthadel, the largest city of the former empire, doesn’t run itself, and Vin and the other members of Kelsier’s crew, who lead the revolution, must learn a whole new set of practical and political skills to help. It certainly won’t get easier with three armies – one of them composed of ferocious giants – now vying to conquer the city, and no sign of the Lord Ruler’s hidden cache of atium, the rarest and most powerful allomantic metal.

As the siege of Luthadel tightens, an ancient legend seems to offer a glimmer of hope. But even if it really exists, no one knows where to find the Well of Ascension or what manner of power it bestows.

Caliban’s War – James S.A. Corey

We are not alone.

On Ganymede, breadbasket of the outer planets, a Martian marine watches as her platoon is slaughtered by a monstrous supersoldier. On Earth, a high-level politician struggles to prevent interplanetary war from reigniting. And on Venus, an alien protomolecule has overrun the planet, wreaking massive, mysterious changes and threatening to spread out into the solar system.

In the vast wilderness of space, James Holden and the crew of the Rocinante have been keeping the peace for the Outer Planets Alliance. When they agree to help a scientist search war-torn Ganymede for a missing child, the future of humanity rests on whether a single ship can prevent an alien invasion that may have already begun . . .

Abaddon’s Gate – James S.A. Corey

For generations, the solar system — Mars, the Moon, the Asteroid Belt — was humanity’s great frontier. Until now. The alien artifact working through its program under the clouds of Venus has appeared in Uranus’s orbit, where it has built a massive gate that leads to a starless dark.

Jim Holden and the crew of the Rocinante are part of a vast flotilla of scientific and military ships going out to examine the artifact. But behind the scenes, a complex plot is unfolding, with the destruction of Holden at its core. As the emissaries of the human race try to find whether the gate is an opportunity or a threat, the greatest danger is the one they brought with them.

Cibola Burn – James S.A. Corey

The gates have opened the way to a thousand new worlds and the rush to colonize has begun. Settlers looking for a new life stream out from humanity’s home planets. Ilus, the first human colony on this vast new frontier, is being born in blood and fire.

Independent settlers stand against the overwhelming power of a corporate colony ship with only their determination, courage, and the skills learned in the long wars of home. Innocent scientists are slaughtered as they try to survey a new and alien world. The struggle on Ilus threatens to spread all the way back to Earth.

James Holden and the crew of his one small ship are sent to make peace in the midst of war and sense in the midst of chaos. But the more he looks at it, the more Holden thinks the mission was meant to fail.

And the whispers of a dead man remind him that the great galactic civilization that once stood on this land is gone. And that something killed it.

The Collapsing Empire – John Scalzi

Our universe is ruled by physics. Faster than light travel is impossible?until the discovery of The Flow, an extradimensional field available at certain points in space-time, which can take us to other planets around other stars.

Riding The Flow, humanity spreads to innumerable other worlds. Earth is forgotten. A new empire arises, the Interdependency, based on the doctrine that no one human outpost can survive without the others. It’s a hedge against interstellar war?and, for the empire’s rulers, a system of control.

The Flow is eternal?but it’s not static. Just as a river changes course, The Flow changes as well. In rare cases, entire worlds have been cut off from the rest of humanity. When it’s discovered that the entire Flow is moving, possibly separating all human worlds from one another forever, three individuals?a scientist, a starship captain, and the emperox of the Interdependency?must race against time to discover what, if anything, can be salvaged from an interstellar empire on the brink of collapse.

Nemesis Games – James S.A. Corey

A thousand worlds have opened, and the greatest land rush in human history has begun. As wave after wave of colonists leave, the power structures of the old solar system begin to buckle.

Ships are disappearing without a trace. Private armies are being secretly formed. The sole remaining protomolecule sample is stolen. Terrorist attacks previously considered impossible bring the inner planets to their knees. The sins of the past are returning to exact a terrible price.

And as a new human order is struggling to be born in blood and fire, James Holden and the crew of the Rocinante must struggle to survive and get back to the only home they have left.

The Hero of Ages – Brandon Sanderson

To end the Final Empire and restore freedom, Vin killed the Lord Ruler. But as a result, the Deepness–the lethal form of the ubiquitous mists–is back, along with increasingly heavy ashfalls and ever more powerful earthquakes. Humanity appears to be doomed.

Having escaped death at the climax of The Well of Ascension only by becoming a Mistborn himself, Emperor Elend Venture hopes to find clues left behind by the Lord Ruler that will allow him to save the world. Vin is consumed with guilt at having been tricked into releasing the mystic force known as Ruin from the Well. Ruin wants to end the world, and its near omniscience and ability to warp reality make stopping it seem impossible. She can’t even discuss it with Elend lest Ruin learn their plans!

Babylon’s Ashes – James S.A. Corey

A revolution brewing for generations has begun in fire. It will end in blood.

The Free Navy – a violent group of Belters in black-market military ships – has crippled the Earth and begun a campaign of piracy and violence among the outer planets. The colony ships heading for the thousand new worlds on the far side of the alien ring gates are easy prey, and no single navy remains strong enough to protect them.

James Holden and his crew know the strengths and weaknesses of this new force better than anyone. Outnumbered and outgunned, the embattled remnants of the old political powers call on the Rocinante for a desperate mission to reach Medina Station at the heart of the gate network.

But the new alliances are as flawed as the old, and the struggle for power has only just begun.

Red Rising – Pierce Brown

Darrow is a Red, a member of the lowest caste in the color-coded society of the future. Like his fellow Reds, he works all day, believing that he and his people are making the surface of Mars livable for future generations. Yet he toils willingly, trusting that his blood and sweat will one day result in a better world for his children.

But Darrow and his kind have been betrayed. Soon he discovers that humanity reached the surface generations ago. Vast cities and lush wilds spread across the planet. Darrow—and Reds like him—are nothing more than slaves to a decadent ruling class.

Inspired by a longing for justice, and driven by the memory of lost love, Darrow sacrifices everything to infiltrate the legendary Institute, a proving ground for the dominant Gold caste, where the next generation of humanity’s overlords struggle for power.  He will be forced to compete for his life and the very future of civilization against the best and most brutal of Society’s ruling class. There, he will stop at nothing to bring down his enemies . . . even if it means he has to become one of them to do so.

Golden Son – Pierce Brown

As a Red, Darrow grew up working the mines deep beneath the surface of Mars, enduring backbreaking labor while dreaming of the better future he was building for his descendants. But the Society he faithfully served was built on lies. Darrow’s kind have been betrayed and denied by their elitist masters, the Golds—and their only path to liberation is revolution. And so Darrow sacrifices himself in the name of the greater good for which Eo, his true love and inspiration, laid down her own life. He becomes a Gold, infiltrating their privileged realm so that he can destroy it from within.

A lamb among wolves in a cruel world, Darrow finds friendship, respect, and even love—but also the wrath of powerful rivals. To wage and win the war that will change humankind’s destiny, Darrow must confront the treachery arrayed against him, overcome his all-too-human desire for retribution—and strive not for violent revolt but a hopeful rebirth. Though the road ahead is fraught with danger and deceit, Darrow must choose to follow Eo’s principles of love and justice to free his people.

He must live for more.

Morning Star – Pierce Brown

Darrow would have lived in peace, but his enemies brought him war. The Gold overlords demanded his obedience, hanged his wife, and enslaved his people. But Darrow is determined to fight back. Risking everything to transform himself and breach Gold society, Darrow has battled to survive the cutthroat rivalries that breed Society’s mightiest warriors, climbed the ranks, and waited patiently to unleash the revolution that will tear the hierarchy apart from within.

Finally, the time has come.

But devotion to honor and hunger for vengeance run deep on both sides. Darrow and his comrades-in-arms face powerful enemies without scruple or mercy. Among them are some Darrow once considered friends. To win, Darrow will need to inspire those shackled in darkness to break their chains, unmake the world their cruel masters have built, and claim a destiny too long denied—and too glorious to surrender.

The Thousand-Dollar Tan – Rob Thomas

Ten years after graduating from high school in Neptune, California, Veronica Mars is back in the land of sun, sand, crime, and corruption. She’s traded in her law degree for her old private investigating license, struggling to keep Mars Investigations afloat on the scant cash earned by catching cheating spouses until she can score her first big case.

Now it’s spring break, and college students descend on Neptune, transforming the beaches and boardwalks into a frenzied, week-long rave. When a girl disappears from a party, Veronica is called in to investigate. But this is no simple missing person’s case; the house the girl vanished from belongs to a man with serious criminal ties, and soon Veronica is plunged into a dangerous underworld of drugs and organized crime. And when a major break in the investigation has a shocking connection to Veronica’s past, the case hits closer to home than she ever imagined.

Artemis – Andy Weir

Jasmine Bashara never signed up to be a hero. She just wanted to get rich.

Not crazy, eccentric-billionaire rich, like many of the visitors to her hometown of Artemis, humanity’s first and only lunar colony. Just rich enough to move out of her coffin-sized apartment and eat something better than flavored algae. Rich enough to pay off a debt she’s owed for a long time.

So when a chance at a huge score finally comes her way, Jazz can’t say no. Sure, it requires her to graduate from small-time smuggler to full-on criminal mastermind. And it calls for a particular combination of cunning, technical skills, and large explosions—not to mention sheer brazen swagger. But Jazz has never run into a challenge her intellect can’t handle, and she figures she’s got the ‘swagger’ part down.

The trouble is, engineering the perfect crime is just the start of Jazz’s problems. Because her little heist is about to land her in the middle of a conspiracy for control of Artemis itself.

Trapped between competing forces, pursued by a killer and the law alike, even Jazz has to admit she’s in way over her head. She’ll have to hatch a truly spectacular scheme to have a chance at staying alive and saving her city.

Jazz is no hero, but she is a very good criminal.

That’ll have to do.

Persopolis Rising – James S.A. Corey

An old enemy returns

In the thousand-sun network of humanity’s expansion, new colony worlds are struggling to find their way. Every new planet lives on a knife edge between collapse and wonder, and the crew of the aging gunship Rocinante have their hands more than full keeping the fragile peace.

In the vast space between Earth and Jupiter, the inner planets and belt have formed a tentative and uncertain alliance still haunted by a history of wars and prejudices. On the lost colony world of Laconia, a hidden enemy has a new vision for all of humanity and the power to enforce it.

New technologies clash with old as the history of human conflict returns to its ancient patterns of war and subjugation. But human nature is not the only enemy, and the forces being unleashed have their own price. A price that will change the shape of humanity — and of the Rocinante — unexpectedly and forever…

WordCamp Sacramento 2017 Photography

This year I took on the role of Photographer Wrangler on the organizing committee. That meant I reached out to all the volunteers who said they would help photograph the event and organized a schedule for everyone. We were a little short on volunteers so I ended up shooting both days and I had to jump around a lot of the talks. I got to see and hear a lot of the convention, but all in short bits. Here are the photos I submitted for both days of the event.

New Adventures

Today marks my final day working at a television station.

It’s been a long journey, with many interviews and jobs that I almost got. I’ve been working on my programming skills for several years. A little more than a month ago I got my first part-time Junior WordPress Developer position that I could do from home. It was the foot in the door I needed and the plan was to do that and the station until the next opportunity came along. As luck would have it that opportunity came about two weeks later. Another WordPress shop based out of Granite Bay needed developers.

I’ll be splitting my time between the two and already have plenty of work to keep me busy. After I get settled I’ll do some of the Granite Bay work remote as well. I’m very excited that both jobs are WordPress related so I can continue to build on my skills and contribute to the community. Last fall I gave my first tech talk at WordCamp Sacramento. While I don’t have a talk for this years WordCamp I did join the organizational committee and will be managing the photographer volunteers.

With the new jobs I’ll be able to wake at a normal hour and have weekend off. And have weekends off. And have weekends off! Between my jobs at the movie theater and the tv stations I’ve never had weekends. Pearl and I are looking forward to having a similar schedule and even making weekend trips (I’m looking at you Santa Cruz!).

I’m very happy for the time and opportunities I’ve had, but it’s time to make a change and look towards the future.

MAMP PRO for Local WordPress Development

I’ve used a few different options for local development on my laptop over the years. I’m at a transition point in my career and I thought I would take a minute to post on my workflow. I hope it helps others and serves as a reference point for me in the future.

For a while I used MAMP. Everything was subfolders of localhost and it worked. It wasn’t fancy but it gave me a working development environment to build and break things.

I remember when I updated my version of MAMP I screwed up and lost a lot of my local databases. Nothing lost was critical, but a lot of the learning projects I had built over the years. Because of this I was pretty frustrated with MAMP and I decided instead I should change my approach. I knew about VVV from listening to WordPress podcasts and it seemed like the right way to go.

Variable Success

VVV is great, though I’m not sure if I ever got the most out of it with my older laptop. I’m still rocking a MacBook Pro late 2009. It gets the job done and I’m looking for the next option but it never quite liked having Vagrant running. I remember the first time I used vagrant up it took FOREVER to download and run everything. When it finally started running I did enjoy using VVV as well as Variable VVV for site creation. The custom local domains and everything did work, for a while.

Over time I ran into more and more problems with VVV. It was either my Vagrant, or Oracle’s Virtual Server, or something else altogether. It’s quite possible I was doing something wrong, but I never did figure it out. One day several sites stopped working and no amount of restarting could alleviate the problem.

I tried to use Desktop Server, but it saw that I had another virtual machine installed on my computer. Even though I had deleted everything Desktop Server would never let me install.

By this point I need something that would work. I decided to throw some money at the problem and ponied up for MAMP PRO.

The main issue I have with MAMP is the lack of good documentation. There some info on their site and now that I have things running I’m having a good time. I hope this post will help others who look for ways to get the most out of the MAMP PRO software.

MAMP PRO Workflow

I started a new remote position about a month ago and many of the projects are editing existing websites. This meant I first needed to get a working local copy of the website. And several of them are HTTPS.

MAMP PRO has a easy way to set a server to use https. When making a new site or changing an existing one you can go to the SSL tab and check the box to turn on SSL. If you have certificate files you could point to them, or you can “Create self-signed certificate…” which lets you setup your own local certificate. Enter any info, it doesn’t matter. When you open the site in browser it will warn you saying that the certificate isn’t secure. You agree that you understand it will continue to the site and work as normal.

mamp-pro-ssl

Apache or Nginx

A nice feature of MAMP PRO is the ability to individually select Apache or Nginx for each site. I started with doing everything as Apache as that’s what I’m used to and it made the transition easy. But I ran into a situation where switching to Nginx was a game changer.

The development sites all had repositories for the theme and I used WP Migrate DB PRO to pull down the database. But instead of downloading all the images they use an Nginx directive to rewrite the file locations to point everything to the live server.

Local Development, Remote Images

In the Nginx tab of MAMP PRO you can add extra parameters for the directive. Here I add

location ~ ^/wp-content/uploads/(.*) {
  if (!-f $request_filename) {
    rewrite ^/wp-content/uploads/(.*)$ http://www.websitename.com/wp-content/uploads/$1 redirect;
  }
}

After the location tag is a regex. It’s looking at any file request that has a beginning, then references /wp-content/uploads/. Then collects whatever comes afterward. If it’s a filename being requested we rewrite that same regex and change it to the live site and use that saved file extension from the search.

Now you don’t have to deal with downloading years worth of images from an existing website.

mamp-pro-nginx

I found that this works, but with Nginx I have an issue with any of my links. They all lead to 404’s. While still in the Nginx tab add the following to the try_files parameter

$uri $uri/ /index.php?q=$uri$args;

This line uses Nginx’s rewrite rules to work with WordPress routing and run everything through index.php. It also keeps the arguments that are part of the url. The $uri here is commonly used to represent everything after the domain name in the URL.

MAMP Bonus

Another bonus to using MAMP is the ability to install “Extras” which include WordPress. With a couple clicks you can install, and setup a database for your WordPress development. Combo this with some command line skills to pull down your favorite WordPress starter theme and you’re all set to build new and exciting WordPress sites.

There is a file that is created in the root directory called extras to show an icon in your MAMP Hosts for each extra you have installed. It’s a little annoying and I normally delete it or just include in my gitignore.

Is anyone else out there using MAMP Pro for your local WordPress development?

Local Timings Application

local-timings-featured

In my day job working at a local television station I spend time in Master Control monitoring our five stations that we broadcast. Two of these are sub-channels that play out old movies and tv shows from a network feed. The network sends a pulse when its time for our local break to air and for the most part it works without problem.

But occasionally a break is missed.

We can get a PDF of that days log and find the exact time our break should roll from the affiliate portal. Then we have to search the log to find the line that is for the local break. Some people prefer to do this ahead of time and leave notes in the playlist so we know when a break is approaching and when it’s been missed.

To do so they would print out a ~30 page PDF and go through manually finding all the local times.

I knew this repetitive task was asking for some automation.

Basic Structure

Since the application was going to be so small I decided to start from scratch and not use any framework. I would use a simple form to upload the PDF file and then use PHP to work with the uploaded file.

I knew I needed to parse the PDF so I found pdfparser by Sebastien Malot. This takes the PDF file and converts it into one giant string.

Now I needed to search through that text and pull out all of the local break times.

The Regex

$regex = "/([0-9]{1,2}:[0-9]{2}:[0-9]{2})\s(AM|PM|XM)\s{0,1}\*{3}\s{0,3}\ *{1,2}LOCAL.*?([0-9]{1,2}:[0-9]{2})/";

The text that I would need to search for is:

8:18:03 AM *** *LOCAL AFFILIATE BREAK 2:00 ***

First I need to grab the time that break occurs, allowing for the first digit to be one or two numbers in length. Then I need to collect the AM, PM, or XM (side note: our logs begin at 4am so the hours from midnight until 4am are referred to as XM).

The stars and spaces after the time are not consistent across different days so I needed to allow for some variance in their number. I only search for the work LOCAL because some breaks are LOCAL/CABLE breaks which we also get, so I include the .*? regex to find everything until the next time.

Then I collect the length of the break similarly to the collecting of the first time.

Here is my final regex:

Some of the problems were found after a couple days of testing so I had to update it when the results were no longer consistent. I used preg_match_all to find all the matches and assign it to a new array that I could loop through to print to the screen.

Loading Spinner

At first I used a simple css spinner for the loading process. Because the PDF file is large it can take 5-10 seconds before the final results are printed. Since there was so much time I wanted to make a fancier loader and made this little guy:

See the Pen TV Color Bars Loading Screen by Anthony Skelton (@ajskelton) on CodePen.

I use a simple onClick javascript event that adds a full screen div with the above svg. It’s not vital to the project but it does make it fun.

The Code

If you want to see the project or use it for your own purpose check it out on github. Be warned I did a lot of it quickly and didn’t spend a lot of time cleaning up things. It works great so I don’t really need to go back to it unless I want to practice some refactoring.

Book Read in 2016

books-read-in-2016

I didn’t read as many books this year but the ones I did were great. I finished reading the Silo series, started the Mistborn and Expanse series. Here are all the books and their descriptions.

Shift – Hugh Howey

In 2007, the Center for Automation in Nanobiotech (CAN) outlined the hardware and software platforms that would one day allow robots smaller than human cells to make medical diagnoses, conduct repairs, and even self-propagate. In the same year, the CBS network re-aired a program about the effects of propranolol on sufferers of extreme trauma. A simple pill, it had been discovered, could wipe out the memory of any traumatic event. At almost the same moment in humanity’s broad history, mankind discovered the means for bringing about its utter downfall. And the ability to forget it ever happened. This is the second volume in the New York Times best-selling Wool series.

The Final Empire – Brandon Sanderson

For a thousand years the ash fell and no flowers bloomed. For a thousand years the Skaa slaved in misery and lived in fear. For a thousand years the Lord Ruler, the “Sliver of Infinity,” reigned with absolute power and ultimate terror, divinely invincible. Then, when hope was so long lost that not even its memory remained, a terribly scarred, heart-broken half-Skaa rediscovered it in the depths of the Lord Ruler’s most hellish prison. Kelsier “snapped” and found in himself the powers of a Mistborn. A brilliant thief and natural leader, he turned his talents to the ultimate caper, with the Lord Ruler himself as the mark.

Dust – Hugh Howey

Juliette, now mayor of Silo 18, doesn’t trust Silo 1, especially its leader, Donald. But in the world of the Silos, there is no black and white — everything is shades of gray. Donald may not be the monster Juliette thinks he is, and may in fact be key to humanity’s continued survival. But can they work together long enough to succeed?

Sharp Objects – Gillian Flynn

Fresh from a brief stay at a psych hospital, reporter Camille Preaker faces a troubling assignment: she must return to her tiny hometown to cover the murders of two preteen girls. For years, Camille has hardly spoken to her neurotic, hypochondriac mother or to the half-sister she barely knows: a beautiful thirteen-year-old with an eerie grip on the town. Now, installed in her old bedroom in her family’s Victorian mansion, Camille finds herself identifying with the young victims—a bit too strongly. Dogged by her own demons, she must unravel the psychological puzzle of her own past if she wants to get the story—and survive this homecoming.

Armor – John Steakley

The planet is called Banshee. The air is unbreathable, the water is poisonous. It is home to the most implacable enemies that humanity, in all its interstellar expansion, has ever encountered.

Body armor has been devised for the commando forces that are to be dropped on Banshee—the culmination of ten thousand years of the armorers’ craft. A trooper in this armor is a one-man, atomic powered battle fortress. But he will have to fight a nearly endless horde of berserk, hard-shelled monsters—the fighting arm of a species which uses biological technology to design perfect, mindless war minions.

Felix is a scout in A-team Two. Highly competent, he is the sole survivor of mission after mission. Yet he is a man consumed by fear and hatred. And he is protected, not only by his custom-fitted body armor, but by an odd being which seems to live within him, a cold killing machine he calls “The Engine.”

This is Felix’s story—a story of the horror, the courage, and the aftermath of combat, and the story, too, of how strength of spirit can be the greatest armor of all.

Oryx and Crake – Margaret Atwood

Oryx and Crake is at once an unforgettable love story and a compelling vision of the future. Snowman, known as Jimmy before mankind was overwhelmed by a plague, is struggling to survive in a world where he may be the last human, and mourning the loss of his best friend, Crake, and the beautiful and elusive Oryx whom they both loved. In search of answers, Snowman embarks on a journey–with the help of the green-eyed Children of Crake–through the lush wilderness that was so recently a great city, until powerful corporations took mankind on an uncontrolled genetic engineering ride. Margaret Atwood projects us into a near future that is both all too familiar and beyond our imagining.

Zoo City – Lauren Beukes

Zinzi has a Sloth on her back, a dirty 419 scam habit, and a talent for finding lost things. When a little old lady turns up dead and the cops confiscate her last paycheck, Zinzi’s forced to take on her least favorite kind of job–missing persons.

Being hired by reclusive music producer Odi Huron to find a teenybop pop star should be her ticket out of Zoo City, the festering slum where the criminal underclass and their animal companions live in the shadow of hell’s undertow. Instead, it catapults Zinzi deeper into the maw of a city twisted by crime and magic, where she’ll be forced to confront the dark secrets of former lives–including her own.

Leviathan Wakes – James S.A. Corey

Two hundred years after migrating into space, mankind is in turmoil. When a reluctant ship’s captain and washed-up detective find themselves involved in the case of a missing girl, what they discover brings our solar system to the brink of civil war, and exposes the greatest conspiracy in human history.

Theft of Swords – Michael J. Sullivan

There’s no ancient evil to defeat or orphan destined for greatness, just unlikely heroes and classic adventure. Royce Melborn, a skilled thief, and his mercenary partner, Hadrian Blackwater, are running for their lives when they’re framed for the murder of the king. Trapped in a conspiracy that goes beyond the overthrow of a tiny kingdom, their only hope is unraveling an ancient mystery before it’s too late.

Legend – Marie Lu

What was once the western United States is now home to the Republic, a nation perpetually at war with its neighbors. Born into an elite family in one of the Republic’s wealthiest districts, fifteen-year-old June is a prodigy being groomed for success in the Republic’s highest military circles. Born into the slums, fifteen-year-old Day is the country’s most wanted criminal. But his motives may not be as malicious as they seem.

From very different worlds, June and Day have no reason to cross paths – until the day June’s brother, Metias, is murdered and Day becomes the prime suspect. Caught in the ultimate game of cat and mouse, Day is in a race for his family’s survival, while June seeks to avenge Metias’s death. But in a shocking turn of events, the two uncover the truth of what has really brought them together, and the sinister lengths their country will go to keep its secrets.

Rediscover Theme Settings with the WordPress Customizer

Rediscover Theme Settings with the WordPress Customizer

Image above taken by Stewart Savage of Abaton Consulting.

This article is a companion piece to my talk at WordCamp Sacramento 2016 of the same title.

The WordPress Customizer became included into core in version 3.4. Over the years it has seen many improvements to use and functionality. It is a tool for previewing changes to your site before you commit them. For new users the most common uses are for the Site’s name and Description. Adjusting colors and managing Menu’s and Widgets are also popular. The default WordPress Customizer has many useful settings and the ability to add and even create our own makes the future exciting.

What is the Customizer?

As I prepared to give this talk at WordCamp Sacramento 2016 it surprised me how many times people asked this question. Many of the attendees and other WordCamp Speakers had no experience using the Customizer, even the default settings in core.

After hearing this I put together the following clip to open my talk. It shows the interface and some examples of things the Customizer can do. Changing the title or description of the site, changing colors, reordering widgets, etc.

WordPress Customizer Example

Accessing the Customizer is easier than ever. You can get to it via the dashboard under the Appearance section. Or while logged in and browsing the site the Customize button appears next to the Dashboard button in the admin bar. When you use this link you’ll open the Customizer and preview the page that you were currently on.

The Customizer is everything

At last years inagural WordCamp US Matt Mullenweg talked about the Customizer and his view of it’s importance. He said customization is the biggest opportunity for improving new user experience. During this summer Jeff Chandler from WP Tavern asked Matt to expand on this. Here’s an excerpt from that interview:

Jeff ChanlerAt WordCamp US you said that Customization is the single biggest opportunity for improving the WordPress experience, and I wanted to know, could you expand on this? And how important is the Customizer in this regard?

Matt MullenwegThe Customizer is everything.

JC – Really?

MM – Yeah. You know, I think that the Customizer is definitely, like if I think about leading a release, I could see the Customizer being a main focus of it. You know? That, it’s so important to the user experience of someone new to WordPress especially, but also to everyone who uses WordPress day to day, and it’s also probably our weakest area to be honest. I mean, it’s had a ton of work, it’s so much better than it was, but if you just look at like we’re only as strong as our weakest link, and right now I think our weakest link in user experience is the customization—it’s not just the Customizer it’s also themes—but the customization of the frontend of someone’s site

Here is the link to the entire podcast.

At the end he hints at the need for customization on the front-end. I think this is the direction that the Customizer is heading, but more on that later.

Getting Started With The Customizer

To make any changes or additions to the Customizer we use the customize_register hook.

function themeslug_customize_register( $wp_customize ) {
  // Add/Get/Remove Customizer Settings
}
add_action( 'customize_register', 'themeslug_customize_register' );

The function you hook in needs to include the $wp_customize argument as this is the WordPress Customize Manager object. This bootstraps the WordPress Customizer experience and serves as the factory to create controls and settings.

It’s best practice to create this function in a customize.php file that you have an an /inc/ folder of your theme/plugin. But there is no requirement to use the Customizer other than using the aforementioned hook.

There are four main Customizer objects that you will access from the Customize Manager: Panels, Sections, Settings, and Controls. Each Object has three methods, add, get, and remove, that you use to make any changes.

Panels are the highest level of hierarchy and hold one or more sections.

Sections hold one or more setting and will not display until there is at least one setting. Panels wont display until one of their sections has a setting.

Setting and Controls are dependent on each other. The Control is the user input and settings determine how that control saves to the database.

Remove

Within the function you can begin to make your changes to the Customizer. WordPress sets up several sections and panels by default. You can remove them if you don’t need them or want to recreate the functionality.

$wp_customize->remove_setting( 'blogname' );

By accessing the Customize Manager and using remove_setting we can pass in an id of a section to remove it from the Customizer. You could remove a panel, setting, or control the same way.

Get

The Get method lets you change parameters that have already been set either through the defaults or one added by a parent theme. Here is an example of how TwentySixteen uses the get method.

$wp_customize->get_setting( 'blogname' )->transport = 'postMessage';
$wp_customize->get_setting( 'blogdescription' )->transport  = 'postMessage';

When you pass in an id the method returns the object you requested. Then you can access any of that objects properties. You could save this to a variable, or in this example change the value of the transport property to postMessage.

Adding to the Customizer

The add method is how we add our own panels, sections, settings and controls to the Customizer. Lets dive in to each one and look at the properties required.

Adding a Panel

$wp_customize->add_panel(
    'panel_id',
    array(
        'priority'   	   => 160,
        'title'      	   => __( 'Panel Title' ), 
        'description'	   => __( 'Panel Description' ),
        'capability' 	   => 'edit_theme_options',
    )
);

The ability to add a new panel to your top level hierarchy came in WordPress 4.0. While you can do this, it’s not recommended for your themes. Panels should provide a specific contextual areas of WordPress like Menus and Widgets. If you’re creating a plugin that has several sections about one specific area then it would be a good option.

The priority determines the placement in the top level hierarchy. Each section and panel already added by WordPress has their own priority, and we’ll see a list of those later.

For themes it is recommended to use the default sections and create your own sections based on the content you are changing.

Adding a Section

$wp_customize->add_section(
    'section_id',
    array(
        'priority'        => 10,
        'title'           => __( 'Section Title' ),
        'description'     => __( 'Section Description' ),
        'panel'           => '',    
        'active_callback' => '',
    )
);

Sections hold one or many controls. You can add your own controls to the core sections or create your own. In most cases your section only needs a couple parameters. Title and perhaps priority if you have a particular place you want to place the section. By default your sections begin below the core sections.

The panel property is only needed if you want to include this section in a specific panel. Also the active_callback property is only needed if you want to display it based on other factors. We’ll cover active_callback more in a bit.

The sections and panels in WordPress core are as followed:

Title ID Priority (Order)
Site Title & Tagline title_tagline 20
Colors colors 40
Header Image header_image 60
Background Image background_image 80
Menus (Panel)* menus 100
Widgets (Panel) widgets 110
Static Front Page static_front_page 120

If you want to add to or remove a section you can access it with the ID. If you want to remove the Menu panel it requires more than just remove_panel(‘menus’). Check out this stack overflow article for more information on removing the panel.

Adding a Setting and Control

$wp_customize->add_setting(
    'setting_id',
    array(
        'type' => 'theme_mod',
        'capability' => 'edit_theme_options',
        'theme_supports' => '',
        'default' => '',
        'transport' => 'refresh',
        'sanitize_callback' => '',
        'validate_callback' => '',
    )
);

Settings handle the live-previewing, saving, sanitation and validation.

  • Type is how it’s saved into the database
  • Capabilities are who has access to the setting
  • Theme Supports not commonly necessary
  • Default is a default value to display
  • Transport controls live previewing options
  • Sanitize_Callback will sanitizing the value before it saving to the database
  • Validate_Callback will confirm the value before attempting to save
$wp_customize->add_control(
    'setting_id',
    array(
        'priority' => 10,
        'label' => _( 'Control Label' ),
        'description' => _( 'Control Description' ),
        'type' => 'text',
        'section' => 'section_id',
        'input_attrs' => array(),
        'active_callback' => '',
    )
);

The Control creates the User Interface that the user will interact with to make changes.

  • Type creates the UI for the customizer
  • Section is the section the control should appear in
  • Input_Attrs are attributes you can give to the Input HTML element.
  • Active_Callback is a contextual control of display

The control type property tells the Customizer what type of UI to generate for the user. This could be a textbox, a set of radio options, or even an image selector. There are many basic and advanced types built into core, here are most of the basic ones:

text textarea date
range url email
password hidden checkbox
radio select dropdown-pages
number time datetime
week search

Advanced types need a little extra work to use and we’ll cover those in a moment. You can also create your own types.

theme_mod vs. option

While the control type creates the ui for the user, the setting type tells the Customizer how the input saves to the database.

theme_mod

Settings saved with theme_mod are tied to the current active theme. Each time you activate a theme WordPress creates a new row in the wp_options table as theme_mods_THEMENAME. All your settings using theme_mod save into an array in this row. This is the default for all settings that you add to the Customizer.

When you change your theme you’ll lose all these changes, but when you switch back everything returns.

option

The option type will save each setting in the wp_options table. The setting ID you assign will be the name of the new table row. This type is not recommended by WordPress for Customizer settings added to themes. If you change your theme the settings will stay. If you’ve added the settings to the Customizer in your theme than the options will not be visible to the user.

If you want to add settings to the Customizer that will work for the user cross-themes you should use a plugin.

Transport Property

The transport property is how the customizer previews new values.

Refresh

Using a full page refresh is the default property for new settings. This was all we had when Customizer became a part of core. The good thing about refresh is it is accurate and doesn’t need any extra code to get working. The user changes the value in the Customizer and the preview screen refreshes to show the changes.

The downside is the page refreshes after every little change. And if the page has a lot of elements the load time could be slow and annoying for the user.

postMessage

With postMessage any change no longer triggers a full page refresh. Instead the Customizer makes an asyncronous request. The new values go to the preview window and you need to update the preview using Javascript. Seeing the updates live gives a better user experience. But it does need a little more setup and in some cases you are duplicating your logic to render the page.

Transport properties in action

Below is a simple example of a user updating a text field and how it updates using the two transport types.

WordPress Customizer Refresh Example
WordPress Customizer Refresh Example

 

WordPress Customizer PostMessage Example
WordPress Customizer PostMessage Example

 

Using postMessage

To utilize the live updating of postMessage we’ll need to enqueue a Javascript file using the customize_preview_init hook. This way our file is only loading when using the Customizer.

function thememod_preview_js() {
     wp_enqueue_script(
        'custom_css_preview',
        'path/to/file.js',
        array( 'customize-preview', 'jquery' )
     );
 }
 add_action( 'customize_preview_init', 'thememod_preview_js' );

When you enqueue the file you’ll need to include two dependencies, jQuery and customize-preview. The later will include the Customize Manager Object that will give us access to the Customizer settings.

Here is some boilerplate Javascript that you can use to set up your postMessage setting.

( function( $ ) {

  wp.customize( 'setting_id', function ( value ) {
    value.bind( function( to ) {
      $( '#custom-theme-css' ).html( to );
    } );
  } );

} )( jQuery );

The wp object gives us access to the customize method in our Javascript. This is similar to the $wp_customize->method we were using in PHP.

Here we pass in the setting_id and a callback function. The callback function takes the value which is the original value. We use bind so that when it changes we target a CSS selector and update the html to the new value.

You could also use this to update CSS or toggle a class. You could do more complicated logic, but you don’t want to go overboard with postMessage. There is a new tool since WordPress 4.5 that makes updating complicated logic easier, and that is Selective Refresh.

Selective Refresh

Added in WordPress 4.5 we can now refresh just an area that we have linked to a setting. This is less disruptive than a full frame refresh. It also allows you to use the same PHP that you wrote to add the elements to the page in the first place.

To use Selective Refresh you need to register a partial that creates a link between your setting and a CSS Selector on your page.

NOTE: This partial is different than a PHP partial that we might include in a page as part of a template part.

$wp_customize->selective_refresh->add_partial( 
     'partial_id',
     array(
         'settings' => 'partial_id'
         'selector' => '#css-selector',
         'container_inclusive' => false,
         'render_callback' => function() {
             // function name or php logic
         },
         'fallback_refresh' => true
    )
 );

Creating a partial is like adding a setting except that you use the selective_refresh method as well as the add_partial method of that object.

You give your partial an ID, and you also declare this same ID in the settings parameter. But if you don’t include the settings parameter it will default to what you have already set as the partial ID.

  • Selector is the element in the page that we want to link to. If you use a selector that has many entities on the page it will only select the first one.
  • Container Inclusive is a booleon value. True means that you want to refresh the parent node as well as it’s children instead of just the children.
  • Render Callback is your PHP logic to update the page. You could do an anonymous function, or pass in the name of a function you have already created.
  • Fallback Refresh simple says that if it can’t find the CSS selector than it will do a full page refresh.

Note that you’ll need to keep your transport property set to postMessage. Otherwise the preview will perform a full page refresh no matter what.

A Selective Refresh Example

Lets take a closer look at creating a new setting that uses Selective Refresh. Selective Refresh allows us to do more than just update a value. We can render our content through a function and see the effect update.

First we need to add a setting and a control to work with:

$wp_customize->add_setting( 
     'backwardstext_setting_id',
     array(
         'capability' => 'edit_theme_options',
         'transport' => 'postMessage',
         'default' => 'Lorem Ipsum',
     )
 ); 

 $wp_customize->add_control( 
     'backwardstext_setting_id',
     array(
         'type' => 'text',
         'priority' => 10,
         'section' => 'custom_section', 
     )
 );

Then we add our partial

$wp_customize->selective_refresh->add_partial( 
    'backwardstext_setting_id',
    array(
        'selector' => '.backwards-text',
        'render_callback' => 'ajs_customizer_partial_backwardstext',
    )
);

You’ll notice a couple things when you look at these example code blocks. First, I use the same ID for my Control, Setting, and Partial. This works, and I prefer it to better organize my code.

Next I reference a new function called ajs_customizer_partial_backwardstext. Let’s make that now.

function ajs_customizer_partial_backwardstext() {
    echo strrev(get_theme_mod('backwardstext_setting_id'));
}

I’m getting the value of my setting from the database. Then reversing the string and echoing out the content. I’ve used this function in the page template to display the initial value.

This isn’t a practical example. But it shows you that the content is rendering through my function. Here’s what it looks like as I update the value in the Customizer.

WordPress Customizer Selective Refresh Example
WordPress Customizer Selective Refresh Example

Only the paragraph tag that has the class .backwards-text is refreshing. It’s using my function to reverse the string before it prints it to the screen.

More Selective Refresh Benefits

Now that we have a link created between the WordPress Customizer control and a section of the page we have a few more features that Selective Refresh adds.

The first allows you to shift-click on the element in the preview window and the Customizer will jump to and focus on that setting.

WordPress Customizer Selective Refresh Shift Click Example
WordPress Customizer Selective Refresh Shift Click Example

This is great, but it’s not obvious. I expect more work done to let users know about this feature either with hover states on partials or indicators next to the partial.

There is another benefit, but it deals with Validation which we’ll get to in a little bit.

Contextual Controls

Sections and Controls both have the active_callback parameters to control when displayed.

WordPress Customizer Contextual Control

 

The above example shows a Front Page Section that disappears when the Customizer Preview changes to a different page. When you are in a section that becomes no longer visible the Customizer Panel moves back to the main panel.

'active_callback' => 'is_front_page'

// or

'active_callback' => function() {
    return is_page();
}

The parameter can take either the name of a function, or an anonymous function as long as it returns a truthy value. WordPress includes many conditional functions that you can use like my use of is_front_page above.

You can do this with an entire section, or just an individual control. You can also base the context not on a page, but on the value of another control.

Otto has a great example that I used during my talk, but you can read about it on his page.

Customizer Sanitization

Any content that you let users add to the database must be sanitized. WordPress has some built in functions that you can use, but to be as safe as possible it would be better to create your own sanitization function.

Here’s an example of using a WordPress function:

'sanitize_callback' => 'sanitize_text_field'

This would work great for simple text fields or text areas. There is also sanitize_hex_color for other simple customizer values.

But if you have a radio or select field there isn’t a default way to know what your values are to sanitize them. Let’s set up a radio setting and sanitization function.

$wp_customize->add_setting( 'radio_setting_id', array(
    'default' => 'blue',
    'sanitize_callback' => 'thememod_customizer_sanitize_radio',
) );

$wp_customize->add_control( 'radio_setting_id', array(
    'type' => 'radio',
    'section' => 'custom_section',.
    'label' => __( 'Custom Radio Selection' ),
    'description' => __( 'This is a custom radio input.' ),
    'choices' => array(
        'red' => __( 'Red' ),
        'blue' => __( 'Blue' ),
        'green' => __( 'Green' ),
    ),
) );

function thememod_customizer_sanitize_radio( $input ) {
    $valid = array(
        'red' => __( 'Red' ),
        'blue' => __( 'Blue' ),
	'green' => __( 'Green' ),
    );

    if( array_key_exists( $input, $valid ) ) {
	return $input;
    } else {
	return '';
    }
}

We’ve added a control with three radio options, red blue and green. We also declared our sanitize_callback and wrote the function below. This function takes the $input of what the user entered in the field.

In our sanitize function we first setup a new array of what the valid responses could be. This would be dependent on your own options. Then we check if the array key from the input value is found within that valid array. If it is we return it, otherwise we return an empty string.

One problem with Sanitization is when the input is bad an unexpected value returns.  Another example could be the user didn’t input a correct email address. The sanitized value saves and the user isn’t given an information about what went wrong. Validation added in WordPress 4.6 fixes this problem.

Customizer Validation

Validation checks the validity of the values. If an error occurs it returns the dirty values, notifies the users, and the data is never sent to the database. In fact if one setting has a validation error nothing saves.

The Customizer also jumps to a section that has a validation error if the user has moved to another panel or section in the Customizer.

Lets take a look at an example from the WordPress handbook, setting up an established year setting.

'validate_callback' => 'validate_established_year'

//

function validate_established_year( $validity, $value ) {
    $value = intval( $value );
    if ( empty( $value ) || ! is_numeric( $value ) ) {
        $validity->add( 'required', __( 'You must supply a valid year.' ) );
    } elseif ( $value < 1900 ) {
        $validity->add( 'year_too_small', __( 'Year is too old.' ) );
    } elseif ( $value > gmdate( 'Y' ) ) {
        $validity->add( 'year_too_big', __( 'Year is too new.' ) );
    }
    return $validity;
}

We pass in two variables to our Validation function, $validity and $value.

The $value is what the user entered into the control similar to Sanitation. $validity will add any errors that occur in the validation, if it returns empty than no validation errors have occurred.

In this example we first do a little sanitation making sure the value is positive integer. Then we check to make sure it is a number. If not we use the $validity->add method with two parameters. The first is the id of the error, the next is the text displayed to the user in a notification.

After checking to make sure the value exists, we check if it is lower than 1900 or greater than the current year. $validity return errors if either are true.

You can do this with any of your settings. This adds a level of communication with users as they add content to the customizer.

WordPress Customizer Validation

Here is that example in action. When I hit Save & Publish the Customizer jumps back to the section that had the error and gives me the notification. When I fix the error and click Save again, the notification goes away. The Saved & Publish button changes to Saved, showing the save was successful.

It would be better if the error went away as soon as the user fixed the issue instead of having to hit save and publish the changes.

This is possible and it’s thanks to Selective Refresh

Validation with Selective Refresh

Earlier I mentioned that Selective Refresh creates a link between the preview and the control. Every time the refresh occurs the control goes through validation.

When an error occurs the notification will appear and the dirty value will remain in the input. However in the preview it will revert to the last saved value.

After the user fixes the error than the Customizer removes the notification.

Lets set up selective refresh with the above example.

$wp_customize->selective_refresh->add_partial(
    'established_year',
    array(
        'selector' => '.established-year',
        'render_callback' => 'thememod_established_year',
    )
);

function thememod_established_year() {
    echo get_theme_mod('established_year');
}

First I register the partial for the established year setting and assign a css selector to link with the page. I have a span tag with this class that wraps around the year.

My render callback is simple echoing the value from the database.

WordPress Customizer Validation with Selective Refresh

As soon as I make the date too old or too new the error notification appears and the value in the preview reverts to 1900, which was the last saved value.

The Future of the WordPress Customizer

The Customizer has seen lots of improvements over the past few versions. As I’m writing up this post 4.7 is nearing completion and it’s adding even more. Here is the slate:

  • Customize Changesets (transactions)
  • Create pages in menus
  • Improve sliding panel UI
  • Custom CSS

Changesets will be a big change. They will allow you to save a draft of your customizations and share those changes with another person before publishing. Also Custom CSS in the core Customizer will be a great addition for small theme-specific CSS. Many people already use plugins to add this functionality and Jetpack has had this as well. The main challenge that be the difference between a theme-specific and site-specific changes used to add styling.

I will write up more about these changes when 4.7 launches.

Missing Pieces

Having now done my talk and written this companion piece I found quite a few things that I should have included. I didn’t talk much about using Javascript to connect to the Customizer API. I also didn’t do much with advanced types like Image Uploads.

As I dig into the Customizer I plan to write more posts about all the features and tools available. I’ll also write about new features that get added to any future releases.

Until then, Happy Customizing.