=== FetchWire — Remote News Feed for Elementor === Contributors: thehopemonger, laurencebahiirwa Donate link: https://store.pesapal.com/kasiryelabs Tags: elementor, news feed, content aggregator, rest api, remote posts Requires at least: 5.8 Tested up to: 6.7 Stable tag: 1.2.0 Requires PHP: 7.4 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html Aggregate and display posts from any WordPress site using 5 beautiful, fully responsive Elementor layouts — no plugin needed on the source. == Description == FetchWire connects your Elementor pages to any external WordPress site and pulls in live posts — titles, featured images, excerpts, categories, dates, and author names — caching the results locally so your site stays fast. No RSS, no iframes, no plugin on the source site. Just a source URL and a layout choice. FetchWire is the ultimate solution for website owners who want to aggregate and display content from other WordPress-powered sites seamlessly. Whether you’re managing a university portal, a corporate news hub, or a niche blog network, FetchWire gives you the tools to pull the latest posts from any WordPress REST API source and present them beautifully on your own site. **The 5 Layouts** = Cards Grid = The classic editorial grid. Each post renders as a white card with a featured image on top, a category badge overlaid at the image bottom, a bold title, an excerpt, the publication date, and a "Read more" arrow. Choose 2, 3, or 4 columns. Cards lift slightly on hover. = Magazine = One large hero post fills the left column with its featured image as a full-bleed background and the title, excerpt, and date overlaid on a dark gradient. The remaining posts stack in a compact sidebar list on the right, each with a small thumbnail and two-line title. On tablets the sidebar drops below the hero as a two-column strip; on phones it becomes a single-column list. = List = A numbered, editorial-style list. Each row shows an index number, a landscape thumbnail, the category badge, a bold two-line title, a one-line excerpt, and the date. An animated arrow on the right nudges right on hover. Best for dense, scannable feeds. = Overlay = Dramatic full-bleed image cards where the category badge, title, and date are laid over a dark gradient at the bottom of the image. Portrait aspect ratio on desktop relaxes to landscape on phones. Cards scale up slightly on hover. Choose 2, 3, or 4 columns. = Ticker = The most compact layout. Numbered rows with a small square thumbnail, the category badge (optional), the post title on one line (truncated with ellipsis), the date, and a right-pointing chevron. Ideal for sidebar widgets or footer news strips. Alternating rows have a subtle background tint. --- **All Layouts Share** * Category name resolved automatically from the source REST API — no manual ID lookup needed for display * Optional category badge, date, section heading, subheading, and "View All" link * Per-widget accent colour override, falling back to the active theme's `--color-accent` CSS variable * No-image fallback placeholder showing the post title's first two initials on a dark gradient background * Outgoing links open in a new tab with `rel="noopener"` * Fully keyboard-navigable anchor elements --- **Performance & Developer Notes** * Responses are cached using the WordPress Transients API (configurable from 15 minutes to 24 hours per widget) * The plugin stylesheet is registered but only enqueued on pages that actually contain the widget, via Elementor's `get_style_depends()` API * No JavaScript — all interactivity is pure CSS transitions * CSS custom properties (`--fw-accent`, `--fw-radius`, `--fw-gap`, `--fw-shadow`) on the widget wrapper make theme integration straightforward * Follows WordPress coding standards throughout: `esc_html()`, `esc_url()`, `esc_attr()`, `wp_kses_post()`, `absint()`, and `sanitize_text_field()` on all inputs and outputs * `uninstall.php` cleans all plugin transients from `wp_options` on deletion == Installation == **From the WordPress Plugin Directory** 1. Go to **Plugins → Add New** in your WordPress dashboard. 2. Search for **FetchWire**. 3. Click **Install Now**, then **Activate**. 4. Open any page in Elementor, search for **FetchWire News** in the widget panel, and drag it onto the canvas. **Manual Installation** 1. Download the plugin ZIP from WordPress.org. 2. Go to **Plugins → Add New → Upload Plugin**. 3. Upload the ZIP and click **Install Now**, then **Activate**. **Via FTP** 1. Extract the ZIP and upload the `fetchwire` folder to `/wp-content/plugins/`. 2. Activate via **Plugins → Installed Plugins**. == Widget Settings Reference == = Source (Content Tab) = * **Section Heading** — Optional heading rendered above the feed (e.g. "Latest News"). Leave blank to hide. * **Subheading** — Optional subtitle rendered below the heading. * **Source Website URL** — The full URL of any WordPress site with its REST API enabled (e.g. `https://example.com`). Required. * **Number of Posts** — How many posts to fetch. Range: 1–50. Default: 6. * **Excerpt Length (words)** — Word count for the auto-generated excerpt. Range: 5–100. Default: 18. * **Cache Duration** — How long fetched data is cached before a fresh request is made. Options: 15 min, 30 min, 1 hr (default), 3 hr, 24 hr. * **Category ID (optional)** — Numeric ID of a category on the source site to filter posts by. * **Tag ID (optional)** — Numeric ID of a tag on the source site to filter posts by. * **"View All" URL** — If set, renders a "View All →" link aligned to the right of the section heading. = Layout (Content Tab) = * **View** — Visual selector for the 5 layouts: Cards, Magazine, List, Overlay, Ticker. * **Columns** — Number of columns for the Cards and Overlay layouts (2, 3, or 4). Not applicable to Magazine, List, or Ticker. * **Show Excerpt** — Toggle excerpt display on Cards, Magazine, and List layouts. * **Show Category Badge** — Toggle the red category pill across all layouts. * **Show Date** — Toggle the publication date across all layouts. = Style (Style Tab) = * **Accent Color** — Overrides the category badge colour, "Read more" link colour, and hover highlights. Defaults to the active theme's `--color-accent` CSS variable, then `#c8102e`. * **Card Border Radius** — Slider controlling the corner radius on cards, list items, and overlay cards. Default: 12 px. * **Title Typography** — Full Elementor typography group control for post titles. * **Excerpt Typography** — Full Elementor typography group control for excerpt text. == Frequently Asked Questions == = Does the source WordPress site need to install anything? = No. FetchWire works with the WordPress REST API, which has been enabled by default since WordPress 4.7. As long as the source site has not deliberately disabled its REST API, FetchWire will work without any changes on their end. = How do I find a category ID or tag ID on the source site? = Log in to the source site's WordPress dashboard and go to **Posts → Categories** (or **Posts → Tags**). Click the item you want to edit — the numeric ID appears in the browser address bar as `tag_ID=123`. Alternatively, hover over the category name in the list and the ID will appear in the status bar link. = The feed shows "No posts found". What should I check? = 1. Confirm the source URL is a live WordPress site with the REST API active by visiting `https://example.com/wp-json/wp/v2/posts` directly in a browser — you should see JSON output. 2. Check that the category or tag ID you entered exists on the source site and has published posts. 3. Some security or caching plugins on the source site block REST API requests from external domains. Contact the source site's administrator to whitelist external REST API access. = How do I clear the cached data immediately? = Change any widget setting (e.g. toggle the section heading on and off) and save the page. This generates a new transient key and triggers a fresh fetch on the next page load. = Can I display posts from multiple different sites on the same page? = Yes. Each FetchWire widget instance maintains its own source URL and its own cache. Drop as many instances as you need and point each at a different source. = Does FetchWire support custom post types? = Not yet. The current version fetches standard `posts` via `/wp-json/wp/v2/posts`. Custom post type support is planned for a future release. = Will it work with a headless or REST-API-only WordPress setup? = Yes, as long as the `/wp-json/wp/v2/posts` endpoint is publicly accessible and returns the standard WP REST API response format with `_embed` support. = Does FetchWire collect any data from my visitors? = No. FetchWire makes server-side requests from your WordPress install to the source site — no visitor data is involved, and no third-party scripts are loaded on your frontend. = Can I use FetchWire without Elementor? = No. The current version is built exclusively as an Elementor widget. A shortcode or Gutenberg block version may be added in a future release. = What happens when the source site is unreachable? = If the remote request fails and no cached data exists, FetchWire renders an empty state notice in place of the feed. If cached data exists, it will continue to display until it expires. == Screenshots == 1. **Cards Grid** — 3-column layout with featured image, category badge, title, excerpt, date, and "Read more" link. 2. **Magazine** — Featured hero post on the left with full-bleed image and gradient overlay; secondary post sidebar on the right. 3. **List** — Numbered rows with thumbnail, category badge, bold title, one-line excerpt, and animated arrow. 4. **Overlay** — Full-bleed image cards with category, title, and date overlaid on a dark gradient. 4-column view. 5. **Ticker** — Ultra-compact numbered rows with small thumbnail, category badge, post title, and date. Sidebar-ready. 6. **Elementor controls panel** — Layout selector (visual icon chooser) and Source settings section. == Changelog == = 1.2.0 = **Responsive & CSS architecture overhaul — no breaking changes.** *Added* * Six responsive breakpoints at 1200 px, 1024 px, 900 px, 768 px, 520 px, and 380 px, covering every major device class from small Android phones to 4K desktops. * CSS custom properties on `.fw-wrap`: `--fw-accent`, `--fw-radius`, `--fw-gap`, and `--fw-shadow`, making per-widget and per-theme overrides cleaner and more predictable. * `box-sizing: border-box` scoped to the widget wrapper so padding cannot break card dimensions inside themes that still use `content-box` globally. * `overflow-x: hidden` and `max-width: 100%` on `.fw-wrap` to prevent any internal layout from causing page-level horizontal scroll. * `min-width` constraints on thumbnail images to prevent flex containers from collapsing them. * `min-width: 0` on grid items (`.fw-card`, `.fw-overlay-card`) to prevent `min-content` blowout in CSS Grid. * `minmax(0, 1fr)` column tracks replacing plain `1fr`, permanently fixing the overflow scrollbar that appeared when 4 cards exceeded their container width. * Fluid typography via `clamp()` on post titles across all layouts, scaling smoothly between breakpoints without hard pixel jumps. * Minimum touch-target heights: 60 px on Ticker rows, 88 px on List rows, meeting WCAG 2.5.5 guidelines. *Improved* * **Magazine layout** — secondary sidebar switches to a 2-column strip below the featured post at 900 px; collapses to single column at 600 px. Sidebar column width narrows to 260 px at 1024 px. * **Overlay layout** — aspect ratio transitions from portrait `2/3` → `3/4` at 768 px → `4/3` at 520 px so cards remain a comfortable height on small screens. * **List layout** — excerpt hidden at 520 px; both row number and excerpt hidden at 380 px to keep rows uncluttered. * **Ticker layout** — row number hidden at 520 px; thumbnail shrinks to 38 px at 380 px so the row stays on one line. * **Cards layout** — featured image now uses `position: absolute; inset: 0` with `object-fit: cover` rather than the percentage padding-top trick, giving sharper rendering and simpler theming. * Plugin stylesheet now registered on both `wp_enqueue_scripts` and `elementor/frontend/after_register_styles` so Elementor's asset manager can always resolve it regardless of page-load hook order. * `readme.txt` fully restructured for WordPress.org reviewer requirements: complete widget reference, Privacy Policy section, Screenshots list, and Upgrade Notice entries. * Plugin file header updated with all required fields: `Requires at least`, `Requires PHP`, `Domain Path`. *Fixed* * Category badge (`.fw-cat`) was stretching full-width inside flex column containers. Fixed with `align-self: flex-start` and `width: fit-content`. * Magazine secondary grid: `border-bottom` was incorrectly stripped from all penultimate items in 2-column state. Now only the true last row loses its separator. * Overlay no-image placeholder did not fill the card height without a `background-image`. Fixed with `position: absolute; inset: 0` on the inner element. * Horizontal overflow scrollbar on 4-column Overlay and Cards grids caused by `1fr` inheriting `min-width: auto` from grid children. Fixed with `minmax(0, 1fr)` tracks and `min-width: 0` on all grid items. = 1.1.0 = **Five new layouts — major feature release.** *Added* * Five display layouts selectable from the Elementor widget panel via a visual icon chooser: Cards Grid, Magazine, List, Overlay, Ticker. * Automatic category name resolution from `_embedded['wp:term']` in the REST API response — no manual ID lookup needed for display. * Section heading, subheading, and "View All" URL controls. * Per-widget accent colour override, falling back to the active theme's `--color-accent` CSS custom property, then `#c8102e`. * No-image fallback placeholder for all five layouts, showing the post title's first two initials on a dark gradient. * `Show Excerpt`, `Show Category Badge`, and `Show Date` toggle controls. * Card border radius slider with Elementor `selectors` binding. * `get_style_depends()` on the Elementor widget class — the plugin stylesheet is loaded only on pages that contain the widget. * `uninstall.php` — deletes all `_transient_fetchwire_*` and `_transient_timeout_fetchwire_*` rows from `wp_options` when the plugin is removed. * Author name extracted from `_embedded['author'][0]['name']` and stored in the post array for future layout use. *Improved* * `class-fetchwire-logic.php` refactored: excerpt cleaner now strips `…` HTML entities and trims whitespace before splitting by word count. * Transient key now factors in `excerpt_length` so changing the word count correctly busts the cache. * `wp_strip_all_tags()` applied to post titles before storage to prevent HTML entities from leaking into layout markup. = 1.0.0 = * Initial public release. * Single grid layout with 1–4 column options. * WordPress Transients API caching with a configurable duration. * Category and tag filtering by numeric ID. * Elementor widget with source URL, post count, excerpt length, and image aspect ratio controls. == Upgrade Notice == = 1.2.0 = CSS architecture update with responsive overhaul. No widget settings are changed and no data is migrated. Safe to upgrade at any time. = 1.1.0 = Major feature update — 5 new layouts, automatic category display, heading and style controls. No existing settings are removed or renamed. == Privacy Policy == FetchWire makes server-side HTTP requests from your WordPress installation to the REST API of the source WordPress site you configure (`/wp-json/wp/v2/posts`). These requests are made using `wp_remote_get()` and fetch only publicly available post data (titles, excerpts, featured images, categories, dates, and author names). **No visitor data is collected, transmitted, or stored by this plugin.** All fetched data is cached locally in your WordPress database via the Transients API and is scoped to your server — it is never sent to any third party. All transients created by FetchWire are automatically removed from your database when the plugin is deleted via **Plugins → Delete**. If you have questions about the data practices of the external WordPress site you are fetching from, please refer to that site's own privacy policy.