{"id":58,"date":"2026-09-18T15:51:45","date_gmt":"2026-09-18T14:51:45","guid":{"rendered":"https:\/\/lg-systems.net\/lgs\/?page_id=58"},"modified":"2026-09-20T17:32:02","modified_gmt":"2026-09-20T16:32:02","slug":"montrafolio","status":"publish","type":"page","link":"https:\/\/lg-systems.net\/lgs\/montrafolio\/","title":{"rendered":"MontraFolio"},"content":{"rendered":"\n<style>\n.lgmf {\n  --lgmf-fg:#1c1c1e; --lgmf-muted:#5a5a60; --lgmf-line:#e2e2e6;\n  --lgmf-accent:#2b5bb5; --lgmf-accent-fg:#fff; --lgmf-soft:#f4f6fa;\n  --lgmf-ok:#1f7a4d;\n  color: var(--lgmf-fg); line-height: 1.65; max-width: 62rem; margin: 0 auto;\n}\n@media (prefers-color-scheme: dark) {\n  .lgmf {\n    --lgmf-fg:#e8e8ea; --lgmf-muted:#a0a0a8; --lgmf-line:#33333a;\n    --lgmf-accent:#7aa2e8; --lgmf-accent-fg:#10131a; --lgmf-soft:#1e2027;\n    --lgmf-ok:#5cc48d;\n  }\n}\n.lgmf * { box-sizing: border-box; }\n.lgmf h1, .lgmf h2, .lgmf h3 { line-height: 1.25; }\n.lgmf h1 { font-size: clamp(1.9rem, 1.2rem + 2.4vw, 2.9rem); margin: 0 0 .6rem; letter-spacing: -.02em; }\n.lgmf h2 { font-size: clamp(1.35rem, 1.1rem + 1vw, 1.75rem); margin: 0 0 .9rem; letter-spacing: -.01em; }\n.lgmf h3 { font-size: 1.05rem; margin: 0 0 .35rem; }\n.lgmf p { margin: 0 0 1rem; }\n.lgmf ul { margin: 0 0 1rem; padding-left: 1.25rem; }\n.lgmf li { margin-bottom: .35rem; }\n.lgmf a { color: var(--lgmf-accent); }\n.lgmf strong { font-weight: 600; }\n.lgmf code { font-size: .92em; }\n\n.lgmf .lgmf-section { padding: 2.6rem 0; border-top: 1px solid var(--lgmf-line); }\n.lgmf .lgmf-section:first-child { border-top: 0; padding-top: 1rem; }\n.lgmf .lgmf-lead { font-size: 1.15rem; color: var(--lgmf-muted); max-width: 42rem; }\n.lgmf .lgmf-kicker {\n  display: inline-block; font-size: .78rem; font-weight: 600; letter-spacing: .09em;\n  text-transform: uppercase; color: var(--lgmf-accent); margin: 0 0 .8rem;\n}\n.lgmf .lgmf-center { text-align: center; }\n.lgmf .lgmf-center .lgmf-lead { margin-left: auto; margin-right: auto; }\n\n\/* --- Hero ------------------------------------------------------------- *\/\n.lgmf .lgmf-hero { padding: 1rem 0 2.6rem; }\n.lgmf .lgmf-hero p.lgmf-lead { font-size: 1.25rem; }\n.lgmf .lgmf-badges { display: flex; flex-wrap: wrap; gap: .45rem; margin: 1.4rem 0 0; padding: 0; list-style: none; }\n.lgmf .lgmf-badges li {\n  margin: 0; font-size: .85rem; color: var(--lgmf-muted);\n  border: 1px solid var(--lgmf-line); border-radius: 999px; padding: .3rem .85rem;\n}\n\n\/* --- Buttons ---------------------------------------------------------- *\/\n.lgmf .lgmf-cta { display: flex; flex-wrap: wrap; gap: .7rem; margin: 1.6rem 0 .8rem; }\n.lgmf .lgmf-btn {\n  display: inline-flex; align-items: center; gap: .5rem; text-decoration: none;\n  font-weight: 600; font-size: .98rem; padding: .7rem 1.35rem; border-radius: 8px;\n  border: 1px solid var(--lgmf-accent); color: var(--lgmf-accent); background: transparent;\n}\n.lgmf .lgmf-btn:hover { background: var(--lgmf-soft); }\n.lgmf .lgmf-btn-primary { background: var(--lgmf-accent); color: var(--lgmf-accent-fg); }\n.lgmf .lgmf-btn-primary:hover { filter: brightness(1.08); background: var(--lgmf-accent); }\n.lgmf .lgmf-btn svg { width: 1.05em; height: 1.05em; flex: none; }\n.lgmf .lgmf-note { font-size: .88rem; color: var(--lgmf-muted); }\n\n\/* --- Grids ------------------------------------------------------------ *\/\n.lgmf .lgmf-grid { display: grid; gap: 1.1rem; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }\n.lgmf .lgmf-card {\n  border: 1px solid var(--lgmf-line); border-radius: 12px; padding: 1.25rem 1.3rem; background: var(--lgmf-soft);\n}\n.lgmf .lgmf-card p:last-child { margin-bottom: 0; }\n.lgmf .lgmf-card p { font-size: .95rem; }\n.lgmf .lgmf-icon { color: var(--lgmf-accent); margin-bottom: .6rem; display: block; }\n.lgmf .lgmf-icon svg { width: 1.6rem; height: 1.6rem; }\n\n\/* --- Steps ------------------------------------------------------------ *\/\n.lgmf ol.lgmf-steps { counter-reset: lgmf-step; list-style: none; padding: 0; margin: 0; display: grid; gap: 1.1rem; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); }\n.lgmf ol.lgmf-steps li { counter-increment: lgmf-step; margin: 0; padding-top: 2.6rem; position: relative; }\n.lgmf ol.lgmf-steps li::before {\n  content: counter(lgmf-step); position: absolute; top: 0; left: 0;\n  width: 1.9rem; height: 1.9rem; border-radius: 999px;\n  background: var(--lgmf-accent); color: var(--lgmf-accent-fg);\n  display: flex; align-items: center; justify-content: center;\n  font-size: .95rem; font-weight: 700;\n}\n.lgmf ol.lgmf-steps p { font-size: .95rem; margin: 0; color: var(--lgmf-muted); }\n\n\/* --- Before\/after ----------------------------------------------------- *\/\n.lgmf .lgmf-compare { display: grid; gap: 1.1rem; grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr)); }\n.lgmf .lgmf-compare > div { border: 1px solid var(--lgmf-line); border-radius: 12px; padding: 1.25rem 1.3rem; }\n.lgmf .lgmf-compare ul { margin: 0; padding-left: 1.15rem; font-size: .95rem; }\n.lgmf .lgmf-compare h3 { display: flex; align-items: center; gap: .45rem; margin-bottom: .7rem; }\n.lgmf .lgmf-after { background: var(--lgmf-soft); border-color: var(--lgmf-accent) !important; }\n.lgmf .lgmf-after h3 { color: var(--lgmf-ok); }\n\n\/* --- Table ------------------------------------------------------------ *\/\n.lgmf .lgmf-tablewrap { overflow-x: auto; }\n.lgmf table { border-collapse: collapse; width: 100%; font-size: .95rem; margin: 0; }\n.lgmf th, .lgmf td { text-align: left; padding: .6rem .8rem; border-bottom: 1px solid var(--lgmf-line); vertical-align: top; }\n.lgmf th { font-weight: 600; white-space: nowrap; }\n\/* Two elements close with a line of their own: a table, through the border of\n   its last row, and the list of frequently asked questions, through the border\n   of the last <details>. When a section ends in one of them, the separator of\n   the next section came to add itself to it \u2014 two identical lines with the gap\n   of the two sections in between, which read as an empty line. The element\n   keeps its border; it is the next section that does not draw the separator,\n   because it has been drawn already. *\/\n.lgmf .lgmf-section:has(> :is(.lgmf-tablewrap, details):last-child) + .lgmf-section { border-top: 0; }\n\n\/* --- Installation ----------------------------------------------------- *\/\n.lgmf .lgmf-dl { display: grid; gap: .9rem; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); }\n.lgmf .lgmf-dl a, .lgmf .lgmf-dl div {\n  display: block; text-decoration: none; color: inherit;\n  border: 1px solid var(--lgmf-line); border-radius: 12px; padding: 1.05rem 1.2rem;\n}\n.lgmf .lgmf-dl a:hover { border-color: var(--lgmf-accent); background: var(--lgmf-soft); }\n.lgmf .lgmf-dl strong { display: block; color: var(--lgmf-accent); margin-bottom: .2rem; }\n.lgmf .lgmf-dl span { font-size: .89rem; color: var(--lgmf-muted); }\n\n\/* --- FAQ -------------------------------------------------------------- *\/\n.lgmf details { border-bottom: 1px solid var(--lgmf-line); padding: .85rem 0; }\n.lgmf summary { cursor: pointer; font-weight: 600; list-style: none; }\n.lgmf summary::-webkit-details-marker { display: none; }\n.lgmf summary::before { content: \"+\"; color: var(--lgmf-accent); font-weight: 700; margin-right: .55rem; }\n.lgmf details[open] summary::before { content: \"\u2013\"; }\n.lgmf details p { margin: .7rem 0 0; font-size: .95rem; color: var(--lgmf-muted); }\n\n\/* --- Footer ----------------------------------------------------------- *\/\n.lgmf .lgmf-foot { font-size: .88rem; color: var(--lgmf-muted); padding-top: 1.6rem; border-top: 1px solid var(--lgmf-line); }\n<\/style>\n<div class=\"lgmf\" lang=\"en-US\">\n\n  <!-- ============================ HERO ============================ -->\n  <section class=\"lgmf-hero\">\n    <span class=\"lgmf-kicker\">WordPress plugin \u00b7 Free in the official directory<\/span>\n    <h1>MontraFolio<\/h1>\n    <p class=\"lgmf-lead\">Gives every user of your site an <strong>image portfolio of their own<\/strong> \u2014 and the organization the shared portfolios of events, field trips and campaigns, with designated contributors. The images live in a <strong>private folder<\/strong>, outside the Media Library.<\/p>\n\n    <div class=\"lgmf-cta\">\n      <a class=\"lgmf-btn lgmf-btn-primary\" href=\"https:\/\/wordpress.org\/plugins\/montrafolio\/\" target=\"_blank\" rel=\"noopener\">\n        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M12 3v12\"\/><path d=\"M7.5 10.5L12 15l4.5-4.5\"\/><path d=\"M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2\"\/><\/svg>\n        Install from WordPress.org\n      <\/a>\n      <a class=\"lgmf-btn\" href=\"#lgmf-install\">\n        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"9\"\/><path d=\"M12 11v5\"\/><path d=\"M12 8h.01\"\/><\/svg>\n        How it installs\n      <\/a>\n    <\/div>\n    <p class=\"lgmf-note\">It installs like any plugin from the directory: <em>Plugins \u2192 Add New<\/em>, search for <strong>MontraFolio<\/strong>, install and activate. No account to create, no license key, no external service.<\/p>\n\n    <ul class=\"lgmf-badges\">\n      <li>The images never leave your server<\/li>\n      <li>Mobile first<\/li>\n      <li>Three blocks and three shortcodes<\/li>\n      <li>Updated by WordPress, like the others<\/li>\n      <li>English \u00b7 Portugu\u00eas \u00b7 Espa\u00f1ol<\/li>\n      <li>WordPress&nbsp;6.5+ \u00b7 PHP&nbsp;8.1+<\/li>\n    <\/ul>\n  <\/section>\n\n  <!-- ======================= PROBLEM \/ SOLUTION ==================== -->\n  <section class=\"lgmf-section\">\n    <span class=\"lgmf-kicker\">The problem<\/span>\n    <h2>The Media Library was not built for this<\/h2>\n    <p class=\"lgmf-lead\">When three hundred people are publishing photographs \u2014 students, trainees, members, staff \u2014 WordPress has one place to put them: the same shared pile, served at a public address anybody can pass on to anybody. And to get there, every one of them needs the back office.<\/p>\n\n    <div class=\"lgmf-compare\">\n      <div>\n        <h3>Without MontraFolio<\/h3>\n        <ul>\n          <li>Every image in the same Media Library pile<\/li>\n          <li>Whoever knows the address sees the file, always<\/li>\n          <li>Either everybody is given wp-admin, or nobody is<\/li>\n          <li>A page built by hand for every class, event or trip<\/li>\n          <li>8&nbsp;MB photos straight off the phone, one at a time<\/li>\n          <li>Nobody knows who uploaded what, or when<\/li>\n        <\/ul>\n      <\/div>\n      <div class=\"lgmf-after\">\n        <h3>With MontraFolio<\/h3>\n        <ul>\n          <li>Each person with a portfolio of their own and their own collections<\/li>\n          <li>Files in a folder the web server does not serve; the plugin decides who sees each image<\/li>\n          <li>An area of their own for the people who publish; wp-admin stays with the people who run the site<\/li>\n          <li>The portfolio page and each collection&#8217;s gallery come ready-made<\/li>\n          <li>The image is resized on the phone <em>before<\/em> it goes up<\/li>\n          <li>Every upload and every designation is recorded<\/li>\n        <\/ul>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <!-- =========================== STEPS ============================ -->\n  <section class=\"lgmf-section\">\n    <span class=\"lgmf-kicker\">How it works<\/span>\n    <h2>Four steps, and the site is ready<\/h2>\n    <ol class=\"lgmf-steps\">\n      <li>\n        <h3>Install<\/h3>\n        <p>Search for MontraFolio in <em>Plugins \u2192 Add New<\/em> and activate it. The private folder and the tables are created right there. In <em>Settings<\/em> you choose the address words and the limits a portfolio is born with.<\/p>\n      <\/li>\n      <li>\n        <h3>Decide who gets in<\/h3>\n        <p>The <em>Permissions by Role<\/em> card, inside <em>Settings<\/em>, decides who manages portfolios. Being an owner or a contributor is not a role: any user who can sign in may have one.<\/p>\n      <\/li>\n      <li>\n        <h3>Publish<\/h3>\n        <p>The people who publish work in the portfolio area, at <code>\/p-admin\/<\/code>: camera, phone gallery or a folder dragged in on a desktop, order by touch, captions.<\/p>\n      <\/li>\n      <li>\n        <h3>Show<\/h3>\n        <p>Every portfolio has its page and every collection its gallery, at the address you chose. Or they go into a page of your theme, through a block.<\/p>\n      <\/li>\n    <\/ol>\n  <\/section>\n\n  <!-- ========================= ADVANTAGES ========================== -->\n  <section class=\"lgmf-section\">\n    <span class=\"lgmf-kicker\">Why this one and not another<\/span>\n    <h2>What sets it apart<\/h2>\n    <div class=\"lgmf-grid\">\n\n      <div class=\"lgmf-card\">\n        <span class=\"lgmf-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"4\" y=\"10\" width=\"16\" height=\"11\" rx=\"2\"\/><path d=\"M8 10V7a4 4 0 0 1 8 0v3\"\/><\/svg><\/span>\n        <h3>Private by construction<\/h3>\n        <p>Nothing goes to the Media Library. The files live in a folder the web server does not serve, under names nobody guesses, and it is the plugin that checks who is asking before it delivers an image. A hidden collection is really hidden.<\/p>\n      <\/div>\n\n      <div class=\"lgmf-card\">\n        <span class=\"lgmf-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"7\" y=\"2\" width=\"10\" height=\"20\" rx=\"2\"\/><path d=\"M11 18h2\"\/><\/svg><\/span>\n        <h3>Mobile first<\/h3>\n        <p>Upload from the camera or the gallery, resized on the device itself before it goes up, reorder by touch, leaf through the carousel with a finger. On a desktop, dragging a whole folder feeds the same pipeline. HEIC photos from an iPhone are accepted with nothing to configure.<\/p>\n      <\/div>\n\n      <div class=\"lgmf-card\">\n        <span class=\"lgmf-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M16 20v-1.5a3.5 3.5 0 0 0-3.5-3.5h-5A3.5 3.5 0 0 0 4 18.5V20\"\/><circle cx=\"10\" cy=\"8\" r=\"3.5\"\/><path d=\"M17 11l2 2 4-4\"\/><\/svg><\/span>\n        <h3>Nobody needs wp-admin<\/h3>\n        <p>Owners and contributors work in an area of the plugin, at the address the site chooses. A user with nothing beyond a reading role lands there after signing in and never sees the WordPress dashboard. An owner runs their portfolio; contributors publish in the collections they were given.<\/p>\n      <\/div>\n\n      <div class=\"lgmf-card\">\n        <span class=\"lgmf-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M4 6h16\"\/><path d=\"M6 11h12\"\/><path d=\"M8 16h8\"\/><path d=\"M10 21h4\"\/><\/svg><\/span>\n        <h3>Limits at four levels<\/h3>\n        <p><em>Settings<\/em> says what limits a portfolio and a collection are born with; then each portfolio has its own ceiling of storage and images, a collection can narrow it, and each contributor can be narrowed further still. No level grants more than the one above it, and lowering a limit never deletes anything \u2014 it decides what the next upload may add.<\/p>\n      <\/div>\n\n      <div class=\"lgmf-card\">\n        <span class=\"lgmf-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\"\/><path d=\"M10 9.5l5 2.5-5 2.5z\"\/><\/svg><\/span>\n        <h3>Videos among the images<\/h3>\n        <p>Paste the address of a video from YouTube, Vimeo, Dailymotion or TikTok and it takes its place among the images, in the same order, with a caption and an observation \u2014 it can even be the cover. Of the video itself only the thumbnail is kept here, and the public page contacts nobody until the visitor presses <em>play<\/em>.<\/p>\n      <\/div>\n\n      <div class=\"lgmf-card\">\n        <span class=\"lgmf-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M12 3l7.5 3.4v5c0 4.4-3.1 8.4-7.5 9.6-4.4-1.2-7.5-5.2-7.5-9.6v-5L12 3z\"\/><path d=\"M9 12l2 2 4-4\"\/><\/svg><\/span>\n        <h3>It never reports anything anywhere<\/h3>\n        <p>No telemetry: no counters, no domain, no versions. The plugin reports nothing whatsoever about your site to anybody. The only requests that ever leave are the ones the videos need \u2014 and every one of them is listed on the plugin page, service by service.<\/p>\n      <\/div>\n\n    <\/div>\n  <\/section>\n\n  <!-- ================= WHERE IT SHOWS \/ BLOCKS ==================== -->\n  <section class=\"lgmf-section\">\n    <span class=\"lgmf-kicker\">Inside your theme<\/span>\n    <h2>Three blocks, and the portfolio goes into any page<\/h2>\n    <p class=\"lgmf-lead\">The plugin serves pages of its own \u2014 the portfolio&#8217;s page and each collection&#8217;s gallery \u2014 but nothing obliges you to use them. The same content goes into a page of your theme through a block, or through the matching shortcode.<\/p>\n    <div class=\"lgmf-tablewrap\">\n      <table>\n        <thead><tr><th>Block<\/th><th>What it shows<\/th><th>Shortcode<\/th><\/tr><\/thead>\n        <tbody>\n          <tr><td>MontraFolio \u2013 Collection<\/td><td>The gallery of one collection, as tiles, as a carousel or as both, with a <em>lightbox<\/em><\/td><td><code>&#91;mtfl_collection portfolio=\"ana\" collection=\"trip\"&#93;<\/code><\/td><\/tr>\n          <tr><td>MontraFolio \u2013 Portfolio<\/td><td>The collections of a portfolio, as cards<\/td><td><code>&#91;mtfl_portfolio&#93;<\/code><\/td><\/tr>\n          <tr><td>MontraFolio \u2013 Details<\/td><td>The cover, the author and the description of either of the two<\/td><td><code>&#91;mtfl_details&#93;<\/code><\/td><\/tr>\n        <\/tbody>\n      <\/table>\n    <\/div>\n    <p class=\"lgmf-note\">The Collection block inherits what the owner proposed when it is not told otherwise. A list of collections can point every line at the same page, so that a single page serves as the index and as the gallery of whichever one the visitor picks.<\/p>\n  <\/section>\n\n  <!-- ================== PERSONAL DATA \/ PRIVACY =================== -->\n  <section class=\"lgmf-section\">\n    <span class=\"lgmf-kicker\">The detail that saves trouble<\/span>\n    <h2>Photographs of people are personal data<\/h2>\n    <p class=\"lgmf-lead\">A site that lets three hundred people publish photographs has obligations the day one of them asks for their data, or leaves. The plugin handles that with no additional plugins.<\/p>\n    <div class=\"lgmf-tablewrap\">\n      <table>\n        <thead><tr><th>What<\/th><th>How<\/th><\/tr><\/thead>\n        <tbody>\n          <tr><td>Camera metadata<\/td><td>Images are stored without it \u2014 not the model, not the date, not the coordinates of where it was taken<\/td><\/tr>\n          <tr><td>Export personal data<\/td><td><em>Tools \u2192 Export Personal Data<\/em> includes everything the plugin keeps about the account<\/td><\/tr>\n          <tr><td>Erase personal data<\/td><td><em>Tools \u2192 Erase Personal Data<\/em> deletes the personal portfolio with its images, releases assigned portfolios without touching their content, and anonymizes who uploaded what in the others<\/td><\/tr>\n          <tr><td>Accounts left behind<\/td><td>A retention rule can remove personal portfolios with no activity: the owner is warned a long time in advance and keeps it with one button<\/td><\/tr>\n          <tr><td>Privacy policy<\/td><td>The paragraphs to include are suggested on the WordPress privacy page<\/td><\/tr>\n          <tr><td>Content terms<\/td><td>Whoever publishes accepts them before the first upload; the version and the date are kept<\/td><\/tr>\n        <\/tbody>\n      <\/table>\n    <\/div>\n  <\/section>\n\n  <!-- ========================== AUDIENCE ========================== -->\n  <section class=\"lgmf-section\">\n    <span class=\"lgmf-kicker\">Who it is for<\/span>\n    <h2>If a lot of people have photographs to show, it is for you<\/h2>\n    <div class=\"lgmf-tablewrap\">\n      <table>\n        <thead><tr><th>Who<\/th><th>What they publish<\/th><\/tr><\/thead>\n        <tbody>\n          <tr><td>Schools and training centers<\/td><td>Portfolios of students and trainees, field trips, class projects, exhibitions<\/td><\/tr>\n          <tr><td>Universities and art schools<\/td><td>Coursework, graduation portfolios, the archive of the studios<\/td><\/tr>\n          <tr><td>Towns and local government<\/td><td>Events, public works, town festivals, a photographic archive by year<\/td><\/tr>\n          <tr><td>Associations and clubs<\/td><td>Competitions, gatherings, tours, each section with its own collections<\/td><\/tr>\n          <tr><td>Photographers and studios<\/td><td>A gallery per job, some public and others hidden until they are shown<\/td><\/tr>\n          <tr><td>Companies and marketing<\/td><td>Campaigns, trade shows, an internal catalog, with people publishing without entering the back office<\/td><\/tr>\n        <\/tbody>\n      <\/table>\n    <\/div>\n  <\/section>\n\n  <!-- ======================== INSTALLATION ======================== -->\n  <section class=\"lgmf-section\" id=\"lgmf-install\">\n    <span class=\"lgmf-kicker\">Install<\/span>\n    <!-- Filled in by the script from update.json; with no fetch it stays\n         hidden \u2014 a static number would be wrong at the next deploy, because\n         this page is not republished with every version. -->\n    <h2>Search, install, activate<\/h2>\n    <p class=\"lgmf-note lgmf-version\" hidden>Version <strong class=\"lgmf-version-num\"><\/strong><span class=\"lgmf-version-date\"><\/span><\/p>\n    <div class=\"lgmf-dl\">\n      <a href=\"https:\/\/wordpress.org\/plugins\/montrafolio\/\" target=\"_blank\" rel=\"noopener\">\n        <strong>The page on WordPress.org<\/strong>\n        <span>The plugin&#8217;s page in the directory, with the version history, the reviews and the support forum.<\/span>\n      <\/a>\n      <div>\n        <strong>From your site&#8217;s dashboard<\/strong>\n        <span><em>Plugins \u2192 Add New<\/em>, search for <strong>MontraFolio<\/strong>, <em>Install Now<\/em> and <em>Activate<\/em>. The private image folder and the tables are created at that moment.<\/span>\n      <\/div>\n      <div>\n        <strong>First steps<\/strong>\n        <span><em>MontraFolio \u2192 Settings<\/em> for the address words and the upload limits, and the <em>Permissions by Role<\/em> card, on the same screen, to decide who manages portfolios.<\/span>\n      <\/div>\n      <a href=\"https:\/\/lg-systems.net\/lgs\/wp-dev\/montrafolio\/montrafolio-latest.zip\">\n        <strong>Zip, to install by hand<\/strong>\n        <span>For sites that install through <em>Upload Plugin<\/em> or by FTP, and for anybody who wants to keep the version they put in production.<\/span>\n      <\/a>\n    <\/div>\n    <p class=\"lgmf-note\" style=\"margin-top:1rem\">Updates arrive through the normal WordPress mechanism, like those of any plugin in the directory. The plugin has no update channel of its own, it will ask nothing of any server of ours, and it does not even know your site&#8217;s address.<\/p>\n  <\/section>\n\n  <!-- ========================= REQUIREMENTS ======================= -->\n  <section class=\"lgmf-section\" id=\"lgmf-requirements\">\n    <span class=\"lgmf-kicker\">Requirements<\/span>\n    <h2>What you need to have<\/h2>\n    <ul>\n      <li><strong>WordPress 6.5<\/strong> or later and <strong>PHP 8.1<\/strong> or later.<\/li>\n      <li><strong>Any theme.<\/strong> The blocks go into the theme&#8217;s pages; the pages the plugin serves it writes whole, and that is what lets it answer a request for an image before the theme has even loaded.<\/li>\n      <li><strong>No server configuration.<\/strong> On Apache and IIS the image folder protects itself; on nginx you add one <code>location<\/code> rule, described in the manual \u2014 but the real defense is the unguessable names and the delivery through the plugin.<\/li>\n      <li><strong>Nothing to change in PHP.<\/strong> A photograph larger than what your host accepts in one request is sent in parts and put back together on the server. No limit of your host&#8217;s forces you to lower quality.<\/li>\n      <li><strong>No external service<\/strong>, except the video ones, and only where somebody uses them.<\/li>\n    <\/ul>\n  <\/section>\n\n  <!-- ============================ FAQ ============================= -->\n  <section class=\"lgmf-section\">\n    <span class=\"lgmf-kicker\">Frequently asked questions<\/span>\n    <h2>Before you ask<\/h2>\n\n    <details>\n      <summary>Do the images really stay out of the Media Library?<\/summary>\n      <p>They do. They are kept in <code>wp-content\/uploads\/montrafolio\/<\/code>, a folder protected against direct access, and delivered by the plugin after it has checked who is asking. They do not appear in the Library, they are not WordPress attachments, and they are not served at an address anybody can pass on.<\/p>\n    <\/details>\n\n    <details>\n      <summary>Do my users have to reach wp-admin?<\/summary>\n      <p>No. Owners and contributors work in the portfolio area, a page of the plugin at the address chosen in Settings (<code>\/p-admin\/<\/code> by default). A user with nothing beyond a reading role lands there after signing in and never sees the dashboard.<\/p>\n    <\/details>\n\n    <details>\n      <summary>Do I need another plugin to sign in?<\/summary>\n      <p>No. People sign in with their own WordPress accounts, on the plugin&#8217;s page. A single sign-on plugin \u2014 Microsoft Entra ID, LDAP and others \u2014 is optional and plugs into the normal WordPress login pipeline; if the site wants it, the WordPress password form can even disappear and leave only the provider&#8217;s button. Sign-in can also be restricted to certain e-mail domains.<\/p>\n    <\/details>\n\n    <details>\n      <summary>Does the plugin send anything out?<\/summary>\n      <p>About your site, nothing: no usage counters, no domain, no versions \u2014 and updates come from WordPress.org along the same path as those of every other plugin. The single exception is videos, and only where somebody uses them: adding one asks the service for the title and the thumbnail; viewing the page asks for nothing until the visitor presses <em>play<\/em>. The four services are listed on the plugin&#8217;s page, with their terms and privacy policies, and any of them can be switched off.<\/p>\n    <\/details>\n\n    <details>\n      <summary>Can I show a portfolio inside a page of my theme?<\/summary>\n      <p>You can, with the three blocks \u2014 Collection, Portfolio and Details \u2014 or with the matching shortcodes. The portfolio is picked on the block itself, and one page can serve at the same time as the list of collections and as the gallery of whichever one the visitor picks.<\/p>\n    <\/details>\n\n    <details>\n      <summary>What about HEIC photos from an iPhone?<\/summary>\n      <p>They are accepted everywhere, and there is nothing to configure. Safari converts them on its own; the other browsers convert them on the device itself, with a library the plugin loads only when such a photograph turns up.<\/p>\n    <\/details>\n\n    <details>\n      <summary>Can I limit how much each person uploads?<\/summary>\n      <p>Yes, at four levels: what the site gives a new portfolio, the ceiling of each portfolio, what a collection narrows inside it, and what each contributor may upload in that collection. A level set to zero has no limit of its own and follows the one above, and the meter each person sees is the level that runs out first for them.<\/p>\n    <\/details>\n\n    <details>\n      <summary>What languages is it in?<\/summary>\n      <p>English, Portuguese and Spanish, chosen in a setting of the plugin itself \u2014 whatever language WordPress is running in. The public pages and the portfolio area were gone through with a fine comb for the keyboard, screen readers, reduced motion and AA contrast.<\/p>\n    <\/details>\n  <\/section>\n\n  <!-- =========================== FINAL CTA ======================== -->\n  <section class=\"lgmf-section lgmf-center\">\n    <h2>Three hundred people, three hundred portfolios<\/h2>\n    <p class=\"lgmf-lead\">Searching for the plugin, activating it and deciding who may have one of their own takes less time than reading this page.<\/p>\n    <div class=\"lgmf-cta\" style=\"justify-content:center\">\n      <a class=\"lgmf-btn lgmf-btn-primary\" href=\"https:\/\/wordpress.org\/plugins\/montrafolio\/\" target=\"_blank\" rel=\"noopener\">Install from WordPress.org<\/a>\n      <a class=\"lgmf-btn\" href=\"#lgmf-requirements\">See the requirements<\/a>\n    <\/div>\n  <\/section>\n\n  <p class=\"lgmf-foot\">MontraFolio is an <strong>LG-Systems<\/strong> product. Support: <a href=\"mailto:support@lg-systems.net\">support@lg-systems.net<\/a> \u00b7 <a href=\"https:\/\/wordpress.org\/support\/plugin\/montrafolio\/\" target=\"_blank\" rel=\"noopener\">Support forum<\/a> \u00b7 <a href=\"https:\/\/wordpress.org\/plugins\/montrafolio\/\" target=\"_blank\" rel=\"noopener\">WordPress.org<\/a> \u00b7 GPLv2 or later license<\/p>\n\n<\/div>\n\n<script>\n\/* Current version and release date read from the update.json published beside\n   the zip (same origin \u2014 no CORS). Defensive by design: the line is hidden in\n   the HTML and only appears if the fetch succeeds, so the page never shows a\n   wrong version. no-store because heuristic caching would hold the old version\n   after a deploy. *\/\n(function () {\n  fetch('https:\/\/lg-systems.net\/lgs\/wp-dev\/montrafolio\/update.json', { cache: 'no-store' })\n    .then(function (r) { return r.ok ? r.json() : null; })\n    .then(function (v) {\n      if (!v || !\/^[\\w.-]+$\/.test(String(v.version))) return;\n      var box = document.querySelector('.lgmf-version');\n      if (!box) return;\n      box.querySelector('.lgmf-version-num').textContent = v.version;\n      var m = \/^(\\d{4})-(\\d{2})-(\\d{2})$\/.exec(String(v.last_updated || ''));\n      if (m) {\n        var when = new Date(Date.UTC(+m[1], +m[2] - 1, +m[3]));\n        box.querySelector('.lgmf-version-date').textContent = ' \u00b7 released on ' +\n          when.toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric', timeZone: 'UTC' });\n      }\n      box.hidden = false;\n    })\n    .catch(function () {});\n})();\n<\/script>\n","protected":false},"excerpt":{"rendered":"<p>WordPress plugin \u00b7 Free in the official directory MontraFolio Gives every user of your site an image portfolio of their own \u2014 and the organization the shared portfolios of events, field trips and campaigns, with designated contributors. The images live in a private folder, outside the Media Library. Install from WordPress.org How it installs It [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_lgs_heading_first":"","_lgs_heading_second":"","_lgs_tagline":"","_lgs_hide_catalog":"","_lgs_kind":"","_lgs_accent":"","_lgs_platform":"","_lgs_version":"","_lgs_status":"","_lgs_released":"","_lgs_size":"","_lgs_license":"","_lgs_is_available":"","_lgs_pricing_model":"","_lgs_price_free":"","_lgs_price_pro":"","_lgs_price_note":"","_lgs_built_on":"","_lgs_requires":"","_lgs_download_url":"","_lgs_docs_url":"","_lgs_privacy_url":"","_lgs_steps":"","_lgs_features":"","_lgs_specs":"","_lgs_highlights":"","_lgs_compare":"","_lgs_changelog":"","_lgs_tiers":"","_lgs_gallery":"","_lgs_icon_id":"","_lgs_downloads":"","_lgs_faq":"","footnotes":""},"class_list":["post-58","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/lg-systems.net\/lgs\/wp-json\/wp\/v2\/pages\/58","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lg-systems.net\/lgs\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/lg-systems.net\/lgs\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/lg-systems.net\/lgs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lg-systems.net\/lgs\/wp-json\/wp\/v2\/comments?post=58"}],"version-history":[{"count":3,"href":"https:\/\/lg-systems.net\/lgs\/wp-json\/wp\/v2\/pages\/58\/revisions"}],"predecessor-version":[{"id":74,"href":"https:\/\/lg-systems.net\/lgs\/wp-json\/wp\/v2\/pages\/58\/revisions\/74"}],"wp:attachment":[{"href":"https:\/\/lg-systems.net\/lgs\/wp-json\/wp\/v2\/media?parent=58"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}