In concrete5 version 5.3.0, we introduced a centralized content repositories called scrapbooks. Here you could add Blocks in one spot, and then paste them throughout your site. Most CMSs start this way, but our focus on in-context editing lead us to add this later. We're glad we did, though – scrapbooks solved a very real problem. For centralized Blocks like Auto-Navs, megamenus, navigation menus or global images, a scrapbook approach makes sense.
Here's a screenshot of a list of all scrapbooks in the system:
Here's a list of all Blocks in a selected scrapbook:
Finally, here's an example of adding a Block from one of the scrapbooks to a page:
Finally, scrapbooks let you name a Block, and then refer to that Block with PHP code. Making changes to the Block through the scrapbook would update all places where that code existed:
$b = Block::getByName('Header Menu');
Scrapbooks were cool. They enabled a large number of third party add-ons to do neat things.
What was wrong with Scrapbooks?
Unfortunately, we didn't give scrapbooks the time or attention to completely shine:
- They were buggy.
If you take a look at bugs reported from 5.3.0 to 184.108.40.206, many of them had to do with the scrapbook. These were frequently cache-related, and we never really got rid of them all. While there have been a few small items regarding Stacks since the release of 5.5.0, they are much smaller in number and much easier to reproduce, understand and fix.
They were insufficiently architected.
While we knew, in a general sense, how we wanted to tackle the problem of centralized content, we didn't put enough effort into naming the feature, designing its interfaces, or figuring out how it would work under the hood.
They were limited by previous decisions. Before 5.3.0, scrapbooks still existed as a simple way to copy Blocks around the site. We piggybacked on this feature with "global scrapbooks," and the whole thing got out of control from that point. Users couldn't paste the same Block into the same area more than once, nor could they add the same Block from the global scrapbook to the same area more than once.
They were confusing.
These limitations made scrapbooks hard to understand. Users had to know the difference between "global scrapbooks" and "personal scrapbooks" and had to understand why they couldn't paste Blocks more than once. Since we hadn't given enough thought to the entire experience, you'd see dialogs like this one, when working with scrapbooks:
You could spend ten minutes reading this dialog and still not know exactly what's going on.
- They only worked with individual Blocks.
When adding a Block from a global scrapbook, only an individual Block could be added to a page. You couldn't reference an entire scrapbook. Yes, third party add-ons could extend this functionality, but defaults matter.
Introducing Clipboard & Stacks
With 5.5, we decided to take what we'd learned from the scrapbook, rebuild it completely and solve all the problems we hadn't anticipated when 5.3.0 came out. We split personal scrapbooks into the Clipboard, which is just a simple way to copy existing Blocks and paste them around a site. We moved global scrapbooks into Stacks, which appear like this in the Dashboard:
You can add the entire contents of a Stack into a page with a simple command:
What is right with Stacks?
A Fresh Approach
Splitting these two items into completely separate experiences allowed us to streamline both of them, and remake Stacks in a scalable way.
Fundamentally, global scrapbooks were different areas on one page in the dashboard; with Stacks, each Stack is a page in the dashboard. This means the versions of a Stack can be tracked independently, without impacting the approved contents of another Stack.
Stacks also let us solve another long-standing problem with concrete5: the lack of global Area support. Global Areas are areas defined in a theme's template which, when added to, display the same Blocks wherever they are, on every page. These are great for login Blocks, site-wide navigations or logos, or copyright text:
Any time you define a global Area within a theme's template, a stack for it is created automatically. You can then manage the contents of this Area from within the site, or on the Stacks Dashboard page.
Defining a global area is easy. It's almost exactly like a regular area:
$ga = new GlobalArea('Header Nav');
Before 5.5, the Global Scrapbook was simply a page in the dashboard. Since global scrapbook Blocks were just Blocks added to this page, sometimes you could add Blocks that wouldn't be viewable on the main page, because permissions on the global Scrapbook page are understandably set to only allow administrators to view them. In 5.5, the Stacks Dashboard page is only viewable by administrators, but the stacks themselves are special concrete5 pages that live outside of the Dashboard. This means their permissions are inherited from the home page (or from the Stack itself). This makes their permissions much easier to work with.
Global Block Reordering
Since you're working with Stacks instead of direct Blocks, you can now paste multiple blocks around your site, knowing that later on you'll be able to add new Blocks to the Stack and reorder them.
Proxy Blocks instead of Direct References
Before 5.5, whenever a global scrapbook was used, a direct pointer to the Block in the scrapbook would be copied to a particular page. If the Block was ever updated in the scrapbook, a new ID would be generated, and that ID would then have to be copied out to all instances of the Block on the site. This lead to many bugs and weird behaviors. Plus, both personal and global scrapbooks were subject to a limitation that their contents couldn't be added multiple times to the same area on the same page. That's because we have unique constraints on the Page ID -> Area Name -> Block ID.
In 5.5, with both the Clipboard and Stacks, we've fixed this. No, we didn't remove the unique constraint. Instead, placing a Stack or pasting an item from the Clipboard actually inserts an internal proxy Block on to the page. This Block references the original Block or Stack. Now you can paste the same Block or Stack multiple times in a row, without any problems whatsoever.
It's still easy to programmatically work with a Stack just like you could with a Block. Instead, reference the Stack by name:
$stack = Stack::getByName('Header Menu');
$ax = Area::get($stack, STACKS_AREA_NAME);
$stack = Stack::getByName('Header Menu');
Stacks are dialed in. We're proud of them, their implementation, and how they work under the hood. We'd love it if third party developers could transition the add-ons that use global scrapbooks to use Stacks instead. It's a pretty easy transition, and your customers will thank you.
Scrapbooks were a great stepping stone; they filled a very real need, and let us experiment with how to bring the functionality to our users. But Stacks improve on scrapbooks in every way, and we're glad they've arrived.