Bookshop

repository·main·Indexed 43 days ago

https://github.com/cloudcannon/bookshop

A standalone Sass compiler and component library system designed to compile styles into a single CSS file with PostCSS integration. It includes a Jekyll plugin (jekyll-bookshop) for rendering components via Liquid tags, a Sass build tool (@bookshop/sass), and a scaffolding CLI (@bookshop/init) for generating component skeletons.

Tokens
36.7K
Snippets
136
Records
172
Agent score
54%

What's inside Bookshop

  1. Overview of Bookshop component workflow

    main

    Bookshop is a component development workflow designed for static websites. It establishes a convention for building self-contained components using the templating languages of various Static Site Generators (SSGs).

    By following these conventions, Bookshop enables developers to:

    • Integrate components seamlessly into their existing SSG stack.
    • Build and browse UI components locally.
    • Provide rich live editing experiences for content editors.

    Currently supported SSGs include:

    • Astro
    • Jekyll
    • Eleventy
    • Hugo
    • SvelteKit
  2. Handle data access during Live Editing

    main

    When live editing, Bookshop connects to a subset of your site's data.

    Important Requirements:

    • You must set data_config: true in your CloudCannon Global Configuration file for data to be accessible.
    • Support is provided for data files in your source; data provided by plugins is not supported.

    SSG Specifics:

    • Hugo: Data is available via site.Data (not .Site.Data). Accessing site pages is not yet supported.
    • Jekyll: Access site.data and site.<collection> as expected. Some fields like page.content and page.excerpt are unavailable.
    • Eleventy: Access site.data and collections.* as expected. Some fields like templateContent are unavailable.

    Best Practice: Passing Data to Components To ensure live editing works, avoid adding logic around components in your site layouts. Instead, move that logic into the component or a helper. Access site data directly inside the component rather than passing it from the layout.

  3. Understand the new Bookshop 3.0 component configuration structure

    main

    In Bookshop 3.0, component configuration files are no longer restricted to TOML and can use YAML, TOML, JSON, or JavaScript (YAML is recommended). The new syntax uses four primary top-level objects:

    • spec: Renamed from component. Contains the core component definition.
    • blueprint: Renamed from props. Defines the explicit default values for component properties.
    • preview: Defines values used specifically for rendering the component in the component browser. This object is deep merged with blueprint.
    • _inputs: Replaces the Bookshop DSL. This allows you to configure CloudCannon inputs manually, providing more control (e.g., adding comments, range sliders, or select menus).

    You can also reference other Bookshop components within your configuration using the bookshop: prefix.

    blueprint:
      button: bookshop:button
      size: 3
    
    preview:
      title: "Hello World"
    
    _inputs:
      size:
        type: range
        options:
          step: 1
          max: 20
          min: 0
      title:
        comment: CMS Comment
  4. Nest components in Bookshop blueprints

    main

    You can create complex page-building experiences by referencing other components or structures within a component's blueprint.

    Nesting a single component

    Use the bookshop:<component-name> syntax. To ensure the component is initialized with data rather than being empty, append an exclamation mark: bookshop:<component-name>!.

    Nesting arrays of components

    To allow an array of components, use the array syntax: buttons: [bookshop:button] or buttons: - bookshop:button.

    Nesting via Structures

    To restrict an array to components registered under a specific structure, use bookshop:structure:<structure-name>. You can also specify which component should be the default in that structure using the ! syntax: column_components: [bookshop:structure:content_blocks!(hero)]

    blueprint:
      hero_text: Hello World
      cta_button: bookshop:button
      column_components: [bookshop:structure:content_blocks]
  5. Configure a Bookshop component file

    main

    The .bookshop.yml file is the core of a component. It contains several key sections:

    • spec: Metadata for the CMS (label, icon, tags) and structures (which array-based inputs this component can be added to).
    • blueprint: The default data structure for the component. These keys become the props available in your template.
    • preview: Data used to populate the component in the local component browser (merged with the blueprint).
    • _inputs: Configuration for CloudCannon-specific input types (e.g., changing a text field to an HTML editor).

    Nesting Components in Blueprints

    You can nest components within other components using the bookshop: prefix:

    • Single Component: button: bookshop:button (initializes as empty).
    • Initialized Component: button: bookshop:button! (initializes with default blueprint values).
    • Component from a Structure: header: bookshop:structure:content_blocks (allows selecting a component from a predefined set).
    spec:
      structures:
        - content_blocks
      label: Hero
    
    blueprint:
      hero_text: Hello World
      cta_button: bookshop:button!
      column_components: [bookshop:structure:content_blocks]
  6. Pass data to Bookshop components for live editing

    main

    To ensure live editing works, Bookshop requires a clear path between a component and the data it uses. Avoid adding logic around Bookshop components in your site layouts. Instead, move that logic into the component or a helper.

    Incorrect (will error in visual editor):

    {% assign my_title = hero_text %}
    {% bookshop 'hero' text: my_title %}

    Correct (works in visual editor):

    {% bookshop 'hero' text: hero_text %}

    This principle also applies to site data and collections; access them directly inside the component rather than passing them through the layout.

  7. Author a Bookshop component configuration file

    main

    Every component requires a .bookshop.<format> file (e.g., .bookshop.yml) to define its schema, metadata, and preview data. This file drives the CloudCannon editor and the local component browser.

    Key Sections

    • spec: Defines metadata like label, description, and icon. The structures array registers the component with specific CloudCannon Structure keys.
    • blueprint: Defines the default data structure (props) for the component.
    • preview: Provides example data that is deep-merged with the blueprint to show a populated component in the browser.
    • _inputs: Configures how specific keys are handled in the CMS (e.g., setting a field type to html).

    Nesting Components

    Use the bookshop: prefix in the blueprint to nest other components or structures:

    • button: bookshop:button (Single component)
    • buttons: [bookshop:button] (Array of components)
    • column_components: [bookshop:structure:content_blocks] (Array of components from a specific structure)

    To ensure a nested component is initialized with data rather than being empty, append an exclamation mark: bookshop:button! or bookshop:structure:content_blocks!(hero).

    # Example hero.bookshop.yml
    spec:
      structures: [content_blocks]
      label: Hero
    
    blueprint:
      hero_text: Hello World
      cta_button: bookshop:button
      column_components: [bookshop:structure:content_blocks]
  8. Author a Bookshop component file (.bookshop.yml)

    main

    The .bookshop.yml file is the core configuration for a component. It defines how the component behaves in the CMS, the local browser, and during live editing. It consists of four main sections:

    1. spec: Metadata for CloudCannon and the component browser. Use structures to register the component with specific array structures. Use label, description, icon, and tags for UI display.
    2. blueprint: Defines the initial state and schema of the component's properties. This is what is passed to your template.
    3. preview: Provides example data that is deep-merged with the blueprint to show a populated version of the component in the component browser.
    4. _inputs: Configures CloudCannon-specific input types (e.g., type: "html") for blueprint keys.

    Nesting Components in Blueprints:

    • Use bookshop:{component_name} to nest a single component.
    • Use [bookshop:{component_name}] or bookshop:{component_name}! to nest an array of components.
    • Use bookshop:structure:{structure_name} to reference a registered structure.
    • Use bookshop:structure:{structure_name}!(component_name) to initialize a structure with a specific component as the default.
    spec:
      structures: [content_blocks]
      label: Example
      icon: book
    
    blueprint:
      hero_text: Hello World
      cta_button: bookshop:button
      column_components: [bookshop:structure:content_blocks]
  9. Upgrade to Bookshop 3.0

    main

    Bookshop 3.0 introduces a new configuration file format and changes how components are defined. You can automate most of the migration process using the @bookshop/up upgrade script. Run this command in a parent directory that contains both your site and your component library.

    To change your preferred configuration format later, you can re-run the command with the --format flag.

    npx @bookshop/up@latest
    
    # To change format later:
    npx @bookshop/up --format <format>
  10. Render different content when live editing

    main

    You can use the Bookshop Live Editor flag to render specialized content (like fallback titles or debug info) specifically for the visual editor environment.

    Hugo:

    {{ if site.Params.env_bookshop_live }}
      <p>I am being edited live!</p>
    {{ else }}
      <p>Standard build output</p>
    {{ end }}

    Eleventy/Jekyll:

    {% if env_bookshop_live %}
      <p>I am being edited live!</p>
    {% else %}
      <p>Standard build output</p>
    {% endif %}
  11. Connect Bookshop to a Hugo site

    main

    Bookshop is distributed as a Hugo Module. To connect it to your site, follow these steps:

    1. Initialize Hugo Modules: If your site root lacks a go.mod file, run hugo mod init site.local.
    2. Configure Hugo Module replacements and imports: Update your site's config.toml to map your local component library and import the Bookshop Hugo module.

    Note: The replacements path is relative to the Hugo themes directory. If your library is in your source directory, use ../component-library.

    # site/config.toml
    [module]
    replacements = "components.local -> ../component-library"
    
    [[module.imports]]
    path = 'components.local'
    
    [[module.imports]]
    path = 'github.com/cloudcannon/bookshop/hugo/v3'
  12. Initialize a new Bookshop component library

    main

    To create the required directory structure for a Bookshop project, run the @bookshop/init command in the root of your repository. This scaffolds the component library, configuration files, and sample components.

    Use the following command structure: npx @bookshop/init --new <library-name> --framework <ssg-engine>

    Example for Eleventy: npx @bookshop/init --new component-library --framework @bookshop/eleventy-engine

    npx @bookshop/init --new component-library --framework @bookshop/eleventy-engine