Mit Copilot zu modernen SharePoint HTML Pages

mit copilot zu modernen sharepoint html pages hintergrundbild blog

Veröffentlicht:

Microsoft erweitert die Möglichkeiten von SharePoint kontinuierlich und ein neues Feature weckt dabei besonderes Interesse: Statt ausschliesslich klassische ASPX-basierte Site Pages zu erstellen, können nun auch HTML Site Pages mit Unterstützung von Copilot generiert oder bestehende HTML-Seiten wiederverwendet werden. Gerade im Zeitalter von KI ist dies ein spannender Ansatz. Während ASPX-Seiten für viele Autoren eher eine technische Hürde darstellen, können KI-Systeme deutlich besser strukturiertes HTML, CSS und JavaScript erzeugen. Grund genug, das Feature einmal genauer unter die Lupe zu nehmen.

Vorgehen

Die Erstellung einer HTML Site Page erfolgt über Copilot Chat. Damit sollte der Ablauf simuliert werden, den eine Person ohne Softwareentwicklungshintergrund am ehesten wählen würde.

Der Test: Personenliste als Kartenansicht

Für den Test wurde eine SharePoint-Liste mit Personen angelegt. Die Liste enthält folgende Informationen:

image

Ziel war es, eine attraktive Übersichtsseite zu erstellen. Der erste Prompt lautete:

Create an HTML Site Page that loads all list items from the list under the URL https://xxx.sharepoint.com/sites/SPOHTMLPages called "Personen". This list contains people, their function and their country of origin. Display them using cards with the given information.

Copilot erzeugte daraufhin eine HTML-Seite inklusive JavaScript-Code, der die Daten direkt aus der SharePoint-Liste laden sollte.

Leider trat unmittelbar ein Fehler auf:

image

Warum dieser Fehler zu erwarten war

Nach einem Blick in die Dokumentation wurde schnell klar: Das Verhalten ist beabsichtigt. HTML Pages werden in einem isolierten, sicherheitsbeschränkten iFrame ausgeführt. Dadurch gelten strenge Content Security Policies.

In der Dokumentation wird dies folgendermassen beschrieben:

HTML pages render in a sandboxed iFrame and use Content Security Policy rules. Arbitrary fetch requests and outbound API calls are blocked. CDN scripts and cross-tenant communications aren't supported; only selected external libraries are allowed.

Mit anderen Worten: Dynamische Zugriffe auf die SharePoint-REST-API oder beliebige APIs sind in diesem Szenario aktuell nicht möglich. Diese Einschränkung reduziert die Einsatzmöglichkeiten zwar deutlich, erklärt jedoch den Sicherheitsansatz hinter dem Feature.

Zweiter Versuch: Statische Inhalte statt Live-Daten

Wenn keine Live-Daten geladen werden können, könnte Copilot die Daten vielleicht direkt aus der Liste übernehmen und statisch ins HTML schreiben.
Ausserdem war der Prompt ziemlich minimal, worauf Copilot mich ebenfalls hingewiesen hatte.

Der nächste Prompt lautete deshalb:

Create a HTML Site Page based on the SharePoint list "Personen" located at:
	
https://xxx.sharepoint.com/sites/SPOHTMLPages/Lists/Personen/AllItems.aspx
	
	 
	
Requirements:
	
- Read all items currently available in the list.
	
- Do NOT use JavaScript, fetch requests, SharePoint REST APIs, Graph APIs, SPHttpClient, dynamic loading or any live data connection.
	
- Create a completely static HTML page.
	
- Copy the current list content into the generated HTML.
	
- Display each person as a modern card.
	
- Show:
	
- Person name
	
- Function
	
- Country of origin
	
- Use responsive CSS with a card grid layout.
	
- Use the SharePoint site theme colors through the provided CSS theme variables.
	
- Generate initials from the person's name inside a circular avatar.
	
- Display the country as a flag emoji overlay on the avatar where possible.
	
- Include all list items currently available in the list.
	
- Produce clean, production-ready HTML and CSS only.
	
- No external libraries.
	
- No JavaScript unless absolutely required for presentation.
	
- The page must continue to work even when disconnected from SharePoint data sources because all content is embedded statically into the HTML.
	
	 
	
Generate the full HTML document including CSS.

Und tatsächlich: Copilot konnte die vorhandenen Listeneinträge lesen und direkt als HTML in die Seite integrieren. Das Ergebnis war deutlich besser als erwartet.

Mit diesem einen Prompt entstand eine ansprechend gestaltete Teamübersicht:

image

Inhalte aktualisieren

Nachdem die Personenliste um weitere Einträge ergänzt worden war, wollte ich testen, wie gut Copilot bestehende Seiten aktualisieren kann.

Der Prompt war denkbar einfach:

I updated the person list. Please update the content to use the new data.

Die neue Person wurde korrekt ergänzt und die Seite entsprechend angepasst.

Damit wird bereits ein interessantes Szenario sichtbar: Statisch generierte Informationsseiten können mit wenigen Prompts aktuell gehalten werden, ohne den HTML-Code manuell bearbeiten zu müssen. Stattdessen kann man einfach das File in der Library ersetzen.
Mein Automatisierungshirn hatte Freude! Alles, was ich soeben gemacht hatte, könnte auch automatisch ausgeführt werden.

image

Designoptimierung mit Copilot

Inhaltlich funktionierte die Lösung bereits gut. Mit dem Design war ich jedoch noch nicht ganz zufrieden.

Mein nächster Wunsch war:

I'm not happy with the design. Please use the site's theme color as the primary color and display the country as a small country flag overlaying the initials circle, also use the person's picture if possible.

Die Idee war, die Karten moderner wirken zu lassen und die Herkunftsländer visuell durch Flaggen darzustellen.

Das Ergebnis war allerdings durchzogen:

  • Der Text wurde plötzlich schwarz angezeigt.
  • Die Flaggen-Emojis wurden nicht angezeigt.
  • Der Header blieb blau, statt in der gewünschten Primärfarbe Orange dargestellt zu werden.
  • Die Personenfotos wurden nicht integriert.

Der letzte Punkt stellte sich schnell als technische Einschränkung heraus. Aufgrund der Sicherheitsmechanismen der HTML Pages können Benutzerbilder nicht einfach eingebunden werden.

image

Ein weiterer Versuch sollte die Darstellung verbessern:

That was not what I meant. The text is now black, please reverse that change. The header background is blue, make this one use the primary theme color of the site. Also the countries are still text, not images. Use emojis if possible.

Das Resultat war gemischt.

Bei genauerem Hinsehen stellte sich heraus, dass der blaue Header gar kein Fehler war. Das verwendete SharePoint-Theme dieser Site war tatsächlich blau. Copilot hatte also korrekt auf die Theme-Farben zugegriffen.

Interessanter wurde die Flaggen-Thematik. Copilot behauptete zwar, Länderflaggen als Emojis integriert zu haben, auf der Seite wurden jedoch weiterhin lediglich die Ländernamen angezeigt.

Nach mehreren Versuchen liess sich das Verhalten nicht vollständig beheben. Erst später wurde klar, dass die Ursache nicht zwangsläufig im generierten HTML lag. Viele Windows-Systeme unterstützen die Darstellung bestimmter Emoji-Flaggen nur eingeschränkt oder gar nicht. Daher handelt es sich eher um eine Einschränkung der Plattform als um einen Fehler von Copilot.

Blick in den generierten Code

Auch der Blick in den erzeugten Quellcode lieferte interessante Erkenntnisse:

<!doctype html>
<html lang="de">
<head>
    <style data-sp-site-theme>
        :root {
            --colorBrandBackground: #004e8c;
            --colorBrandBackgroundHover: #00457e;
            --colorBrandBackground2: #f0f6fa;
            --colorBrandForeground1: #004e8c;
            --colorNeutralForeground1: #323130;
            --colorNeutralForeground2: #605e5c;
            --colorNeutralForegroundOnBrand: #ffffff;
            --colorNeutralBackground1: #ffffff;
            --colorNeutralBackground2: #faf9f8;
            --colorNeutralStroke1: #d2d0ce;
            --fontFamily: 'Segoe UI', 'Segoe UI Web (West European)', -apple-system, BlinkMacSystemFont, Roboto, 'Helvetica Neue', sans-serif;
        }
    </style>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Personen</title>
    <style>
        * {
            box-sizing: border-box
        }
        body {
            margin: 0;
            background: var(--colorNeutralBackground2);
            font-family: var(--fontFamily);
            color: var(--colorNeutralForeground1)
        }
        .people-page {
            max-width: 1180px;
            margin: auto;
            padding: 34px 20px 52px
        }
        .hero {
            position: relative;
            overflow: hidden;
            padding: 42px;
            border-radius: 24px;
            background: var(--colorBrandBackground);
            color: var(--colorNeutralForegroundOnBrand);
            box-shadow: 0 18px 44px rgba(0, 0, 0, .14);
            margin-bottom: 28px
        }
        .hero:after {
            content: '';
            position: absolute;
            width: 260px;
            height: 260px;
            border-radius: 50%;
            right: -70px;
            top: -110px;
            background: rgba(255, 255, 255, .1)
        }
        .hero>* {
            position: relative;
            z-index: 1;
            color: var(--colorNeutralForegroundOnBrand)
        }
        .eyebrow {
            font-size: 12px;
            letter-spacing: .16em;
            font-weight: 800;
            opacity: .86
        }
        .hero h1 {
            font-size: 40px;
            line-height: 1.1;
            margin: 10px 0
        }
        .hero p {
            margin: 0;
            font-size: 17px;
            opacity: .9
        }
        .count {
            display: inline-flex;
            margin-top: 22px;
            padding: 8px 13px;
            border-radius: 999px;
            background: rgba(255, 255, 255, .18);
            font-weight: 700
        }
        .people-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(285px, 1fr));
            gap: 18px
        }
        .person-card {
            display: flex;
            align-items: center;
            gap: 19px;
            min-height: 126px;
            padding: 22px;
            border-radius: 18px;
            background: var(--colorNeutralBackground1);
            border: 1px solid var(--colorNeutralStroke1);
            box-shadow: 0 6px 20px rgba(0, 0, 0, .07)
        }
        .avatar-wrap {
            position: relative;
            flex: 0 0 auto
        }
        .avatar {
            width: 74px;
            height: 74px;
            border-radius: 50%;
            display: grid;
            place-items: center;
            background: var(--colorBrandBackground);
            color: var(--colorNeutralForegroundOnBrand);
            font-size: 23px;
            font-weight: 800
        }
        .flag {
            position: absolute;
            right: -8px;
            bottom: -8px;
            z-index: 10;
            min-width: 38px;
            height: 38px;
            padding: 0 3px;
            display: flex;
            align-items: center;
            justify-content: center;
            border-radius: 50%;
            background: #fff;
            border: 3px solid #fff;
            font-family: "Segoe UI Emoji", "Apple Color Emoji", "Noto Color Emoji", sans-serif;
            font-size: 25px;
            font-weight: 400;
            line-height: 1;
            letter-spacing: 0;
            white-space: nowrap;
            box-shadow: 0 2px 7px rgba(0, 0, 0, .25)
        }
        .person-card h2 {
            font-size: 19px;
            line-height: 1.25;
            margin: 0 0 8px;
            color: var(--colorBrandForeground1)
        }
        .role {
            display: inline-block;
            margin: 0;
            padding: 5px 9px;
            border-radius: 7px;
            background: var(--colorBrandBackground2);
            color: var(--colorBrandForeground1);
            font-size: 13px;
            font-weight: 750
        }
        @media(max-width:600px) {
            .people-page {
                padding: 18px 12px 36px
            }
            .hero {
                padding: 30px 24px
            }
            .hero h1 {
                font-size: 32px
            }
            .people-grid {
                grid-template-columns: 1fr
            }
        }
    </style>
</head>
<body>
    <main class="people-page">
        <header class="hero">
            <div class="eyebrow">TEAM</div>
            <h1>Unsere Personen</h1>
            <p>Menschen, Funktionen und Herkunft auf einen Blick.</p>
            <div class="count">5 Personen</div>
        </header>
        <section class="people-grid">
            <article class="person-card">
                <div class="avatar-wrap">
                    <div class="avatar">WF</div><span class="flag" role="img" title="Schweiz"
                        aria-label="Schweiz">&#x1F1E8;&#x1F1ED;</span>
                </div>
                <div>
                    <h2>Wapf Flavio</h2>
                    <p class="role">PL</p>
                </div>
            </article>
            <article class="person-card">
                <div class="avatar-wrap">
                    <div class="avatar">IS</div><span class="flag" role="img" title="Deutschland"
                        aria-label="Deutschland">&#x1F1E9;&#x1F1EA;</span>
                </div>
                <div>
                    <h2>Ineichen Sandro</h2>
                    <p class="role">PL</p>
                </div>
            </article>
            <article class="person-card">
                <div class="avatar-wrap">
                    <div class="avatar">KP</div><span class="flag" role="img" title="Österreich"
                        aria-label="Österreich">&#x1F1E6;&#x1F1F9;</span>
                </div>
                <div>
                    <h2>Kälin Patrick</h2>
                    <p class="role">PL</p>
                </div>
            </article>
            <article class="person-card">
                <div class="avatar-wrap">
                    <div class="avatar">FB</div><span class="flag" role="img" title="Deutschland"
                        aria-label="Deutschland">&#x1F1E9;&#x1F1EA;</span>
                </div>
                <div>
                    <h2>Forgas Benjamin</h2>
                    <p class="role">PL</p>
                </div>
            </article>
            <article class="person-card">
                <div class="avatar-wrap">
                    <div class="avatar">SR</div><span class="flag" role="img" title="Schweiz"
                        aria-label="Schweiz">&#x1F1E8;&#x1F1ED;</span>
                </div>
                <div>
                    <h2>Stadelmann Reto</h2>
                    <p class="role">CSD</p>
                </div>
            </article>
        </section>
    </main>
</body>
</html>

Während der erste Entwurf mit JavaScript relativ chaotisch wirkte, war die finale HTML-Version überraschend sauber strukturiert:

  • Verwendung von CSS-Variablen für das Site-Theme
  • Responsives Grid-Layout
  • Moderne Kartenansicht
  • Sinnvolle Klassenstruktur
  • Gute Lesbarkeit des Quellcodes
  • Keine unnötige Komplexität

Besonders positiv fiel auf, dass Copilot die Theme-Farben automatisch über CSS-Variablen eingebunden hat. Dadurch kann sich die Seite grundsätzlich an das verwendete SharePoint-Theme anpassen.

Der generierte Code war insgesamt nahe an dem, was man als Entwickler selbst schreiben würde.

Ergänzung von Filtern

Ich wollte anschliessend noch etwas JavaScript testen und liess deshalb zusätzliche Filter hinzufügen.

Diese sind ebenfalls State of the Art, wie ich sie auch selbst schreiben würde:

image

Wo liegen die Einsatzmöglichkeiten?

Aktuell eignen sich die neuen HTML Pages vor allem für statische Inhalte. Wie gezeigt, können jedoch auch Inhalte aus Datenquellen genutzt werden. Allerdings nur als statischer HTML Content.

Geeignete Szenarien könnten sein:

  • Team-Vorstellungsseiten
  • Willkommensseiten für neue Mitarbeitende
  • Projekt-Landingpages
  • Informationsseiten mit Marketing- oder Agenturdesigns
  • Event- oder Kampagnenseiten
  • Interne Microsites

Weniger geeignet sind derzeit:

  • Anwendungen mit Dateninteraktion
  • Dashboards mit Live-Daten
  • API-basierte Lösungen
  • Seiten mit dynamischen SharePoint-Abfragen

Die Sicherheitsbeschränkungen verhindern momentan viele dieser Anwendungsfälle.
Solche Ansätze würden zudem grundlegenden Prinzipien moderner Softwareentwicklung widersprechen. Eine mögliche Alternative sind SPFx-Webparts.

Fazit

Das neue HTML-Page-Feature in SharePoint ist ein spannender Schritt in Richtung moderner, KI-gestützter Seitenerstellung.

Die grosse Stärke liegt aktuell weniger in der Entwicklung interaktiver Anwendungen als vielmehr in der schnellen Erstellung hochwertiger, statischer Präsentationsseiten. Gerade weil Copilot HTML wesentlich besser erzeugen kann als komplexe ASPX-Strukturen, lassen sich in kurzer Zeit durchaus ansprechende Ergebnisse erzielen.

Besonders spannend ist ausserdem, dass man nicht ausschliesslich auf Copilot-generierte Seiten angewiesen ist. Bereits vorhandene HTML-Seiten können ebenfalls verwendet werden. Dadurch eröffnen sich interessante Möglichkeiten für Designs, die beispielsweise von externen Agenturen erstellt und anschliessend in SharePoint eingebunden werden können.

Mein Fazit nach diesem ersten Test: Für statische, optisch ansprechende Informationsseiten ist das Feature bereits heute gut einsetzbar. Wer jedoch auf Dateninteraktion oder dynamische Inhalte angewiesen ist, wird aktuell noch an die Grenzen des Sandboxing-Konzepts stossen. Dennoch zeigt das Feature deutlich, welches Potenzial die Kombination aus SharePoint und Copilot bietet.

Weitere spannende technische Hintergründe sowie eine Erklärung zu den deklarativ anbindbaren Datenquellen findet man hier: SharePoint HTML pages, what they can and cannot do | Denis Molodtsov Blog

Beitrag teilen
Geschrieben von

Reto Stadelmann

Content Services Developer

Profil anzeigen

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

IOZ_LOGO_weiss

Profis für M365-Intranets & digitale Arbeitsplätze, Power Apps, Power Automate Workflows, sowie Managementsysteme.

Angebote

Angebotsübersicht

   
Nach oben scrollen