https://bit.ly/sdc-workflow

(a sappy aside about the community)
But for some projects they are overkill.

Will I miss my fancy frameworks?
also...The one true way



Astro is current tool of choice



<retro-card> is valid htmlSlots - unstructured data - markup, other components
Props - key value pairs (think attributes)
<retro-card>
  <div class="card">
    <div class="card-image">
      <slot name="image" />
    </div>
    <div class="card-content">
      <div class="card-meta">
        <span class="date">{date}</span>
        <div class="tags">
          <span class="tag">{tag}</span>
        </div>
      </div>
      <h2 class="card-title">{title}</h2>
      <div class="card-text">
        <slot name="body" />
      </div>
      <a href={url} class="read-more">Jack In →</a>
    </div>
  </div>
</retro-card>
---
import Card from '../components/Card.astro';
import Layout from '../layouts/Layout.astro';
---
<Layout>
    <Card
    date="March 14, 2024"
    tag="Retro"
    title="Synthwave Dreams"
    url="/synthwave-dreams"
  >
    <img slot="image" src="https://picsum.photos/400/250" alt="Card image" />
    <p slot="body">Welcome to the future that never was. A nostalgic journey through neon-lit streets and digital horizons. Where synthwave meets design in a perfect harmony.</p>
  </Card>
</Layout>
---
interface Props {
  date: string;
  tag: string;
  title: string;
  url: string;
}
const { title, date, tag, url } = Astro.props;
---


<script>
  // Add glitch effect to image on click
const cardImage = document.querySelector('.card-image');
cardImage?.addEventListener('click', () => {
  cardImage.classList.add('glitch');
  setTimeout(() => {
    cardImage.classList.remove('glitch');
  }, 300);
});
// Add flicker effect to tags on click
const tags = document.querySelectorAll('.tag');
tags.forEach(tag => {
  tag.addEventListener('click', () => {
    tag.classList.add('flicker');
    setTimeout(() => {
      tag.classList.remove('flicker');
    }, 300);
  });
});
</script>


<retro-card>Spoiler: this should feel pretty similar
components/card subdirectory in a module or theme
card.component.yml filebare minimum version:
name: Card
props:
  type: object
  properties: {}
card.twig:
<retro-card>Card component</retro-card>
Note that the extension is .twig not .html.twig
card.css
retro-card {
  color: green;
}
We'll add more css/markup along the way...
In our drupal_cms_olivero_sdc theme
node--card.html.twig:
{% embed 'drupal_cms_olivero_sdc:card' %}{% endembed %}

Slots in our prototype looked like:
<div class="card-text">
  <slot name="body" />
</div>
For Drupal, we first define the slot in yml
slots:
  body:
    title: Body
    description: Body markup
Next, we define it as a block in our twig template
<div class="card-text">
  {% block body %}{% endblock %}
</div>
And populate the block in our Twig embed
{% embed 'drupal_cms_olivero_sdc:card' %}
  {% block body %}
    {{ content|without('field_featured_image', 'links') }}
  {% endblock %}
{% endembed %}
Slots in our prototype looked like:
<Card
   date="March 14, 2024"
   tag="Retro"
   title="Synthwave Dreams"
   url="/synthwave-dreams"
 >
For Drupal, we first update our yml to add a date prop:
name: Card
props:
  type: object
  properties:
    date:
      type: string
      title: date
      description: "The date content was created"
Next we use the date prop in our twig template:
{% if display_submitted %}
  <span class="date">{{date}}</span>
{% endif %}
And pass the prop in our Twig embed
{% embed 'drupal_cms_olivero_sdc:card' with { date: date} %}
Similar to TypeScript, you can enforce your schema
---
interface Props {
  date: string;
  tag: string;
  title: string;
  url: string;
}
const { title, date, tag, url } = Astro.props;
---
For theme components:
enforce_prop_schemas: true
No modifications required in this case.


drush generate sdc

Easy as...
{% embed 'drupal_cms_olivero_sdc:card' %}
vs
{% embed 'drupal_cms_olivero_sdc:business_card' %}
nomarkup module

twig_tweak module
