> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devinenterprise.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Visuelle Regressionen vor jedem PR erkennen

export const UseCaseHero = ({title, description, prompt, category, features, devinUrl, agent, intent, playbookId, type}) => {
  const encodedPrompt = encodeURIComponent(prompt || '');
  const tag = 'docs-use-case-gallery';
  const utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=hero-cta';
  const agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  const devinHref = type === 'schedule' ? 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + (prompt ? '&prompt=' + encodedPrompt : '') : type === 'review' ? 'https://app.devin.ai/review?' + utm : agent === 'ada' ? 'https://app.devin.ai/search?' + utm + '&noSubmit=true' + (prompt ? '&prompt=' + encodedPrompt : '') : devinUrl ? devinUrl.includes('?') ? devinUrl + '&' + utm + agentParams : devinUrl + '?' + utm + agentParams : prompt ? 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encodedPrompt : 'https://app.devin.ai/?' + utm + agentParams;
  const buttonLabel = type === 'schedule' ? 'Schedule in Devin ↗' : type === 'review' ? 'Set Up Devin Review ↗' : agent === 'advanced' ? 'Try in Devin ↗' : agent === 'dana' ? 'Try in Dana ↗' : agent === 'ada' ? 'Try in Ask Devin ↗' : 'Try in Devin ↗';
  const featureList = features ? features.split(',').map(f => f.trim()) : [];
  return <div className="uc-hero">
      <div className="uc-hero-inner">
        <div className="uc-hero-left">
          <h1 className="uc-hero-title">{title}</h1>
          <p className="uc-hero-desc">{description}</p>
          <div>
            <a href={devinHref} target="_blank" rel="noopener noreferrer" className="try-in-devin-btn">
              {buttonLabel}
            </a>
          </div>
        </div>
        <div className="uc-hero-meta">
          <div className="uc-meta-item">
            <span className="uc-meta-label">Author</span>
            <span className="uc-meta-value">Cognition</span>
          </div>
          <div className="uc-meta-item">
            <span className="uc-meta-label">Category</span>
            <span className="uc-meta-value">{category}</span>
          </div>
          {featureList.length > 0 && <div className="uc-meta-item">
              <span className="uc-meta-label">Features</span>
              <span className="uc-meta-value">{featureList.join(', ')}</span>
            </div>}
        </div>
      </div>
    </div>;
};

export const PromptBlock = ({children, type, agent, intent, playbookId}) => {
  var utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=prompt-block';
  var tag = 'docs-use-case-gallery';
  var agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  var label = type === 'schedule' ? 'Schedule in Devin' : type === 'playbook' ? 'Create Playbook' : type === 'knowledge' ? 'Add to Knowledge' : agent === 'advanced' ? 'Try in Devin' : agent === 'dana' ? 'Try in Dana' : agent === 'ada' ? 'Try in Ask Devin' : 'Try in Devin';
  var buildUrl = function (text) {
    var encoded = encodeURIComponent(text);
    if (type === 'schedule') return 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + '&prompt=' + encoded;
    if (type === 'playbook') return 'https://app.devin.ai/settings/playbooks/create?' + utm + '&body=' + encoded;
    if (type === 'knowledge') return 'https://app.devin.ai/knowledge?' + utm + '&body=' + encoded;
    if (agent === 'ada') return 'https://app.devin.ai/search?' + utm + '&noSubmit=true&prompt=' + encoded;
    return 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encoded;
  };
  const ref = React.useRef(null);
  const [href, setHref] = React.useState('#');
  React.useEffect(() => {
    if (!ref.current) return;
    var codeEl = ref.current.querySelector('pre code');
    if (codeEl) {
      var text = codeEl.textContent.trim();
      if (text) setHref(buildUrl(text));
    }
    var header = ref.current.querySelector('[data-component-part="code-block-header"]');
    if (header && !header.querySelector('.prompt-block-devin-link')) {
      var link = document.createElement('a');
      link.href = href;
      link.target = '_blank';
      link.rel = 'noopener noreferrer';
      link.className = 'prompt-block-devin-link';
      link.style.cssText = 'display:inline-flex;align-items:center;gap:6px;text-decoration:none;color:#fff;font-size:11px;font-weight:500;padding:4px 10px;border-radius:6px;white-space:nowrap;background:#317CFF;transition:background 0.2s;margin-left:8px;';
      link.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg> ' + label;
      link.onmouseenter = function () {
        link.style.background = '#2968D9';
      };
      link.onmouseleave = function () {
        link.style.background = '#317CFF';
      };
      header.appendChild(link);
    }
    var existingLink = ref.current.querySelector('.prompt-block-devin-link');
    if (existingLink && href !== '#') existingLink.href = href;
  });
  return <div className="prompt-block" ref={ref}>{children}</div>;
};

<UseCaseHero title="Visuelle Regressionen vor jedem PR erkennen" description="Ein Repo-Skill, mit dem Devin jede betroffene Seite per Screenshot erfasst und Layoutprobleme meldet, bevor ein PR erstellt wird." prompt="Lege unter .agents/skills/visual-regression/visual-regression.md einen Repo-Skill an, der Devin beschreibt, wie er unsere Next.js-App startet, jede vom aktuellen Diff betroffene Seite aufruft, bei Desktop- und Mobilbreite Screenshots erstellt und etwaige Layoutprobleme meldet – bevor ein PR erstellt wird." category="Feature-Entwicklung" features="Skills" />

<div className="uc-detail-wrapper">
  <Tip>Möchten Sie dies nicht manuell einrichten? Fügen Sie einen Link zu dieser Seite in eine Devin-Sitzung ein und bitten Sie Devin, alles für Sie einzurichten.</Tip>

  <Steps>
    <Step title="Das Problem: CSS-Bugs bleiben in Unit-Tests unentdeckt">
      Ihre Test-Suite läuft durch, CI ist grün und der PR wird gemergt — aber auf der Einstellungsseite überlagern sich jetzt Texte auf Mobilgeräten, und der Checkout-Button ist hinter dem Footer verschwunden. Unit-Tests und Linter erkennen visuelle Fehler nicht, sodass der Fehler in Produktion landet und ein Kunde ihn meldet.

      Ein Repository-Skill löst dieses Problem. Skills sind Markdown-Dateien, die Sie in `.agents/skills/<your-skill>/` in einem Ihrer Repositories committen. Devin sieht alle Skills in allen verbundenen Repositories — Sie können sie manuell triggern, oder Devin kann sie automatisch triggern, wenn eine relevante Situation erkannt wird. Dieser Skill sagt Devin genau, wie es Ihre App starten, zu den vom Diff betroffenen Seiten navigieren und dort bei mehreren Viewport-Breiten Screenshots aufnehmen soll — jedes Mal, vor jedem PR.
    </Step>

    <Step title="Fügen Sie den Skill visual-regression zu Ihrem Repo hinzu">
      Committe eine Datei unter dem Pfad `.agents/skills/visual-regression/visual-regression.md`, in der die manuelle QA-Checkliste deines Teams als Schritte codiert ist, denen Devin folgen kann:

      ```markdown theme={null}
      # Visual Regression Check

      ## Description
      Before opening any PR, start the app locally and screenshot every
      page affected by the current diff at desktop and mobile widths.
      Flag any layout issues found.

      ## Prerequisites
      - Docker running (for the database)
      - Port 3000 available

      ## Setup
      1. Install dependencies: `npm install`
      2. Start services: `docker-compose up -d postgres redis`
      3. Run migrations: `npx prisma migrate dev`
      4. Seed test data: `npm run db:seed`
      5. Start the dev server: `npm run dev`
      6. Wait for "Ready on http://localhost:3000" in the terminal

      ## Visual Checks
      1. Read the current git diff to identify which pages are affected
      2. For each affected page:
         a. Open the page in the browser at http://localhost:3000/{route}
         b. Screenshot at 1280px width (desktop)
         c. Resize the browser to 375px width (mobile)
         d. Screenshot at mobile width
         e. Check for: overlapping text, elements hidden behind other
            elements, horizontal scroll, buttons or links that are
            unreachable, missing images or icons, console errors
      3. If any issue is found, list it with the page URL, viewport
         width, and a description of the problem

      ## Before Opening the PR
      1. Run `npm run lint` and fix any issues
      2. Run `npm test` and confirm all tests pass
      3. Include all screenshots in the PR description
      4. If issues were found, list them at the top of the PR body
      ```

      Diese Datei wird mit Ihrem Code ausgeliefert. Sobald sie committed ist, betrachtet Devin sie als verfügbare Fähigkeit – immer wenn eine Sitzung UI-Dateien in diesem Repo bearbeitet, kann Devin die visuellen Regressionstests automatisch ausführen, oder Sie können sie jederzeit manuell anstoßen.
    </Step>

    <Step title="Passen Sie die Checks an Ihre Seiten an">
      Generische Anweisungen wie "überprüfe, ob die Seite richtig aussieht" führen zu vagen Ergebnissen. Der wertvollste Teil dieses Skills besteht darin, Devin zu sagen, wie „korrekt“ für jeden Bereich deiner App aussieht.

      Füge deinem Skill routenspezifische Abschnitte hinzu:

      ```markdown theme={null}
      ## Routenspezifische Prüfungen

      ### Dashboard (`/dashboard`)
      - Die Metrikkarten sollten auf dem Desktop in einem 3-spaltigen Raster angezeigt werden
      - Karten sollten auf Mobilgeräten zu einer einzelnen Spalte gestapelt werden
      - Das Diagramm sollte ohne horizontales Scrollen vollständig sichtbar sein

      ### Checkout (`/checkout`)
      - Die Schaltfläche „Bestellung aufgeben" muss ohne Scrollen sichtbar sein
        – sowohl auf dem Desktop als auch auf Mobilgeräten
      - Die Bestellübersichts-Seitenleiste sollte auf Mobilgeräten zu einem Akkordeon zusammenklappen
      - Die Preisaufschlüsselung sollte Zwischensumme, Steuer und Gesamtbetrag in separaten Zeilen anzeigen

      ### Settings (`/settings`)
      - Alle Formularetiketten sollten linksbündig mit ihren Eingabefeldern ausgerichtet sein
      - Die Schaltfläche „Speichern" muss am unteren Ende des Formulars erreichbar sein
      - Die Tab-Navigation zwischen Abschnitten sollte den URL-Hash aktualisieren
      ```

      Devin liest das Diff, identifiziert, welche Routen betroffen waren, und folgt dem entsprechenden Abschnitt – sodass die Prüfungen gezielt statt generisch sind.
    </Step>

    <Step title="Sehen Sie, wie es einen echten Regressionsfehler erkennt">
      Nehmen wir an, eine Entwicklerin ändert das CSS-Grid auf dem Dashboard von `grid-template-columns: repeat(3, 1fr)` zu `repeat(auto-fit, minmax(200px, 1fr))`, um das Layout responsiv zu machen. Die Unit-Tests bestehen – es wurde keine Logik geändert. Aber auf Mobilgeräten ragen die Karten jetzt über den Viewport hinaus.

      Wenn Devin die Codeänderung abgeschlossen hat, führt es diese Fähigkeit automatisch aus:

      1. **Startet die App** — installiert Abhängigkeiten, startet Docker, führt Migrationen aus, seedet Daten, startet den Dev-Server
      2. **Liest das Diff** — erkennt, dass sich `src/components/Dashboard.tsx` geändert hat, und ordnet es der Route `/dashboard` zu
      3. **Macht Screenshots bei 1280px** — das 3-Spalten-Grid wird korrekt gerendert
      4. **Macht Screenshots bei 375px** — erkennt horizontalen Überlauf: Die Karten passen nicht in den Viewport
      5. **Markiert das Problem** — meldet "Horizontaler Bildlauf auf /dashboard bei 375px Breite erkannt — Metrik-Karten ragen über den Viewport hinaus"
      6. **Behebt das CSS** — fügt `overflow-x: hidden` hinzu und passt das `minmax`-Minimum auf `150px` an
      7. **Erstellt erneut Screenshots** — bestätigt die Korrektur bei beiden Breiten
      8. **Öffnet den PR** — fügt Vorher-/Nachher-Screenshots und die Korrektur in die Beschreibung ein

      Sie können dies in Echtzeit im Browser-Tab in Ihrem [Sitzungs-Workspace](/de/work-with-devin/devin-session-tools) beobachten.
    </Step>

    <Step title="Für Ihren Stack erweiterbar">
      Passe den Skill für zusätzliche Tools und projektspezifische Verifizierungsschritte an:

      <PromptBlock>
        ```txt Füge Storybook-Komponentenprüfungen hinzu theme={null}
        Aktualisiere den Skill für visuelle Regressionstests so, dass er außerdem
        `npm run storybook` ausführt, http://localhost:6006 öffnet und
        jede Story der im aktuellen Diff geänderten Komponenten als Screenshot erfasst. Markiere alle
        Stories, die einen Rendering-Fehler oder eine leere Fläche anzeigen.
        ```
      </PromptBlock>

      <PromptBlock>
        ```txt Füge Dark-Mode-Verifizierung hinzu theme={null}
        Aktualisiere den Skill für visuelle Regressionstests so, dass er außerdem die App in den Dark Mode
        schaltet (klicke oben rechts auf den Theme-Umschalter) und jede
        betroffene Seite erneut als Screenshot erfasst. Markiere jeden Text, der vor dem
        dunklen Hintergrund unlesbar wird, sowie alle Elemente, die ihre Umrandung verlieren.
        ```
      </PromptBlock>
    </Step>
  </Steps>
</div>
