DEV Community

hubs
hubs

Posted on

Generating a Card in the FacetWP Listing Builder

good day dear folks

"Generating a Card in the FacetWP Listing Builder"

description: "A step-by-step guide on building a mini-catalog with WordPress, CPT-UI, ACF Pro, and FacetWP, focusing on card design, performance, and GDPR."

tags: "wordpress, facetwp, tutorial, webdev"

Hi there, good evening, dear friends,

How are you doing? Today, we're going to dive into generating a card in the FacetWP Listing Builder.

I currently want to build a mini-catalog website using:

  • WordPress
  • CPT-UI (for custom post types)
  • ACF Pro (for custom fields)
  • FacetWP (for filtering/search)

The Goal: I want to display ~300 catalog items as clean, professional cards, using ONLY public data (no personal info for GDPR safety).

Since I've been receiving lots of help on such WordPress postings, I want to ask here if somebody could help out!

So, here is the start... see below my current setup and the plan, with some ASCII images that I have created.

First Things First: Understanding FacetWP

First of all, as I am pretty new to FacetWP, here are some preliminary questions and assumptions:

a. FacetWP allows us to visually design how we search results (posts, products, etc.). That said:
b. All the data should appear on the WordPress site.

The core question is: how to generate a card using the FacetWP Listing Builder?
Which methods and techniques are used here? Which pitfalls are known and what approaches can you recommend?

Below, I have written down some thoughts, ideas, and some possible "approaches."

I look forward to hearing from you.

Greetings,
ps. See some of the things I already have, which are the conceptual basics. Now I have to find out how to operate all these things.

The Master Plan

A schematic view of the setup:

Week 1: Setup

├── Create CPT via CPT-UI
├── Add ACF fields
└── Import data (manually or via CSV)
Enter fullscreen mode Exit fullscreen mode

Then: Design

├── Build basic card in FacetWP
├── Add grid layout
├── Style hover effects
└── Test on mobile
Enter fullscreen mode Exit fullscreen mode

Then: Filters & Polish

├── Configure facets
├── Add facet labels
├── Test all combinations
└── GDPR/legal review
Enter fullscreen mode Exit fullscreen mode

System Architecture & GDPR Safety

Here is a general overview of the card-creation process:

┌─────────────────────────────────────────────────────────┐
│              MINI-CATALOG SYSTEM ARCHITECTURE           │
└─────────────────────────────────────────────────────────┘

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   DATA SOURCE   │───▶│   STRUCTURE     │───▶│  PRESENTATION   │
│  (Source Data)  │    │  (WordPress)    │    │   (FacetWP)     │
├─────────────────┤    ├─────────────────┤    ├─────────────────┤
│ Public Data     │    │ Custom Post Type│    │ Listing Builder │
│ Source (e.g.,   │    │ "Catalog Items" │    │ Card Template   │
│ EU Database)    │    │ (via CPT-UI)    │    ├─────────────────┤
├─────────────────┤    ├─────────────────┤    │ • Card Design   │
│ SELECT ONLY:    │    │ ACF Pro Fields: │    │ • Grid Layout   │
│ ✓ Item Title    │    │ • Title         │    │ • Filters       │
│ ✓ Country       │    │ • Country       │    │ • Search        │
│ ✓ Category      │    │ • Website       │    └─────────────────┘
│ ✓ Technologies  │    │ • Type          │            │
│ ✓ Sector        │    │ • Technologies  │            ▼
│ ✓ Website       │    │ • Sector        │    ┌─────────────────┐
│ ✗ No Personal   │    │ • Description   │    │   FINAL OUTPUT  │
│   Data          │    └─────────────────┘    │  Mini-Catalog   │
└─────────────────┘              │             │  Cards with:    │
         │                       │             │ • Clean design  │
         ▼                       ▼             │ • Hover effects │
┌─────────────────────────────────────────────────────────┐   │ • 2-3 columns   │
│                 GDPR SAFE ZONE                           │   └─────────────────┘
│  ✓ No personal data stored                                │
│  ✓ Only institutional information                         │
│  ✓ Public data only                                       │
│  ✓ Legal notice on website                                │
└─────────────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Card Design Overview

Here are a few design options I'm considering:

Option 1: Minimal Option 2: With Icons Option 3: Compact
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Item Name │ │ Item Name │ │ Item Name │
│ │ │ │ │ ┌─────────────┐ │
│ Type: Value │ │ Type: ● Value │ │ │ Type/Country│ │
│ Country: Value │ │ Country: DE │ │ └─────────────┘ │
│ │ │ Tech: Cloud │ │ │
│ [Details] │ │ [Details] │ │ [→] │
└─────────────────┘ └─────────────────┘ └─────────────────┘

Step-by-Step Card Building: My Approaches

Step 1: Outer Card

┌─────────────────────────────────┐
│  Padding: 20px                  │
│  Border: 1px solid #e5e5e5      │
│  Border-Radius: 8px             │
│  Background: #ffffff             │
└─────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Step 2: Title

┌─────────────────────────────────┐
│   Title (clickable)              │
│  Font: Large, Bold              │
│  Margin-bottom: 10px            │
└─────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Step 3: Meta Area

┌─────────────────────────────────┐
│  Type: Example                  │
│  Technologies: Cloud, AI        │ ← Font: Small
│  Sector: Health                 │ ← Color: #666
└─────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Step 4: Button

┌─────────────────────────────────┐
│     [ View Item ]               │ ← Border-Radius: 6px
└─────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

The Current Setup: A Summary

┌─────────────────────────────────────────────────────────┐
│                    SYSTEM ARCHITECTURE                   │
├─────────────────────────────────────────────────────────┤
│ 1. Custom Post Type "Catalog Items" (CPT-UI)           │
│ 2. ACF Fields: Title, Country, Type,                    │
│    Technologies, Sector, Website, Description           │
│ 3. FacetWP Listing Builder for card design              │
│ 4. Frontend: Filterable grid of cards                   │
└─────────────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

I've created the taxonomies in the Listing Builder. I think I can add lots of the above-mentioned data in these fields.

My To-Do List for the Card Design

I have to create the following things:

  • Basic card with padding, border, border-radius
  • Clickable title linked to single page
  • Meta information in small gray text
  • "View Item" button
  • Grid layout with CSS

The Card Design I am aiming for:

┌─────────────────────────────────┐
│   [Item Title - clickable]      │
├─────────────────────────────────┤
│ Type: Example Value             │
│ Technologies: Cloud, AI, IoT    │
│ Sector: Healthcare              │
├─────────────────────────────────┤
│         [ View Item ]           │
└─────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

The Game-Changing Advice I Received

The community provided some incredible insights. Here’s the corrected understanding and best practices.

The Core Concept: FacetWP's Role

My previous thinking was that FacetWP "builds" the card. The reality is that FacetWP delivers the data, and you tell it what to display.

My previous thinking:           Corrected understanding:
┌─────────────────┐             ┌─────────────────┐
│ FacetWP         │             │ FacetWP         │
│ "builds" the    │             │ delivers data   │
│ card            │             │                 │
├─────────────────┤             ├─────────────────┤
│ That was too    │             │ YOU tell it:    │
│ optimistic      │             │ "Show title,    │
│                 │             │ then ACF field X│
└─────────────────┘             │ then button"    │
                                  └─────────────────┘
                                          │
                                          ▼
                                  ┌─────────────────┐
                                  │ CSS formats     │
                                  │ everything into │
                                  │ a proper card   │
                                  └─────────────────┘
Enter fullscreen mode Exit fullscreen mode

The Golden Rule: Conditional Display

"Only show fields if they have values." This is GOLD for a clean design!

Without condition check: With condition check:
┌─────────────────┐ ┌─────────────────┐
│ Hub XYZ │ │ Hub XYZ │
│ Type: │ ← empty! │ Technologies: │
│ Technologies: │ │ Cloud, AI │
│ Cloud, AI │ │ Sector: Health │
│ Sector: Health │ └─────────────────┘
│ Website: │ ← empty!
└─────────────────┘

In FacetWP Listing Builder: For each field, check "Show if not empty".

The Performance Tip Par Excellence: Pagination

Don't load all 300 at once!

Bad practice: Good practice:
┌─────────────────┐ ┌─────────────────┐
│ 300 Cards │ │ Page 1: 12 Cards│
│ → slow │ │ → fast │
│ → overwhelming │ │ → clear │
│ → mobile nightmare│ │ → "Load More" │
└─────────────────┘ │ or pager │
                        `└─────────────────┘`
Enter fullscreen mode Exit fullscreen mode

FacetWP → Settings → Pager:

  • [x] Enable pager
  • Results per page: 12
  • Pager style: (●) Numbers / ( ) Load more / ( ) Infinite scroll

Practical Implementation in FacetWP

Here’s how the logic translates into a card structure:

STEP 1: Base Structure (always visible)
┌─────────────────────────────────────┐
│ ⬛ TITLE (Post Title)                │ ← always there
│    • Link: Post URL                  │
│    • Style: Large, Bold              │
├─────────────────────────────────────┤
│                                      │
│ STEP 2: Conditional Fields           │
│ ┌─────────────────────────────────┐ │
│ │ [SHOW ONLY IF NOT EMPTY]        │ │
│ │ ⬛ Type ACF Field                │ │
│ │   • Label: "Type: "             │ │
│ │   • Condition: "Show if not empty"│
│ └─────────────────────────────────┘ │
│                                      │
│ ┌─────────────────────────────────┐ │
│ │ [SHOW ONLY IF NOT EMPTY]        │ │
│ │ ⬛ Technologies ACF Field        │ │
│ │   • Label: "Technologies: "     │ │
│ │   • Condition: "Show if not empty"│
│ └─────────────────────────────────┘ │
│                                      │
│ ┌─────────────────────────────────┐ │
│ │ [SHOW ONLY IF NOT EMPTY]        │ │
│ │ ⬛ Sector ACF Field              │ │
│ │   • Label: "Sector: "           │ │
│ │   • Condition: "Show if not empty"│
│ └─────────────────────────────────┘ │
├─────────────────────────────────────┤
│ ⬛ BUTTON                            │ ← always there
│    • Text: "View Details"           │
│    • Link: Post URL                 │
└─────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

The Result: From Cluttered to Clean

BEFORE (all fields, even empty ones):

┌─────────────────────────────────┐
│ Digital Hub Berlin             │
│ Type:                          │ ← empty!
│ Technologies: Cloud, AI        │
│ Sector:                        │ ← empty!
│ Website:                       │ ← empty!
│ [View Hub]                     │
└─────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

AFTER (only filled fields):

┌─────────────────────────────────┐
│ Digital Hub Berlin             │
│ Technologies: Cloud, AI        │
│ [View Hub]                     │
└─────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

MUCH cleaner!

The CSS: Making it a Real Grid

This CSS handles the grid, the card styling, and ensures equal heights (button always at the bottom).

/* Equal height cards with different content */
.facetwp-template {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 24px;
    align-items: stretch;  /* Critical for equal heights */
}

.catalog-card {
    display: flex;
    flex-direction: column;
    height: 100%;  /* Full height in grid */
    padding: 20px;
    border: 1px solid #e5e5e5;
    border-radius: 8px;
    background: #ffffff;
    transition: all 0.3s ease;
}

.catalog-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 10px 20px rgba(0,0,0,0.15);
}

.catalog-card .button {
    margin-top: auto;  /* Pushes button to the bottom */
    align-self: flex-start;
    padding: 8px 16px;
    background: #0073aa;
    color: white;
    text-decoration: none;
    border-radius: 4px;
    border: none;
}

/* Meta information styling */
.card-meta {
    font-size: 0.9em;
    color: #666;
    margin: 10px 0;
    line-height: 1.6;
}

.card-meta p {
    margin: 5px 0;
}
Enter fullscreen mode Exit fullscreen mode

Responsive Behavior

The CSS handles this automatically with grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));.

Desktop (3 cols): Tablet (2 cols): Mobile (1 col):
┌───┬───┬───┐ ┌───┬───┐ ┌─────────┐
│ C │ C │ C │ │ C │ C │ │ C │
├───┼───┼───┤ ├───┼───┤ ├─────────┤
│ C │ C │ C │ │ C │ C │ │ C │
└───┴───┴───┘ └───┴───┘ └─────────┘

For fine-tuning on mobile:

@media (max-width: 768px) {
    .facetwp-template {
        gap: 16px;  /* Smaller gap on mobile */
    }
}
Enter fullscreen mode Exit fullscreen mode

Accessibility Implementation

Ensure keyboard users can navigate your cards easily.

Keyboard Navigation:

[Tab] → [Hub Title] (focus)
  ↓
[Tab] → [View Button] (focus)
  ↓
[Enter] → Open link
Enter fullscreen mode Exit fullscreen mode

Suggested HTML structure:

<a href="..." class="card-link" aria-label="View details for Hub Name">
    Hub Name
</a>
... content ...
<a href="..." class="button" aria-label="View full details">
    View Details
</a>
Enter fullscreen mode Exit fullscreen mode

Implementation Checklist

  • [ ] Listing Builder: Enable "Show if not empty" for all ACF fields.
  • [ ] Pagination: Set to 12-24 items per page.
  • [ ] CSS: Implement equal height cards (button always at bottom).
  • [ ] Testing: Check cards with 1-2 fields vs. fully filled ones.
  • [ ] Mobile: Test in Chrome DevTools for all screen sizes.
  • [ ] Accessibility: Ensure keyboard navigation works.
  • [ ] Performance: Monitor load time with 300+ items.

Bonus: Handling Empty States

What if ALL optional fields are empty?

┌─────────────────────────────────┐
│ Digital Hub Berlin             │
│ [View Hub]                     │
└─────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

→ Still works! Clean and honest.

Summary & Key Takeaways

  1. FacetWP delivers data, you design the cards.
  2. Conditional display is crucial—only show what exists.
  3. Pagination is crucial—never overwhelm the user or the browser.
  4. CSS does the heavy lifting—grid, hover effects, and responsiveness.

Questions for the Community

I'm still looking for advice on:

  • Grid Layout: 2 vs 3 columns on desktop? What's your experience?
  • Hover Effects: Subtle vs noticeable? Any creative ideas?
  • Empty Fields: How do you handle missing data elegantly?
  • Performance: Best practices for ~300 items with filters?
  • Accessibility: What should I consider for card interfaces?
  • Responsive Design: How do your cards behave on mobile?

What's working well:

  • FacetWP Listing Builder is intuitive for visual design.
  • Clear separation (CPT for structure, ACF for data, FacetWP for display).
  • No code needed for basic card layout.

Current challenges:

  • Adding facet labels requires custom PHP.
  • Ensuring consistent card heights.
  • Mobile optimization.
  • Performance with many filters.

I'd love to hear from you!

  • How do you structure your ACF fields for catalog items?
  • Any FacetWP tips/tricks you've discovered?
  • What's your approach to card design in 2024?
  • How do you handle GDPR when displaying third-party data?

Would love to see examples of your FacetWP projects and hear about what worked (or didn't)!

Thanks in advance!

Top comments (0)