Progressive Enhancement logo

Progressive Enhancement

Community
mgifford
progressive-enhancement

Load this skill when building any web feature, reviewing architecture decisions, or evaluating JavaScript dependencies. Under no circumstances build features that break completely when JavaScript is unavailable or fails. Absolutely always start with semantic HTML, layer CSS enhancements, and add JavaScript as the final, optional layer. Prioritize resilience and universal access over cutting-edge features.

Overview

Publishermgifford
Repositoryaccessibility-skills
Skill nameprogressive-enhancement
Stars
57
Forks
5
Bundled files
1
LicenseAGPL-3.0
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 1 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by mgifford on GitHub. Read the source before you install it.

Installation

Install the Progressive Enhancement AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/mgifford/accessibility-skills/tree/main/skills/progressive-enhancement
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/mgifford/accessibility-skills.git /tmp/accessibility-skills
mkdir -p .claude/skills
cp -r /tmp/accessibility-skills/skills/progressive-enhancement .claude/skills/progressive-enhancement
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Progressive Enhancement in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Progressive Enhancement on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Progressive Enhancement is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Progressive Enhancement Accessibility Skill

Canonical source: examples/PROGRESSIVE_ENHANCEMENT_BEST_PRACTICES.md in mgifford/ACCESSIBILITY.md This skill is derived from that file. When in doubt, the example is authoritative.

Apply these rules when building any web feature or reviewing architecture decisions.


Core Mandate

Start with a solid foundation that works for every user, then layer enhancements. Every user — regardless of browser capability, network speed, assistive technology, or JavaScript availability — must be able to access core content and complete core tasks.

Progressive enhancement is also a sustainability practice. Pages that work without JavaScript are dramatically lighter: fewer bytes transferred, less CPU spent on parsing and executing scripts, and less energy consumed per page view. See SUSTAINABILITY.md and the Web Sustainability Guidelines.


Severity Scale (this skill)

LevelMeaning
CriticalCore content or task inaccessible without JS/CSS
SeriousCore content accessible but significantly degraded without JS/CSS
ModerateEnhancement degrades gracefully but with friction
MinorBest-practice gap; marginal impact

The Three Layers

Layer 1 — Semantic HTML (always required)

Failure here is Critical.

  • All core content readable in plain HTML — no CSS or JS required
  • Forms submittable with native browser behaviour
  • Navigation functions as standard links
  • Headings, lists, tables, and landmarks accurately reflect document structure

Layer 2 — CSS (enhance presentation)

Failure here is Moderate to Serious.

  • External stylesheets that can be disabled without losing content
  • Respect user preferences: prefers-reduced-motion, prefers-color-scheme, prefers-contrast, forced-colors
  • Page remains usable if stylesheets fail to load

Layer 3 — JavaScript (enhance interactivity)

JS that gates core content or tasks is Critical.

  • JS enhances; it does not gate access to core content or tasks
  • Apply JS-dependent classes/behaviours from scripts, not static markup
  • Handle script failure gracefully — the HTML layer must still work
  • Use feature detection, not browser detection:
js
if ('fetch' in window && 'querySelector' in document) {
  // apply enhanced experience
}

Layer 3 extension — Service Workers (offline capability)

Service Workers are a Layer 3 enhancement: they require JavaScript, are registered by a script, and must degrade gracefully when unavailable (private browsing, unsupported browsers, HTTPS not available).

When implemented, they extend both accessibility and sustainability:

  • Accessibility: users on unreliable connections (common in rural areas, low-income households, and developing regions) can continue to access previously loaded content offline
  • Sustainability: cached responses eliminate repeat network requests, reducing data transfer and server energy per page view
js
// Register Service Worker only if supported — classic PE feature detection
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js').catch((err) => {
    // Registration failure: page continues to work normally without it
    console.warn('Service Worker registration failed:', err);
  });
}

Offline fallback pattern:

js
// sw.js — cache-first with network fallback
const CACHE_NAME = 'v1';
const OFFLINE_URL = '/offline.html';

self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME).then((cache) =>
      cache.addAll([OFFLINE_URL, '/', '/styles.css'])
    )
  );
});

self.addEventListener('fetch', (event) => {
  if (event.request.mode === 'navigate') {
    event.respondWith(
      fetch(event.request).catch(() => caches.match(OFFLINE_URL))
    );
  }
});

The offline fallback page (/offline.html) must itself be a valid Layer 1 HTML document — semantic, readable without CSS or JS.

Service Worker caching strategies (cache-first, network-first, stale-while- revalidate) should be chosen based on content update frequency. Avoid caching strategies that serve stale content for content that changes frequently without a cache-invalidation plan.


Critical: Core Content Must Not Require JavaScript

Rendering page content exclusively in JavaScript is Critical — users with JS disabled, AT users encountering compatibility issues, and low-bandwidth users are completely excluded.

  • Deliver complete HTML from the server; hydrate interactivity in the browser
  • Core content must be in the initial HTML response
  • When using React/Vue/Angular/Svelte: configure SSR or static generation
  • Avoid SPA patterns that require JS to render any visible content

Every byte of JavaScript that is not needed to access core content is unnecessary energy consumption. Prefer server rendering — it transfers HTML once; a JS bundle transfers code that must then be parsed, compiled, and executed on every visit.


Critical: Forms Must Work Without JavaScript

html
<!-- Layer 1: works without JS -->
<form action="/search" method="get">
  <label for="query">Search</label>
  <input id="query" name="q" type="search">
  <button type="submit">Search</button>
</form>

Enhance with JS for instant results, autocomplete, or inline validation — while keeping the server-processed form as fallback.

A form that cannot be submitted without JS is Critical.


Critical: Navigation Must Work Without JavaScript

html
<!-- Layer 1: plain links always work -->
<nav aria-label="Main">
  <ul>
    <li><a href="/about">About</a></li>
    <li><a href="/contact">Contact</a></li>
  </ul>
</nav>

Enhance with JS for dropdowns or animated transitions.


Serious: Dynamic Content Must Have a Fallback Route

js
if ('fetch' in window) {
  loadContentAsync(url);
} else {
  // Standard link navigation works automatically
}

Use aria-live regions only after confirming the base content is accessible without them.


Moderate: CSS User Preferences Must Be Respected

prefers-reduced-motion, prefers-color-scheme, prefers-contrast, and forced-colors are Layer 2 responsibilities. Ignoring them is Moderate at minimum; ignoring prefers-reduced-motion for fast or flashing animations can reach Serious.


What to Avoid

  • Rendering page content exclusively in JavaScript — Critical
  • display:none / visibility:hidden on content required at the HTML layer — Critical
  • Requiring JS to navigate between pages without a server-rendered fallback — Critical
  • user-scalable=no — Serious (prevents zoom for low-vision users)
  • Assuming scripts will execute — always handle failure states
  • Polyfills as a substitute for progressive enhancement (they patch features; PE builds around their absence)
  • Shipping large JS bundles for functionality that could be server-rendered — this is both an accessibility risk and a sustainability cost

Definition of Done Checklist

  • Core content readable with JavaScript disabled
  • Core tasks completable with JavaScript disabled
  • Forms submit via native browser behaviour
  • Navigation works as standard HTML links
  • CSS respects prefers-reduced-motion, prefers-color-scheme, prefers-contrast
  • Script failure handled gracefully
  • Feature detection used (not browser detection)
  • SSR or static generation configured for JS frameworks
  • Service Worker registered with feature detection and silent failure handling
  • Offline fallback page is valid Layer 1 HTML
  • Caching strategy documented and matched to content update frequency
  • Tested: disable JS → verify core content; disable CSS → verify logical reading order

Key WCAG Criteria

  • 2.1.1 Keyboard (A) — native elements have built-in keyboard support
  • 4.1.2 Name, Role, Value (A)

Note: WCAG 4.1.1 Parsing was removed in WCAG 2.2 (August 2023). Modern browsers handle parsing errors uniformly. Valid semantic HTML remains important as a progressive enhancement foundation, but it is no longer a testable WCAG criterion. Do not cite it in audits or compliance statements.


References

Standards horizon: WCAG 3.0 is in development. No breaking changes to progressive enhancement principles are anticipated. Monitor: https://www.w3.org/TR/wcag-3.0/

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Progressive Enhancement AI skill do?

Load this skill when building any web feature, reviewing architecture decisions, or evaluating JavaScript dependencies. Under no circumstances build features that break completely when JavaScript is unavailable or fails. Absolutely always start with semantic HTML, layer CSS enhancements, and add JavaScript as the final, optional layer. Prioritize resilience and universal access over cutting-edge features.

Why use Progressive Enhancement on TypingMind?

Because you install it once and use it with any model. Progressive Enhancement is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Progressive Enhancement in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/mgifford/accessibility-skills/tree/main/skills/progressive-enhancement. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Progressive Enhancement?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Progressive Enhancement?

As many as you like. As long as a model supports skills, you can use Progressive Enhancement with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Progressive Enhancement AI skill free?

Yes. It is published on GitHub by mgifford under the AGPL-3.0 license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇