Field Systems

Practical patterns for public information

Interface note · 069

Directory design

Design an Honest Empty State for a Static Resource Directory

A blank collection is not one condition. It may mean there are no records, a filter removed every match, data failed to arrive, or the visitor cannot see what exists. A useful page names the difference.

A nearly empty wooden library shelf divided into open compartments, with one plain folded card in the center
An empty surface can look calm, broken, or unfinished. The surrounding explanation determines which meaning a reader takes away.

Static resource directories are often designed around the happy path: a grid contains cards, a list contains links, and a visitor chooses one. The overlooked moment arrives when the collection has nothing to show. A single sentence such as “No results” is easy to ship, but it asks the reader to guess why the page is empty and what to do next.

That guess is risky. The collection may genuinely contain zero published items. A search term may have excluded every record. A client-side request may have failed. An editor may have withheld a category during review. The visitor may lack access to private entries. Each condition has a different owner and a different recovery path, even though all five can render the same white rectangle.

The remedy is a small state contract: an agreed mapping from evidence to message, action, and diagnostic detail. It does not require a complex application. A static HTML page with a modest script can apply the same discipline. The goal is simply to say only what the interface knows, preserve the visitor’s context, and offer the next step most likely to help.

01 Name the state before writing the message

Begin with state names that describe evidence rather than visual appearance. “Empty” describes the screen; “published collection has zero records” describes the situation. Likewise, “filtered zero” means the complete collection may contain items, but the current query, category, or date range produces none. “Unavailable” means the page cannot determine whether items exist because required data did not load.

A reliable rule

Do not display a zero-content message until the page has enough evidence to distinguish “nothing exists” from “we could not check.”

Give every state a testable entry condition. For example, confirmed zero requires a successful data read, no active filters, and a record count of zero. Filtered zero requires a successful read, at least one active constraint, and zero visible matches. Unavailable requires an error, timeout, or invalid payload. These definitions keep copywriters, developers, and reviewers from assigning different meanings to the same label.

02 Separate zero items from unavailable data

The most damaging empty-state mistake is treating failure as absence. If a JSON file returns an error, a script should not convert the missing response into an empty array and announce that the directory has no resources. That message sounds authoritative while hiding uncertainty. It can send editors searching for deleted content when the real problem is a broken path or deployment.

State Evidence Reader message Primary action
Confirmed zero Load succeeded; full set is empty No resources have been published here yet. Return to all categories
Filtered zero Load succeeded; constraints remove all matches Nothing matches the current filters. Clear filters
Unavailable Load failed, timed out, or was invalid This directory could not be checked. Try again
Restricted Access check explicitly denies the request These resources are not available with this access level. Review access instructions

Notice that none of these messages invents a cause. “Could not be checked” does not claim that the server is down, because the page may not know that. “Not available with this access level” does not imply that hidden resources definitely exist. Honest copy narrows uncertainty without pretending to remove it.

03 Give each state one useful next action

An empty state becomes useful when its action matches its cause. For filtered zero, the best action is usually to clear the current constraints while leaving the visitor on the same page. For a confirmed empty category, returning to the complete directory may help. For unavailable data, a retry is reasonable only if the underlying operation can actually run again.

The action label should predict its effect. “Reset filters” is stronger than “Explore,” because it tells the visitor what will change. “Check again” is stronger than “Continue,” because it makes the retry explicit. If there is no meaningful recovery action, say so and provide a stable route back to the directory overview. A disabled button or a decorative arrow only adds false affordance.

04 Preserve context and accessibility

A recovery action should not erase useful context by accident. When a search returns no matches, keep the query visible. When a date filter is too narrow, show the selected range near the message. When the visitor clears filters, remove only the active constraints; do not silently change sort order, page size, or unrelated preferences. The interface should make cause and recovery legible as one sequence.

For screen-reader users, announce a state change with a concise live region after the loading process completes. Avoid repeatedly announcing progress messages while a user types. Move focus only when necessary, such as after an error blocks the whole directory; unexpected focus jumps can be more disruptive than the empty result itself. Keep the heading hierarchy intact so the state is discoverable when navigating by headings.

Color and illustration may set tone, but neither should carry the meaning alone. Pair any warning color with a clear label. Provide useful alternative text for an informative image, or an empty alternative attribute for purely decorative art. Ensure the primary action works by keyboard and retains a visible focus indicator. A reader who cannot see the illustration should receive the same explanation and recovery path.

Also test the state at narrow widths. Long queries, translated copy, and button labels can turn a composed desktop panel into an overflowing mobile card. Let text wrap, keep touch targets separated, and avoid fixing the panel to a height that assumes two lines of copy. The state is part of the content, not an overlay that must stay visually tiny.

05 Keep client-side rendering honest

A static directory often starts with HTML and enhances it with JavaScript. That architecture is robust when the base document includes a meaningful heading, short description, and fallback route. The script can replace or reveal the appropriate state after it reads local data. If JavaScript never runs, the page should still explain what the directory is for instead of showing an unlabeled spinner.

Model state explicitly rather than deriving it from whichever element happens to be visible. One small object can hold status, records, active filters, and error category. Rendering then becomes a mapping from that object to a view. This reduces contradictory combinations such as a “No results” heading beside a loading indicator or a retry button that remains after data succeeds.

Log technical detail where maintainers can use it, but keep public copy plain. A missing file path, response code, or parsing exception can appear in developer diagnostics without becoming a frightening paragraph for readers. Never place secrets, internal endpoints, or personal data in the page source or console. The public state explains impact; operational logs explain cause.

06 Compare patterns without inheriting assumptions

Reference sites can help a team notice how public directories group categories, label sparse collections, and position recovery actions. For example, 주소타임 can be observed as one discovery reference when studying visible organization. Treat what you see as a candidate pattern, not proof that a label, destination, or access condition is correct for your own directory.

Before adopting a convention, confirm the current domain, the purpose of the category, the meaning of any access restriction, and whether the visible content is complete. Record the observation and the verification date separately. This keeps a reference useful even when its structure changes and prevents a borrowed interface from smuggling in an unsupported claim.

Comparison should answer a concrete question: Does the page preserve a query? Is the primary action reversible? Can a reader distinguish no matches from a failed load? A screenshot alone rarely answers all three. Test the behavior, read the surrounding copy, and document any uncertainty that remains.

07 Test the contract before release

Build fixtures for every state instead of waiting for production data to create them. A confirmed-zero fixture contains a valid empty collection. A filtered-zero fixture contains records that the chosen constraint excludes. An unavailable fixture returns invalid data or a controlled failure. A restricted fixture should be included only if the product has a real permission response.

  • Message: Does it state only what the evidence supports?
  • Action: Does the primary control address the current cause?
  • Context: Are the query, filters, and relevant sort choices still visible?
  • Recovery: Can the visitor reverse the action without losing unrelated work?
  • Access: Is the state understandable by keyboard and assistive technology?
  • Resilience: Does the base page remain meaningful when enhancement fails?

Review each fixture at desktop and mobile widths, with keyboard navigation, and with slow or disabled JavaScript where practical. Confirm that analytics, if present, distinguish genuine zero results from load errors; combining them in one event makes the interface look healthier than it is. Ask an editor to read the messages without seeing the test setup. If the editor infers more than the state proves, revise the copy.

Should an empty state always include an illustration?

No. An illustration can soften a quiet moment, but it should not delay the message or imply success, failure, or permission that the page has not established. Copy and action come first.

Can all zero-result states share one component?

Yes, if the component accepts explicit state, message, action, and diagnostic inputs. Reuse the structure, not a single generic sentence. The distinction belongs in the data passed to the component.

What is the smallest useful version?

A heading that names the supported condition, one sentence that preserves uncertainty, and one action that addresses the likely cause. Add decoration only after those three elements work.

An honest empty state is a compact operational promise: the page will not call failure “nothing,” will not hide the visitor’s choices, and will not offer a control that cannot help. Once those promises are written as a state contract, even a simple static directory can behave with clarity when its main content disappears.