[{"data":1,"prerenderedAt":477},["ShallowReactive",2],{"writing-articles":3},[4,114,218,252,336,402,453],{"id":5,"title":6,"articleType":7,"categories":8,"date":12,"description":13,"extension":14,"meta":15,"paragraphs":16,"path":109,"readingTime":110,"sitemap":111,"stem":112,"__hash__":113},"articleEntries\u002Farticles-data\u002Fjsonapi-views-120-20260812.json","JSON:API Views 8.x-1.2","Blog post",[9,10,11],"Drupal","Druxt","Planet Drupal","2026-08-12T20:00:00+10:00","JSON:API gets you entities, not listings - JSON:API Views exposes any Drupal View as a JSON:API resource. 8.x-1.2: faster route building on view-heavy sites, cache headers that actually invalidate, a corrected preview URL, and a reworked OpenAPI fix.","json",{},[17,29,61,77,83],{"type":18,"layout":19,"regions":20},"section","layout_onecol",{"content":21},[22,25,27],{"type":23,"html":24},"text_formatted","\u003Cp>JSON:API on its own gets you decoupled entities: fetch a node, fetch a set of IDs, done. It doesn't get you the filtering, sorting and pagination that most real content listings actually need - a list of articles by tag, a paginated product catalogue, an events calendar with a date filter. You either reimplement that logic on the frontend, or Drupal ships a hand-written custom resource for every list on the site. That gap is the same regardless of what's rendering on the other end, React and Next.js, Vue and Nuxt, or anything else that can call an API.\u003C\u002Fp>\n\n\u003Cp>JSON:API Views closes it: whatever a View can already do, a decoupled frontend can ask for over JSON:API, using the access checks and query logic the view already has, no separate endpoint to write or maintain. It's also, not coincidentally, why I still maintain the module at all: it's the backend half of DruxtViews, the piece that makes Views work in Druxt, my own Nuxt-based decoupled Drupal framework.\u003C\u002Fp>",{"type":23,"html":26},"\u003Cp>8.x-1.2 lands six fixes, five of which already had a patch sitting in the queue: route building that's dramatically faster on sites with a lot of exposed views, a preview URL that finally matches what an exposed filter is actually configured to accept, a caching fix so front-end caches actually invalidate, a routing crash tied to numeric bundle names, and a reworked fix for an OpenAPI export crash. Just fixes, no updating required.\u003C\u002Fp>",{"type":23,"html":28},"\u003Cp>JSON:API Views isn't mine originally. \u003Ca href=\"https:\u002F\u002Fwww.drupal.org\u002Fu\u002Fpixelwhip\">pixelwhip\u003C\u002Fa> built the module and shipped its first releases; I took over maintenance after that, and 8.x-1.2 is the first release I've cut on the 1.x line. Thanks to pixelwhip for building the thing in the first place.\u003C\u002Fp>",{"type":18,"title":30,"layout":19,"regions":31},"If you haven't used it before",{"content":32},[33,35,42,44,50,52,56,58],{"type":23,"html":34},"\u003Cp>Views is what most Drupal sites already lean on for anything with filtering, sorting or pagination baked in: a list of articles by tag, a paginated product catalogue, an events calendar with a date filter. JSON:API on its own gets a decoupled frontend entities, but it doesn't know about any of that. JSON:API Views bridges the two: enable it on a display and Drupal generates a route for it under \u003Ccode>\u002Fjsonapi\u002Fviews\u002F{view_id}\u002F{display_id}\u003C\u002Fcode>, backed by the same query, filters and access checks the display already has.\u003C\u002Fp>",{"type":36,"alt":37,"caption":38,"width":39,"height":40,"src":41},"media","The 'Expose via JSON:API' checkbox on a view display's settings, checked by default, with the description 'Controls exposure the view with JSON:API.'","Every display ships exposed by default. One checkbox turns it off (for now, see What's next below).",960,254,"\u002Fimages\u002Fwriting\u002Fjsonapi-views-expose-checkbox.png",{"type":23,"html":43},"\u003Cp>The preview panel in the Views UI picks it up too, once a display is exposed: the same query info table that already shows you the page's path grows a JSON:API Views row with the live URL for that display, arguments and exposed filter values included.\u003C\u002Fp>",{"type":36,"alt":45,"caption":46,"width":47,"height":48,"src":49},"The Views UI preview panel's query info table, showing Title, Path, and a JSON:API Views row linking to \u002Fjsonapi\u002Fviews\u002Ffrontpage\u002Fpage_1","The generated JSON:API endpoint for a view, right there in the Views UI preview panel.",886,137,"\u002Fimages\u002Fwriting\u002Fjsonapi-views-preview-url.png",{"type":23,"html":51},"\u003Cp>Hit that URL and it's a normal JSON:API response, whatever content types the view actually mixes together:\u003C\u002Fp>",{"type":53,"title":54,"code":55},"code","GET \u002Fjsonapi\u002Fviews\u002Ffrontpage\u002Fpage_1","{\n  \"data\": [\n    {\n      \"type\": \"node--page\",\n      \"id\": \"19e113d5-c838-43e1-ba75-1def5466e3de\",\n      \"attributes\": {\n        \"title\": \"About this site\",\n        \"status\": true,\n        \"created\": \"2026-08-09T09:07:37+00:00\"\n      }\n    },\n    {\n      \"type\": \"node--article\",\n      \"id\": \"62c2d25d-93c9-438b-8bdf-a75b69d05dc5\",\n      \"attributes\": {\n        \"title\": \"Building decoupled Views with jsonapi_views\",\n        \"status\": true,\n        \"created\": \"2026-08-08T10:18:06+00:00\"\n      }\n    }\n  ],\n  \"meta\": { \"count\": \"2\" }\n}",{"type":23,"html":57},"\u003Cp>On the frontend, \u003Ca href=\"https:\u002F\u002Fdruxtjs.org\">Druxt\u003C\u002Fa>'s \u003Ccode>&lt;DruxtView&gt;\u003C\u002Fcode> component renders that exact route as Vue components, filters, sorting and pagination included, no custom resource on either side. It's the frontend half of the same pipeline. DruxtViews targets Nuxt 2 today; a Nuxt 3\u002F4-compatible Druxt is actively in progress, more on that soon.\u003C\u002Fp>",{"type":53,"title":59,"code":60},"Render a View with Druxt","\u003CDruxtView view-id=\"frontpage\" display-id=\"page_1\" \u002F>",{"type":18,"title":62,"layout":19,"regions":63},"What's fixed",{"content":64},[65,67,69,71,73,75],{"type":23,"html":66},"\u003Cp>Five bug fixes, with a big thanks to the community whose patches made most of them possible:\u003C\u002Fp>",{"type":23,"html":68},"\u003Cp>\u003Cstrong>Cache headers weren't being set\u003C\u002Fstrong> (\u003Ca href=\"https:\u002F\u002Fwww.drupal.org\u002Fproject\u002Fjsonapi_views\u002Fissues\u002F3202583\">#3202583\u003C\u002Fa>, patch by \u003Ca href=\"https:\u002F\u002Fwww.drupal.org\u002Fu\u002Fyahyaalhamad\">yahyaalhamad\u003C\u002Fa>). View cache tags weren't reaching the JSON:API response's headers, so a page cache in front of the site never invalidated when the underlying content changed. Fixed by pushing the tags onto the response's bubbleable metadata.\u003C\u002Fp>",{"type":23,"html":70},"\u003Cp>\u003Cstrong>Route building got slow with a lot of exposed views\u003C\u002Fstrong> (\u003Ca href=\"https:\u002F\u002Fwww.drupal.org\u002Fproject\u002Fjsonapi_views\u002Fissues\u002F3484714\">#3484714\u003C\u002Fa>, patch by \u003Ca href=\"https:\u002F\u002Fwww.drupal.org\u002Fu\u002Fjacobbell84\">jacobbell84\u003C\u002Fa>). Every rebuild looked up each view's resource type from scratch, once per view per entity type. Caching it per entity type instead: 637 calls to \u003Ccode>ResourceTypeRepository::get()\u003C\u002Fcode> down to 13, at the scale the issue reported.\u003C\u002Fp>",{"type":23,"html":72},"\u003Cp>\u003Cstrong>Numeric bundle machine names broke routing entirely\u003C\u002Fstrong> (\u003Ca href=\"https:\u002F\u002Fwww.drupal.org\u002Fproject\u002Fjsonapi_views\u002Fissues\u002F3503402\">#3503402\u003C\u002Fa>, patch by \u003Ca href=\"https:\u002F\u002Fwww.drupal.org\u002Fu\u002Fchodec\">chodec\u003C\u002Fa>). An all-digit bundle machine name threw an \u003Ccode>AssertionError\u003C\u002Fcode> during route building instead of returning a route. Cast to string before the lookup, fixed.\u003C\u002Fp>",{"type":23,"html":74},"\u003Cp>\u003Cstrong>The preview URL used the wrong query parameter\u003C\u002Fstrong> (\u003Ca href=\"https:\u002F\u002Fwww.drupal.org\u002Fproject\u002Fjsonapi_views\u002Fissues\u002F3376193\">#3376193\u003C\u002Fa>, patch by \u003Ca href=\"https:\u002F\u002Fwww.drupal.org\u002Fu\u002Fjeffschuler\">jeffschuler\u003C\u002Fa>). The Views UI preview panel was reading an exposed filter's field name instead of its configured identifier, breaking any view where you'd renamed a filter to something readable. It now reads the identifier the display is actually configured with.\u003C\u002Fp>",{"type":23,"html":76},"\u003Cp>\u003Cstrong>OpenAPI schema export crashed with jsonapi_views enabled\u003C\u002Fstrong> (\u003Ca href=\"https:\u002F\u002Fwww.drupal.org\u002Fproject\u002Fjsonapi_views\u002Fissues\u002F3265781\">#3265781\u003C\u002Fa>). jsonapi_views now reports a view's real \u003Ccode>ResourceType\u003C\u002Fcode> on the route when its entity type has exactly one bundle, so OpenAPI describes it correctly; multi-bundle views are left alone.\u003C\u002Fp>",{"type":18,"title":78,"layout":19,"regions":79},"What's next",{"content":80},[81],{"type":23,"html":82},"\u003Cp>This is part of the same push that got Field Tokens 2.0.0 and Custom Formatters 4.1.0 out the door: working through my modules one at a time and actually clearing the backlog, not just triaging it. There's more coming for JSON:API Views too, tighter access control at the route level, more performance headroom for sites well past a hundred exposed views, and eventually a 2.0.x that flips exposure from opt-out to opt-in. File (Field) Paths is next up though, tens of thousands of sites and still sitting in RC ahead of a stable 1.0.\u003C\u002Fp>",{"type":18,"layout":19,"regions":84},{"content":85},[86,97,99,101,107],{"type":87,"title":88,"content":89},"jumbotron","If your project depends on this work",[90,92],{"type":23,"html":91},"\u003Cp>JSON:API Views, the wider Druxt ecosystem, the other modules I maintain - I build all of it in the open, and sponsorship is what keeps it actively maintained.\u003C\u002Fp>",{"type":93,"link":94},"link",{"href":95,"label":96},"https:\u002F\u002Fgithub.com\u002Fsponsors\u002FDecipher","Sponsor on GitHub",{"type":23,"html":98},"\u003Cp>If any of this is useful to you, 8.x-1.2 is out now:\u003C\u002Fp>",{"type":53,"code":100},"composer require 'drupal\u002Fjsonapi_views:^1.2'",{"type":102,"description":103,"url":104,"gitpod":105,"drupalUrl":106},"repository","Source on GitHub, project page on Drupal.org, patches welcome in the issue queue. If your project depends on this, sponsoring keeps it actively maintained.","https:\u002F\u002Fgithub.com\u002FDecipher\u002Fjsonapi_views",false,"https:\u002F\u002Fwww.drupal.org\u002Fproject\u002Fjsonapi_views",{"type":23,"html":108},"\u003Cp>What's your decoupled stack - are you hand-rolling a listing endpoint for every view, or reaching for something like this? I'd genuinely like to know.\u003C\u002Fp>","\u002Fwriting\u002Fjsonapi-views-120-20260812","6 min",{"loc":109},"articles-data\u002Fjsonapi-views-120-20260812","IsRHTHtqIKYhqX2U3Spkek9suuSbvuZjZBeYs_Gog8c",{"id":115,"title":116,"articleType":7,"categories":117,"date":118,"description":119,"extension":14,"meta":120,"paragraphs":121,"path":213,"readingTime":214,"sitemap":215,"stem":216,"__hash__":217},"articleEntries\u002Farticles-data\u002Fcustom-formatters-410-20260731.json","Custom Formatters 4.1.0",[9,11],"2026-07-31T13:30:00+10:00","Nearly a decade after stepping away, 4.1.0 picks the module back up and brings back formatter settings, live preview, a CodeMirror editor, and Devel Generate support, with more to come.",{},[122,129,154,166,172,183,189,202],{"type":18,"layout":19,"regions":123},{"content":124},[125,127],{"type":23,"html":126},"\u003Cp>Custom Formatters is old. I started it in 2009, my first year building seriously for Drupal, and shipped it through Drupal 6 and 7. Then in late 2016, not long after the first Drupal 8 alpha, I stepped away (work, life, the usual reasons) and for the best part of a decade it wasn't mine to ship.\u003C\u002Fp>\n\n\u003Cp>It didn't die, though, and that's almost entirely down to one person. \u003Ca href=\"https:\u002F\u002Fwww.drupal.org\u002Fu\u002Fpodarok\">Andrii Podanenko\u003C\u002Fa> (\u003Cem>podarok\u003C\u002Fem>), backed by \u003Ca href=\"https:\u002F\u002Fwww.drupal.org\u002Fitcare\">ITCare\u003C\u002Fa> and the \u003Ca href=\"https:\u002F\u002Fwww.drupal.org\u002Fopen-y\">Open Y\u003C\u002Fa> distribution, carried it through the Drupal 8 beta, the Drupal 10 port, and the start of the Drupal 11 line, essentially single-handedly, for years. Huge thanks to Andrii for looking after it all that time. I've picked the 4.1.x line back up alongside him, and 4.1.0 is the first release to come out of that.\u003C\u002Fp>",{"type":23,"html":128},"\u003Cp>4.1.0 is, deliberately, a bit of a nostalgia trip. A handful of the things that made the module worth reaching for in the first place quietly went missing during the Drupal 8 port (formatter settings, live preview, a real code editor, Devel Generate support), and this release brings four of them back. There's new stuff too.\u003C\u002Fp>",{"type":18,"title":130,"layout":19,"regions":131},"Formatter settings",{"content":132},[133,135,141,143,149,151],{"type":23,"html":134},"\u003Cp>The old approach leaned on the Form Builder module, a separate drag-and-drop form builder bolted on the side. You'd end up with a real settings form in theory, but what it actually generated behind the scenes was a block of PHP form arrays that got \u003Ccode>eval()\u003C\u002Fcode>'d at render time. Clever for 2011. Not exactly integrated, and it quietly disappeared in the Drupal 8 port along with a few other things.\u003C\u002Fp>\n\n\u003Cp>4.1.0 finally replaces it. Formatter settings are just fields now, attached to a formatter the same way you'd attach fields to any content type: a text field for a CSS class, a boolean for whether to link to the entity, whatever the formatter needs. In the template it's \u003Ccode>settings.field_name\u003C\u002Fcode> for the rendered value, or \u003Ccode>raw_settings.field_name\u003C\u002Fcode> if you want it unformatted.\u003C\u002Fp>",{"type":36,"src":136,"alt":137,"caption":138,"width":139,"height":140},"\u002Fimages\u002Fwriting\u002Fcustom-formatters-settings-fields.png","The Manage Fields tab on a Custom Formatters formatter, listing two attached fields: CSS class (Short text) and Link to entity (Boolean)","Attached like any other field.",1198,298,{"type":23,"html":142},"\u003Cp>You attach the fields the normal way, and configure them per placement right from Manage Display, the same way you'd configure an image style:\u003C\u002Fp>",{"type":36,"src":144,"alt":145,"caption":146,"width":147,"height":148},"\u002Fimages\u002Fwriting\u002Fcustom-formatters-settings-manage-display.png","The inline formatter settings on a Manage Display row for the Linkable title formatter, with a CSS class field set to text-lg and a Link to entity toggle switched on","Configured the same way as an image style.",810,463,{"type":23,"html":150},"\u003Cp>The module ships its own example of this, a Twig formatter called \"Linkable title\" that wraps the field value in a link and applies whatever class you've given it:\u003C\u002Fp>",{"type":53,"title":152,"code":153},"Example: Linkable title (Twig + settings)","{% for item in items %}\n  {% set class = settings.field_css_class ? ' class=\"' ~ settings.field_css_class|clean_class ~ '\"' : '' %}\n  {% if settings.field_link and settings.field_link|lower not in ['no', 'off', 'false', '0', ''] %}\n    \u003Ca href=\"{{ entity.id ? path('entity.node.canonical', {'node': entity.id}) : '#' }}\"{{ class|raw }}>{{ item.value }}\u003C\u002Fa>\n  {% else %}\n    \u003Cspan{{ class|raw }}>{{ item.value }}\u003C\u002Fspan>\n  {% endif %}\n{% endfor %}",{"type":18,"title":155,"layout":19,"regions":156},"Live preview",{"content":157},[158,160],{"type":23,"html":159},"\u003Cp>Settings only matter if you can see what they do, so live preview is back too, and it's wired into settings. Pick an entity, fill in the settings, and watch the output render right there on the edit form. The panel gives you per-engine debug output alongside the render itself (a variables dump for Twig and PHP, the raw HTML for HTML+Token), so you can see exactly what reached the template.\u003C\u002Fp>",{"type":36,"src":161,"alt":162,"caption":163,"width":164,"height":165},"\u002Fimages\u002Fwriting\u002Fcustom-formatters-settings-hero.png","The formatter edit form showing the syntax-highlighted CodeMirror editor for the Linkable title Twig template above a live preview panel, with CSS class set to text-lg and Link to entity enabled, a rendered link to a node, and a debug dump showing the settings and raw_settings values","Fill in the settings, see it render.",1312,1656,{"type":18,"title":167,"layout":19,"regions":168},"Devel Generate",{"content":169},[170],{"type":23,"html":171},"\u003Cp>And if nothing on the site has the right field type yet (say you're building an image formatter before any image field exists), Devel Generate support steps in. It builds a throwaway sample entity for the preview instead of leaving it blank, so you're never creating a dummy node just to see your formatter render.\u003C\u002Fp>",{"type":18,"title":173,"layout":19,"regions":174},"A real code editor",{"content":175},[176,178],{"type":23,"html":177},"\u003Cp>The last of the four returning features is the one I'm most pleased with: a real code editor. The template field is now a CodeMirror editor, syntax-highlighted with HTML-aware auto-closing tags, instead of a plain textarea. More usefully, its autocomplete actually knows what each engine supports. Type \u003Ccode>{{\u003C\u002Fcode> in a Twig formatter and it offers the variables in scope; type \u003Ccode>[\u003C\u002Fcode> in an HTML+Token formatter and it offers Drupal tokens, including the \u003Ccode>[formatter_setting:...]\u003C\u002Fcode> ones; \u003Ccode>Ctrl+Space\u003C\u002Fcode> gives you context-appropriate suggestions in any engine.\u003C\u002Fp>",{"type":36,"src":179,"alt":180,"caption":181,"width":139,"height":182},"\u002Fimages\u002Fwriting\u002Fcustom-formatters-autocomplete.png","The CodeMirror editor on a Twig formatter with the autocomplete dropdown open after typing {{, offering the in-scope variables items, entity, langcode, settings and raw_settings","Type {{ in a Twig formatter: autocomplete knows what's in scope.",633,{"type":18,"title":184,"layout":19,"regions":185},"Also back",{"content":186},[187],{"type":23,"html":188},"\u003Cp>A few smaller things are back as well: a Save &amp; Edit button, so you're not bounced back to the formatter list every time you tweak something; and an \u003Ccode>entity\u003C\u002Fcode> variable in Twig templates, so a formatter can reach the parent entity directly instead of only the field it's attached to. Drupal 11 support is locked in.\u003C\u002Fp>\n\n\u003Cp>Integration with the \u003Ca href=\"https:\u002F\u002Fwww.drupal.org\u002Fproject\u002Finsert\">Insert\u003C\u002Fa> module is back too. Any formatter targeting an image, file, or entity reference field is automatically exposed as an Insert style and can be dropped straight into a WYSIWYG.\u003C\u002Fp>",{"type":18,"title":190,"layout":19,"regions":191},"Connected to Field Tokens",{"content":192},[193,195],{"type":23,"html":194},"\u003Cp>If you're running Field Tokens as well, this connects to something I fixed there too. The \u003Ccode>[formatted_field-*]\u003C\u002Fcode> integration, which lets a token render a field through one of these formatters, broke during Field Tokens' own Drupal 8 port and stayed broken for years. 2.0.0 rebuilt that data provider from scratch, so whatever you build here, settings included, is reachable from a token again.\u003C\u002Fp>",{"type":196,"title":197,"description":198,"link":199},"card","Field Tokens 2.0.0","Wildcard deltas, dot notation for nested formatter settings, and a restored Custom Formatters integration.",{"href":200,"label":201},"\u002Fwriting\u002Ffield-tokens-200-20260722","Read the Field Tokens 2.0.0 post",{"type":18,"layout":19,"regions":203},{"content":204},[205,207,209],{"type":23,"html":206},"\u003Cp>If any of this is useful to you, 4.1.0 is out now:\u003C\u002Fp>",{"type":53,"code":208},"composer require 'drupal\u002Fcustom_formatters:^4.1'",{"type":102,"description":210,"url":211,"gitpod":105,"drupalUrl":212},"Source on GitHub, the full project page on Drupal.org, and if it's saved you some time, sponsorship is always appreciated.","https:\u002F\u002Fgithub.com\u002FDecipher\u002Fcustom_formatters","https:\u002F\u002Fwww.drupal.org\u002Fproject\u002Fcustom_formatters","\u002Fwriting\u002Fcustom-formatters-410-20260731","4 min",{"loc":213},"articles-data\u002Fcustom-formatters-410-20260731","b94HneyZbDy5y7s94XfcKeA2cLF4sAIZQ_Wkloh7mv8",{"id":219,"title":197,"articleType":7,"categories":220,"date":221,"description":222,"extension":14,"meta":223,"paragraphs":224,"path":200,"readingTime":248,"sitemap":249,"stem":250,"__hash__":251},"articleEntries\u002Farticles-data\u002Ffield-tokens-200-20260722.json",[9,11],"2026-07-23T09:00:00+10:00","Wildcard deltas, dot notation for nested formatter settings, and Drupal 11 support: what changed in the first stable 2.x release.",{},[225],{"type":18,"layout":19,"regions":226},{"content":227},[228,230,233,235,238,240,242,246],{"type":23,"html":229},"\u003Cp>I lose count of how many times I've reached for Field Tokens on a project, then hit the same wall: a multi-value image field, and no clean way to say \"give me all of them, formatted\" in a single token. You could grab one delta at a time, or write custom PHP to loop over the field yourself, but there was no in-between.\u003C\u002Fp>\n\n\u003Cp>If you haven't used it: \u003Ca href=\"https:\u002F\u002Fwww.drupal.org\u002Fproject\u002Ffield_tokens\">Field Tokens\u003C\u002Fa> adds two token types Drupal core doesn't ship with, formatted field tokens (render a field value through a chosen formatter) and field property tokens (reach into a field's raw properties, like an image's alt text or a link's URL). It's one of those modules that quietly becomes load-bearing on a token-heavy site the moment you need either.\u003C\u002Fp>\n\n\u003Cp>2.0.0 finally gives that in-between a real syntax. The delta segment of a formatted field token now accepts a single index (\u003Ccode>0\u003C\u002Fcode>), a comma list (\u003Ccode>0,2,4\u003C\u002Fcode>), a range (\u003Ccode>0-2\u003C\u002Fcode>), a mix of the two (\u003Ccode>0-2,4\u003C\u002Fcode>), a wildcard for every value (\u003Ccode>*\u003C\u002Fcode>), or nothing at all, which also means every value, with a configurable delimiter for however you want the output joined. So a multi-value image field, rendered through the \u003Ccode>thumbnail\u003C\u002Fcode> image style, all values at once, is just:\u003C\u002Fp>",{"type":53,"title":231,"code":232},"Wildcard delta, image style","[node:field_image-formatted:*:image:image_style-thumbnail]",{"type":23,"html":234},"\u003Cp>That's the whole token. No loop, no custom formatter, no falling back to a Twig template just to get every value out. The wildcard and range syntax came out of \u003Ca href=\"https:\u002F\u002Fwww.drupal.org\u002Fproject\u002Ffield_tokens\u002Fissues\u002F3267442\">issue #3267442\u003C\u002Fa>.\u003C\u002Fp>\n\n\u003Cp>The other half of 2.0.0 is dot notation, for two separate things. First, reaching into a nested formatter setting: most image style and responsive image formatters bury their real configuration a level or two deep, and before 2.0.0 you simply couldn't address that from a token. Now you can chain keys with a dot:\u003C\u002Fp>",{"type":53,"title":236,"code":237},"Nested formatter setting","[node:field_image-formatted:0:image:image_loading.loading-lazy]",{"type":23,"html":239},"\u003Cp>Second, the same dot notation works on field property tokens, so a nested key inside a property value is addressable the same way, rather than only ever returning the whole structure and leaving you to parse it yourself downstream.\u003C\u002Fp>\n\n\u003Cp>Custom Formatters integration is back too. The original data provider broke during the Drupal 8 port, which meant if you were using the Custom Formatters module to build your own formatter plugins, Field Tokens simply couldn't see them, and \u003Ccode>[formatted_field-*]\u003C\u002Fcode> tokens went quiet. 2.0.0 re-implements that data provider from scratch, so if you've been maintaining a workaround, you can retire it.\u003C\u002Fp>\n\n\u003Cp>And for anyone weighing Drupal 11 readiness before committing to a module: Field Tokens 2.0.0 declares \u003Ccode>^10.1 || ^11\u003C\u002Fcode>, so it's covered.\u003C\u002Fp>\n\n\u003Cp>If any of this solves a problem you've been working around:\u003C\u002Fp>",{"type":53,"code":241},"composer require 'drupal\u002Ffield_tokens:^2.0'",{"type":102,"description":243,"url":244,"gitpod":105,"drupalUrl":245},"\u003Cp>Source on GitHub, the full project page on Drupal.org, and if it's saved you some time, sponsorship is always appreciated.\u003C\u002Fp>","https:\u002F\u002Fgithub.com\u002FDecipher\u002Ffield_tokens","https:\u002F\u002Fwww.drupal.org\u002Fproject\u002Ffield_tokens",{"type":23,"html":247},"\u003Cp>This one's part of a bigger push I'm on at the moment: going back through my modules one at a time and getting them stabilised: real code coverage, CI that actually means something, releases that don't sit in RC for years. Field Tokens is the first of several I've got lined up, so expect more of this over the coming months.\u003C\u002Fp>","2 min",{"loc":200},"articles-data\u002Ffield-tokens-200-20260722","EZUFMNfRN7oDoqBO_4m9QWTH48qbbcv8-Wt9lg5q6i0",{"id":253,"title":254,"articleType":7,"categories":255,"date":256,"description":257,"extension":14,"meta":258,"paragraphs":259,"path":331,"readingTime":332,"sitemap":333,"stem":334,"__hash__":335},"articleEntries\u002Farticles-data\u002Fdecoupling-configuration-config-pages-20220412.json","Decoupling configuration with Config Pages",[10,11],"2022-04-12T11:33:53+10:00","Drupal exposes a lot of data that a decoupled app can consume, but in most cases it is limited to content rather than configuration; site title, slogan, logo among others are not readily available on a JSON:API build. Today I'll be looking at the Config Pages module for Drupal, and the newly released Druxt companion module.",{},[260,266,286,298,318,325],{"type":18,"title":261,"layout":19,"regions":262},"Decoupled configuration",{"content":263},[264],{"type":23,"html":265},"\u003Cp>One of the first Vue and Nuxt projects that I worked on was a calculator of sorts; a single page app (SPA) that used user input and calculated it against algorithms that used data and configuration provided by Drupal.\u003C\u002Fp>\n\n\u003Cp>In that case it was a simple case of providing some \"configuration data\" in Drupal, and consuming that data in the SPA. While not groundbreaking in concept, having Drupal as an administrative UI for Nuxt powered applications and sites has so much potential.\u003C\u002Fp>\n\n\u003Cp>While there may seem to be an emphasis that Decoupling Drupal is all about getting a better render engine for Drupal, the benefits Nuxt (or your preferred Frontend framework) get from Drupal are huge. And Decoupled Configuration is definitely one of the biggest. It was one of the reasons I started building Druxt.\u003C\u002Fp>\n\n\u003Cp>While the Drupal JSON:API still doesn't provide anyway to access basic site configuration, there are many ways it can be done...\u003C\u002Fp>",{"type":18,"title":267,"layout":268,"regions":269},"Config Pages","layout_twocol",{"top":270,"first":273,"second":276,"bottom":283},[271],{"type":23,"html":272},"\u003Cp>The Drupal \u003Ca href=\"https:\u002F\u002Fdrupal.org\u002Fproject\u002Fconfig_pages\">Config Pages\u003C\u002Fa> module has been my goto for Decoupled Configuration for many years now.\u003C\u002Fp>",[274],{"type":23,"html":275},"\u003Cp>The module provides a fieldable Config Pages entity type, each Config Page type you create can only have one entity, and the data is exposed via the JSON:API if you have the appropriate permissions.\u003C\u002Fp>\n\n\u003Cp>One Config Page type per application with any fields you want. It's a pretty straight forward solution to the issue.\u003C\u002Fp>",[277],{"type":36,"alt":278,"caption":279,"width":280,"height":281,"src":282},"Drupal Config Pages module example","\u003Cp>Drupal Config Pages module example\u003C\u002Fp>",1020,770,"\u002Fimages\u002Fwriting\u002Fconfig_pages_0.png",[284],{"type":23,"html":285},"\u003Cp>Install and setup is pretty standard for a Drupal Entity type based module:\u003C\u002Fp>\n\n\u003Col>\u003Cli>Download the module: \u003Cstrong>composer require drupal\u002Fconfig_pages\u003C\u002Fstrong>\u003C\u002Fli>\n\t\u003Cli>Enable the module: \u003Cstrong>drush en config_pages -y\u003C\u002Fstrong>\u003C\u002Fli>\n\t\u003Cli>Create a Config Page type: \u003Cstrong>\u002Fadmin\u002Fstructure\u002Fconfig_pages\u002Ftypes\u002Fadd\u003C\u002Fstrong>\u003C\u002Fli>\n\t\u003Cli>Add fields to the content type: \u003Cstrong>\u002Fadmin\u002Fstructure\u002Fconfig_pages\u002Ftypes\u002Fmanage\u002F[TYPE]\u002Ffields\u003C\u002Fstrong>\u003C\u002Fli>\n\t\u003Cli>Set the \"\u003Cstrong>View the [TYPE] config page entity\u003C\u002Fstrong>\" permission for the user role used be Druxt (anonymous in most instances): \u003Cstrong>\u002Fadmin\u002Fpeople\u002Fpermissions\u002Fmodule\u002Fconfig_pages\u003C\u002Fstrong>\u003C\u002Fli>\n\u003C\u002Fol>\u003Cp>Once the Config Page type is set up, you will also need to create the Config Page entity with the values you wish to provide to the frontend application: \u003Cstrong>\u002Fadmin\u002Fstructure\u002Fconfig_pages\u002F[TYPE]\u002Fedit\u003C\u002Fstrong>\u003C\u002Fp>",{"type":18,"title":287,"layout":19,"regions":288},"Consuming Config Pages",{"content":289},[290,292,294,296],{"type":23,"html":291},"\u003Cp>As the Config Page entity is just a regular Content Entity as far as Drupal is concerned, the data is accessible via the JSON:API and can be consumed in any number of ways by any number of clients and consumers. That's the joy of the JSON:API.\u003C\u002Fp>",{"type":53,"code":293},"const config = await druxt.getResource('config_pages--TYPE', uuid)",{"type":53,"code":295},"\u003CDruxtEntity type=\"config_pages--TYPE\" :uuid=\"uuid\">\r\n  \u003Ctemplate #default=\"{ entity }\">\r\n    entity.attributes.field_NAME\r\n  \u003C\u002Ftemplate>\r\n\u003C\u002FDruxtEntity>",{"type":23,"html":297},"\u003Cp>There's many solutions, it just depends on what your needs are.\u003C\u002Fp>\n\n\u003Cp>For me, I wanted to have basic site settings as easily available to my site, no matter what component. Things like site name, slogan, social media accounts, colours and other customisations.\u003C\u002Fp>\n\n\u003Cp>So I wrote a Druxt contrib module to take the data from the JSON:API and make it available in a Vuex store.\u003C\u002Fp>",{"type":18,"title":299,"layout":268,"regions":300},"@druxt-contrib\u002Fconfig-pages",{"top":301,"first":304,"second":307,"bottom":311},[302],{"type":23,"html":303},"\u003Cp>The module pulls in the configured Config Pages entities and populates a Vuex store during the Nuxt build process, made accessible via the Vuex store and \u003Cstrong>$druxtConfigPages\u003C\u002Fstrong> plugin.\u003C\u002Fp>\n\n\u003Col>\u003C\u002Fol>",[305],{"type":23,"html":306},"\u003Cp>Installation and setup is pretty standard Nuxt:\u003C\u002Fp>\n\n\u003Col>\u003Cli>Download the module: \u003Cstrong>npm i @druxt-contrib\u002Fconfig-pages\u003C\u002Fstrong>\u003C\u002Fli>\n\t\u003Cli>Add and configure the module in your \u003Cstrong>nuxt.config.js\u003C\u002Fstrong> file.\u003C\u002Fli>\n\t\u003Cli>The DruxtConfigPages module needs to have at least one page configured to operate.\u003C\u002Fli>\n\u003C\u002Fol>",[308],{"type":53,"title":309,"code":310},"nuxt.config.js","export default {\r\n  buildModules: [\r\n    '@druxt-contrib\u002Fconfig-pages',\r\n    'druxt'\r\n  ],\r\n  druxt: {\r\n    baseUrl,\r\n    configPages: {\r\n      pages: ['foo']\r\n    }\r\n  }\r\n}",[312,314,316],{"type":23,"html":313},"\u003Cp>The module stores the data in its raw JSON:API format, but provides a Getter and Nuxt plugin to provide the data in a simplified format.\u003C\u002Fp>",{"type":53,"code":315},"\u003Ctemplate>\r\n  \u003Ch1>{{ $druxtConfigPages.get('foo').bar }}\u003C\u002Fh1>\r\n\u003C\u002Ftemplate>",{"type":53,"code":317},"$druxtConfigPages.get('foo.bar')",{"type":18,"layout":19,"regions":319},{"content":320},[321],{"type":102,"description":322,"url":323,"gitpod":324},"\u003Cp>The module and issue queue can be found on Github, and there's more features planned for future releases.\u003C\u002Fp>","https:\u002F\u002Fgithub.com\u002Fdruxt-contrib\u002Fdruxt-config-pages",true,{"type":18,"title":326,"layout":19,"regions":327},"Alternatives?",{"content":328},[329],{"type":23,"html":330},"\u003Cp>I've been working on Decoupled project that uses Taxonomy among other things to provide multi-site functionality. One Drupal backend for many targeted consumers, Nuxt and other.\u003C\u002Fp>&#13;\n&#13;\n\u003Cp>While I find the other side of the multi-site coin far more intriguing, one Druxt frontend for many Drupal backends, individually or concurrently, both use cases have a common need for consumer based configuration.\u003C\u002Fp>&#13;\n&#13;\n\u003Cp>One of my future experiments with Druxt will be to look at the options of using the Drupal \u003Ca href=\"https:\u002F\u002Fwww.drupal.org\u002Fproject\u002Fconsumers\">Consumers\u003C\u002Fa> module alongside Drupal theme settings as a solution.\u003C\u002Fp>&#13;\n&#13;\n\u003Cp>I'm curious to hear from others, have you dealt with Decoupled Configuration? What approach did you use? Let me know in the comments below.\u003C\u002Fp>&#13;","\u002Fwriting\u002Fdecoupling-configuration-config-pages-20220412","3 min",{"loc":331},"articles-data\u002Fdecoupling-configuration-config-pages-20220412","E8L6et1rtXg6DhxjFTw63KDJ0QKosV6EJVvVCAFYk3g",{"id":337,"title":338,"articleType":7,"categories":339,"date":340,"description":341,"extension":14,"meta":342,"paragraphs":343,"path":398,"readingTime":332,"sitemap":399,"stem":400,"__hash__":401},"articleEntries\u002Farticles-data\u002Fwhat-no-images-20220315.json","What, no images?",[10,11],"2022-03-15T12:21:10+11:00","A picture is worth a thousand words, but how many lines of code does it take to add images to a serverless Druxt site? A blog without images is hard, but is getting Drupal managed files from an un-hosted Drupal backend harder?",{},[344,350,356,362,368,389],{"type":18,"title":345,"layout":19,"regions":346},"What's the problem with images?",{"content":347},[348],{"type":23,"html":349},"\u003Cp>Drupal is a very powerful open-source content management system, and over the years there has been a large emphasis on media management, because, really, it's quite rare to build a site, blog or web application without images.\u003C\u002Fp>&#13;\n&#13;\n\u003Cp>But when launching this site, and building the \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fdruxt\u002Fquickstart-druxt-serverless\">Druxt serverless quickstart template\u003C\u002Fa>, I had to make the decision to exclude images.\u003C\u002Fp>&#13;\n&#13;\n\u003Cp>Why?\u003C\u002Fp>&#13;\n&#13;\n\u003Cp>Because out of the box, Drupal media, and files, are served by Drupal. But the whole point of a serverless site is to not have a server, and no server means no images.\u003C\u002Fp>&#13;",{"type":18,"title":351,"layout":19,"regions":352},"So, no images then?",{"content":353},[354],{"type":23,"html":355},"\u003Cp>Well, not exactly. Where there is a problem, there is inevitably a workaround, and ideally a solution. The workaround is relatively straight forward; have your images in the frontend, e.g., make your images part of the Nuxt theme components.\u003C\u002Fp>\n\n\u003Cp>However, this only solves theme and layout images, and does nothing to solve the issue of content managed issues.\u003C\u002Fp>\n\n\u003Cp>So what's the solution?\u003C\u002Fp>",{"type":18,"title":357,"layout":19,"regions":358},"Experimenting with Cloudinary",{"content":359},[360],{"type":23,"html":361},"\u003Cp>My original thoughts, and the experiment I put the most time into; host the images on a third-party image service provider, like Cloudinary.\u003C\u002Fp>&#13;\n&#13;\n\u003Cp>I specifically chose Cloudinary for a few reasons:\u003C\u002Fp>&#13;\n&#13;\n\u003Col>&#13;\n\t\u003Cli>There's a Drupal module: \u003Ca href=\"https:\u002F\u002Fwww.drupal.org\u002Fproject\u002Fcloudinary\">https:\u002F\u002Fwww.drupal.org\u002Fproject\u002Fcloudinary\u003C\u002Fa>\u003C\u002Fli>&#13;\n\t\u003Cli>There's a Nuxt Image module provider: \u003Ca href=\"https:\u002F\u002Fimage.nuxtjs.org\u002Fproviders\u002Fcloudinary\">https:\u002F\u002Fimage.nuxtjs.org\u002Fproviders\u002Fcloudinary\u003C\u002Fa>\u003C\u002Fli>&#13;\n\t\u003Cli>There's a free option, and serverless is all about hosting your Drupal content for free, where possible.\u003C\u002Fli>&#13;\n\u003C\u002Fol>&#13;\n&#13;\n\u003Cp>Unfortunately the Drupal module does not yet have a viable release for Drupal 9.\u003C\u002Fp>&#13;\n&#13;\n\u003Cp>While there is \u003Ca href=\"https:\u002F\u002Fwww.drupal.org\u002Fproject\u002Fcloudinary\u002Fissues\u002F3168749\">an open merge request\u003C\u002Fa> to add support, through testing I have determined that it is not yet ready for use.\u003C\u002Fp>&#13;",{"type":18,"title":363,"layout":19,"regions":364},"Next? Nuxt (Image)!",{"content":365},[366],{"type":23,"html":367},"\u003Cp>While I was certain I had been on the right direction with Cloudinary, or more specifically, a CDN based image provide, I \u003Cstrong>know\u003C\u002Fstrong> I am on the right direction with the Nuxt Image module.\u003C\u002Fp>\n\n\u003Cp>One of my original thoughts was that the Drupal file system could be symbolically linked into the Nuxt assets directory, or alternatively Nuxt could pull the images in from the Drupal backend during the Nuxt build\u002Fgenerate process.\u003C\u002Fp>\n\n\u003Cp>Turns out the Nuxt Image module already has the ability built in, so no third-party image service provider is required at all.\u003C\u002Fp>",{"type":18,"title":369,"layout":19,"regions":370},"The steps",{"content":371},[372,374,376,378,381,383],{"type":23,"html":373},"\u003Cp>There's not a lot involved to get it working, which is the best kind of solution.\u003C\u002Fp>",{"type":53,"code":375},"npm install --save-dev @nuxt\u002Fimage",{"type":53,"title":309,"code":377},"buildModules: [\r\n  ['@nuxt\u002Fimage', { domains: [baseUrl] }],\r\n]",{"type":53,"title":379,"code":380},"~\u002Fcomponents\u002Fdruxt\u002Ffield\u002FImage.vue","\u003Ctemplate>\r\n  \u003CDruxtEntity type=\"file--file\" :uuid=\"model.data.id\">\r\n    \u003Ctemplate #default=\"{ entity }\">\r\n      \u003CNuxtImg :src=\"src(entity)\" \u002F>\r\n    \u003C\u002Ftemplate>\r\n  \u003C\u002FDruxtEntity>\r\n\u003C\u002Ftemplate>\r\n\r\n\u003Cscript>\r\nimport { DruxtFieldMixin } from 'druxt-entity'\r\nexport default {\r\n  mixins: [DruxtFieldMixin],\r\n  methods: {\r\n    src(entity) {\r\n      return [this.$druxt.settings.baseUrl, entity.attributes.uri.url].join('\u002F')\r\n    },\r\n  },\r\n}\r\n\u003C\u002Fscript>",{"type":23,"html":382},"\u003Cp>The DruxtFieldImage component also converts the relative URL of the image to an absolute URL, which is required for the Nuxt Image module to do it's job.\u003C\u002Fp>\n\n\u003Cp>And that's it, assuming everything was done correctly you are now able to run the \u003Cstrong>nuxt generate\u003C\u002Fstrong> command and it will process your Drupal hosted images into the your \u003Cstrong>dist\u003C\u002Fstrong> folder.\u003C\u002Fp>",{"type":36,"alt":384,"caption":385,"width":386,"height":387,"src":388},"Serverless image generation","\u003Cp>Serverless image generation\u003C\u002Fp>",1300,400,"\u002Fimages\u002Fwriting\u002Fnuxt-image-generate.png",{"type":18,"title":390,"layout":19,"regions":391},"The end result",{"content":392},[393,395],{"type":23,"html":394},"\u003Cp>\"No images\" no more, and thankfully it was much easier than expected; I had been expecting to have to update the merge request for Cloudinary, which is not a small task and not something I was looking forward to.\u003C\u002Fp>\n\n\u003Cp>The Nuxt Image module is fantastic, it does everything I needed, and more than I could have hoped for.\u003C\u002Fp>\n\n\u003Cp>And of course, with a solution found I have also updated the Druxt Serverless Quickstart template so that next time I, or anyone else, wants a serverless Druxt site with the full power of Drupal Media it is ready to go out of the box.\u003C\u002Fp>",{"type":102,"description":396,"url":397,"gitpod":324},"\u003Cp>One click, Fully Decoupled, Full Static, Serverless Drupal Site starter-kit with Druxt.\u003C\u002Fp>","https:\u002F\u002Fgithub.com\u002Fdruxt\u002Fquickstart-druxt-serverless","\u002Fwriting\u002Fwhat-no-images-20220315",{"loc":398},"articles-data\u002Fwhat-no-images-20220315","ot-FEsW0OYPz09Ex8ohp0Tp_bEL1Tsu0lEeRQzbyGDs",{"id":403,"title":404,"articleType":7,"categories":405,"date":406,"description":407,"extension":14,"meta":408,"paragraphs":409,"path":449,"readingTime":248,"sitemap":450,"stem":451,"__hash__":452},"articleEntries\u002Farticles-data\u002Flayout-paragraphs-module-20220301.json","Layout Paragraphs module",[10,11],"2022-03-01T12:29:30+11:00","There are many complaints about the Paragraphs module, but it's a module I wouldn't build a Drupal site without, Decoupled or otherwise. Complexity with nested paragraphs is a common issue though, but usually a necessary evil. However we recently implemented the Layout Paragraphs module into the Foundry Drupal backend, and I've been really happy with what I've seen. So today I'm experimenting with Druxt and the Layout Paragraphs module",{},[410,416,425,431,434,443],{"type":18,"title":411,"layout":19,"regions":412},"What does the Layout Paragraphs module do?",{"content":413},[414],{"type":23,"html":415},"\u003Cp>When you have the \u003Ca href=\"https:\u002F\u002Fwww.drupal.org\u002Fproject\u002Flayout_paragraphs\">Layouts Paragraphs module\u003C\u002Fa> installed and configured correctly, which is not something that this post is going to cover, Layout Paragraphs allows you to create \u003Cstrong>Sections\u003C\u002Fstrong> for your Paragraphs.\u003C\u002Fp>\n\n\u003Cp>Each section has it's own settings and layouts, and layouts can of course have regions; one column, two column, etc.\u003C\u002Fp>",{"type":18,"title":417,"layout":268,"regions":418},"Experimenting with two coloums",{"first":419,"second":422},[420],{"type":23,"html":421},"\u003Cp>The module provides a very easy to use javascript interface allowing me to add my paragraphs into the regions, preview them and rearrange the content with buttons or drag and drop.\u003C\u002Fp>",[423],{"type":23,"html":424},"\u003Cp>This allows the content creator the ability to make layout decisions within the content, while still allowing the frontend developer full control over the output.\u003C\u002Fp>",{"type":18,"title":426,"layout":19,"regions":427},"But does it work with Druxt?",{"content":428},[429],{"type":23,"html":430},"\u003Cp>That's a good question, and as I write these specific words I don't yet have the answer, I'm pretty confident it will work though, because:\u003C\u002Fp>\n\n\u003Cp>Druxt module components use a Vue based theming system that allows the frontend developer, in this case me, to create a correctly named component in the Nuxt components directory allowing full control over the rendered markup.\u003C\u002Fp>\n\n\u003Cp>This means that I can create a Field theme component that targets any Layout Paragraphs, \u003Cstrong>nuxt\u002Fcomponents\u002Fdruxt\u002Ffield\u002FLayoutParagraphs.vue\u003C\u002Fstrong>, and pass the field data through to a custom \u003Cstrong>DruxtLayoutParagraph\u003C\u002Fstrong> module.\u003C\u002Fp>",{"type":18,"title":432,"layout":19,"regions":433},"Time to experiment",{},{"type":18,"title":435,"layout":19,"regions":436},"The results",{"content":437},[438,440],{"type":23,"html":439},"\u003Cp>All the required data to replicate the Layout Paragraphs behaviour is thankfully available in the provided JSON:API data, which allows for a relatively simple custom Druxt module to provide templates that can be used by the frontend developer.\u003C\u002Fp>\n\n\u003Cp>I was happy enough with the results of the experiment, that I actually published the result as the \u003Cstrong>\u003Ca href=\"https:\u002F\u002Fgithub.com\u002FDecipher\u002Fdruxt-layout-paragraphs\">DruxtLayoutParagraphs\u003C\u002Fa>\u003C\u002Fstrong> module.\u003C\u002Fp>",{"type":102,"description":441,"url":442,"gitpod":105},"\u003Cp>The module adds a Field template and the DruxtLayoutParagraph component to render any fields using the Layout Paragraph field formatter.\u003C\u002Fp>\n\n\u003Cp>As with other modules, component options are provided theming the module component based on the layout used in Drupal. E.g, ~\u002Fcomponents\u002Fdruxt\u002Flayout-paragraph\u002FOnecol.vue\u003C\u002Fp>\n\n\u003Cp> \u003C\u002Fp>","https:\u002F\u002Fgithub.com\u002FDecipher\u002Fdruxt-layout-paragraphs",{"type":18,"title":444,"layout":19,"regions":445},"What next?",{"content":446},[447],{"type":23,"html":448},"\u003Cp>While the module in its current state it's already able to do everything I need for the moment, there's still more improvements to be made, and more features to be added.\u003C\u002Fp>\n\n\u003Cp>Default slots, a Mixin and Storybook integration all need to be added to simplify the theming process.\u003C\u002Fp>\n\n\u003Cp>And of course, more experiments to be done; Drag'n'Drop editing from the frontend is high on the list.\u003C\u002Fp>","\u002Fwriting\u002Flayout-paragraphs-module-20220301",{"loc":449},"articles-data\u002Flayout-paragraphs-module-20220301","gOxuhPrGbLSVm5DptkEqhY5AwFRAgsYv3MRTHAZ-ibQ",{"id":454,"title":455,"articleType":7,"categories":456,"date":457,"description":458,"extension":14,"meta":459,"paragraphs":460,"path":473,"readingTime":248,"sitemap":474,"stem":475,"__hash__":476},"articleEntries\u002Farticles-data\u002Fhello-world-20211126.json","Hello world",[10],"2022-03-01T08:12:55+11:00","With every new blog there needs to be a first post, so Hello World and welcome to the Stuart Clark Druxt blog. The purpose of this site is to give me a playground, a place to post on the progress and implement the results of my various Decoupled Drupal experiments. This site in itself is the result of an experiment; a Databaseless and Serverless, Statically generated Druxt frontend hosted on the CDN.",{},[461],{"type":18,"layout":19,"regions":462},{"content":463},[464,466,468,470],{"type":23,"html":465},"\u003Ch2>Who is Stuart?\u003C\u002Fh2>\n\n\u003Cp>Professionally, I'm a \u003Cstrong>Senior Decoupled Drupal developer\u003C\u002Fstrong> at \u003Cstrong>Realityloop\u003C\u002Fstrong> in Victoria, Australia.\u003C\u002Fp>\n\n\u003Cp>I've been working with \u003Cstrong>Drupal\u003C\u002Fstrong> for over \u003Cstrong>15 years\u003C\u002Fstrong>, both professional and as member of open source development community.\u003C\u002Fp>\n\n\u003Cp>For the last 4 years I've been focusing on \u003Cstrong>Vue.js \u003C\u002Fstrong>and \u003Cstrong>Nuxt.js\u003C\u002Fstrong>, leading to the creation of the \u003Cstrong>Druxt\u003C\u002Fstrong> framework.\u003C\u002Fp>",{"type":23,"html":467},"\u003Ch2>What is Druxt?\u003C\u002Fh2>&#13;\n&#13;\n\u003Cp>Druxt is an open source framework for building Fully Decoupled Drupal sites or integrations with the Nuxt.js frontend framework.\u003C\u002Fp>&#13;\n&#13;\n\u003Cblockquote>&#13;\n\u003Cp>Druxt = Drupal + Nuxt\u003C\u002Fp>&#13;\n\u003C\u002Fblockquote>&#13;\n&#13;\n\u003Cp>Decoupling Drupal is the practice of separating the presentation layer, the frontend, from the content management and site administration, the backend. A primary reason this is done is to gain the advantages of a modern javascript frontend frameworks and languages, like Nuxt.js and Vue.js.\u003C\u002Fp>&#13;\n&#13;\n\u003Cp>Druxt bridges the gap between Drupal and Nuxt, and provides Vue components that consume both content and configuration to provide default behaviour. e.g, Drupal Entities with support for Display modes, Drupal views with filters, pagination, etc.\u003C\u002Fp>&#13;\n&#13;\n\u003Cp>You can find out more about Druxt @ \u003Ca href=\"https:\u002F\u002Fdruxtjs.org\">druxtjs.org\u003C\u002Fa>\u003C\u002Fp>&#13;",{"type":23,"html":469},"\u003Ch2>The Blog \u002F The Experiment\u003C\u002Fh2>\n\n\u003Cp>For me, as a developer, a personal website is more about the build than the result; it's an opportunity to experiment with web technologies, being able to build something fun and interesting, to see what can be done.\u003C\u002Fp>\n\n\u003Cp>Being the developer of Druxt, it's relatively important that I also maintain my own Druxt site, to use the technology in real world situations.\u003C\u002Fp>\n\n\u003Cp>But on top of that, this site is an experiment of running and maintaining a serverless and databaseless, decoupled Drupal site on a CDN (Netlify) for free.\u003C\u002Fp>\n\n\u003Cp>This is achieved by running Druxt inside of Gitpod with the Drupal Tome module and using Nuxt as a static site generator.\u003C\u002Fp>\n\n\u003Cp>Spoiler alert, if you are reading this, the experiment was a success.\u003C\u002Fp>\n\n\u003Cp>Over the life of this blog\u002Fsite I will be posting more details on this and other decoupled Drupal experiments, including guides and tutorials. Stay tuned for more.\u003C\u002Fp>",{"type":102,"description":471,"url":472,"gitpod":324},"\u003Ch2>The code\u003C\u002Fh2>\n\n\u003Cp>This site is entirely open source, the content, configuration and codebase all live in a public Github repository which is configured to run entirely within Gitpod.\u003C\u002Fp>","https:\u002F\u002Fgithub.com\u002FDecipher\u002Fstuar.tc","\u002Fwriting\u002Fhello-world-20211126",{"loc":473},"articles-data\u002Fhello-world-20211126","cbkzbL-aB59DHtWbQz7eH96M5hEXh52fCumFNwsOAQI",1786513039256]