Everything posted by Ernest Defoe
-
Bespoke — support and discussion
Bespoke — Custom Theme & Live Builder for Flarum 2 Design your whole forum on the live page — colours, fonts, layout, widgets, chrome — and publish when it's perfect. No code, no rebuilds, no guesswork. Bespoke is a premium theme and an in-context visual theme builder for Flarum 2, in the spirit of Invision Community's Theme Designer. Open the overlay editor right on your forum, change anything, watch it repaint instantly, and hit Publish when you're happy. Visitors only ever see the published result. Table of contentsWhy Bespoke Feature tour The live editor Palette & accessibility Typography (any Google Font) Shape & depth Layout modes — Feed / Grid / Category Hero Effects — header, dark mode, glass, tag colouring Site chrome — announcement bar & footer Widgets Inspector Presets, import & export How it works Installation Using the editor Permissions Internationalisation Performance & security Requirements & compatibility FAQ Pricing Support License Why BespokeMost Flarum theming means editing LESS, redeploying, and refreshing to see what you got. Bespoke replaces that loop with a live, in-context editor: Instant — colour, font, radius, spacing and effect changes repaint with zero server round-trips. Safe — everything you change is a private draft until you Publish; one click reverts. Deep — it's a complete theme in itself (three discussion-list layouts, hero, posts, avatars, header variants), not just a colour picker. No code — but power users still get a Custom CSS escape hatch. Feature tourThe live editorA floating ✦ Edit theme launcher appears for admins. It opens a docked overlay with tabs for every part of the theme; the forum stays fully interactive behind it so you always edit in real context. A light/dark preview switch, Save draft, and Publish sit in the footer. Palette & accessibilitySet every colour role — brand, accent, background, surface, text, muted, border — with independent light and dark values. Don't want to hand-pick seven colours? Generate harmony from Brand derives a balanced palette from one hue. A built-in WCAG contrast checker grades the key text/background pairings live (AA / AAA / fail) so your theme stays readable as you go. Typography (any Google Font)Pick any Google Font by name — not a short curated list, the whole library — for headings and body independently, plus base size, modular type scale, and line-height. System and already-loaded fonts work too. Font links are injected server-side so there's no flash of the wrong typeface. Shape & depthCorner radius, border width, elevation/shadow depth, button styles (solid / soft / outline / ghost), post styles (boxed / flat / bubble), and avatar shapes (circle / rounded / square / hexagon). Layout modes — Feed / Grid / CategoryThe discussion list ships in three first-class layouts, switchable live: | Mode | Look | |---|---| | Feed | Comfortable, separated cards — the refined default. | | Grid | Magazine cards with a cover image (pulled from the first post), excerpt, tag pills, and a participant/reply footer. Configurable columns or auto-fit. | | Category | A classic forum category index built from your tags, inspired by fof/categories — parent tags become sections, child tags become rows with icons, descriptions and counts. | HeroFull control of the welcome hero: height, contained vs. full-bleed width, a brand→accent gradient or a background image, custom text colours, and an admin-locked (non-dismissible) option so the hero always shows. Effects — header, dark mode, glass, tag colouringThe Effects tab is where Bespoke earns its keep: Header style — solid, transparent, or gradient; optional centred logo; sticky on/off. Visitor dark-mode toggle — adds a sun/moon switch to the header so each visitor picks their own scheme (remembered locally, applied before paint — no flash). Glassmorphism — frosted, translucent surfaces; pairs beautifully with a site background image. Subtle animations — tasteful hover/entrance motion, toggleable. Colour UI by active tag — a built-in ramon/colored replacement: on a tag page the hero adopts that tag's colour (with automatically-contrasting text), and the brand accent follows too. Card tag accent — give each discussion card a left bar or full border in its own primary-tag colour, so a mixed list reads as a colour-coded index. Site chrome — announcement bar & footerAnnouncement bar — a dismissible, optionally-linked banner across the top of every page. Custom footer — your own links, social icons (X, Discord, GitHub, YouTube, Facebook, Instagram), and copyright/text — no second extension required. WidgetsDrag widgets from the tray into any zone — above the list, sidebar, below the list, header, hero, or footer — then reorder them by their handle. Click a placed widget to edit its settings in the inspector. | Widget | What it shows | |---|---| | Hero banner | Heading, subheading, CTA, background image. | | Community stats | Discussions / posts / members / online counts. | | Online users | Avatars of who's online now. | | Top Contributors | Ranked by posts, likes received, or discussions, over week / month / all-time. | | Newest Members | Most-recent sign-ups, as a list with join dates or an avatar grid. | | Trending threads | Most-active discussions over 24h / 48h / 7d. | | Call to action | Heading, body, button + link. | | Markdown / HTML | Free-form content block. | | Tag cloud | Popular tags. | | Articles | From Page Builder, shown automatically when that extension is installed. | All data-driven widgets share one cached request per page, so a widget-heavy sidebar stays cheap. InspectorToggle Inspect (⊹) and hover any element on the page — Bespoke highlights it and labels it; click to jump straight to the controls that style it. Presets, import & exportStart from curated themes (Aurora, Carbon, Sunrise, Newsprint, Terminal, Grape), then export your finished theme as a portable .bespoke.json and import it on another Bespoke site — perfect for moving a look between staging and production, or shipping a house style across forums. How it worksBespoke splits styling into two layers so editing feels instant but still reaches deep into Flarum: | Layer | Carries | Mechanism | When | |---|---|---|---| | Instant | colours, fonts, radius, spacing, shadows, effects, layout switches | CSS custom properties in <style id="bespoke-vars"> + data-bespoke-* attributes on <html> | every page load; mutated client-side in the editor for zero-latency preview | | Structural | the premium base theme, layout modes, component styling | compiled LESS (less/forum.less) | at build/compile time | The theme is stored as a single JSON document (tokens + layout + zones + custom CSS + chrome). The editor edits an in-memory copy and applies it live; Save draft persists it for admins only; Publish promotes it to what every visitor sees. Because the instant layer is server-injected, the forum is themed before JavaScript runs — there's no flash of an unstyled or default theme. Installationcomposer require ernestdefoe/bespoke Then enable Bespoke in Admin → Extensions, open your forum, and click ✦ Edit theme (bottom-right). To update: php flarum cache:clear``` --- ## Using the editor 1. Click **✦ Edit theme**. The overlay docks to the side; your forum stays live behind it. 2. Work through the tabs — **Palette, Type, Shape, Layout, Hero, Discussion, Effects, Site, Widgets, Presets**. Every change previews instantly. 3. Use the footer **◑** switch to preview light vs. dark. 4. **Save draft** to keep working privately, or **Publish** to go live for everyone. 5. Use **Inspect (⊹)** any time to jump from an on-page element to its controls. --- ## Permissions The editor and the theme save/publish API are gated on the `bespoke.edit` ability, which is granted to **administrators**. Visitors and regular members never load the editor and cannot write theme data or custom CSS. --- ## Internationalisation Every user-facing string is translatable via standard Flarum locale files (`resources/locale/en.yml`) — tab names, control labels, widget names, hints, and messages. Translations are welcome. --- ## Performance & security * **One request for widgets** — all data widgets share a single, 60-second-cached `widget-data` call per page. * **No render flash** — colours/fonts are injected server-side before JS. * **Visibility-aware** — the Trending widget is scoped to guest-visible discussions, so its shared cache can never leak titles of private or tag-gated threads. * **Admin-only writes** — theme save/publish (including Custom CSS) require `bespoke.edit`; injected custom CSS is additionally sanitised against tag-breakout as defence-in-depth. --- ## Requirements & compatibility * **Flarum** `^2.0` * **PHP** `8.3+` (Flarum 2's minimum) * Optional: [Flarum Tags](https://github.com/flarum/tags) (Category layout, tag colouring, tag accents) and Page Builder (Articles widget) light up automatically when present. --- ## FAQ **Will my visitors see my experiments?** No. Everything is a private draft until you **Publish**. One click reverts. **Can I use a font that isn't in the suggestions?** Yes — type *any* Google Font name; the whole library is available. **Does it replace ramon/colored or fof/categories?** It includes native equivalents — tag-driven colouring and a tag-based category index — so you don't need to run both. **Can I move a theme between forums?** Export `.bespoke.json` on one and import it on another. **Is there a flash of the default theme on load?** No — the instant layer is server-rendered. --- ## Pricing Bespoke is a premium extension sold on [Floxum](https://floxum.com/extension/ernestdefoe/bespoke): | Plan | Price | |---|---| | **Annual** | **$20.00 / year** | | **Lifetime** | **$100.00 one-time** | Both plans include all features and updates. Buy at [floxum.com/extension/ernestdefoe/bespoke](https://floxum.com/extension/ernestdefoe/bespoke). --- ## Support Found a bug or have a request? * **Support site:** [ernestdefoe.online](https://ernestdefoe.online) * **Issues:** [github.com/ernestdefoe/bespoke/issues](https://github.com/ernestdefoe/bespoke/issues) --- ## License Proprietary — commercial license. © 2026 ernestdefoe. See `LICENSE.md`.
-
Page Builder — support and discussion
page-builder 3.0.1 What changed Audit fixes — performance, robustness, and type-safety: Performance: ContentRecordResource::scope() and the record-list block's settings schema now reuse the shared content-types cache (ForumAttributes::cachedTypes()) instead of scanning pagebuilder_content_types on every request. Robustness: comment-provisioning (ShowRecordController) and SEO head-population (PopulateHead) failures are now logged via PSR-3 instead of being silently swallowed; removed a redundant try/catch around the stable core User display_name/avatar_url accessors in ContentSerializer. Type-safety: the record editor page (RecordEditorPage) is fully typed — any replaced with ContentType/Record/Field/Category interfaces and a typed API response shape. Fixed an implicit-nullable parameter deprecation (PHP 8.4+). Install / update: php flarum cache:clear php flarum assets:publish``` [View release on GitHub](https://github.com/ernestdefoe/page-builder/releases/tag/3.0.1)
-
Page Builder — support and discussion
page-builder 3.0.0 Page Builder 3.0.0 Changed (breaking — schema) Discussion record-link data moved off the core discussions table into a new pagebuilder_discussion_data companion table. The pagebuilder_record_id and pagebuilder_promoted columns are removed from discussions. This resolves the §45 finding (extensions shouldn't add columns to core tables) and avoids the install-time ADD COLUMN lock on large discussions tables. The migration is automatic and one-way: on update it creates the companion table, copies existing linked/promoted discussions into it, and drops the old columns. No data is lost (comment threads and promoted-article links are preserved). There's nothing to do beyond the normal update steps. php flarum migrate php flarum cache:clear``` If any of your own code or another extension reads `discussions.pagebuilder_record_id` / `pagebuilder_promoted` directly, switch it to the `pagebuilderData` relation (`$discussion->pagebuilderData?->record_id` / `->promoted`). The built-in promote/demote, comment threads, and listing-hide behaviour are unchanged. ### Verified Migration (create + backfill + drop), the binding-free listing-hide mutator (comment threads stay hidden, promoted discussions stay listed), promote/demote, and article-URL resolution were all verified end-to-end on Flarum 2.0-rc.1. [View release on GitHub](https://github.com/ernestdefoe/page-builder/releases/tag/3.0.0)
-
Page Builder — support and discussion
page-builder 2.2.2 Internal Self-audit pass against the full Flarum 2 security/structure checklist found no new security, performance, mass-assignment, injection, or dead-code issues on top of the 2.1.0–2.2.1 fixes. The only change here is a corrected RelationshipFieldType docblock: it now accurately states that present() returns raw ids and that resolution + visibility gating happen on the frontend via Flarum's own gated API (no server-side resolution). No behaviour change. Known/accepted: pagebuilder_record_id and pagebuilder_promoted live as columns on the core discussions table (rather than a companion table). This is a deliberate design read on hot discussion-listing paths; both are nullable and guarded. A companion-table refactor is deferred to a future major version. View release on GitHub
-
Page Builder — support and discussion
page-builder 2.2.1 Fixed Comment threads are now created atomically. When a published, comment-enabled record is first viewed, its backing discussion + first post are created inside a DB transaction. A failure between the two writes previously could leave an orphaned discussion with no first post, which breaks core discussion listings and serializers. Performance The forum payload no longer scans the content-types table on every page load. pagebuilderContentTypes now reads a 60-second cache of the (actor-independent) content-types list and applies per-actor visibility in PHP; the cache is invalidated immediately when a content type is created, updated, or deleted. Verified live on Flarum 2.0-rc.1. No user-facing behaviour changes. View release on GitHub
-
Page Builder — support and discussion
page-builder 2.2.0 Added Records are now a first-class JSON:API resource at /api/pagebuilder-content-records. They can be loaded via Flarum's app.store and extended by other extensions with the standard Extend\ApiResource(...)->fields(...) extender. Read-only (index + show); the existing gated CMS controllers still handle writes and the type-scoped frontend reads, so nothing about the current UI changes. Visibility is enforced server-side (content-type view permission, published-only for non-admins plus your own drafts) — drafts and restricted-type records are never exposed. Fixed php flarum CLI commands no longer fatal. Since 2.1.0, the pagebuilder:seed-demo command declared an incompatible return type (fire(): void vs Flarum's fire(): int), which crashed every php flarum … console command (cache:clear, migrate, assets:publish, …) when the extension was enabled. Fixed. (Web requests were unaffected.) Verified live against Flarum 2.0-rc.1: the new endpoints, relationship includes, 404s, visibility scoping, and the markdown-render pipeline all serialize correctly, and existing endpoints/forum/admin are unchanged. View release on GitHub
-
Page Builder — support and discussion
page-builder 2.1.2 Security HTML block sanitizer no longer allows the style attribute. Even with javascript:/expression() stripped, a stored style="background:url(https://tracker/p.png)" fired a request from every visitor's browser, leaking their IP and visit time to a third party. Inline styles are now removed wholesale. Performance Forum Stats block caches its counts (members/discussions/posts/online) for 60s instead of running four COUNT queries on every page render — meaningful on large forums where those scans are slow and contend with writes. Internal Extracted the duplicated slug-uniqueness loop (5 controllers) into a single SlugGenerator service with a max-attempts guard. Demo seeder now uses Eloquent models instead of a raw DB connection. Hardened the record-thread listing filter against future Eloquent internals changes. Removed an unused model/table (pagebuilder_areas) that was installed but never referenced. No user-facing behaviour changes besides the sanitizer tightening. View release on GitHub
-
Page Builder — support and discussion
page-builder 2.1.1 Fixed Hero buttons now stay the same size even when the active theme pins a fixed button height. Some themes (e.g. Mosaic) set .Button--primary { height: 36px }. Only the filled hero button carries .Button--primary, so it shrank while the outline button kept its natural height — leaving "Browse articles" and "Browse forum" visibly different sizes. The hero buttons now force height: auto (at a specificity that beats theme .Button rules), so both size from padding and match. Upgrade: composer update ernestdefoe/page-builder && php flarum cache:clear && php flarum assets:publish, then hard-refresh (the compiled forum.css is cached). View release on GitHub
-
Page Builder — support and discussion
page-builder 2.1.0 Changed Fresh installs no longer create demo content. The sample home page and Articles content type were previously seeded by migrations on every install, including production. They are now opt-in. Added php flarum pagebuilder:seed-demo — an idempotent console command that creates the sample home page and Articles content type (with one example record) on demand. Run it whenever you want example content to explore. Performance The pagebuilderRecordUrl discussion attribute now resolves with zero per-discussion queries: the promoted record and its content type are eager-loaded for the whole result set at the DiscussionResource level (with a safe single-lookup fallback). Upgrade notes: existing installs keep any demo content they already have — this only changes behavior for new installs. No action required. View release on GitHub
-
Page Builder — support and discussion
page-builder 2.0.4 Fixed PostgreSQL: discussion listings and search no longer 500. The record-hiding query used pagebuilder_promoted = 1, which Postgres rejects (operator does not exist: boolean = integer). Now uses the SQL-standard IS TRUE, valid on MySQL 8+, MariaDB 10.3+, SQLite 3.23+, and PostgreSQL. Record view counts no longer lose increments under concurrent views — switched to an atomic DB-level increment('view_count'). Failed layout saves in the live editor now show an error instead of silently dropping the spinner (which made a failed save look successful). Image upload shows a clear notice when fof/upload isn't installed instead of failing with a generic error. Changed The promoted-discussion URL attribute resolves the record and its type in a single eager-loaded query instead of two per discussion in listing responses. Admin detection on the page-builder page reads the serialized isAdmin attribute rather than walking the groups relation. Docs Added a Pricing section and Floxum purchase link ($10/year) to the README, plus a note that demo content is seeded on install. fof/upload is now listed under suggest in composer.json (optional, for image uploads). View release on GitHub
-
Page Builder — support and discussion
page-builder 2.0.3 Fixed Homepage hero buttons now render at identical size on every install. The outline (secondary) button drew its border with a real CSS border, which enlarges an auto-sized box; on forums where another extension's sitewide .Button rule won the cascade and reset the filled button's border, the outline button ("Browse forum") rendered larger than the filled one ("Browse articles"). The outline is now drawn with an inset box-shadow (zero layout impact) and the size rules are scoped under .PB-Hero, so the pair stays identical regardless of other extensions' CSS. After updating, run php flarum cache:clear and php flarum assets:publish so the recompiled stylesheet is served. View release on GitHub
-
Page Builder — support and discussion
page-builder 2.0.2 Fixed Admin "Add field" crash -- opening the field editor threw TypeError: e is not a function. The field-type dropdown's map callback shadowed Mithril's global m, so the <option> JSX tried to call a plain object. Renamed the variable. Homepage hero buttons now render at identical size. The outline (secondary) button's 1.5px border made it slightly taller/wider than the filled primary button; the base button now reserves the same border box. Article comments now show every reply instead of just the first batch. The view relied on the discussion endpoint's ~20-post window; it now pages through all of a record's posts. Added The latest-articles / content-list widget now shows a record's category badge when one is assigned, matching the content listing page. View release on GitHub
-
Pick'em — support and discussion
picks 2.1.1 What's Changed A performance + robustness release addressing an 8-item code audit. No user-facing pick/leaderboard behaviour changes. Performance Schedule sync preloads every existing game in one query instead of a lookup per game - a full 17-week FBS season went from ~1,500 individual SELECTs down to one. Live ESPN polling now pre-builds the set of games that already have picks, replacing a per-game existence query on game-day Saturdays. Score aggregation sums each user's totals (points, earned/penalty, accuracy) directly in SQL instead of loading every scored pick into memory - heavy multi-season users no longer pull hundreds of thousands of rows per scoring job. Profile history computes a user's longest streak with a single window-function query rather than walking every pick in PHP. Week pick list reuses the week record already eager-loaded on each game instead of a separate lookup. Internal Extracted the duplicated leaderboard rank helper into one shared UserScore::rankIn() method. Score-sync uses the imported Week class name consistently; removed now-unused imports. Fixed A failed confidence change in the pick UI now rolls back the optimistic update instead of leaving the wrong confidence value on screen. View release on GitHub
-
Mosaic — support and discussion
mosaic 3.4.1 Added Hero nav: a pill for each Page Builder content type (e.g. Articles) now appears in the hero navigation, linking to its /c/{slug} listing. Read from the pagebuilderContentTypes forum attribute, so it works automatically for any content type you define. View release on GitHub
-
Page Builder — support and discussion
page-builder 2.0.1 Added Demote to discussion — reverse a promotion from the discussion controls dropdown (it now toggles Promote/Demote). Deletes the article and restores the discussion; its replies are kept. Changed Promoted discussions now stay in the forum listing and redirect to their article on click (admins aren't redirected, so they can still open the discussion to manage or demote it). Auto-created comment threads remain hidden. Fixed Forum listing 500 (SQLSTATE[HY093]) caused by a bound parameter in the discussion-search union filter — the listing filter is now binding-free. View release on GitHub
-
Page Builder — support and discussion
page-builder 2.0.0 Initial release of the premium Page Builder + CMS for Flarum 2 (versioned 2.0.0 to track Flarum 2 compatibility). Highlights Visual page designer — drag-and-drop blocks in the admin, plus a live WYSIWYG editor on the front end. 15 blocks — hero, heading, text, HTML, image, button, divider, recent & featured discussions, online users, newest members, forum stats, content list, tag grid, and media embeds. Customizable hero banners — full-width or split layouts; gradient, solid, or image backgrounds; custom text color; dual call-to-action buttons. Content types (CMS) — define your own content (articles, downloads, a knowledge base) with custom fields, categories, per-group permissions, listing pages, and comments. Promote a discussion to an article — first post becomes the body, the first image becomes the cover; the discussion becomes the article's comment thread and redirects to it. Built-in SEO — server-rendered title, description, and Open Graph / Twitter tags for pages and records. Fully translatable — every UI string is localized. Requirements: Flarum ^2.0, PHP ^8.3. View release on GitHub
-
Page Builder — support and discussion
Page Builder for Flarum 2A premium drag‑and‑drop page builder + CMS for Flarum 2. Design custom pages from blocks, run structured content types ("databases") like an articles section or knowledge base, and edit it all visually — in the admin **or live on the front end**. No code required. Table of contentsFeatures Requirements Installation Quick start Pages & the block designer The live front‑end editor Block reference Hero banners Content types (the CMS) Comments on records Promote a discussion to an article SEO Setting a custom homepage Permissions For developers: the block & field APIs License FeaturesVisual page designer — build pages from a responsive 12‑column grid of rows → columns → blocks, with drag‑and‑drop reordering, in the admin. Live WYSIWYG editor on the front end — admins get an Edit layout button on any Page Builder page; drag blocks around and edit their settings while seeing the real, rendered result. 15 built‑in blocks — heroes, text/HTML/images/buttons, forum widgets (recent & featured discussions, online users, newest members, stats, tag grid), content lists, and media embeds. Customizable hero banners — full‑width or split layouts; gradient, solid, or uploaded/linked image backgrounds; custom text color; one or two buttons. Content types (CMS) — define your own kinds of content (articles, downloads, a directory, a knowledge base) with custom fields, categories, and per‑group permissions. Records get listing pages, detail pages, and comments. Promote a discussion to an article in one click. Built‑in SEO — server‑rendered titles, meta descriptions, and Open Graph / Twitter cards for every page and record. Open block & field APIs — other extensions can register their own blocks and field types. RequirementsFlarum ^2.0 PHP 8.1+ Optional: flarum/tags — required only for the **Tag Grid** block. Installation php flarum migrate php flarum cache:clear``` Then enable **Page Builder** under *Admin → Extensions*. This is a proprietary, paid extension — see License. --- ## Quick start 1. Open **Admin → Extensions → Page Builder**. 2. Click **New page**, give it a title, and you're dropped into the designer. 3. **Add row → Add block**, pick a **Hero banner**, and edit its heading, background, and buttons. 4. Click **Save changes**, then **Preview**. 5. (Optional) Use the **Forum homepage** card to make your page the site's front page — see Setting a custom homepage.  --- ## Pages & the block designer A **page** lives at `/p/{slug}` (or `/` when set as the homepage) and is built from a layout tree: ```Page └── Row (full‑width / wide / narrow, padding, background) └── Column (1–12 of a 12‑column grid) └── Block (hero, text, widget, …)``` In the designer you can: * **Add / delete / reorder rows**, set each row's width and padding, and give it a background color. * **Add / delete / reorder columns** within a row and set each column's width (out of 12). * **Add / delete / reorder blocks** within and across columns. * **Edit every block's settings** inline (the form is generated from the block's schema). * Set **per‑block visibility** — which device sizes (desktop / mobile) and which user groups can see it. Everything reorders by **dragging the grip handle** (☰); drop zones appear between items as you drag.  --- ## The live front‑end editor Open any Page Builder page as an admin and click **Edit layout** (bottom‑right). The page turns into a live editor where the **real blocks render as you work**: * Drag rows, columns, and blocks to rearrange them. * Click the **⚙ settings** icon on a block to edit it — changes update the live preview instantly (true WYSIWYG). * **Add block** / delete blocks per column. * Click **Save layout** to publish, or **Cancel** to discard.  --- ## Block reference | Block | Category | What it does | |-------|----------|--------------| | **Hero banner** | content | Full‑width or split banner; gradient/solid/image background, heading, subheading, up to two buttons. See Hero banners. | | **Heading** | content | A styled heading (h1–h4), alignment. | | **Text** | content | A rich text paragraph block, alignment. | | **HTML** | content | Raw HTML, **sanitized on save** (scripts & event handlers stripped). Authoring is admin‑only. Great for embeds and custom markup. | | **Image** | media | A single image (uploaded or by URL), optional rounded corners, alignment. | | **Button** | content | A call‑to‑action button (primary/secondary), link, alignment. | | **Divider** | layout | A horizontal rule with adjustable spacing. | | **Recent Discussions** | forum | The latest discussions, visibility‑filtered. | | **Featured Discussions** | forum | Hand‑picked discussions by ID, in your chosen order, with optional excerpts. | | **Online Users** | forum | Avatars of who's online now. | | **Newest Members** | forum | The most recently joined members, with join dates. | | **Forum Stats** | forum | Member / discussion / post / online counts. | | **Content list** | content | Embeds records from a content type (e.g. latest articles) as cards. | | **Tag Grid** | forum | Forum tags as clickable cards (requires `flarum/tags`). | | **Embed** | media | A responsive YouTube/Vimeo embed from a URL, with caption. | --- ## Hero banners The **Hero banner** block (and each content type's optional **listing hero**) is fully customizable: * **Layout** — *Full‑width background* (centered or left text) or *Split* (text panel beside an image panel). * **Background** — **Gradient** (start/end colors + angle), **Solid** color, or **Image** (upload or paste a URL, with an adjustable dark overlay). * **Text** — heading, subheading, and **text color**: light, dark, or a **custom color** to match your theme. * **Buttons** — a primary and an optional secondary button (e.g. "Browse articles" + "Browse forum"). * **Height** & **alignment**. --- ## Content types (the CMS) Page Builder includes a full content‑management layer. A **content type** is your own kind of content — *Articles*, *Downloads*, a *Knowledge base*, a *Directory* — each with its own fields, categories, permissions, and URLs.  **Create one** under *Page Builder → Content types → New content type*, then configure: * **Fields** — text, textarea, rich text, **markdown** (the full Flarum composer with uploads/mentions/emoji), **image** (upload or URL), number, date, boolean, select, multiselect, URL, email, color, rating, and relationship. Mark one as the **title**, and choose which appear in the list view. * **Categories** — optional taxonomy with a filter bar and badges on the listing. * **Permissions** — which groups can **view**, **submit**, and **manage** records. * **Listing hero** — an optional hero banner on the type's `/c/{type}` page. Each type gives you: * A **listing** at `/c/{type}` (cards, category filter, pagination). * A **record page** at `/c/{type}/{slug}`. * A **composer** at `/c/{type}/new` and `/c/{type}/{slug}/edit`.  --- ## Comments on records When enabled for a type, each published record gets a **comment thread** backed by a real Flarum discussion — so comments get mentions, reactions, notifications, and moderation for free. The thread is created lazily on first view and hidden from the normal discussion list. --- ## Promote a discussion to an article Turn any forum discussion into an article from its **controls dropdown → Promote to article** (admin only). The discussion's title becomes the article title and its first post becomes the body; the original discussion is then attached to the new article as its **comment thread** (and drops out of the forum listing). --- ## SEO Page Builder renders SEO tags **server‑side** (so crawlers and social cards see them without running JavaScript) for `/home`, `/p/{slug}`, `/c/{type}`, and `/c/{type}/{slug}`: * `<title>` and `<meta name="description">` * **Open Graph** (`og:type`, `og:title`, `og:url`, `og:description`, `og:image`) * **Twitter** card tags * `article:published_time` for records, plus a canonical URL Record descriptions come from a summary/excerpt and `og:image` from the record's cover image. Pages use the **Meta description** field you set in the designer. The tags are authoritative and de‑duplicated, so they coexist cleanly with a dedicated SEO extension. --- ## Setting a custom homepage 1. In **Page Builder → Forum homepage**, choose the page to use as your front page. 2. Go to **Admin → Basics → Home Page** and select **“Home (Page Builder)”**. Your custom page now serves as the forum's landing route (`/`), Invision‑style. --- ## Permissions * **Pages & the designer** (admin) — building pages and editing HTML blocks is admin‑only. * **Content types** — set per‑type **view / submit / manage** group permissions in the content‑type editor. * **Block visibility** — limit individual blocks to specific groups (enforced server‑side) and device sizes. --- ## For developers: the block & field APIs Register a **block** from any extension: ```// extend.php (new Ernestdefoe\PageBuilder\Extend\PageBuilderBlock(MyBlock::class)),``` ```// forum JS app.pageBuilder.registerBlock('my-block', MyBlockComponent);``` `MyBlock` extends `Ernestdefoe\PageBuilder\Block\AbstractBlock`: declare `type()/name()/icon()/category()`, a `settingsSchema()` (the same schema language the editor renders), and a `resolve($settings, $actor)` returning data **scoped to the actor's visibility**. The matching JS component receives `{ settings, data }`. Register a custom **field type** for content types via `app.pageBuilderFields.register(type, InputComponent, DisplayComponent)`. --- ## License **Proprietary © Ernest Defoe.** A premium paid extension — see [LICENSE](https://github.com/ernestdefoe/page-builder/blob/main/LICENSE) for terms. For licensing inquiries: ernestdefoe@gmail.com
-
Pick'em — support and discussion
picks 2.1.0 What's Changed A performance + robustness release addressing an 11-item code audit. No user-facing pick/leaderboard behaviour changes. Performance Score sync preloads games and pick-existence in bulk instead of two queries per game — a full season went from ~1,800 queries to a couple. Live ESPN polling (every 5 minutes) now bulk-loads the scoreboard's games in one query rather than one lookup per game. Profile stat cards compute each scope's rank and player total in memory from a single load per scope, instead of a separate count query per scope. Public stats resolve all followed-team logos in one query and count scored picks once (previously the same count ran twice). Admin stats resolve the top contested games' teams in a single batched query. Changed Score sync now runs in the background. Clicking "Sync Scores" dispatches a queued job and returns immediately; the admin UI polls for completion and shows the result. Previously the multi-week fetch ran synchronously and could exceed PHP's execution limit on a full season, leaving scores half-synced. (For true async, configure a real queue driver — redis/database — in config.php.) Test-data seeding bulk-inserts picks in chunks instead of one row at a time, so seeding a full fake season no longer times out on shared hosting. Fixed Confidence values are now ignored when confidence mode is disabled and range-checked only when enabled. Logo conversion/save failures are written to the log instead of failing silently, so missing team logos can be diagnosed. Internal Removed redundant service-container bindings in favour of automatic injection. View release on GitHub
-
Mosaic — support and discussion
mosaic 3.4.0 What's Changed Adds blog post creation entry points and section navigation when linkrobins/blog is installed. Added Blog nav pill in the hero pill-row (uses the admin-configured blog nav label/icon, falling back to "Blog" with a feather icon). "Write a Blog Post" in the Quick Actions sidebar panel — shown to members with permission to write posts. "Write a Post" button in the site header on /blog routes — gives authors a direct path to the compose editor on the blog's own pages, which use the blog extension's layout rather than the forum index. Section nav pills ("Discussions" / "Blog") above the blog index and category pages, so the blog feels like a first-class section — useful if you set the blog as your landing page. All entry points are permission-gated (canCreateBlogPost) and only appear when the blog extension is present. Fixed A blank-page crash when navigating to the blog via the in-app nav pill. The blog-page nav wrapper now keys its fragment consistently, resolving a Mithril "vnodes must either all have keys or none have keys" error that only triggered on client-side route transitions. View release on GitHub
-
Mosaic — support and discussion
mosaic 3.3.0 What's Changed Two visual fixes in the discussion list and the sidebar contributor panel. Fixed Top Contributors avatars — the panel now shows actual user profile photos when members have uploaded an avatar. Previously a PHP method-call bug ($u->avatarUrl() rather than $u->avatar_url) silently returned null for every user, falling back to colour-coded initials every time. Tag pills beside the discussion title — tag chips now appear on the same line as the discussion title rather than in a separate full-width row below it. Uses display: contents on the info <ul> to promote tag <li> elements into the title row's flex context, with an invisible row-break sentinel pushing metadata (poster, time) to the next row. View release on GitHub
-
Pick'em — support and discussion
picks 2.0.7 What's Changed A maintenance release — query-performance, robustness, and code-structure fixes. No user-facing feature changes. Performance Schedule sync builds the team lookup once per run instead of re-querying it for every week. The leaderboard-history and profile-history endpoints load all seasons/weeks in batched queries instead of one query per season. The public stats endpoint caches a database-schema check (1 hour) instead of probing it on every request. Fixed The user-scores and leaderboard-context endpoints now return a proper 500 error on an unexpected failure, so a real error is distinguishable from the normal "no picks yet" state. The current_rank score column is now declared on the model, so it's read as an integer (no manual casting). Internal Removed redundant service-container bindings in favour of automatic injection. Split the large /picks page component into a shared state store plus four focused tab components (Matches / My Picks / Leaderboard / History), keeping behaviour identical. View release on GitHub
-
Mosaic — support and discussion
mosaic 3.2.0 What's Changed A code-audit release — the contributor/trending panels now work forum-wide, plus internal robustness fixes. Fixed Top Contributors and Trending panels show real forum-wide data. They previously ranked only the handful of records the current page had loaded (≈20 discussions, often 0 users), so they were usually empty or unrepresentative — and the admin "top contributors" path never worked because its data was never sent to the frontend. Both are now computed and cached server-side and sent as forum attributes. Trending is computed against guest visibility, so it never surfaces a discussion a guest couldn't already see. Marketplace promo + hero stat labels are translatable. They were hardcoded English; they now route through the locale file so translators' overrides take effect. Internal The forum-payload fields are built by a container-injected class instead of manual service resolution. Resolved-ticket counting uses a small Eloquent read-model rather than a borrowed raw database connection. The hero pill-row no longer instantiates a core component out of its lifecycle to read its nav items; it builds its own row. Removed an unused duplicate component and de-duplicated the composer-open helper into a single utility. View release on GitHub
-
Pick'em — support and discussion
picks 2.0.6 What's Changed Fixed Route id handling for admin/user actions. Result entry, week open/close, pick deletion, and individual team-logo refresh now read the {id} path segment via $request->getAttribute('routeParameters') — the canonical Flarum 2 source for route parameters. Leaderboard movement arrows. previous_rank was freezing at a user's first-ever rank, so the up/down arrows showed stale deltas. A new current_rank column now lets each scoring pass roll the prior rank into previous_rank, so the arrows reflect the real change since the last scoring. Performance Live scoring writes rank movement in one batched database statement per scope instead of one update per player (a popular game previously fired hundreds of updates). The public stats widget resolves all referenced teams in a single query instead of up to ten lookups per request. Profile history loads a user's season scores in one query instead of one per season. Security / packaging The admin "Testing" data-seeding tools are now gated behind debug mode, so they aren't a permanent admin API on production installs. The seeding engine was extracted into its own service and made more memory-efficient. composer.json now explicitly requires guzzlehttp/guzzle and intervention/image (previously relied on transitively). Internal Split the profile-history controller into focused builder methods. View release on GitHub
-
Mosaic — support and discussion
mosaic 3.1.0 What's Changed A code-audit release — the hero stats are now accurate, plus internal robustness and type-safety fixes. Fixed Accurate hero counts. The "Discussions" and "Posts" tiles previously fell back to counting only the discussions loaded on the current page — so every visitor saw a small, misleading number (e.g. "20 Discussions"). They're now backed by real, cached forum-wide totals computed server-side. Dead "extra nav links" branch removed. A header-nav feature that was never wired to any setting or admin control has been removed. Fallback category tiles now navigate. On a fresh install without flarum/tags, the six placeholder category tiles linked to # and did nothing; they now go to the discussion index. Internal The statistics service no longer depends on a low-level database connection interface, and the support-extension table probe is now resolved through Flarum's own model connection (the DB/Schema facades aren't usable in Flarum). The shared translate() helper, previously copy-pasted into three components, is now a single utility. Every frontend component is fully TypeScript type-checked — the @ts-nocheck escape hatches are gone, so attribute typos are caught at compile time. View release on GitHub
-
Mosaic — support and discussion
Mosaic A polished, configurable Flarum 2 theme. Works as a standalone visual upgrade on any forum, with opt-in integrations for fof/best-answer, fof/reactions, ram0ng1/colored, and (when installed) linkrobins/support and ramon/marketplace. Status: active development. LESS theme is complete, JS components are in place, design preview ships in preview/. What you getTiled hero panel with title, search, and a configurable stats strip (Members / Discussions / Posts / Online Now — and Tickets Resolved when linkrobins/support is detected) Category tiles below the hero — auto-populated from flarum/tags when installed Configurable sidebar — Marketplace promo, Quick Actions (admin-editable rows: icon, label, URL), Top Contributors, Trending. Each panel can be hidden from the admin UI Optional support-ticket styling — when linkrobins/support is enabled, the 5-state workflow (Open → In Progress → Awaiting You → Resolved → Closed), staff control bar, internal notes, and SLA pills all light up Optional marketplace styling — when ramon/marketplace is enabled, the storefront, product cards, and cart get themed (verified against the real .MpShop-* DOM) Best-answer highlight for fof/best-answer — full-width banner on the chosen reply Reactions popup styled after ram0ng1/avocado's cascade pattern Tag-coloured borders for ram0ng1/colored on the discussion list and posts Full dark mode via Flarum 2's native [data-theme^=dark] selector DM Sans typography, organic 14px radii, calm primary palette Install php flarum cache:clear``` Then enable in **Admin → Extensions → Mosaic**. ### Configure All theme settings live in **Admin → Extensions → Mosaic**: * **Hide sidebar widgets** — toggle Marketplace promo / Quick Actions / Top Contributors / Trending individually * **Quick Actions editor** — dynamic row editor for the sidebar's Quick Actions card. Each row is an icon class, a label, and a URL. Defaults to `Start a Discussion / Browse Tags / Recent Activity` for any Flarum install, and surfaces `Open a Support Ticket` / `Visit the Marketplace` extras when those extensions are detected * **Section URL overrides** — point the auto-detected support / marketplace links elsewhere if you've mounted them on non-default paths ## Develop ```cd js npm install npm run dev # watch mode npm run build # production``` The frontend uses `flarum-webpack-config` v3 — `js/forum.js` and `js/admin.js` are auto-discovered, with webpack running from `js/` and emitting to `js/dist/`. Compiled bundles in `js/dist/` are committed because Flarum extensions installed via Composer ship prebuilt assets. ## Structure ```mosaic/ ├── composer.json # Flarum 2 extension manifest ├── extend.php # PHP extender — registers forum/admin frontends + settings bridge ├── src/Api/ │ ├── AddForumSettings.php # SettingsRepositoryInterface helpers │ └── AddForumStatistics.php # Member/online/resolved counts ├── js/ │ ├── package.json │ ├── webpack.config.js │ ├── forum.js / admin.js # entries (discovered by webpack) │ ├── dist/ # compiled bundles, committed │ └── src/ │ ├── forum/ │ │ ├── index.js # initializer + IndexPage hooks │ │ └── components/ │ │ ├── HeroPanel.js # branded hero + stats strip │ │ ├── CategoryTiles.js # category grid │ │ ├── SidebarPanels.js # Marketplace promo / QA / contributors / trending │ │ ├── MarketplacePromoCard.js # sidebar CTA │ │ ├── HeaderNav.js # primary nav items │ │ └── SectionHeader.js │ └── admin/ │ ├── index.js │ └── extend.js # Admin settings (visibility, URLs, QA editor) ├── less/ │ ├── forum.less / admin.less # entries │ ├── tokens.less # CSS custom properties │ ├── base.less, header.less, hero.less, categories.less, discussions.less, │ │ post.less, sidebar.less, composer.less, support.less, marketplace.less, │ │ reactions.less, colored.less, layout.less, dark.less ├── locale/en.yml └── preview/ # static HTML mockup (design source of truth)``` ## Pairing with optional extensions | Surface | Source | Where styled | |---|---|---| | Discussion list / detail | Flarum core | `discussions.less`, `post.less` | | Tags (coloured borders) | `ram0ng1/colored` | `colored.less` | | Reactions popup | `fof/reactions` | `reactions.less` | | Best-answer highlight | `fof/best-answer` | `post.less` `.Post--bestAnswer` | | Tickets (5-state workflow, internal notes) | `linkrobins/support` *(optional)* | `support.less` | | Marketplace storefront / cards / cart | `ramon/marketplace` *(optional, paid)* | `marketplace.less` | Each integration's LESS is a no-op when the source extension isn't installed — Mosaic stays clean on a vanilla Flarum. ## Design preview The `preview/` directory ships a static HTML mockup of every surface — open `preview/index.html` directly or run `npx serve preview/` to inspect the design without a Flarum install. Treat that mockup as the visual source of truth. ## Credits * **DM Sans** by Colophon Foundry, via Google Fonts * **Font Awesome 7** for iconography * Visual cues borrowed from [Avocado](https://discuss.flarum.org/d/27126) by ramon ## Support Questions, bug reports, and feature requests: * **Support forum:** https://ernestdefoe.online * **Issues:** https://github.com/ernestdefoe/mosaic/issues ## License MIT — see [LICENSE](https://github.com/ernestdefoe/mosaic/blob/main/LICENSE).