Version 1.0. Sunday, May 3, 2020 / Johan Ronsse
Bedrock is a prototyping tool to empower designers to help ship real software. It focusses on the design perspective while at the same time providing an immensely helpful deliverable for development.
This document is intended as a design document to talk about the reasoning behind the Bedrock 2.0 project.
Your feedback on this design document is more than welcome. What do you think of the ideas in this document? Is solving this problem appealing to you? How would you contribute?
In order to make highly interactive experiences that have a great user experience, designers and developers need to work together.
However, they often have a different angle when working. Bedrock 2.0 aims to provide designers with an environment where they can meaningfully contribute to development, while providing tools that help with their mindset: feature validation, prototyping (i.e. figuring out the problem) and finally the quality of the end result.
A product designer typically meaningfully contributes to app development in 3 ways:
- by providing static designs using a design app
- by providing static HTML/CSS to development
- by directly working in the development environment
Bedrock 2.0 aims to provide a bridge between (2) and (3) by providing product designers with an environment where:
- They are writing front-end code that directly works with the development stack (i.e. using the templating logic of the framework used)
- They can create prototypes that can be tested before development to validate feature requests
- They can show new designs simply by sharing a URL, through branch-based deployment
- They can profit from existing component libraries on the development side to create designs that are integrated with the development workflow
If you are not familiar with Bedrock 1.0, this might be good to read.
In this section, you will find a listing of the two major features of Bedrock 1.0. All of these features should be part of Bedrock 2.0.
- Prototype navigation
- Automatic prototype navigation based on a dynamic route listing, with a hideable page tree
- Page states: show the different routes in their different states (e.g. empty state, succsss state, error state)
- A page index which lists all the possible pages in the prototype
- Documentation (style guide): static pages where documentation can live, with the following categories
- Static documentation: simple pages, written in Markdown
- Component pages: a dynamic listing of components based on a set of file structure and metadata rules, which shows the different variations of a component, e.g. a button
- This documentation is enhanced with code examples
- Components are linkable with a # link
- Listing pages: a dynamic listing of design tokens, with typically 3 important pages: a list of used colors in the project, used typographic styles, and a list of icons
- Design pattern pages, which are a combination of (1) and (2)
- Deployable: Bedrock is architected in such a way that the resulting prototype deployable on a URL. Using a branch-based system, several versions of the design can be compared to each other.
The difference with Bedrock 1.0 is that Bedrock 2.0 will consist of different variants. A Bedrock variant will work together with a parent framework (e.g. Vue, React) to provide an environment to develop code in that can be re-used in the actual development environment.
The following workflow examples show how Bedrock 2.0 can help with its 3 features, while being conceptually integrated in the development environment (as opposed to Bedrock 1.X, which generates a static website totally separate from the dev environment).
Let us give an example of how you might use Bedrock 2.0 in practice.
The design team has designs in Figma. The development stack is Ember.js.
The developers have a production application that uses Ember. It uses Ember 3.X but the view layer doesn't use Ember Octane components yet.
The designers prepare new designs in their visual design app Figma. After a while, they have a need to prototype a new feature. They develop their visual design into HTML/CSS pages.
To develop their HTML/CSS pages in a productive way, they employ bedrock2-ember
. This package provides them with an environment where they can develop components.
It contains the features from Bedrock 1 (see above), but applied to an Ember environment. This effectively means the designers use the same tools as the developers to create their code. They use ember serve
, they write templates in Handlebars, they create Glimmer components.
The designers go on to test their product designs with real users. In lieu of a working backend they have provided fake data using placeholder JS objects. The users give their feedback on the demo, and the designers go on to implement the feedback. A 2nd test is held, and the feature is deemed ready to build.
The designers then make their HTML/CSS production ready. A design-savvy developer helps with some guidance regarding Ember Octane and its new syntax.
The design-savvy developer takes the prototype templates, which are already using Ember Octane components, and uses this prototype as a base to build out the feature in the real production app.
Let's give another example, this time for Vue.js.
The design team has designs in Framer X.
The development stack is Laravel and Vue.js. Some parts of the application are pure Laravel, some are combined with Vue.js, some are using the new Livewire. There are also mini-apps within the overall architecture that are pure Vue.js and use the API directly.
The new designs are for a highly interactive part of the application that will be written in pure Vue.js as an SPA.
The designers prepare new designs in their visual design app FramerX. After a while, they have a need to prototype a new feature. They develop their visual design into HTML/CSS pages.
To develop their HTML/CSS pages in a productive way, they employ bedrock2-vue
. This package provides them with an environment where they can develop components. Instead of static HTML, they write Vue.js SFCs (Single File Components).
During the process, they also document the components using the styleguide feature of Bedrock 2.0.
Illustration: Bedrock 2.0 styleguide in action.
The bedrock2-vue
package employs Nuxt.js to provide a Vue environment in which a demo can be developed. Nuxt.js takes care of the routing and serves an as example of a typical Vue app.
As it happens, the development team also has taken a liking to Nuxt.js. After the feature has been validated, they use it to develop the real application. The developers employ the styleguide as a reference to build out the real app, and make an npm package out the Vue components.
In a next projects, the designers load in the npm package directly, providing a great link for a source of truth between design and development.
Let us take another look at working with another framework. Every framework is different, and every version of Bedrock aims to work in the “spirit of the framework”.
The design team has designs in Sketch. The development uses Svelte with Routify.
The new designs are for a documentation part of the application that will be written in Svelte + Routify using MDSvx.
The designers prepare a single design of one page in their visual design app Sketch. To build out the rest of the design, they feel it would be more interesting to work in the browser from an efficiency perspective.
To develop their HTML/CSS pages in a productive way, they employ bedrock2-svelte
. This is essentially a modified version of the Routify starter package.
This package provides them with an environment where they can develop the documentation. They write a combination of Svelte components (which essentially consist of HTML), CSS and also provide some basic content.
When the designers are ready, they deploy their work using a simple command:
npm run deploy:now
The design for the documentation is deployed to a CI URL e.g. https://master.my-manual-demo.now.sh/
.
This URL is sent to the manual writer for reference of in what kind of enviroment his content would land. This eases the communication and through working together and seeing each others perspectives, a great documentation site takes shape.
- An early version using Svelte + Sapper (September 2019)
- A version using Vue + Nuxt (April 2020)
- (Unreleased)
- A version using Routify + Svelte
- A version using Ember.js 3
In this section, some general thoughts about how to go about implementing a bedrock2-variant.
A bedrock2-variant is a version of Bedrock that builds on a certain framework, and provides the expected features of Bedrock:
- Page tree
- Style guide
- Deployment
Providing either 1 or 2 is already of value.
Providing 1 with manual creation is also already of value.
Providing all 3 features with deep automation (like in Bedrock 1.0) delivers the ultimate value.
A variant preferably takes on the name of:
bedrock2-[parent-framework]-[child-framework]
For example
- bedrock2-vuejs-nuxt
- bedrock2-svelte-routify
- bedrock2-svelte-sapper
- bedrock2-react-next
- Consider the relationship between the templating logic and the expected output of a production app
Framework | Templating logic |
---|---|
Vue.js | Vue.js SFC |
React | JSX |
Ember.js | Handlebars |
Svelte | Svelte templates |
Angular | Angular SFC |
- Consider existing tools that are already maintained in their respective communities
Framework | Existing tools |
---|---|
Vue.js | Nuxt.js, Gridsome |
React | Next.js |
Ember.js | Empress, Ember itself |
Svelte | Routify, Sapper |
Angular | ? |
- Consider what a designer has to know to use the tools, and try to find a balance between what they would have to learn vs. how a simplified workflow would imply a worse deliverable
- CLI: run a certain command or series of commands
- Ideally, a single command to run a dev workflow, with no extra tools to install
- Having to install LiveReload or BrowserSync is definitely acceptable & normal
- Template language: learn a certain template language or logic?
- It's inevitable to have to learn something new
- Setup: go through a wizard with unknown options
- E.g. nuxt.js runs you through a wizard with a bunch of options, but the designer does not care about the middleware used, do a bedrock2-variant for nuxt could already have sensible defaults
- CLI: run a certain command or series of commands
This section describes how one would implement the page tree feature.
It is described in a framework-agnostic manner, and thus it might feel a bit abstract.
The page tree allows the user to view a list of possible pages (routes) by pressing a keyboard shortcut on any page.
The shortcut is Ctrl+M, but an alternative Ctrl+B shortcut also needs to be implemented for browsers where Ctrl+M is already mapped to another function.
Invoking this shortcut shows a list of pages. Ideally this list of pages is automatically generated from the routes, but a manual list in an include is definitely acceptable for a first implementation.
The fact that the page tree is visible or not has to be remembered across route changes. This can be implemented with a localStorage item that remembers the visible state. It is useful to tie this localStorage to the project name or a local variable (e.g. a random string) so that there is no chance storage item conflict when multiple prototypes are opened.
The styles from the page tree are ideally shielded from the rest of the implementation. In Bedrock 1.0 this is done by scoping everything to a .br
namespace and providing SCSS variables to make sure the page tree can render correctly regardless of font sizing strategy. In Bedrock 1.0, we also provide variables to customize the page tree look.
This section describes how one would implement the styleguide feature.
It is described in a framework-agnostic manner, and thus it might feel a bit abstract.
The styleguide is a separate route which lives as /styleguide
.
Within the styleguide, the user sees an entirely custom layout which consists of a sidebar and a content area. The sidebar contains a list of static pages and components. The content area contains the content of the selected page.
There are 4 types of pages.
- Static documentation: simple pages, typically written in Markdown
- Component pages: a dynamic listing of components based on a set of file structure and metadata rules, which shows the different variations of a component, e.g. a button
- This documentation is enhanced with code examples
- Components are linkable with a # link
- Listing pages: a dynamic listing of design tokens, with typically 3 important pages: a list of used colors in the project, used typographic styles, and a list of icons
- Design pattern pages, which are a combination of (1) and (2)
The Bedrock2-variant should provide the user (designer) with an easy way to create a new page. An ideal implementation updates the navigation of the styleguide automatically based on the existence of files.
This section describes how one would implement the deployable feature.
It is described in a framework-agnostic manner, and thus it might feel a bit abstract.
A Bedrock2-variant should ideally come with a deployment strategy.
This section has to be expanded upon, but the easy way to describe this is that there should be a command to create a deploy, or that the deploy should be git-backed, after which a build can be created through the use of a continuous integration service such as Github Actions or CircleCI.
This section is part of the reasoning why Bedrock exists, but currently has no specific place.
Developers are tasked with making the application work. Designers are tasked with the visual design and the user experience.
Now, this is a vast simplification. In a mature product team, everyone cares about the user experience, from the product manager to the backend engineer. There's also a lot of designers that have learnt parts of the development workflow, and the reverse: developers who are design-savvy.
The current development landscape (see addendum B. Development landscape) has moved towards Javascript-heavy applications.
This section can be helped to explain why Bedrock 2.0 could exist alongside Bedrock 1.X.
Over the past few years, the world of front-end development has moved to Javascript-heavy frameworks. Nowadays, people are building web apps in different frameworks. The most popular frameworks are React.js and Vue.js. Next there is Angular, Ember and some newcomers like Svelte.
These frameworks have their differences. Ember.js and Angular.js can be categorized under the "full-stack" frameworks in the sense that they can be used to build a complete application, end-to-end. Vue.js is marketed as the progressive Javascript framework, and can be used to enhance a web development stack that relies on traditional server-rendered languages, such as Ruby or PHP.
Vue.js can be put next Svelte, and to React, as frameworks which only concern themself with the view layer. If you need a server, or backend connectivity, you're going to have to make a combination with something else.
By providing a design document, and being open about our goals, the story of Bedrock becomes bigger than being an internal tool at our company.
As a contributor
- you can learn about better design/dev workflows, design systems, prototyping by helping to build the tools used for this exact reason
- you can work on a side project which might help in your main project
- you can give back to open source
Why are we doing this?
We would love for more software companies to build software with an eye for design. We see a clear need to provide tools to make the design/development workflow process smoother. By providing this kind of tooling in the open, we are serving different goals at the same time
- We profit from open source, by doing this, we give back to open source
- If the quality is high, Bedrock is also an advertisement for the design services of Mono. We want to design at a very high quality level.
We want working on Bedrock2 to be a friendly and welcome environment, and we will not tolerate any harassment or unwanted behavior. Be human, be nice to each other.
Bedrock2 will be MIT licensed and publicly available.
We have worked on Bedrock 1.0 for five years, pushing out 19 feature releases which have been versioned semantically.
A marketing site was created at https://bedrockapp.org/ including documentation and a blog.
We've created a CLI tool to upgrade Bedrock (bedrock-cli) and informed users of breaking changes.
We never reached a tipping point of external usage with Bedrock 1.0, but we are hoping to take the lessons learned and apply these to Bedrock 2.0.
- Designers typically want to focus on solving the design problem at hand, and not focus on:
- Complex setups with Docker
- Complex authentication setups
- Private npm packages
- Long build processes
- It is unlikely that the development setup matches the needs of prototyping.
You can't simply integrate style templating into another environment without creating a massive development task, one that is in fact already handled by the frameworks build on top of frameworks (such as Nuxt.js).