{"id":369007,"date":"2026-09-23T01:28:49","date_gmt":"2026-09-23T01:28:49","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/lg-portfolio\/"},"modified":"2026-09-23T09:44:16","modified_gmt":"2026-09-23T09:44:16","slug":"montrafolio","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/montrafolio\/","author":23563568,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.1.3","stable_tag":"1.1.3","tested":"7.1.2","requires":"6.5","requires_php":"8.1","requires_plugins":null,"header_name":"MontraFolio","header_author":"LG-Systems","header_description":"Image portfolios for organisations. Every user can have a portfolio of their own, staff run shared portfolios with designated contributors, and visitors browse collections as tiles or a carousel. Images stay in a private folder, never in the Media Library.","assets_banners_color":"b0ada8","last_updated":"2026-09-23 09:44:16","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/lg-systems.net\/lgs\/montrafolio\/","header_author_uri":"https:\/\/lg-systems.net\/lgs\/","rating":0,"author_block_rating":0,"active_installs":0,"downloads":65,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.1.1":{"tag":"1.1.1","author":"luismiggarcia","date":"2026-09-23 01:28:18","revision":3708312},"1.1.2":{"tag":"1.1.2","author":"luismiggarcia","date":"2026-09-23 02:20:36","revision":3708337},"1.1.3":{"tag":"1.1.3","author":"luismiggarcia","date":"2026-09-23 09:44:16","revision":3709007}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3708312,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3708312,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500-es.png":{"filename":"banner-1544x500-es.png","revision":3708312,"resolution":"1544x500","location":"assets","locale":"es","width":1544,"height":500},"banner-1544x500-pt.png":{"filename":"banner-1544x500-pt.png","revision":3708312,"resolution":"1544x500","location":"assets","locale":"pt","width":1544,"height":500},"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3708312,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250-es.png":{"filename":"banner-772x250-es.png","revision":3708312,"resolution":"772x250","location":"assets","locale":"es","width":772,"height":250},"banner-772x250-pt.png":{"filename":"banner-772x250-pt.png","revision":3708312,"resolution":"772x250","location":"assets","locale":"pt","width":772,"height":250},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3708312,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":{"montrafolio\/collection":{"$schema":"https:\/\/schemas.wp.org\/trunk\/block.json","apiVersion":3,"name":"montrafolio\/collection","title":"MontraFolio - Collection","category":"embed","description":"One collection, as tiles or a carousel, from MontraFolio.","keywords":["collection","gallery","carousel"],"textdomain":"montrafolio","icon":"format-gallery","supports":{"html":false,"align":["wide","full"]},"editorScript":"mtfl-blocks","editorStyle":"mtfl-blocks-editor","style":"mtfl-gallery"},"montrafolio\/details":{"$schema":"https:\/\/schemas.wp.org\/trunk\/block.json","apiVersion":3,"name":"montrafolio\/details","title":"MontraFolio - Details","category":"embed","description":"The description of a portfolio and\/or of a collection, from MontraFolio.","keywords":["portfolio","collection","description"],"textdomain":"montrafolio","icon":"excerpt-view","supports":{"html":false,"align":["wide","full"]},"editorScript":"mtfl-blocks","editorStyle":"mtfl-blocks-editor","style":"mtfl-gallery"},"montrafolio\/portfolio":{"$schema":"https:\/\/schemas.wp.org\/trunk\/block.json","apiVersion":3,"name":"montrafolio\/portfolio","title":"MontraFolio - Portfolio","category":"embed","description":"The collections of a portfolio, as cards or as a list, from MontraFolio.","keywords":["portfolio","collections","gallery"],"textdomain":"montrafolio","icon":"portfolio","supports":{"html":false,"align":["wide","full"]},"editorScript":"mtfl-blocks","editorStyle":"mtfl-blocks-editor","style":"mtfl-gallery"}},"tagged_versions":["1.1.1","1.1.2","1.1.3"],"block_files":[],"assets_screenshots":{"screenshot-1-es.png":{"filename":"screenshot-1-es.png","revision":3708312,"resolution":"1","location":"assets","locale":"es","width":2200,"height":1660},"screenshot-1-pt.png":{"filename":"screenshot-1-pt.png","revision":3708312,"resolution":"1","location":"assets","locale":"pt","width":2200,"height":1660},"screenshot-1.png":{"filename":"screenshot-1.png","revision":3708312,"resolution":"1","location":"assets","locale":"","width":2200,"height":1660},"screenshot-2-es.png":{"filename":"screenshot-2-es.png","revision":3708312,"resolution":"2","location":"assets","locale":"es","width":1320,"height":2868},"screenshot-2-pt.png":{"filename":"screenshot-2-pt.png","revision":3708312,"resolution":"2","location":"assets","locale":"pt","width":1320,"height":2868},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3708312,"resolution":"2","location":"assets","locale":"","width":1320,"height":2868},"screenshot-3-es.png":{"filename":"screenshot-3-es.png","revision":3708312,"resolution":"3","location":"assets","locale":"es","width":3360,"height":1660},"screenshot-3-pt.png":{"filename":"screenshot-3-pt.png","revision":3708312,"resolution":"3","location":"assets","locale":"pt","width":3360,"height":1660},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3708312,"resolution":"3","location":"assets","locale":"","width":3360,"height":1660},"screenshot-4-es.png":{"filename":"screenshot-4-es.png","revision":3708312,"resolution":"4","location":"assets","locale":"es","width":3360,"height":1660},"screenshot-4-pt.png":{"filename":"screenshot-4-pt.png","revision":3708312,"resolution":"4","location":"assets","locale":"pt","width":3360,"height":1660},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3708312,"resolution":"4","location":"assets","locale":"","width":3360,"height":1660},"screenshot-5-es.png":{"filename":"screenshot-5-es.png","revision":3708312,"resolution":"5","location":"assets","locale":"es","width":2200,"height":1660},"screenshot-5-pt.png":{"filename":"screenshot-5-pt.png","revision":3708312,"resolution":"5","location":"assets","locale":"pt","width":2200,"height":1660},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3708312,"resolution":"5","location":"assets","locale":"","width":2200,"height":1660},"screenshot-6-es.png":{"filename":"screenshot-6-es.png","revision":3708312,"resolution":"6","location":"assets","locale":"es","width":2200,"height":1660},"screenshot-6-pt.png":{"filename":"screenshot-6-pt.png","revision":3708312,"resolution":"6","location":"assets","locale":"pt","width":2200,"height":1660},"screenshot-6.png":{"filename":"screenshot-6.png","revision":3708312,"resolution":"6","location":"assets","locale":"","width":2200,"height":1660},"screenshot-7-es.png":{"filename":"screenshot-7-es.png","revision":3708312,"resolution":"7","location":"assets","locale":"es","width":2200,"height":1660},"screenshot-7-pt.png":{"filename":"screenshot-7-pt.png","revision":3708312,"resolution":"7","location":"assets","locale":"pt","width":2200,"height":1660},"screenshot-7.png":{"filename":"screenshot-7.png","revision":3708312,"resolution":"7","location":"assets","locale":"","width":2200,"height":1660},"screenshot-8-es.png":{"filename":"screenshot-8-es.png","revision":3708312,"resolution":"8","location":"assets","locale":"es","width":3360,"height":1660},"screenshot-8-pt.png":{"filename":"screenshot-8-pt.png","revision":3708312,"resolution":"8","location":"assets","locale":"pt","width":3360,"height":1660},"screenshot-8.png":{"filename":"screenshot-8.png","revision":3708312,"resolution":"8","location":"assets","locale":"","width":3360,"height":1660}},"screenshots":{"1":"The portfolio area on a desktop: what the portfolio is on the left, everything done to it on the right.","2":"The portfolio area on a phone: the cover, and the collections shown, hidden and ordered by touch.","3":"The portfolios list in wp-admin, with its filters and the storage report.","4":"Permissions by role: what each role of the site may do with portfolios.","5":"The page of a portfolio: the cover, the owner, the description, and the collections as cards.","6":"A collection as tiles.","7":"The same collection as a carousel; the visitor switches between the two.","8":"An image opened large, with its caption and its observation."}},"plugin_section":[],"plugin_tags":[786,210,163,789,222],"plugin_category":[43,50],"plugin_contributors":[282176],"plugin_business_model":[],"class_list":["post-369007","plugin","type-plugin","status-publish","hentry","plugin_tags-carousel","plugin_tags-gallery","plugin_tags-images","plugin_tags-portfolio","plugin_tags-video","plugin_category-customization","plugin_category-media","plugin_contributors-luismiggarcia","plugin_committers-luismiggarcia"],"banners":{"banner":"https:\/\/ps.w.org\/montrafolio\/assets\/banner-772x250.png?rev=3708312","banner_2x":"https:\/\/ps.w.org\/montrafolio\/assets\/banner-1544x500.png?rev=3708312","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/montrafolio\/assets\/icon-128x128.png?rev=3708312","icon_2x":"https:\/\/ps.w.org\/montrafolio\/assets\/icon-256x256.png?rev=3708312","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/montrafolio\/assets\/screenshot-1.png?rev=3708312","caption":"The portfolio area on a desktop: what the portfolio is on the left, everything done to it on the right."},{"src":"https:\/\/ps.w.org\/montrafolio\/assets\/screenshot-2.png?rev=3708312","caption":"The portfolio area on a phone: the cover, and the collections shown, hidden and ordered by touch."},{"src":"https:\/\/ps.w.org\/montrafolio\/assets\/screenshot-3.png?rev=3708312","caption":"The portfolios list in wp-admin, with its filters and the storage report."},{"src":"https:\/\/ps.w.org\/montrafolio\/assets\/screenshot-4.png?rev=3708312","caption":"Permissions by role: what each role of the site may do with portfolios."},{"src":"https:\/\/ps.w.org\/montrafolio\/assets\/screenshot-5.png?rev=3708312","caption":"The page of a portfolio: the cover, the owner, the description, and the collections as cards."},{"src":"https:\/\/ps.w.org\/montrafolio\/assets\/screenshot-6.png?rev=3708312","caption":"A collection as tiles."},{"src":"https:\/\/ps.w.org\/montrafolio\/assets\/screenshot-7.png?rev=3708312","caption":"The same collection as a carousel; the visitor switches between the two."},{"src":"https:\/\/ps.w.org\/montrafolio\/assets\/screenshot-8.png?rev=3708312","caption":"An image opened large, with its caption and its observation."}],"raw_content":"<!--section=description-->\n<p>MontraFolio gives every user of the site an image portfolio of their own, and lets staff run shared portfolios \u2014 events, trips, campaigns \u2014 with designated contributors.<\/p>\n\n<ul>\n<li><strong>Portfolio, collection, image.<\/strong> A portfolio has one owner and any number of collections; each collection holds images and can be visible or hidden.<\/li>\n<li><strong>Private by construction.<\/strong> Nothing goes to the Media Library. Files live in a folder the web server does not serve; the plugin checks who may see each image before delivering it.<\/li>\n<li><strong>Mobile first.<\/strong> Camera and gallery uploads from a mobile device, images resized on the device, reorder by touch, carousel by swipe. Folder drag-and-drop on a desktop feeds the same pipeline.<\/li>\n<li><strong>A page for the portfolio, a gallery for each collection.<\/strong> The portfolio page presents the cover, the owner and a full description, then its collections as cards. Each collection shows its images as tiles or a carousel: visitors switch between the two, the collection decides which modes are available and which opens first.<\/li>\n<li><strong>Chronological order.<\/strong> Images can be ordered by their original capture time, across contributors.<\/li>\n<li><strong>Owners and contributors.<\/strong> One owner administers a portfolio; contributors publish in the collections they were given, or in all of them.<\/li>\n<li><strong>Limits at four levels.<\/strong> The site sets what a new portfolio and a new collection are born with; from there the portfolio carries its own storage and image ceilings, a collection may narrow them, and each contributor may be narrowed further. No level ever grants more than the level above it, and lowering one deletes nothing \u2014 it only narrows the next upload.<\/li>\n<li><strong>Videos in a collection.<\/strong> Paste the address of a video on YouTube, Vimeo, Dailymotion or TikTok and it takes its place among the images, in the same order, with the same caption and observation. Only its thumbnail is stored here; by default the public page contacts nobody until a visitor presses play.<\/li>\n<li><strong>Videos on networks that answer nobody.<\/strong> Instagram, Facebook and LinkedIn answer no plugin about an address, so nothing is asked of them: you paste the address, choose the picture the card will show, and the card opens the video in a new tab. Those networks are never contacted by this site \u2014 not when you add the video, not when a visitor looks at the collection.<\/li>\n<li><strong>No telemetry, ever.<\/strong> Sign-in with WordPress accounts; optional single sign-on through any plugin that hooks the WordPress login. The only requests that ever leave the site are the ones videos need, listed under External services.<\/li>\n<li><p><strong>Interface in English, Portuguese and Spanish<\/strong>, independently of the WordPress language.<\/p><\/li>\n<li><p><strong>In any page of the theme.<\/strong> Three blocks, each with a shortcode: a collection with its lightbox, the collections of a portfolio, and the descriptions of either.<\/p><\/li>\n<li><strong>Personal data under control.<\/strong> Images are stored without camera metadata; the personal data export of WordPress includes the plugin's data; a retention rule can remove unused personal portfolios, warning their owners a long time before and letting them keep them with one button; the privacy policy paragraphs are suggested under Settings \u2192 Privacy.<\/li>\n<li><strong>Accessible.<\/strong> Keyboard, screen readers, reduced motion and AA contrast on the public pages and in the portfolio area.<\/li>\n<\/ul>\n\n<p>Everything described above is in this version and covered by tests: the portfolio area (sign-in, content terms, portfolios, collections, contributors, uploads, limits), the private storage and the image delivery, the public pages and the three blocks with their shortcodes, the wp-admin management screens (the portfolios list with its filters, creation of assigned portfolios, editing, owner change, rename with redirect, contributors, limits, suspension, deletion, storage report, regeneration of the derived sizes), the permissions by role, the personal data exporter and eraser, the retention rule with its notice, and the accessibility and performance passes.<\/p>\n\n<h3>External services<\/h3>\n\n<p>This plugin connects to four video services, and only when somebody uses the video feature. Nothing else on the site ever contacts them, and with every service switched off in <strong>Settings \u2192 Videos<\/strong> no request is made at all.<\/p>\n\n<p><strong>When an owner or a contributor adds a video<\/strong> by pasting its address, the site asks that service's public oEmbed endpoint about the address, to learn the title and the address of the thumbnail. What is sent is the address that was pasted and the site's own address, in the request; the thumbnail is then downloaded once and stored on this site. Nothing about the visitor is involved: this happens while somebody is administering a collection.<\/p>\n\n<p><strong>When a visitor presses play<\/strong> on a video, that visitor's browser loads the player from the service, which receives their IP address and whatever their browser sends, and may set cookies. Until play is pressed nothing is requested, unless the site turns <em>Load the video only when the visitor presses play<\/em> off.<\/p>\n\n<p><strong>Linked videos contact nobody.<\/strong> The networks the <em>Link a video<\/em> feature points at \u2014 Instagram, Facebook, LinkedIn, and whichever else a site adds to the list \u2014 are <strong>not<\/strong> external services of this plugin: no request is ever made to them, at any moment, by the site or by the pages it serves. The address is stored as text and the picture is one the site uploaded itself. A visitor who presses the link goes there under their own steam, exactly as they would follow any link written in any post.<\/p>\n\n<p>The services, with their terms and their privacy policies:<\/p>\n\n<ul>\n<li>YouTube (<code>https:\/\/www.youtube.com\/oembed<\/code>, player on <code>youtube-nocookie.com<\/code> or <code>youtube.com<\/code>) \u2014 terms https:\/\/www.youtube.com\/t\/terms \u00b7 privacy https:\/\/policies.google.com\/privacy<\/li>\n<li>Vimeo (<code>https:\/\/vimeo.com\/api\/oembed.json<\/code>, player on <code>player.vimeo.com<\/code>) \u2014 terms https:\/\/vimeo.com\/terms \u00b7 privacy https:\/\/vimeo.com\/privacy<\/li>\n<li>Dailymotion (<code>https:\/\/www.dailymotion.com\/services\/oembed<\/code>, player on <code>geo.dailymotion.com<\/code>) \u2014 terms https:\/\/legal.dailymotion.com\/en\/terms-of-use\/ \u00b7 privacy https:\/\/legal.dailymotion.com\/en\/privacy-policy\/<\/li>\n<li>TikTok (<code>https:\/\/www.tiktok.com\/oembed<\/code>, player on <code>tiktok.com<\/code>) \u2014 terms https:\/\/www.tiktok.com\/legal\/terms-of-service \u00b7 privacy https:\/\/www.tiktok.com\/legal\/privacy-policy<\/li>\n<\/ul>\n\n<h3>Source code<\/h3>\n\n<p>Everything this plugin ships is its source. The JavaScript and the CSS under <code>assets\/<\/code> are written\nby hand and served exactly as they are written: there is no build step, no bundler and no minifier,\nso what runs in a browser is the file you can open in the plugin's folder. Nothing here is generated\nfrom something kept elsewhere. The only compiled files are the two third-party libraries below, and\neach is named with the address of its own source.<\/p>\n\n<p>The translations are not carried in the package: WordPress.org delivers them as language packs, and\na site that wants a language nobody has published yet drops the catalog into\n    wp-content\/languages\/plugins.<\/p>\n\n<h3>Third-party code<\/h3>\n\n<ul>\n<li>The QR code component uses <em>qrcode-generator<\/em> by Kazuhiko Arase (MIT license). The plugin ships the minified build; the unminified source is available at https:\/\/github.com\/kazuhikoarase\/qrcode-generator<\/li>\n<li>HEIC photos are decoded on the device by <em>libheif<\/em> (LGPL-3.0), in the WebAssembly build published as <em>libheif-js<\/em> version 1.23.2. The plugin ships <code>assets\/vendor\/libheif\/libheif.js<\/code> (Emscripten glue, minified) and <code>assets\/vendor\/libheif\/libheif.wasm<\/code> (the compiled library); the sources are at https:\/\/github.com\/strukturag\/libheif and the build that produces these files at https:\/\/github.com\/catdad-experiments\/libheif-js<\/li>\n<\/ul>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin folder to <code>\/wp-content\/plugins\/<\/code> or install it from the Plugins screen.<\/li>\n<li>Activate it. The private image folder and the database tables are created on activation.<\/li>\n<li>Open <strong>MontraFolio \u2192 Settings<\/strong> to choose the address words and the upload limits, and <strong>Permissions by Role<\/strong> to decide who manages portfolios.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20the%20plugin%20send%20any%20data%20anywhere%3F\"><h3>Does the plugin send any data anywhere?<\/h3><\/dt>\n<dd><p>No usage data, no domain, no versions: the plugin never reports anything about your site to anybody, and updates come from WordPress.org through the normal WordPress mechanism. The single exception is videos, and only where somebody uses them: adding a video asks its service for the title and the thumbnail, and playing one loads it from that service. Both are listed under External services below.<\/p><\/dd>\n<dt id=\"can%20i%20put%20a%20youtube%20video%20in%20a%20collection%3F\"><h3>Can I put a YouTube video in a collection?<\/h3><\/dt>\n<dd><p>Yes \u2014 YouTube, Vimeo, Dailymotion or TikTok, by pasting the address of the video. It becomes an item of the collection like an image: same order, same caption, same observation, and it can even be the cover. Nothing of the video is stored on your site except its thumbnail, which counts as one image against the collection's limits. Each service can be switched off in <strong>Settings \u2192 Videos<\/strong>, and switching them all off removes the feature from the portfolio area.<\/p><\/dd>\n<dt id=\"what%20about%20a%20video%20on%20instagram%2C%20facebook%20or%20linkedin%3F\"><h3>What about a video on Instagram, Facebook or LinkedIn?<\/h3><\/dt>\n<dd><p>Those cannot be played inside your pages, and this plugin does not pretend otherwise. Since 2020 Meta answers the Facebook and Instagram oEmbed only to an application registered with Meta, which a plugin installed on sites it knows nothing about cannot be; LinkedIn never published an endpoint at all. So there is no title and no thumbnail to fetch \u2014 and nothing is fetched.<\/p>\n\n<p>Instead there is <strong>Link a video<\/strong>: you paste the address and choose a picture of your own for the card. It takes its place in the collection like any other item, and the card opens the address in a new tab. Those networks are never contacted by your site, at any moment, so no script of theirs runs on your pages and no visitor's address reaches them until that visitor chooses to go. The accepted networks are a list you can edit in <strong>Settings \u2192 Videos<\/strong>.<\/p><\/dd>\n<dt id=\"do%20my%20visitors%20get%20tracked%20by%20the%20video%20services%3F\"><h3>Do my visitors get tracked by the video services?<\/h3><\/dt>\n<dd><p>Not until they choose to be. With <em>Load the video only when the visitor presses play<\/em> on \u2014 which is how it is installed \u2014 a public page showing a video makes no request at all to the video service: the visitor sees the thumbnail stored on your own server, and a notice saying what pressing play will load. Only then is the player loaded \u2014 and it starts playing right away, because pressing play is the gesture browsers ask for before a video may start, so one press is all it takes. YouTube is played from youtube-nocookie.com unless you say otherwise, Vimeo is asked not to keep a session about the viewer, and the text of the notice is yours to write.<\/p><\/dd>\n<dt id=\"do%20i%20need%20another%20plugin%20to%20sign%20in%3F\"><h3>Do I need another plugin to sign in?<\/h3><\/dt>\n<dd><p>No. Users sign in with their WordPress accounts on the plugin's own page. A single sign-on plugin (Microsoft Entra ID, LDAP and others) is optional and plugs into the WordPress login pipeline.<\/p><\/dd>\n<dt id=\"where%20are%20the%20images%20stored%3F\"><h3>Where are the images stored?<\/h3><\/dt>\n<dd><p>In <code>wp-content\/uploads\/montrafolio\/<\/code>, a folder protected against direct access on Apache and IIS. On nginx, add the <code>location<\/code> rule described in the manual; the unguessable file names and the delivery through the plugin remain the real defence.<\/p><\/dd>\n<dt id=\"do%20users%20need%20wp-admin%3F\"><h3>Do users need wp-admin?<\/h3><\/dt>\n<dd><p>No. Owners and contributors work in p-admin, a page of the plugin at the address chosen in Settings (<code>\/p-admin\/<\/code> by default). Users with nothing beyond a reading role land there after signing in and never see wp-admin.<\/p><\/dd>\n<dt id=\"can%20i%20show%20a%20portfolio%20inside%20a%20page%20of%20my%20theme%3F\"><h3>Can I show a portfolio inside a page of my theme?<\/h3><\/dt>\n<dd><p>Yes, with three blocks \u2014 <strong>MontraFolio - Collection<\/strong> (the gallery), <strong>MontraFolio - Details<\/strong> (the descriptions) and <strong>MontraFolio - Portfolio<\/strong> (the list of collections) \u2014 or their shortcodes, <code>[mtfl_collection portfolio=\"ana\" collection=\"trip\"]<\/code>, <code>[mtfl_details]<\/code> and <code>[mtfl_portfolio]<\/code>. The portfolio is picked on the block itself. The Collection block presents it as tiles, as a carousel or as both, inheriting what the owner proposed when it is not told otherwise; a list of collections can point each line at the same page, so that one page holds the list and the gallery of whichever collection the visitor picks.<\/p><\/dd>\n<dt id=\"what%20personal%20data%20does%20the%20plugin%20store%2C%20and%20can%20users%20export%20it%3F\"><h3>What personal data does the plugin store, and can users export it?<\/h3><\/dt>\n<dd><p>The owner name shown on a portfolio and the owner e-mail kept with it, which is never published (copied from the profile, editable by the site staff without changing the account), which account made each contributor designation and each upload, the file name an image had on the device, the content terms accepted (version and date) and the date of the last activity in the portfolio area. Images are stored without camera metadata. <strong>Tools \u2192 Export Personal Data<\/strong> includes all of it. <strong>Tools \u2192 Erase Personal Data<\/strong> deletes the personal portfolio with its images, releases assigned portfolios without touching their content, removes the account's designations, anonymises the uploader and the device file name of images in other portfolios, and keeps only the acceptance of the content terms, as the proof that what is still published was uploaded under them. Nothing is sent to another server.<\/p><\/dd>\n<dt id=\"what%20happens%20to%20a%20portfolio%20when%20its%20user%20is%20deleted%3F\"><h3>What happens to a portfolio when its user is deleted?<\/h3><\/dt>\n<dd><p>If the person deleting the account attributes its content to another user, that user receives every portfolio of the deleted one. Otherwise <strong>Settings \u2192 Privacy<\/strong> decides for the personal portfolio (delete it with its images, or hand it to a chosen account), and assigned portfolios wait for a new owner. Optionally, a retention period removes the personal portfolios of users with no activity for that long: the portfolio is marked, its owner is written to, the portfolio area offers a button that keeps it, any use of it takes the mark off, and only after the notice period (a year by default) is it deleted.<\/p><\/dd>\n<dt id=\"can%20i%20limit%20how%20much%20each%20person%20uploads%3F\"><h3>Can I limit how much each person uploads?<\/h3><\/dt>\n<dd><p>Yes, at four levels. <strong>Settings<\/strong> decides what a new portfolio and a new collection start with. A manager holding <em>set the limits of a portfolio<\/em> then gives each portfolio its own storage and image ceilings in wp-admin; the owner sees that ceiling and, in the portfolio area, may narrow any collection and any contributor within it. A level set to 0 has no limit of its own and follows the level above. Changing a limit never deletes anything: it decides what the next upload may add, and the meter each person sees is whichever level runs out first for them.<\/p><\/dd>\n<dt id=\"can%20i%20put%20a%20portfolio%20inside%20a%20page%20of%20my%20theme%3F\"><h3>Can I put a portfolio inside a page of my theme?<\/h3><\/dt>\n<dd><p>Yes \u2014 see the blocks above. Beyond that, the pages the plugin serves itself (the sign-in, the content terms, the portfolio area, the public gallery) are documents it writes whole, without the theme's header and footer: that is what lets a public image be answered before the theme even loads. A site adds what it needs to them through three actions of the plugin \u2014 <code>mtfl_page_head<\/code>, <code>mtfl_page_body_start<\/code> and <code>mtfl_page_footer<\/code> \u2014 each given the context of the page, so a consent banner or an analytics script can be placed where the site means it and kept off the sign-in page. The public pages carry their own Open Graph and Twitter tags, built from the title, the description and the cover.<\/p><\/dd>\n<dt id=\"my%20host%20only%20allows%202%20mb%20uploads.%20do%20i%20have%20to%20change%20that%3F\"><h3>My host only allows 2 MB uploads. Do I have to change that?<\/h3><\/dt>\n<dd><p>No. A photo bigger than one request can carry is sent in parts and put back together on the\nserver, exactly as a backup file is. The only limit that can make a photo smaller is the one in\n<strong>Settings \u2192 Uploads<\/strong>, which is yours to choose. Nothing in the plugin asks you to change a PHP\nsetting, and it never lowers quality to fit your host's.<\/p><\/dd>\n<dt id=\"what%20about%20heic%20photos%20from%20an%20iphone%3F\"><h3>What about HEIC photos from an iPhone?<\/h3><\/dt>\n<dd><p>They are accepted everywhere, and nothing has to be configured for it. Safari converts them itself; every other browser converts them with libheif, which the plugin loads on the device only when such a photo appears. A server whose Imagick was built with HEIC support converts them too, which is only faster; <em>Tools \u2192 Site Health \u2192 Info \u2192 Media Handling<\/em> says whether yours was.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.1.3<\/h4>\n\n<ul>\n<li><strong>The blocks are found by words in the site's language.<\/strong> The search words of the three blocks \u2014 the ones the editor's inserter matches \u2014 live in <code>block.json<\/code>, and the translation catalog did not carry them, so they stayed in English whatever the language of the site. The catalog now holds them, with the title and description written there too, and a language pack translates them along with everything else.<\/li>\n<li><strong>The help under the address parameter reads as a pattern.<\/strong> The two lines that explain it \u2014 <code>?name={portfolio}<\/code> and <code>?name={collection}<\/code> \u2014 used angle brackets, which translators and their tools took for HTML and asked to keep untouched. Braces say what they mean: put the name of the parameter here and the address there, in any language.<\/li>\n<\/ul>\n\n<h4>1.1.2<\/h4>\n\n<ul>\n<li><strong>A changed icon is fetched again.<\/strong> The icon in the wp-admin menu, the one in the browser tab and the one beside the blocks in the editor were served from an address that never changed, so a browser that had already seen an older one went on showing it \u2014 sometimes long after the update, with nothing to explain why. They now carry the version of the file, as everything else the plugin serves already did.<\/li>\n<li><strong>The three blocks now describe themselves on WordPress.org.<\/strong> Each block's name, title, description and icon move into its own <code>block.json<\/code>, the file the directory reads \u2014 so the <em>Blocks<\/em> section of the plugin page tells what <em>MontraFolio - Details<\/em>, <em>- Portfolio<\/em> and <em>- Collection<\/em> each do, instead of listing only their names. Nothing changes in the editor: the same titles, the same descriptions and the same mark as before.<\/li>\n<\/ul>\n\n<h4>1.1.1<\/h4>\n\n<p><strong>The name is written MontraFolio<\/strong>, with a capital F. It reads that way wherever the plugin names itself: the header WordPress shows, the titles of the three blocks in the editor, the menu of wp-admin, the settings screens, the export and the erasure of personal data, and the line above the title of the pages the plugin serves, for sites that did not put a name of their own there.<\/p>\n\n<ul>\n<li><strong>Nothing that addresses anything changed.<\/strong> The folder of the plugin, the shortcodes, the blocks, the REST addresses and the private folder of the images are written exactly as in 1.1.0. A page built with 1.1.0 needs nothing done to it, and an update is only an update of the text.<\/li>\n<li><strong>The translations were rebuilt with it<\/strong>, so the Portuguese and the Spanish name the plugin the same way.<\/li>\n<\/ul>\n\n<h4>1.1.0<\/h4>\n\n<p><strong>MontraFolio.<\/strong> The plugin carries its name through everything it names: the blocks, the REST addresses, the folder the images live in and the graphics.<\/p>\n\n<ul>\n<li><strong>It has a mark of its own.<\/strong> The monogram appears on the menu in wp-admin, in the tab of every page the plugin serves, and beside its blocks in the editor.<\/li>\n<li><strong>The blocks and the shortcodes are named for it.<\/strong> <em>MontraFolio - Collection<\/em>, <em>- Details<\/em> and <em>- Portfolio<\/em>, and <code>[mtfl_collection]<\/code>, <code>[mtfl_details]<\/code>, <code>[mtfl_portfolio]<\/code>. A page built with an earlier set shows the blocks as unrecognised, and an earlier shortcode prints nothing, until each is written with these names.<\/li>\n<li><strong>What the plugin stores is named for it too<\/strong>, and moves there on the first request after the update: the tables, the settings, the permissions granted by role and what each person's account remembers. Nothing is copied and nothing is rebuilt \u2014 the names change and the rows stay where they are. In the one case where a table cannot move because a table of the new name already holds rows, every screen says so and neither set is touched.<\/li>\n<li><strong>The private folder is <code>uploads\/montrafolio<\/code><\/strong>, and an earlier one is renamed to it on the first request after the update. Nothing is copied and nothing is rebuilt \u2014 the folder is renamed with everything in it, and the images go on being served from the same addresses. A site that named its own folder is left alone. In the one case where the rename cannot be done, every screen of the plugin says so plainly, names both folders and says that nothing was deleted.<\/li>\n<li><p><strong>The REST addresses are <code>montrafolio\/v1<\/code>.<\/strong> Only something written against them by hand would notice.<\/p><\/li>\n<li><p><strong>Translations now come from WordPress.org instead of travelling inside the plugin.<\/strong> They are delivered as language packs and installed into <code>wp-content\/languages\/plugins<\/code>, the folder WordPress keeps for them \u2014 which means a translation now survives an update of the plugin instead of being replaced by it, and a site can put a language of its own in that same folder for a language nobody has published yet. <em>Settings \u2192 Plugin \u2192 Plugin language<\/em>, which makes the plugin speak a language the rest of the site does not, reads from there too; a language that is not installed reads in English. Until the packs for a language exist, the plugin reads in English unless its file is placed by hand \u2014 the manual says how.<\/p><\/li>\n<li>Every form and every address the plugin reads is now taken apart field by field, each value through the sanitizer that field deserves, instead of the request being read whole. Nothing a person does changes: what a form was allowed to save, it still saves, and what it refused, it still refuses. It is the reading itself that is narrower \u2014 a field the form does not have never reaches the plugin at all.<\/li>\n<li>The pages the plugin serves on its own \u2014 the sign-in, the portfolio area and the public galleries \u2014 now hand their stylesheets and scripts to WordPress instead of writing the tags themselves. Nothing a visitor sees changes: the same files load, in the same order, deferred as before. What it buys is that these pages are no longer invisible to everything that works through WordPress's own asset list \u2014 a caching or optimisation plugin now sees them like any other page, and a site that wants to add a stylesheet of its own, or take one away, has a name to call it by.<\/li>\n<\/ul>\n\n<h4>1.0.1<\/h4>\n\n<ul>\n<li><strong>A portfolio now says it changed when its photographs change.<\/strong> The date each portfolio carries only moved when somebody edited a setting of it \u2014 a title, a description, a collection created or renamed. An afternoon of uploading moved nothing, so the portfolios that had seen the most work looked exactly like the ones nobody had opened in months. Two screens read that date and both were misleading because of it: the <em>Updated<\/em> column of the list in wp-admin, and the portfolio picker, which offers the most recently updated first when nothing is typed in it. Photographs arriving and leaving, captions written and images reordered now all move it, and those two screens say what actually happened.<\/li>\n<li><strong>A collection's date follows what its images say, and the order they are in.<\/strong> Images arriving and leaving already moved it. Editing a caption, an observation or a capture date moved nothing at all \u2014 an afternoon spent captioning a collection left it looking untouched \u2014 and neither did reordering by hand or arranging by capture time. All of those are printed on the public page, so all of them are changes now. What it buys today is that a Portfolio block set to <em>Recent<\/em> orders collections by when they last actually changed; what it buys later is a date worth trusting for anything that needs to know whether a collection is still what it was.<\/li>\n<\/ul>\n\n<p>Nothing a visitor sees was changed by this version, and nothing needs doing on update.<\/p>\n\n<h4>1.0.0<\/h4>\n\n<p>First version published on WordPress.org.<\/p>\n\n<p>What it is: portfolios of images for an organisation, one for each person who wants one and as\nmany shared ones as the staff need; collections shown as tiles or as a carousel; images kept in\na private folder the plugin serves itself, never in the Media Library; uploads from a phone's\ncamera, resized on the device before they travel; limits at four levels; videos hosted elsewhere\nadded beside the images without a visitor being handed to anybody until they press play; a portfolio\narea built for a phone, and management screens in wp-admin for whoever runs the site; the personal\ndata export and erasure of WordPress, a retention rule for portfolios nobody uses any more, and no\ntelemetry of any kind.<\/p>\n\n<p>The development that got here \u2014 fifteen versions, from 0.5.0 to 0.9.5 \u2014 is in <code>changelog.txt<\/code>.<\/p>","raw_excerpt":"Image portfolios for organisations: every user can have one, staff run shared ones with designated contributors, and images stay in a private folder.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/369007","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=369007"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/luismiggarcia"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=369007"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=369007"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=369007"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=369007"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=369007"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=369007"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}