etechflow / module-faq
etechflow/module-faq
Help-Centre / FAQ module for Magento 2 with categories, slug-based detail pages, search, related articles, REST API, and admin management. Theme-agnostic — works on Hyvä, Luma, and any custom theme.
Etechflow_Faq — Help-Centre / FAQ Module for Magento 2
A self-contained FAQ / knowledge-base module with public detail pages,
admin management, REST API, and full theme/branding configurability.
Works on Magento Open Source, Adobe Commerce, with Hyvä or
Luma themes — no Tailwind, no Alpine, no PageBuilder dependencies.
┌─────────────────────────────────────────────────────────────┐
│ Help Centre & FAQs │
│ │
│ [Search articles...] [Search] │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ ORDERS │ │ RETURNS │ │ DELIVERY │ … │
│ │ ▸ q1 │ │ ▸ q1 │ │ ▸ q1 │ │
│ │ ▸ q2 │ │ ▸ q2 │ │ ▸ q2 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────┘
/faqs → listing of all categories
/faqs/orders/can-i-return-x → detail page with related articles
/rest/V1/etechflow/faq → REST: all categories with items
Features
- Categories with display label, URL identifier, icon, sort order, active toggle.
- Q&A items with auto-generated slugs (unique per category), subtitle, rich answer body, SEO meta title + description.
- Slug-based detail pages at
/faqs/{category}/{slug}— breadcrumb, left-rail category navigation, main content card, right-rail (search/helpful/contact), related articles grid. - Listing page at
/faqs— categories grid (desktop) + mobile accordion, in-page search filter, per-category modal showing all questions. - REST API — three read-only public endpoints returning JSON, no auth required.
- System Configuration for branding (colours, font), hero (image + copy), contact details, and display toggles — no template hacking needed.
- Theme-agnostic — vanilla CSS scoped under
.kfaq-*, vanilla JS (no framework). Renders identically on Hyvä and Luma. - Demo data (opt-in) seeds 9 categories + 36 sample questions for a working out-of-the-box page.
Requirements
| Requirement | Version |
|---|---|
| Magento | 2.4.4 → 2.4.8 (Open Source or Adobe Commerce) |
| PHP | 8.1, 8.2, or 8.3 |
| Frontend theme | Any (Hyvä, Luma, blank, custom) |
Quick start
Manual install (no Composer)
cd <magento-root>
mkdir -p app/code/Etechflow/Faq
# unzip the package into the directory above (so registration.php sits at app/code/Etechflow/Faq/registration.php)
unzip Etechflow_Faq-v1.0.0.zip -d app/code/Etechflow/Faq
bin/magento module:enable Etechflow_Faq
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento setup:static-content:deploy -f
bin/magento cache:flush
Composer install (path repository)
# In <magento-root>/composer.json add:
# "repositories": [{ "type": "path", "url": "../Etechflow_Faq" }]
composer require etechflow/module-faq:^1.0
bin/magento setup:upgrade && bin/magento setup:di:compile && bin/magento cache:flush
Verify
- Admin → Content → FAQs → Categories — lists 0 rows (or 9 if demo data enabled).
- Admin → Stores → Configuration → EtechFlow → FAQ — defaults are populated.
- Storefront →
/faqs— renders the listing page.
Documentation
| File | What's inside |
|---|---|
| INSTALL.md | Manual + Composer install, troubleshooting, post-install cleanup, demo data toggle |
| USAGE.md | Admin walkthrough, REST API, system-config reference, customising the look, layout extension points |
| CHANGELOG.md | Version history |
| LICENSE | MIT |
Module structure
app/code/Etechflow/Faq/
├── Api/ service contracts
│ ├── Data/{Category,Item}Interface.php
│ └── FaqRepositoryInterface.php
├── Block/ view blocks
│ ├── Config.php — reads Stores → Configuration values
│ ├── Listing.php — /faqs landing
│ └── View.php — /faqs/{cat}/{slug} detail
├── Controller/
│ ├── Adminhtml/{Category,Item}/*.php — admin CRUD
│ ├── Index/Index.php — /faqs route
│ ├── Router.php — matches /faqs/{cat}/{slug}
│ └── View/Index.php — detail-page controller
├── Model/ models, resource models, source models, repository
├── Setup/Patch/Data/
│ ├── BackfillUrlKeys.php — populates slugs for legacy rows
│ └── InstallDemoData.php — opt-in seed (9 cats + 36 items)
├── Ui/ admin form/listing data providers + action columns
├── etc/ module config (acl, di, db_schema, system.xml, etc.)
├── view/
│ ├── adminhtml/ admin layouts + UI components
│ └── frontend/ layouts + templates (listing.phtml, view.phtml)
├── composer.json
├── registration.php
└── *.md, LICENSE
Support
Open an issue or reach the maintainer at the email in composer.json.
Changelog
All notable changes to Etechflow_Faq will be documented in this file. The
format is based on Keep a Changelog and
this project adheres to Semantic Versioning.
[1.1.0] — 2026-06-05 — Stripe portal licensing + admin gate + storefront/REST gating + Hero image upload
Added
- Stripe portal subscription licensing. Adds the SP-XXXX subscription-key flow — same pattern shipped on
ETechFlow_BackorderEtaDisplayv1.3.0,ETechFlow_NextDayEligibilityv1.8.0, andETechFlow_ShippingTableRatesv1.2.0. Three plan tiers (Starter $9/mo, Professional $19/mo, Enterprise $49/mo) with in-admin Stripe Checkout, automatic key activation, portal-validated server-IP enforcement, IP-block auto-restore, and 48-hour offline grace when the portal is unreachable. HMAC per-module + bundle keys (LICENSING_PROTOCOL.md) also accepted for offline / bundle activation. Model/LicenseValidator.php(greenfield) — 5-arg constructor with tri-statevalidateViaPortal(): ?boolper the enforcement contract.MODULE_ID = 'faq', uniqueSECRET_FRAGMENTS, sharedBUNDLE_SECRET_FRAGMENTS.- License gate page under Content → FAQs → License & Plans with dark plan-cards UI and a Stripe Checkout button.
- Module Status banner at the top of Stores → Configuration → ETECHFLOW → FAQ / Help Centre. Always-expanded, 5-state (info / warning / success) — tells the merchant exactly why the module is locked (or that it's active).
- Admin gating plugin (
Plugin/Adminhtml/LicenseGatePlugin.php) — every admin Item / Category / Pending / Categoryimage controller redirects to the license gate when not licensed. - Storefront gating plugin (
Plugin/Controller/StorefrontGatePlugin.php) — every/faqs/*request forwards to Magento's noroute (clean 404) when not licensed. - REST API gating plugin (
Plugin/Api/FaqRepositoryGatePlugin.php) — all 12 read methods onFaqRepositoryInterfacereturn empty arrays / null when not licensed. No content leakage via API. <payment>config group for Stripesk_test/sk_live/currency (Encrypted backend model on the secret key).<license>config group withproduction_environment,license_key,bundle_license_key(obscure + Encrypted),portal_url, and auto-managedissued_key+issued_at+ip_blockedfields.
Changed
- Hero image path → image upload widget. Replaced the plain text input with Magento's
type="image"field +backend_model="Image". Files now upload topub/media/etechflow_faq/hero/directly through the admin UI.Block\Config::getHeroImageUrl()updated to resolve bare filenames, scope-prefixed paths (default/foo.jpg), and legacy plain paths — fully backward compatible.
Migration
composer update etechflow/module-faq
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
After upgrade, on a production host the module is locked by default. Go to Stores → Configuration → ETECHFLOW → FAQ / Help Centre → License & Plans and either paste an existing SP-XXXX / HMAC / bundle key, or click "Select Plan & Pay" to buy a subscription via Stripe.
Dev hosts (localhost, *.test, *.local, staging.*, *.ngrok-free.dev, etc.) auto-bypass licensing. Production hosts that aren't auto-detected can opt out with Production Environment = No.
Notes
License Portal URLdefaults tohttps://subpanel-paralyses-president.ngrok-free.dev/license/validate(the eTechFlow portal). For production, change this when eTechFlow publishes the final portal URL.- Portal IP-revoke + suspend lock the module within ~60 seconds (
CACHE_TTL_REJECT= 60). Re-activating in the portal restores the module within the same window viaissued_keyauto-restore.
[1.0.0] — 2026-05-16
Added
- Initial public release.
- Admin: Categories CRUD (label, identifier/slug, icon, sort order, active flag).
- Admin: Q&A items CRUD (question, url_key, subtitle, answer, SEO meta, sort, active).
- Slug auto-generation on save with per-category uniqueness (
-2,-3, … suffix). - Schema-version backfill patch (
BackfillUrlKeys) populates slugs for legacy rows. - Storefront listing at
/faqs— categories grid, mobile accordion, search filter,
modal "all questions in category", contact cards, trust bar. - Storefront detail at
/faqs/{category}/{slug}— breadcrumb, left categories
sidebar with active state, main card (eyebrow + H1 + subtitle + rich answer),
right rail (search, helpful Y/N, contact card), related articles grid. - Custom
Controller/Router.phphandles the/faqs/{cat}/{slug}URL pattern
without colliding with the/faqslisting. - REST API endpoints:
GET /V1/etechflow/faq,GET /V1/etechflow/faq/categories,
GET /V1/etechflow/faq/categories/:id/items. - System Configuration section Stores → Configuration → EtechFlow → FAQ for
branding (primary/secondary/text colors, font), hero (image + title + subtitle),
contact (phone, email, contact-form URL, store-finder URL), and display toggles. - CSS custom properties wired to config so any host theme can re-skin without
forking templates. - Optional demo-data patch (
InstallDemoData, off by default) seeds 9 categories- 36 Q&A items for a new install.
- Composer manifest (
magento2-module, MIT). - INSTALL.md, USAGE.md, README.md, CHANGELOG.md.
Compatible with
- Magento Open Source 2.4.4 → 2.4.8
- Adobe Commerce 2.4.4 → 2.4.8
- PHP 8.1, 8.2, 8.3
- Hyvä Theme 1.3+ (no Hyvä-only code — works on Luma too)
- Luma / blank / any custom frontend theme
| Version | Stability | QA Status | Compatibility | Released |
|---|---|---|---|---|
| 1.2.1 | stable | Fail | Magento 2.4.7-2.4.8 Details | 2026-06-22 14:35:28 |
| 1.2.0 | stable | Not tested | Not yet tested Details | 2026-06-22 14:25:45 |
| 1.1.3 | stable | Not tested | Not yet tested Details | 2026-06-16 09:02:14 |
| 1.1.2 | stable | Not tested | Not yet tested Details | 2026-06-15 10:47:16 |
| 1.1.1 | stable | Not tested | Not yet tested Details | 2026-06-15 09:28:20 |
| 1.1.0 | stable | Not tested | Not yet tested Details | 2026-06-05 11:05:21 |
| 1.0.0 | stable | Not tested | Not yet tested Details | 2026-06-05 10:46:30 |
Requires 6
| Package | Constraint |
|---|---|
| magento/framework | >=103.0 |
| magento/module-backend | >=102.0 |
| magento/module-config | >=101.0 |
| magento/module-store | >=101.0 |
| magento/module-ui | >=101.0 |
| php | ~8.1.0||~8.2.0||~8.3.0||~8.4.0 |
No QA results yet
QA pipelines haven't run for this version. Compatibility and quality results appear here once the vendor publishes a tagged release that gets ingested.
More from etechflow
View vendorDynamic 'View Other Options/Finishes/Sizes' PDP buttons driven by per-product link attributes; replaces hardcoded in-description buttons and strips the old ones at render time.
Theme-agnostic mega menu for Magento 2. Renders on Hyvä, Luma, Adobe Commerce default and custom themes via automatic runtime detection. Provides a JSON endpoint for lazy-loaded subcategory + featured-product data.
EtechFlow Store Locator — admin-managed store/branch finder for Magento 2 with a Leaflet + OpenStreetMap map and postcode proximity search (postcodes.io). Hyva and Luma compatible. No paid map API key required.
Universal Product Fitment Finder for Magento 2 — Make/Model/Year/Part filtering on any fitment domain (automotive, motorcycle, marine, RV, phone cases, watches, appliance parts, anywhere a customer asks "will this fit my X?"). Admin-configurable labels + URL prefix so the same module rebrands to any merchant domain. Includes PDP fitment badge, SEO URLs, customer garage with cross-device sync, OEM/part-number search, and admin tooltips throughout. Theme-agnostic — Hyvä, Luma, custom themes. Renamed from "module-vehicle-compat" in v2.0.0.
Turn an existing module into recurring revenue.
If you already maintain a Magento 2 module on GitHub or GitLab, listing it on Packagento takes about five minutes. We mirror your tags, handle distribution signing, and route paid licenses through Stripe Connect, so you can keep shipping the way you already do.