Go REST

Test loading skeletons with simulated latency

Use ?delay=N to make Go REST take seconds to respond, so you can verify your skeleton screens render without flicker.

Skeleton screens look great when they actually appear. The problem in development is that requests on localhost return in 20 milliseconds, so you never see the skeleton at all. The first time you hit production with a slow connection, you discover that your skeleton flickers, mis-sizes, or never renders. This recipe fixes that by giving you control over how long the API takes to respond, without changing any production code.

The trick

Append?delay=N to any Go REST GET request, and the API pauses N milliseconds before responding (capped at 5000). TheX-Simulated-Delay-Ms response header confirms the simulation fired.

curl -i "https://gorest.co.in/public/v2/users?delay=2000"

Two seconds is enough to see your skeleton; ten seconds tells you if it gets stuck. Combined with throttling in DevTools (Network tab → throttling preset → "Slow 4G"), you can simulate real network conditions accurately.

A working React component

Standard pattern: render skeleton whenusers === null, real data otherwise. Setusers to[] if the call returns no rows, so the empty state and loading state stay distinct.

function UserList() {
  const [users, setUsers] = useState(null);

  useEffect(() => {
    fetch("https://gorest.co.in/public/v2/users?delay=2000")
      .then(r => r.json())
      .then(setUsers);
  }, []);

  if (users === null) {
    return (
      <ul>
        {Array.from({ length: 6 }).map((_, i) => (
          <li key={i} className="skeleton-row">
            <div className="skeleton skeleton-avatar" />
            <div className="skeleton skeleton-line" />
          </li>
        ))}
      </ul>
    );
  }

  return (
    <ul>
      {users.map(u => (
        <li key={u.id}>{u.name} ({u.email})</li>
      ))}
    </ul>
  );
}

The CSS

A simple shimmer keyframe is enough. Tune the colours to your design system; the key is the moving gradient, which signals "loading, not just blank".

.skeleton {
  background: linear-gradient(90deg, #e5e7eb 25%, #f3f4f6 50%, #e5e7eb 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  border-radius: 4px;
}
@keyframes shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.skeleton-avatar { width: 32px; height: 32px; border-radius: 50%; }
.skeleton-line   { height: 16px; flex: 1; }

Avoid skeleton flicker on fast responses

If your real-world latency averages 80 ms, the skeleton appears for 80 ms and then jumps to data, which is jarring. Two fixes:

Code for the second:

async function fetchWithMinDuration(url, minMs = 400) {
  const [data] = await Promise.all([
    fetch(url).then(r => r.json()),
    new Promise(r => setTimeout(r, minMs))
  ]);
  return data;
}

Test the layout shift

Skeleton sizes should match the real content sizes; otherwise the layout shifts when data arrives. Set explicitheight /width on the skeleton elements that match the rendered content. Lighthouse's Cumulative Layout Shift metric will catch mistakes if you forget.

Other simulation flags

The simulation parameters compose. To test "slow + then 500", combine them:

fetch("/public/v2/users?delay=2000&force_status=500")

This pauses 2 seconds and then returns 500. Useful for testing skeleton + error state in sequence.

Production checklist

More recipes

Keep building

All recipes Integration guides