[{"data":1,"prerenderedAt":465},["ShallowReactive",2],{"footer-primary":3,"footer-secondary":93,"footer-description":119,"request-review-public-forms":121,"request-review-public-forms-next":192,"sales-reps":213},{"items":4},[5,29,49,69],{"id":6,"title":7,"url":8,"page":8,"children":9},"522e608a-77b0-4333-820d-d4f44be2ade1","Solutions",null,[10,15,20,25],{"id":11,"title":12,"url":8,"page":13},"fcafe85a-a798-4710-9e7a-776fe413aae5","Headless CMS",{"permalink":14},"/solutions/headless-cms",{"id":16,"title":17,"url":8,"page":18},"79972923-93cf-4777-9e32-5c9b0315fc10","Backend-as-a-Service",{"permalink":19},"/solutions/backend-as-a-service",{"id":21,"title":22,"url":8,"page":23},"0fa8d0c1-7b64-4f6f-939d-d7fdb99fc407","Product Information",{"permalink":24},"/solutions/product-information-management",{"id":26,"title":27,"url":28,"page":8},"63946d54-6052-4780-8ff4-91f5a9931dcc","100+ Things to Build","https://directus.io/blog/100-tools-apps-and-platforms-you-can-build-with-directus",{"id":30,"title":31,"url":8,"page":8,"children":32},"8ab4f9b1-f3e2-44d6-919b-011d91fe072f","Resources",[33,37,41,45],{"id":34,"title":35,"url":36,"page":8},"f951fb84-8777-4b84-9e91-996fe9d25483","Documentation","https://docs.directus.io",{"id":38,"title":39,"url":40,"page":8},"366febc7-a538-4c08-a326-e6204957f1e3","Guides","https://docs.directus.io/guides/",{"id":42,"title":43,"url":44,"page":8},"aeb9128e-1c5f-417f-863c-2449416433cd","Community","https://directus.chat",{"id":46,"title":47,"url":48,"page":8},"da1c2ed8-0a77-49b0-a903-49c56cb07de5","Release Notes","https://github.com/directus/directus/releases",{"id":50,"title":51,"url":8,"page":8,"children":52},"d61fae8c-7502-494a-822f-19ecff3d0256","Support",[53,57,61,65],{"id":54,"title":55,"url":56,"page":8},"8c43c781-7ebd-475f-a931-747e293c0a88","Issue Tracker","https://github.com/directus/directus/issues",{"id":58,"title":59,"url":60,"page":8},"d77bb78e-cf7b-4e01-932a-514414ba49d3","Feature Requests","https://github.com/directus/directus/discussions?discussions_q=is:open+sort:top",{"id":62,"title":63,"url":64,"page":8},"4346be2b-2c53-476e-b53b-becacec626a6","Community Chat","https://discord.com/channels/725371605378924594/741317677397704757",{"id":66,"title":67,"url":68,"page":8},"26c115d2-49f7-4edc-935e-d37d427fb89d","Cloud Dashboard","https://directus.cloud",{"id":70,"title":71,"url":8,"page":8,"children":72},"49141403-4f20-44ac-8453-25ace1265812","Organization",[73,78,84,88],{"id":74,"title":75,"url":76,"page":77},"1f36ea92-8a5e-47c8-914c-9822a8b9538a","About","/about",{"permalink":76},{"id":79,"title":80,"url":81,"page":82},"b84bf525-5471-4b14-a93c-225f6c386005","Careers","#",{"permalink":83},"/careers",{"id":85,"title":86,"url":87,"page":8},"86aabc3a-433d-434b-9efa-ad1d34be0a34","Brand Assets","https://drive.google.com/drive/folders/1lBOTba4RaA5ikqOn8Ewo4RYzD0XcymG9?usp=sharing",{"id":89,"title":90,"url":8,"page":91},"8d2fa1e3-198e-4405-81e1-2ceb858bc237","Contact",{"permalink":92},"/contact",{"items":94},[95,101,107,113],{"id":96,"title":97,"url":8,"page":98,"children":100},"8a1b7bfa-429d-4ffc-a650-2a5fdcf356da","Cloud Policies",{"permalink":99},"/cloud-policies",[],{"id":102,"title":103,"url":81,"page":104,"children":106},"bea848ef-828f-4306-8017-6b00ec5d4a0c","License",{"permalink":105},"/bsl",[],{"id":108,"title":109,"url":81,"page":110,"children":112},"4e914f47-4bee-42b7-b445-3119ee4196ef","Terms",{"permalink":111},"/terms",[],{"id":114,"title":115,"url":81,"page":116,"children":118},"ea69eda6-d317-4981-8421-fcabb1826bfd","Privacy",{"permalink":117},"/privacy",[],{"description":120},"\u003Cp>A composable backend to build your Headless CMS, BaaS, and more.&nbsp;\u003C/p>",{"id":122,"slug":123,"vimeo_id":124,"description":125,"tile":126,"length":127,"resources":128,"people":8,"episode_number":132,"published":133,"title":134,"video_transcript_html":135,"video_transcript_text":136,"content":8,"status":137,"episode_people":138,"recommendations":170,"season":171,"seo":191},"69ad81e8-5e1d-4b85-9fa9-3b767a3a3478","public-forms","932168576","In this recording of our live event on April 4 2024, Rijk, Jonathan, and Daniel discuss sharable forms for adding content to collections.","5e3ff428-f8d8-49a9-9c0f-34d2f0b0c4ca",56,[129],{"name":130,"url":131},"Github Discussion","https://github.com/directus/directus/discussions/18807",6,"2024-04-11","Public Forms","\u003Cp>Speaker 0: Hello. Hello, everyone. Welcome to another exciting episode of, request review, where we go over your guys' hopes, wishes, and dreams, and potentially crush them because software is not easy. Joking aside though, we're here to give we're here to go over your discussions inside of our repository. So if you're interested in a few feature or future features, please let us know.\u003C/p>\n\u003Cp>We have an existing, discussion template that you can use inside of our, repository or, extend existing ones. We also love to see that. And, today's topic, as you might have guessed with the title, is public forms or in other words shareable forms. So just, judging by the amount of people that I hear, I assume that this is pretty exciting for you guys. So give us a sign of life in the chat, please.\u003C/p>\n\u003Cp>Oh, that's what I future.\u003C/p>\n\u003Cp>Speaker 1: Like the people at home applauding. That's that's\u003C/p>\n\u003Cp>Speaker 0: that's Yes. Totally. Oh, yeah. We gotta oh, Oh, it's not French, it's Spanish for Noah. Okay.\u003C/p>\n\u003Cp>Okay. Okay. It's nice nice to see some interaction going. So public forms, shareable forms. Let's do a quick let's do a quick poll.\u003C/p>\n\u003Cp>So, how many of you guys used the current already existing feature of sharing forms or entries or however you would like to call it, share items. Because, I guess, public forms are very, very similar to that. It's, Brian says, I do not like sharing my forms. I do not like them then. I am.\u003C/p>\n\u003Cp>Yeah. Isn't that the the author's name? What is his name? Like a children's book author? Oh my god.\u003C/p>\n\u003Cp>Like, I'm blanking so hard right now. Doctor Seuss. Yes. Yes. Yes.\u003C/p>\n\u003Cp>Okay. Okay. Okay. Anyway, let's, let's go over some examples. So public forums, I think everybody has a mental image of what public forums are in their mind.\u003C/p>\n\u003Cp>But, let's make a very, very The most simple example that you could think of is just a contact form for me, basically. So you have a text input, and you want to put it on your website, and people reach out, fill it out, you get an entry, and you have an item in your database. Alright. Fair enough. But as you might have guessed, this is Directus after all, so this is not as easy in every single case.\u003C/p>\n\u003Cp>So, I I would I would love to quote, let give me give me one second to quote the person who opened the discussion, because there's such an amazing quote in there. I hope I did not oh my god. I think I closed the tab. I'm very sorry. Because the quote in there is just too good.\u003C/p>\n\u003Cp>Yeah. Very, very professional. Oh, my god. Maybe in the meantime, you could also think of a couple other examples, while I search for the thing because we're we're doing a show up.\u003C/p>\n\u003Cp>Speaker 1: Yeah. For sure. I think I mean, one thing that is probably, a good bit of context to kick off this discussion is just to go through what the current sharing thing looks like and what it does, and some of the requirements that we know exist around sharing things in general. And then sort of take it from there and elevate. Okay.\u003C/p>\n\u003Cp>What do we do to then unlock, you know, create and update and delete access next to just read access. Right? Because there's a reason we just started with reads and not the other ones. And that's that's sort of the complexity that I like to extract in in this session.\u003C/p>\n\u003Cp>Speaker 0: Speaking of complexity, I found the quote that I was looking for. And the quote is in the discussion itself is, the feature itself could start very small, but it could be very complicated if we wanted to cover more use cases. That's, like, literally every single every single feature that we could ever do.\u003C/p>\n\u003Cp>Speaker 1: That's the request review format for you, isn't it? So for those who are new in this session, one on good bit of context for what these live streams are all about. We just wanna take, you know, the discussion as it exists. Divergently think about, okay, what are all of the edge cases? Find sort of the use case, find all of the unknowns, and then take it back down.\u003C/p>\n\u003Cp>So, like, what is that MVP? What is the minimum viable product that we wanna ship for this to be a success? Right? What are the must haves? What could we add in the future?\u003C/p>\n\u003Cp>Where do we wanna start with this? Right? It's easy to say, oh, the the forms that you're sharing, just make them create access. Right? Done.\u003C/p>\n\u003Cp>But there's a lot more stuff going on into the hood as per usual. And also for the first time in days, we're getting some sun in here. So excuse my exposure.\u003C/p>\n\u003Cp>Speaker 0: Oh, we got some interaction. But, let me let me give let me give another example because there's many, many different use cases for public forms. So it's not just about, like, let's say, you put an email in there and a text box or something. It could also be more involved, for example, inside of your organization because directors is often used as a, like, enterprise tool inside of your company, for example, in the Internet even. So you could build a support ticket system in Directus, and we know that people do that.\u003C/p>\n\u003Cp>So, a public forum could be you visit a site inside of your Internet with an extensive, like, public forum describing what issue do I have, what department is this in, when did this happen, is this critical or not, other descriptions, related persons, or whatever. I mean there's also like very often for marketplaces or adding data to a validation queue because this is, like, very, very often the case. For example, if you have a marketplace and you want to open it up to new, merchants, they have to apply somewhere. Right? They they have to they have to ask, hey.\u003C/p>\n\u003Cp>I am this merchant. Can you please add me to your, shop? Or there was another example inside of the discussion itself regarding, let's say you have, like, a lunch app or whatever where you can off order food. So you want to get more restaurants or or bistros or whatever, and they can apply at your place. So you give them a public form.\u003C/p>\n\u003Cp>They can enter their information, and then you have, like, inside of your validation queue, all of the people or entries that you could go over and then, make sure that they get applied to your public to your service. Alright. Sounds like one of\u003C/p>\n\u003Cp>Speaker 1: the the initial requirements that you're sort of sneaking in with these examples is that this form can live both as a public website page in your direct instance or as an embedded form somewhere on\u003C/p>\n\u003Cp>Speaker 0: your website. Exactly. This is We're\u003C/p>\n\u003Cp>Speaker 1: we're immediately diving in, and we're off.\u003C/p>\n\u003Cp>Speaker 0: That that is that is literally I I wrote this down. This is exactly what I was, coming up with now because, like, the first the first requirement that kinda diverges, like you said, is, okay, so I have this public form. Where is it? Where where where can I find it? Because, like, it really depends.\u003C/p>\n\u003Cp>If I send somebody a link via email for example, it could be sufficient if the link is directly to your directors instance and you get served up like a complete page. And, there's the whole thing with the logo or whatever. And then you have an entire dedicated page for it. But very often also, you would like to embed your form into your existing website. Let's say with the with the, contact form example.\u003C/p>\n\u003Cp>Right? You just want to have a little contact form and on the bottom of your website. But, yeah, then then it starts then it starts. Okay. So you can have 2 different ways.\u003C/p>\n\u003Cp>Speaker 1: Yeah. I was gonna say, let's start let's start with what we have today. Right? So we don't have, writable forms. Let's call it that forms you can change stuff in.\u003C/p>\n\u003Cp>But we do have sort of the shared form where if you open a single item in a collection, you can share share that item. And what that does for the folk who've never tried it, which I believe is most, is that it will create sort of a temporary role, so to speak, a temporary access token that has access to just that one item with the role permissions that you associate to the share. So that sounds a little confusing, but that basically means you can give away a link that contains, you know, basically a long obfuscated URL that gives read access to just that one item and the relations that it has based on the rule that you associate for read permissions, Then that public link, it's, a directus page. So you will be navigated to your directus instance slash admin or slash shares, what we call it then for the public ones. And then, if you open that up, you basically get a read only state of the form that you just shared.\u003C/p>\n\u003Cp>Right? And there's some additional options on that share. You have you can set a password on it. You can set a maximum time, start, and end date that it's available to the public. Those those are the main ones.\u003C/p>\n\u003Cp>I think there's some other options. But long story short, the first step there is, like, if we were to just just enable a share on, the collection level, we can use that as a starting point, but that is only for forms that are then within that sort of share context of directors itself. Right? So you'd be able to use it as an alternative to something like Google forms or, type form or something where you create a form, you share it, you have a public page that you can share it, that you can, link people to. To me, the the fun complexity of this is really when it comes to, a, spam protection, and b, embedding it elsewhere.\u003C/p>\n\u003Cp>Right? Because somebody in the chat, our very own team just now, just half joking said just iframe it into your front end, which, sure, you can do that. But at the same time, somebody else in the chat also mentioned, you know, it would be great if there's a contact form on each of the products in my sort of web shop or or, renting, vending vending thing. At which point, you need to be able to dynamically inject some sort of default value into this form before you submit it. Now if we're talking about embeddable forms, it's almost like a different feature request.\u003C/p>\n\u003Cp>Because if you think about it, you could open up, write access to the public role and just build a form. Right? You can build a query you can build a form in your website and just post a request that straight out to, you know, your direct this instance. So, I think we wanna split this discussion up in, a, the shareable form, which is more sort of the Google form alternative versus embeddable forms, which is, like, what can we do to sort of make it easier to request or build a form indirect and then request it and display it just like that on your website?\u003C/p>\n\u003Cp>Speaker 0: Because, also, how much control do you want to have regarding the styling, for example, with, like, branding? Do your inputs look different? Because, you know, it looks out of place. It could look out of place if, you use our design guidelines, but your brand uses, like, way smaller inputs. It just looks very weird then.\u003C/p>\n\u003Cp>So we also had a nice, suggestion for, by Tim that I like. Where is it? Oh, no. No. By by by Brian.\u003C/p>\n\u003Cp>By a nice, by Brian. Pre filling fields by query parameters could be very cool. And hidden fields, of course. Like, there are many, many, there are so many things that you could do because there's so many different use cases. Like you said, for example, if you want to embed it, do we want to a do we want to be able to also restrict, like, how many different links there are to that form, for example?\u003C/p>\n\u003Cp>So, if I have a email list and I want to contact all of my contacts and I I give them each a personalized input field because I want to avoid the spam issue that you just mentioned, you know? So let's, say, okay, I only want people to be able to answer the form once, at least, you know, on that link, for example. But can they be different? Should they be the same all the time?\u003C/p>\n\u003Cp>Speaker 1: So using the form once, that's the part that we do currently support with the read only share. Right? Where there is a setting for how many times can this item be opened. And every time somebody opens that that item, it just, you know, it decreases the number by 1. And then once the number hit 0s, the link, you know, goes goes this disabled.\u003C/p>\n\u003Cp>Now for creates, how do you confirm that it was done by 1 person? Right? If you associate it to an email address or something, are we gonna do email validation? Do do does there have to be a confirm step? Which is sort of like I'm I'm thinking about other forms I've seen in the wild.\u003C/p>\n\u003Cp>Right? Where it's like you wanna sign up to a raffle or something and you leave an email address and that's your that's your ticket, so to speak. But you can only use it once. Yeah. Somebody in the chat rightfully now at that point, aren't you just logged in to the app anyways?\u003C/p>\n\u003Cp>Because now you have some sort of an account or a verified account within that direct to this instance. Maybe. Maybe. Right? Hard to tell.\u003C/p>\n\u003Cp>Well, I think the other the the question that closely ties into this as well around things like CAPTCHA. How do you prevent robots? How do you prevent AI from just pulling up the form and spamming it to death? Right? Of course, an obvious one for a lot of folks like, oh, just smack a a Google recap on that and you're done.\u003C/p>\n\u003Cp>But, of course, this wouldn't be a direct this request review chat if it was that simple. Because there's a lot of sort of like wrecking and accessibility concerns around, CAPTCHA as a whole When it comes to Google CAPTCHA specifically, I I I'm a little fuzzy on the details, but I'm pretty sure there were some GDPR concerns around embedding Google services as a whole, that already requiring, you know, cookie notices and whatnot because almost every Google service will track you to bits, if you embed stuff on your page. So that's a concern. It also relies on a third party service, which is something that historically we have to be a little bit careful with, because we wanna support multiple different options. Right?\u003C/p>\n\u003Cp>But now here we go. This is the point where now we need to think about how do we have a standardized CAPTCHA system that can work with providers that works across form, right, for both shared forms and into and, like, in internal forms. Another question from the chat. To add some more complexity, who creates the public form? Is it an administrator or a nontechnical CMS user for whom setting up a form with the data model interface might be overwhelmed?\u003C/p>\n\u003Cp>Another great question. Right? So in in the direct to this model form is basically tied to your data model. So if you share an item, you share the item that you're seeing with somebody else. Right?\u003C/p>\n\u003Cp>So in its simplest form, you would share the form that you're currently seeing with the world. Is that what you want? Maybe not. Probably not. In Daniel's example from earlier, if you wanna do a simple tech form with just an email and some text, it's very likely that in your data model, you end up with a status field that says has been responded yes or no or metadata that you wanna have in your system.\u003C/p>\n\u003Cp>But how do you differentiate between the 2? Are we gonna ask the user who is sharing the form to then pick and choose fields to share specifically? Are we gonna attach it to another role soon to be policy? Or are we gonna, or or plan c is, are we gonna strip public forms from the regular content model altogether and just have a whole different section somewhere that says, here is public forms. And then perform, you just have to configure where the responses are saved.\u003C/p>\n\u003Cp>Speaker 0: Yeah. Regarding your point of configuring specific fields like the status, for example. Like, if somebody submits the form, should it be, you know, active, reviewed, tool review, draft, or whatever? So that that really sounds to me like a field preset sign type of thing, but that exact same vein. Okay?\u003C/p>\n\u003Cp>Let's say you have a form with a user created field that automatically adds the user that created that row. Okay. What do we put in there? Who who who created that? I mean, the user could, you know, make their own public user, so to speak, and link them via a field preset, but then also kind of fields just not quite thought through.\u003C/p>\n\u003Cp>Like, to me at least, like, just thinking about it right now, like, it feels, like, so hacky that people would need to do that themselves, that it feels like this is not really thought through. But on the other hand, like, do we want to have, like, a global invisible user that we could reference? Maybe.\u003C/p>\n\u003Cp>Speaker 1: I mean, we do have the concept of a public role. So with the user created example, it would be null because there's no user indirect because that created the thing. So if we if we zoom back out just a little bit, I think the first question that we sort of had this session hey, Jonathan. Welcome to join you, Just to catch you up. The first question was, shareable forms versus embeddable forms.\u003C/p>\n\u003Cp>Right? Which is a shared form is basically the way I see it now as a page within Directus that you'll to, and they just get, you know, a nice looking Directus connected to stuff. It's safe. Done. Little you know, think about Google Forms sort of mentally, that style.\u003C/p>\n\u003Cp>Right? The second thing is some sort of UI component or some sort of auto generated API endpoint or maybe just a public post could be, to render a configured form and direct us on your own app or website in whatever way is appropriate for your tool. Right? To me, those are 2 separate discussions. I think we start with the shareable forms because then the embeddable forms could use the same permission system and shared, configuration from the shareable form to then embed one of the shared forms.\u003C/p>\n\u003Cp>Right? That's kind of what I think that that would be a 2 step 2 step approach.\u003C/p>\n\u003Cp>Speaker 2: Nope. I like that. So that's what you're seeing here. Right? So this is the current it's read only at the moment.\u003C/p>\n\u003Cp>Hard coded is read only. Even though we allow we've kind of plumbed this for role support in the future, it's currently read only. It's hard coded read only. So you get a read only form that looks like this, and it is to a degree, there are some permissionings. So the role does give access to the fields that are available and the relational content that's technically available and visible in the form.\u003C/p>\n\u003Cp>So you can see here my image isn't showing because I don't allow I haven't allowed the permissions correctly on that particular role. So you could have that kind of capability, And I believe we should I haven't tested this, actually. I because I'm logged in as an admin right now, but I think we can restrict the role list here based on the so the the allowed roles and permissions for the user.\u003C/p>\n\u003Cp>Speaker 1: Permissions again? Yep. Exactly.\u003C/p>\n\u003Cp>Speaker 2: So permissioning should control what's available in this list. So I think, again, I think the general plumbing is there for a shareable, editable form? The question becomes, what is it that we're sharing? You know, are you allowing them to create a an item from the form? What does that look like?\u003C/p>\n\u003Cp>Because right now, we are sharing an existing record. So there'd be work to be done around that, I think. Absolutely. As an embeddable I like the embeddable idea. Technically, you can kinda do that already.\u003C/p>\n\u003Cp>You know, we we see examples of that in the structures that, our good friend, Bryant, has set up where, you know, he set up these kinds of forms where\u003C/p>\n\u003Cp>Speaker 1: Right.\u003C/p>\n\u003Cp>Speaker 2: He's almost replicating our schema management capabilities of being able to create an editable form. So he's made it so that you can create a schema field, add whatever, you know, value type. This is a And as we're\u003C/p>\n\u003Cp>Speaker 1: talking segue into, the second question I wanted to bring up, which is for shareable forms, are we sharing an existing form and you will still limit it down. Limit it down. Or is it effectively a separate form builder where you can create one of forms that you then connect the dots between that and your actual data model?\u003C/p>\n\u003Cp>Speaker 2: Yeah. Similar to I think our our CRM has that kind of capability where you can build a form. Right? And then behind the scenes, the data gets stored wherever you direct those fields to store. Exactly.\u003C/p>\n\u003Cp>But you've got an and it's embeddable as a you know, you can get it as a link or you can direct them straight to the form or you can embed it as an embeddable link underneath the hood.\u003C/p>\n\u003Cp>Speaker 1: Because the one thing I do recognize about the current share system is that it's a little bit a little very opaque. What's the right word? It's a little opaque to to know what you're sharing. I mean, by default, you're sharing what you're seeing. Right?\u003C/p>\n\u003Cp>It's like you're sharing the item that you're currently seeing. Yep. But what's actually gonna\u003C/p>\n\u003Cp>Speaker 2: be shown to the user is different. Right? So you have to go check the link and see what it's gonna\u003C/p>\n\u003Cp>Speaker 1: look\u003C/p>\n\u003Cp>Speaker 2: like versus\u003C/p>\n\u003Cp>Speaker 1: It's because it's based on the role that you then associate with the share. So if you use your own role, it's what you see is what you get. But other than that, it's a bit of a, you know, to your point, you have to create the share, pull it up, double check. If you're creating a dedicated form to share, be it read or write, that confusion is taken away immediately because it's the form that you created. It's the form that you're seeing.\u003C/p>\n\u003Cp>Right? I think the big question then becomes, how do we handle permissions if at all? Do we auto generate the permissions based on the stuff you put in the form? And therefore, you make it very explicit. Like, you put, an email address field, so therefore, you can see an email address.\u003C/p>\n\u003Cp>Or do we make it a little more opaque again by associating a role or multiple policies to TM to control the permissions for that shared item. Right? That's that's where it's a little finicky. So when when I meant that permissions, for example, if, where permissions become really important is for nested relationships. Right?\u003C/p>\n\u003Cp>So if you have a read item with a many to one field to a related category or something, what part of the category are you also supposed to be able to read from this entry point of the top level item? So having some sort of permission set there is gonna be required. Because otherwise, theoretically, if your relationships are a little complicated, you could pose a hell of a lot of data. Right? Because if we were to say, auto generate all of them, if you have a user created field because you just wanna show somebody's name, avatar, you could now theoretically go to that user record and you go to a direct to files record because you now have that connection through the user.\u003C/p>\n\u003Cp>Right? So that also, makes me wonder, there's another feature request that is completely unrelated to this, but it might actually directly be related now. One that I opened, I feel like 20 years. It's configuring access control permissions based on a parent child. So instead of saying, you have access to direct these files, you have access to direct these users.\u003C/p>\n\u003Cp>It's saying the permission, you can read a file if it's attached to a user if you're coming through the user and only then.\u003C/p>\n\u003Cp>Speaker 0: Oh. Oh, yeah. Yeah. Yeah. Yeah.\u003C/p>\n\u003Cp>Yeah. That's, that would be very cool. That would be very cool.\u003C/p>\n\u003Cp>Speaker 1: Top the clock. I think we need to need to start a new game. It's like, at what point do we get Jonathan to do that?\u003C/p>\n\u003Cp>Speaker 2: It doesn't take much.\u003C/p>\n\u003Cp>Speaker 1: It doesn't take much. Because because that would that would also potentially solve for this. Because then you could say, okay. If you have many to 1 on the record that you're sharing, you now have access to read just that one record from the related table, but nothing else from the related. Right?\u003C/p>\n\u003Cp>And for the record, that is how the current share system works actually under the hood. It is a hell of a lot more complicated, because what it does is it looks at the item that you're sharing and it checks what items are related, and then it makes a new permission set that says you can read just that one item from the related table. Right? But all of the other API ends work the same, which is interesting. But that's that's the way it does it right now.\u003C/p>\n\u003Cp>So it does actually, you know, specifically look up which items are related, which items are shared as per the role, but then lock it down to only allow you to ex that one particular item that is associated to the shared thing to make sure that we don't overexpose data in your system. Food for thought. But it it, you know, we're getting real quick into the weeds here again. Just from the question, is it sharing the existing form from your data model or are we sharing new one off forms? It sounds like and I've I've it it sounds like we probably wanna look into some sort of system.\u003C/p>\n\u003Cp>You can create individual forms and associate them back to your data model. Just in those cases where you wanna have multiple different forms with different fields that go to the same item.\u003C/p>\n\u003Cp>Speaker 2: Commonly the case. Right? So if I was setting up a, you know, a a newsletter subscription, I might have very simple, but I still wanna register the contact. I still wanna be able to, you know, track their compliance or other things that I may wanna track or need to track versus the same contact information I would collect for a you know, you're signing up for a meeting or a webinar or something else. So the the forms can be storing data to the same places or to additional places.\u003C/p>\n\u003Cp>Speaker 1: Follow-up question. What is that? One of these public forms, and I'll I'll get to Tim's question in the chat very soon because that's another level of complexity. But should we allow one of custom forms to save to multiple tables at the same time?\u003C/p>\n\u003Cp>Speaker 2: Yes. Technically, yes.\u003C/p>\n\u003Cp>Speaker 1: Form can one form create 5 different records in 5 different tables?\u003C/p>\n\u003Cp>Speaker 0: Oh, I think it must. Right? Because of relations?\u003C/p>\n\u003Cp>Speaker 2: Well, not even relations.\u003C/p>\n\u003Cp>Speaker 1: Go Independent of relations. Right? Yeah.\u003C/p>\n\u003Cp>Speaker 2: So if I'm if I'm setting up a form to collect, medical data, you know, to sign you up or set you up or do something or I'm collecting a survey, I might have survey information that I'm storing in the survey table, contact information I'm storing in the contact table. Just simple example. Right? Just 2 tables. But the contact information is in one place, the survey data is somewhere else.\u003C/p>\n\u003Cp>And I may from a from a compliance perspective, I may not be associating the user. I'm just tracking that the user responded, but the survey data has to be independent. Right? No relation at all.\u003C/p>\n\u003Cp>Speaker 1: Here's one quick question.\u003C/p>\n\u003Cp>Speaker 0: Good point, but Tim, wait beef before we go further further down the rabbit hole, there's another good point by Tim. It it it really sounds like a job for a flow or hook. And I think I agree, actually, because, like, the complexity then of setting it up and then the UI that has to be added for that and, stuff that could go wrong and stuff. Like, maybe, you know, just as a as a simple example. Okay.\u003C/p>\n\u003Cp>You have you just make one row in one table. That would that could be the cutoff that we decide on, maybe. I don't know. But it it really sounds like maybe a hook or a flow would then should be responsible for, you know, taking the the depending on the status, it takes the user's email and puts them also into the contacts table or the whatever table. I think I agree with that take.\u003C/p>\n\u003Cp>How do you guys feel about that?\u003C/p>\n\u003Cp>Speaker 1: It's both ways because you could say you'd save all the data to a table and then run the flow based on that change or you save the form to a flow and then handle it yourself. I and I think there's a case to be made for both because for a simple contact us form that is always going through the same table in the same format and it matches your data model, it feels like flows could be a lot of, you know, complexity to configure just for that simple use case. But for everything else, I fully agree. Once you go, I wanna touch 5 different tables and I wanna submit to a different web, and all that kind of stuff. Yeah.\u003C/p>\n\u003Cp>Form to a flow, makes a lot of sense. Right?\u003C/p>\n\u003Cp>Speaker 0: Right. So let's blow up this, let's blow up this discussion further because Tim also said, alright. How about, should public forms be able to save to a specific content version as well.\u003C/p>\n\u003Cp>Speaker 1: If you call the first deal with the safety of a specific content version. Well, the nice thing is if we're going with this whole form safe to flow as idea, then sure do whatever you want. Right? That's that's kind of the beauty of the escape hatch that could be flows as the back end forms. Because at that point, if you wanna save it to a conversion, go for it.\u003C/p>\n\u003Cp>Right? What do we care? What when how when would you use that, though? Let's think about that for a second. So you have draft state basis for an item.\u003C/p>\n\u003Cp>Speaker 2: I guess if you were updating existing content, you may wanna do that as a version, possibly. Typically, in shareable forms, I don't see it as a version necessarily. But if you were allowing someone, say, to update but even then revisions would track the the content changes over time if you were inclined.\u003C/p>\n\u003Cp>Speaker 1: I I think yeah. What I was just about to say is what Tim again just put in the chat. Let's say you want to review and approve the changes that were made in pub. Right? So if you're running a sort of Wikipedia style, Wiki style, page Mhmm.\u003C/p>\n\u003Cp>And you wanna allow people to suggest edits, you could have a public form to update that one particular page, and then those updates go into a version that then can be reviewed and approved by the old person in charter, which is an interesting an\u003C/p>\n\u003Cp>Speaker 0: interesting use\u003C/p>\n\u003Cp>Speaker 2: case. That's a cool that's a cool freaking use case.\u003C/p>\n\u003Cp>Speaker 1: Which actually would be very convenient for our own docs for that record.\u003C/p>\n\u003Cp>Speaker 0: For example, that's what I was thinking about. I have the little button on the bottom here. Edit this page. Edit\u003C/p>\n\u003Cp>Speaker 1: this line. That would be very cool.\u003C/p>\n\u003Cp>Speaker 0: Hang on.\u003C/p>\n\u003Cp>Speaker 1: Another use case from the audience in, in that updating existing thing from, Jay Shue says, another use case is a business directory and the users being able to suggest changes. Agreed. And the Durb saying we could actually use that fairly well as well. That's it. It could be implemented in flows.\u003C/p>\n\u003Cp>Right? Which is where it gets interesting again. Right? Because flows really become that sort of escape hatch for this type of stuff that, like, oh, you wanna save it to a version instead of to a table? You wanna save it to a different whatever you wanna do.\u003C/p>\n\u003Cp>Just use a flow. It it does also answer the question, is this just for create or is this also for update? And I think we've just concluded that also updates are important. Click updates. That's when you can do you can update an existing submission that you've already done, or you could, you know, the Wiki example or the business directory example or some of those.\u003C/p>\n\u003Cp>Speaker 2: Yep. I think about, in particular, things like, you know, some of these online forms could be fairly complex. Right? I've I've done this. I've I've got you know, you're filling out something for a financial thing and you, you know, it's gonna take you an hour to do the form while you may be saving and coming back later.\u003C/p>\n\u003Cp>You can come and go from it. We do a lot with secured online security forms, you know, where we're filling out answers to complex questions that take hours or days to finish. And so, essentially, saving state and coming back and making updates and, oh, I mean, I I wanna fix that answer that I did, you know, 3 pages back in the form, and I wanna go make that adjustment.\u003C/p>\n\u003Cp>Speaker 1: I think we found another use case for the saving it to a version.\u003C/p>\n\u003Cp>Speaker 0: Mhmm.\u003C/p>\n\u003Cp>Speaker 1: Because if you save it to a version, the validation of the database doesn't have yet because it only needs the saves to the database rather than to your stage to changes. Right? So the, what would you call it, plausible forms where you can enter a bunch of stuff, hit save as draft basically, and then come back later. That would be relying on content versioning.\u003C/p>\n\u003Cp>Speaker 2: Good. Yep. Good very well. Doesn't have to, but it could. Right?\u003C/p>\n\u003Cp>You can manage that via state or status or other things as well. But,\u003C/p>\n\u003Cp>Speaker 1: yeah. Unless you're thinking about validation in that case. Right? If you have data integrity rules that say the column cannot be So in your form, it has to be filled out. But you don't want the force to use the whole form once, you need to have an in been safe, which would be, you know, a version conversion version.\u003C/p>\n\u003Cp>Speaker 2: I like it.\u003C/p>\n\u003Cp>Speaker 0: It's Okay. Let's\u003C/p>\n\u003Cp>Speaker 1: I need to switch to a slightly simpler question. Otherwise, my brain is gonna go What about deletes? Is Is that a thing you do publicly?\u003C/p>\n\u003Cp>Speaker 0: My first gut reaction was no. Hell no. But, let's give it a little more thought.\u003C/p>\n\u003Cp>Speaker 2: But I guess if it's user data, I don't know. I could see a use case for it. I don't I don't think from our side of things, if depending on how it's implemented, If you got compliance issues, GDPR, other kinds of things where the user has the right and choice to do that, that's that's gonna it's gonna be very use case specific.\u003C/p>\n\u003Cp>Speaker 1: Because for the case\u003C/p>\n\u003Cp>Speaker 2: we we try not to delete data in general. We put it in the soft archival state. You know, we use status or other things to handle that. But where you have compliance requirements where you must delete, But I don't know if that's a form. That that could be flows driven.\u003C/p>\n\u003Cp>That can be log business logic driven at that point as opposed to something to do with the form itself. I think you'd have to have a form that says I wanna I want my data to later. I wanna unsubscribe. And by doing that behind the scenes, the flows and data data management happen the way that you need them to happen.\u003C/p>\n\u003Cp>Speaker 1: Right. Because I I could imagine that the because because deletes blank at least sound kind of insane. Because you would have what? You would show the user, here's all the records and go whichever delete whichever one you want. It that that feels like not something that you'd realistically want.\u003C/p>\n\u003Cp>But I could imagine that if we connect it to an account again, not not so much a a direct as app account, but, like, the moment you create a form submission, I could imagine that you maybe wanna do a public read of a layout. Here's a new question that we're gonna discuss in 5 minutes. Where you can just as a user as a temporary user all the submissions that you've done in the past and then delete a previous submission.\u003C/p>\n\u003Cp>Speaker 2: To me, again, business logic. Right? That that tends to be not so much I I think you'd I think someone suggested it here. I think you'd do it as a delete request. You'd submit a request to delete and then confirm whatever mechanisms.\u003C/p>\n\u003Cp>Your your business logic, your flows, your your any additional code processing that you're doing on top of that would handle those things and send notifications accordingly. Feels very much like you would submit that as a specific form request to remove data, not the ability to delete data from the form. I think I agree in general that that shouldn't be allowed. You'd have to submit that as a separate form, maybe. I don't know.\u003C/p>\n\u003Cp>I'm sure there's a use case that I'm not thinking of. But\u003C/p>\n\u003Cp>Speaker 1: Yeah. But to your point, if you create a new form that triggers a flow rather than saves to a table, that flow then just deletes it, whatever, based on your business logic, then prop solved. Right? You you don't necessarily go the mile to\u003C/p>\n\u003Cp>Speaker 2: Yep.\u003C/p>\n\u003Cp>Speaker 1: Have native victim delete support for that specific of a use case. Okay. Interesting. Interesting. Interesting.\u003C/p>\n\u003Cp>Interesting. Tricky. Tricky. Tricky questions. Tricky questions.\u003C/p>\n\u003Cp>Another another question in the chat here from user. So what about editable forms or relational data where items can be deleted after it's been saved and the user edits the data?\u003C/p>\n\u003Cp>Speaker 0: We got it. Ladies and gentlemen, we got it.\u003C/p>\n\u003Cp>Speaker 2: That's the real goal. If we can get right to do it, then we're then we're successful.\u003C/p>\n\u003Cp>Speaker 1: What about editable foreign situational data where items can be deleted as it's been saved and use it as the data? I mean, I guess that kinda goes for any editable forms that it's like, user creates it, admin changes it, user tries to edit it, and that looks different. Which, yes, it will look different because you changed it. You changed somebody's submission. Right?\u003C/p>\n\u003Cp>I think that becomes becomes more of a workflow or a business process, thing where tell your staff don't touch, you know, don't go changing somebody submission. That's bad mojo. But I guess yes.\u003C/p>\n\u003Cp>Speaker 0: What about resubmitting of shareable forms? We're kind of in the midst of thinking this through because, in the beginning, we said, okay. If you have a fixed link that you can send somebody and then they submit the thing, we could restrict that you can only submit once with that link. Or you can have a general link where, like, every single submission results in a new row every time. But then it's very use case dependent, I think.\u003C/p>\n\u003Cp>No. Like, that should be just configurable. Okay. Is this, will this result then in a on on my second visit to that link, will it show me the actual item, or is the form empty again, and can I resubmit it? I mean, that's, like, very dependent on on on the configuration, I think.\u003C/p>\n\u003Cp>Speaker 2: Yeah. I think it should be doable, though. Some additional configurations here, potential validation checks. So, again, if it's an embeddable form or it's a shareable, editable form from our side, then this is gonna need some updating as well. Right?\u003C/p>\n\u003Cp>We'll need some additional parameters and things here. You'd have to potentially check the data, validate the data on save. Flows, again, can handle some of that, but to give the user feedback of you've already submitted or disabling the form because they've already made a submission. How do we check that? What does what does that look like?\u003C/p>\n\u003Cp>Because now you actually have to have something, you know, activity wise that says your device or whatever has been registered. We know that it was you, and you've already submitted the form. Yeah. That gets that's where I I don't know. It almost feels like that should just be front end dev work and get managed from that side of things.\u003C/p>\n\u003Cp>But Oh, here's here's\u003C/p>\n\u003Cp>Speaker 1: the problem though, Jonathan, when it comes to the form that we're sharing, who's the front end dev doing the work?\u003C/p>\n\u003Cp>Speaker 2: It's it's us.\u003C/p>\n\u003Cp>Speaker 1: It's us.\u003C/p>\n\u003Cp>Speaker 2: It's us. I know. So this needs more complex kinds of things because now max 5 uses, well, is that 5 users, or is that 5 you know, one person could submit all 5 or use all 5\u003C/p>\n\u003Cp>Speaker 1: values. Right? Is a user?\u003C/p>\n\u003Cp>Speaker 2: What is a user? Right? What is the\u003C/p>\n\u003Cp>Speaker 0: Are we getting deep? What am I I mean,\u003C/p>\n\u003Cp>Speaker 1: that's that's kinda the question\u003C/p>\n\u003Cp>Speaker 2: right now. I think about like same thing. We we track this on, you know, AppSight anyway, but now we've got this floating thing out there that would also have to track an activity record of who the IP and device and things are and be able to validate against that as part of this form configuration or this shareable form configuration. Now it's, you know, one time per user or per IP or, you know, whatever we consider that to be. There'd be something here, you know, max uses.\u003C/p>\n\u003Cp>So I want a 1,000 submissions, but then I wanna be able to also say per something.\u003C/p>\n\u003Cp>Speaker 1: The the problem of the the how do you confirm the per something? Because you could say you could you could I mean, you could get away with it by just having a unique column. Right? That it's like you can only have one submission with this email address, and that's it. Done.\u003C/p>\n\u003Cp>It could be unique. Already exists. Can save it. Done. Right?\u003C/p>\n\u003Cp>But how do you prevent somebody, you know, with a Gmail account, for example, you can do the plus something something and it will come back to you anyways. You prevent somebody from submitting times with the same, you know, plus 1, plus 2, plus 3, that will work. And I can use all information still. Because there's no way for us to validate that. And then, you know, for email specifically, you can start thinking about, maybe we have some sort of email validation or we send an email and you have to click confirm or all that kind of stuff.\u003C/p>\n\u003Cp>But then what happens if you wanna use something else as the unique identifier? What if you're doing some of the phone numbers? Right? Where it's like, enter your phone number, we'll send you a text when it's your turn to to for for like reservations. Right?\u003C/p>\n\u003Cp>If you're doing a reservation at and it's it's that's that's very common around here. I don't know. Over in your parts of the world. But, you know, if you go to a restaurant here and it's full and it's like, oh, your your table's gonna be about 40 minutes and you your phone number, they'll send you a text when it's ready. Right?\u003C/p>\n\u003Cp>Mhmm. Or about 10 minutes before it's ready. So in that case, you wanna duplicate it on the phone number, but how can you confirm that? Right? You you can't really, there's no way for us to know that.\u003C/p>\n\u003Cp>Speaker 0: A simpler a simple example would be if if you have first sorry, the delay delay is giving us. No, but but a simple example for, limiting that kind of, use would be, let's say you have a form that you can resubmit with, let's say, you have an online shop and then you want to use this for functionality for giving out promotion codes, and you only want to give out a 100 promotion codes, okay, Then it's just a matter of counting the rows, you know, so so we don't have to have a unique field or whatever. We just say, okay. This form can be submitted 100 times. That's it.\u003C/p>\n\u003Cp>I think there's like, it's a little different to your guys' use case, what you just described with the email and and phone and whatever. But, I mean, this is also a valid use case, I think. You know? I I want this form to just be usable for 100 submissions. Okay?\u003C/p>\n\u003Cp>Then it's just a matter of counting.\u003C/p>\n\u003Cp>Speaker 1: Mhmm.\u003C/p>\n\u003Cp>Speaker 2: Well, that's our that's already built in. Right? So we already support that max five uses. So and we keep track. Similarly, if we want this to be 1 per or 2 per source, right, then we have to actually track from a and, I guess, because it's an embeddable form or it's a, you know, we we have information and knowledge about the browser.\u003C/p>\n\u003Cp>Right? We we can track that. It just requires that we store the activity information and utilize that as part of the additional values here in a sense. There's still ways around. Right?\u003C/p>\n\u003Cp>There's always a way around. I've got 5 devices, and I wanna submit 5 submissions. You know, I can I can do that, but and and, you know, we can do things like enforcement of uniqueness on the values coming in and those things? That's already there. It's more about can I at least track to know that this user has already submitted a form because of their IP address slash device ID, that we track anyway from the browser cookie side of things?\u003C/p>\n\u003Cp>Speaker 1: I think, I think I'm reaching the same conclusion as Tim. It's like we're going down the bot detection rabbit hole, which is like, can we fingerprint an individual user? No. There's no way. There's there's no way because IP address is shared with the location.\u003C/p>\n\u003Cp>So, therefore, everybody in the same household or the same business is gonna have a similar bound IP address. So that that doesn't work. I mean, this this fingerprint in question has been a cat and mouse between browser makers and, you know, back end implementers. It doesn't exist. The only way to do that is to require a sign through some sort of secondary authentication method, like send you an email with a magic link.\u003C/p>\n\u003Cp>So therefore, you prove you have access to the email, and that's it. Right? Before it submits or text with a phone number, that kind of stuff. Or log in through an SSO provide to confirm your, you know, your identity there, which actually is a different question I didn't even think about. But it would be kinda nice if you could sort of, like, connect the dots between what is your GitHub account click here to to o auth your way in to confirm, but that's not gonna be a 5 minute conversation, I don't think.\u003C/p>\n\u003Cp>Another question from the chat here, from from user and I'm gonna butcher your name. Sorry about that. Mama. That's what I'm gonna go with. How about the ability to show already submitted values to the user when filling out a form?\u003C/p>\n\u003Cp>Thinking about a sign up form for a party, and showing what food others already bring with them. Which is so this is an interesting question, which I think is not so much, the shareable, writable form. This is the question of readable lists of items. So right now, the share that we offer is just for a single item. You share that one.\u003C/p>\n\u003Cp>Right? What we don't allow you to do yet though, you can go to a layout and share the whole in a simple fashion. I could imagine that for this particular use case, what you would do is you would basically make a public share for your record of foodstuffs people bring to the party, long collection name, and then you can give people that link. Right? And then when they go there, they just see a layout like you would expect from directives with all of the stuff that has been previously entered with a click to to open an individual, I imagine, and then a, you know, a plug or something to go to the create page if you have create permissions through that public share.\u003C/p>\n\u003Cp>Speaker 2: I think this is actually related to Hannes' question as well. More so because the food items being brought can be a many to many or a relational junction that's already there. So we'd show that in the current form. Right? Just like we did, you know, I only have translations in here right now, but equivalent kinds of things where you've got a a relational structure.\u003C/p>\n\u003Cp>The real question becomes when you're adding or removing relational items, this is considered potentially a delete operation under the hood. Right? So there there's there's a little bit of a tie between the delete conversation we were having and this ability to show or allow or not allow you to you know, you might be able to see what other people have brought, but you can't remove their food item. You can only add your own food item. Right?\u003C/p>\n\u003Cp>And or remove your own food item. I think role permissions generally work correctly for that, but it becomes a question of making sure that you test and set those things correctly. But is that considered a delete? Right? If you've got a cascade operation on, you know, removing a a relational item, well, that's potentially gonna cascade and cause a delete down the line.\u003C/p>\n\u003Cp>Speaker 1: I think that would always be a deselect from the relational perspective. The\u003C/p>\n\u003Cp>Speaker 2: Well, that depends on what you set your permissions for. Right?\u003C/p>\n\u003Cp>Speaker 1: Oh, it's what you do. It's not permissions. The field\u003C/p>\n\u003Cp>Speaker 2: oh, I guess it's what you set your field settings for. Right? If you set by default, yes, we set it to nullify so we don't actually delete any data. But if they've got cascade delete permissions, you know, if the cascade delete is turned on, that's going to actually delete data or contact.\u003C/p>\n\u003Cp>Speaker 1: Point. Yeah. So the that's here's the security vulnerability way to happen. If you have an edit access to a simple item with a many the one many the one is configured to delete on select. If the user edit the field and they deselect, they now can theoretically delete stuff in your database, which is fun.\u003C/p>\n\u003Cp>Alright. Oh, jeez. It's already we're very we're already on on the dot here almost at 11. Oh, yeah. 11 for me.\u003C/p>\n\u003Cp>Times for everybody else. Just to to summarize all of this, because we went very much like this, but not a lot like that yet. We're running out of time. I think some some initial conclusions as far as I sort of take it now from this session. Right?\u003C/p>\n\u003Cp>It's like there's definitely a difference between shareable forms and embeddable forms. Shareable forms is part 1. Embeddable forms can then reuse whatever configuration that has for embedding stuff. I think that's conclusion number 1. I think to me, conclusion number 2, it's ideally you can create forms separately from the data model.\u003C/p>\n\u003Cp>Model. Although, that is quite a bit, you know, more involved to build and experiment with and etcetera etcetera. I think starting with create access is the most straightforward as you don't have problems with who can read what, how do you update previous submissions, how do people know what submissions they've previously done, etcetera. So in order of operations, shareable pages create first, then, read access for a listing would be very useful because then you have a way to click into an update item there. And then I think as a sort of your v 2, we should think about what do we form creation to look like in the first place and how does that tie into sharing?\u003C/p>\n\u003Cp>And a different question is, should sharing even be tied to collections and items, or is it just pages in the app altogether? Because I can also imagine that there's other places, like, folder in your file library that you might wanna share. Don't know. Like, another feature request for a different day, because I got skipped is, what about shareable dashboards from Insights? That'd be cool.\u003C/p>\n\u003Cp>But let's not do that right now. We'll save that for a different session. For now, Daniel, back to you to close it out.\u003C/p>\n\u003Cp>Speaker 0: Thanks everybody for coming. If you enjoyed this discussion or are interested in other discussions, you can head over to directors. Iotv where you can find lots of other interesting shows and also this one. And, we hope to have you to see you again.\u003C/p>","Hello. Hello, everyone. Welcome to another exciting episode of, request review, where we go over your guys' hopes, wishes, and dreams, and potentially crush them because software is not easy. Joking aside though, we're here to give we're here to go over your discussions inside of our repository. So if you're interested in a few feature or future features, please let us know. We have an existing, discussion template that you can use inside of our, repository or, extend existing ones. We also love to see that. And, today's topic, as you might have guessed with the title, is public forms or in other words shareable forms. So just, judging by the amount of people that I hear, I assume that this is pretty exciting for you guys. So give us a sign of life in the chat, please. Oh, that's what I future. Like the people at home applauding. That's that's that's Yes. Totally. Oh, yeah. We gotta oh, Oh, it's not French, it's Spanish for Noah. Okay. Okay. Okay. It's nice nice to see some interaction going. So public forms, shareable forms. Let's do a quick let's do a quick poll. So, how many of you guys used the current already existing feature of sharing forms or entries or however you would like to call it, share items. Because, I guess, public forms are very, very similar to that. It's, Brian says, I do not like sharing my forms. I do not like them then. I am. Yeah. Isn't that the the author's name? What is his name? Like a children's book author? Oh my god. Like, I'm blanking so hard right now. Doctor Seuss. Yes. Yes. Yes. Okay. Okay. Okay. Anyway, let's, let's go over some examples. So public forums, I think everybody has a mental image of what public forums are in their mind. But, let's make a very, very The most simple example that you could think of is just a contact form for me, basically. So you have a text input, and you want to put it on your website, and people reach out, fill it out, you get an entry, and you have an item in your database. Alright. Fair enough. But as you might have guessed, this is Directus after all, so this is not as easy in every single case. So, I I would I would love to quote, let give me give me one second to quote the person who opened the discussion, because there's such an amazing quote in there. I hope I did not oh my god. I think I closed the tab. I'm very sorry. Because the quote in there is just too good. Yeah. Very, very professional. Oh, my god. Maybe in the meantime, you could also think of a couple other examples, while I search for the thing because we're we're doing a show up. Yeah. For sure. I think I mean, one thing that is probably, a good bit of context to kick off this discussion is just to go through what the current sharing thing looks like and what it does, and some of the requirements that we know exist around sharing things in general. And then sort of take it from there and elevate. Okay. What do we do to then unlock, you know, create and update and delete access next to just read access. Right? Because there's a reason we just started with reads and not the other ones. And that's that's sort of the complexity that I like to extract in in this session. Speaking of complexity, I found the quote that I was looking for. And the quote is in the discussion itself is, the feature itself could start very small, but it could be very complicated if we wanted to cover more use cases. That's, like, literally every single every single feature that we could ever do. That's the request review format for you, isn't it? So for those who are new in this session, one on good bit of context for what these live streams are all about. We just wanna take, you know, the discussion as it exists. Divergently think about, okay, what are all of the edge cases? Find sort of the use case, find all of the unknowns, and then take it back down. So, like, what is that MVP? What is the minimum viable product that we wanna ship for this to be a success? Right? What are the must haves? What could we add in the future? Where do we wanna start with this? Right? It's easy to say, oh, the the forms that you're sharing, just make them create access. Right? Done. But there's a lot more stuff going on into the hood as per usual. And also for the first time in days, we're getting some sun in here. So excuse my exposure. Oh, we got some interaction. But, let me let me give let me give another example because there's many, many different use cases for public forms. So it's not just about, like, let's say, you put an email in there and a text box or something. It could also be more involved, for example, inside of your organization because directors is often used as a, like, enterprise tool inside of your company, for example, in the Internet even. So you could build a support ticket system in Directus, and we know that people do that. So, a public forum could be you visit a site inside of your Internet with an extensive, like, public forum describing what issue do I have, what department is this in, when did this happen, is this critical or not, other descriptions, related persons, or whatever. I mean there's also like very often for marketplaces or adding data to a validation queue because this is, like, very, very often the case. For example, if you have a marketplace and you want to open it up to new, merchants, they have to apply somewhere. Right? They they have to they have to ask, hey. I am this merchant. Can you please add me to your, shop? Or there was another example inside of the discussion itself regarding, let's say you have, like, a lunch app or whatever where you can off order food. So you want to get more restaurants or or bistros or whatever, and they can apply at your place. So you give them a public form. They can enter their information, and then you have, like, inside of your validation queue, all of the people or entries that you could go over and then, make sure that they get applied to your public to your service. Alright. Sounds like one of the the initial requirements that you're sort of sneaking in with these examples is that this form can live both as a public website page in your direct instance or as an embedded form somewhere on your website. Exactly. This is We're we're immediately diving in, and we're off. That that is that is literally I I wrote this down. This is exactly what I was, coming up with now because, like, the first the first requirement that kinda diverges, like you said, is, okay, so I have this public form. Where is it? Where where where can I find it? Because, like, it really depends. If I send somebody a link via email for example, it could be sufficient if the link is directly to your directors instance and you get served up like a complete page. And, there's the whole thing with the logo or whatever. And then you have an entire dedicated page for it. But very often also, you would like to embed your form into your existing website. Let's say with the with the, contact form example. Right? You just want to have a little contact form and on the bottom of your website. But, yeah, then then it starts then it starts. Okay. So you can have 2 different ways. Yeah. I was gonna say, let's start let's start with what we have today. Right? So we don't have, writable forms. Let's call it that forms you can change stuff in. But we do have sort of the shared form where if you open a single item in a collection, you can share share that item. And what that does for the folk who've never tried it, which I believe is most, is that it will create sort of a temporary role, so to speak, a temporary access token that has access to just that one item with the role permissions that you associate to the share. So that sounds a little confusing, but that basically means you can give away a link that contains, you know, basically a long obfuscated URL that gives read access to just that one item and the relations that it has based on the rule that you associate for read permissions, Then that public link, it's, a directus page. So you will be navigated to your directus instance slash admin or slash shares, what we call it then for the public ones. And then, if you open that up, you basically get a read only state of the form that you just shared. Right? And there's some additional options on that share. You have you can set a password on it. You can set a maximum time, start, and end date that it's available to the public. Those those are the main ones. I think there's some other options. But long story short, the first step there is, like, if we were to just just enable a share on, the collection level, we can use that as a starting point, but that is only for forms that are then within that sort of share context of directors itself. Right? So you'd be able to use it as an alternative to something like Google forms or, type form or something where you create a form, you share it, you have a public page that you can share it, that you can, link people to. To me, the the fun complexity of this is really when it comes to, a, spam protection, and b, embedding it elsewhere. Right? Because somebody in the chat, our very own team just now, just half joking said just iframe it into your front end, which, sure, you can do that. But at the same time, somebody else in the chat also mentioned, you know, it would be great if there's a contact form on each of the products in my sort of web shop or or, renting, vending vending thing. At which point, you need to be able to dynamically inject some sort of default value into this form before you submit it. Now if we're talking about embeddable forms, it's almost like a different feature request. Because if you think about it, you could open up, write access to the public role and just build a form. Right? You can build a query you can build a form in your website and just post a request that straight out to, you know, your direct this instance. So, I think we wanna split this discussion up in, a, the shareable form, which is more sort of the Google form alternative versus embeddable forms, which is, like, what can we do to sort of make it easier to request or build a form indirect and then request it and display it just like that on your website? Because, also, how much control do you want to have regarding the styling, for example, with, like, branding? Do your inputs look different? Because, you know, it looks out of place. It could look out of place if, you use our design guidelines, but your brand uses, like, way smaller inputs. It just looks very weird then. So we also had a nice, suggestion for, by Tim that I like. Where is it? Oh, no. No. By by by Brian. By a nice, by Brian. Pre filling fields by query parameters could be very cool. And hidden fields, of course. Like, there are many, many, there are so many things that you could do because there's so many different use cases. Like you said, for example, if you want to embed it, do we want to a do we want to be able to also restrict, like, how many different links there are to that form, for example? So, if I have a email list and I want to contact all of my contacts and I I give them each a personalized input field because I want to avoid the spam issue that you just mentioned, you know? So let's, say, okay, I only want people to be able to answer the form once, at least, you know, on that link, for example. But can they be different? Should they be the same all the time? So using the form once, that's the part that we do currently support with the read only share. Right? Where there is a setting for how many times can this item be opened. And every time somebody opens that that item, it just, you know, it decreases the number by 1. And then once the number hit 0s, the link, you know, goes goes this disabled. Now for creates, how do you confirm that it was done by 1 person? Right? If you associate it to an email address or something, are we gonna do email validation? Do do does there have to be a confirm step? Which is sort of like I'm I'm thinking about other forms I've seen in the wild. Right? Where it's like you wanna sign up to a raffle or something and you leave an email address and that's your that's your ticket, so to speak. But you can only use it once. Yeah. Somebody in the chat rightfully now at that point, aren't you just logged in to the app anyways? Because now you have some sort of an account or a verified account within that direct to this instance. Maybe. Maybe. Right? Hard to tell. Well, I think the other the the question that closely ties into this as well around things like CAPTCHA. How do you prevent robots? How do you prevent AI from just pulling up the form and spamming it to death? Right? Of course, an obvious one for a lot of folks like, oh, just smack a a Google recap on that and you're done. But, of course, this wouldn't be a direct this request review chat if it was that simple. Because there's a lot of sort of like wrecking and accessibility concerns around, CAPTCHA as a whole When it comes to Google CAPTCHA specifically, I I I'm a little fuzzy on the details, but I'm pretty sure there were some GDPR concerns around embedding Google services as a whole, that already requiring, you know, cookie notices and whatnot because almost every Google service will track you to bits, if you embed stuff on your page. So that's a concern. It also relies on a third party service, which is something that historically we have to be a little bit careful with, because we wanna support multiple different options. Right? But now here we go. This is the point where now we need to think about how do we have a standardized CAPTCHA system that can work with providers that works across form, right, for both shared forms and into and, like, in internal forms. Another question from the chat. To add some more complexity, who creates the public form? Is it an administrator or a nontechnical CMS user for whom setting up a form with the data model interface might be overwhelmed? Another great question. Right? So in in the direct to this model form is basically tied to your data model. So if you share an item, you share the item that you're seeing with somebody else. Right? So in its simplest form, you would share the form that you're currently seeing with the world. Is that what you want? Maybe not. Probably not. In Daniel's example from earlier, if you wanna do a simple tech form with just an email and some text, it's very likely that in your data model, you end up with a status field that says has been responded yes or no or metadata that you wanna have in your system. But how do you differentiate between the 2? Are we gonna ask the user who is sharing the form to then pick and choose fields to share specifically? Are we gonna attach it to another role soon to be policy? Or are we gonna, or or plan c is, are we gonna strip public forms from the regular content model altogether and just have a whole different section somewhere that says, here is public forms. And then perform, you just have to configure where the responses are saved. Yeah. Regarding your point of configuring specific fields like the status, for example. Like, if somebody submits the form, should it be, you know, active, reviewed, tool review, draft, or whatever? So that that really sounds to me like a field preset sign type of thing, but that exact same vein. Okay? Let's say you have a form with a user created field that automatically adds the user that created that row. Okay. What do we put in there? Who who who created that? I mean, the user could, you know, make their own public user, so to speak, and link them via a field preset, but then also kind of fields just not quite thought through. Like, to me at least, like, just thinking about it right now, like, it feels, like, so hacky that people would need to do that themselves, that it feels like this is not really thought through. But on the other hand, like, do we want to have, like, a global invisible user that we could reference? Maybe. I mean, we do have the concept of a public role. So with the user created example, it would be null because there's no user indirect because that created the thing. So if we if we zoom back out just a little bit, I think the first question that we sort of had this session hey, Jonathan. Welcome to join you, Just to catch you up. The first question was, shareable forms versus embeddable forms. Right? Which is a shared form is basically the way I see it now as a page within Directus that you'll to, and they just get, you know, a nice looking Directus connected to stuff. It's safe. Done. Little you know, think about Google Forms sort of mentally, that style. Right? The second thing is some sort of UI component or some sort of auto generated API endpoint or maybe just a public post could be, to render a configured form and direct us on your own app or website in whatever way is appropriate for your tool. Right? To me, those are 2 separate discussions. I think we start with the shareable forms because then the embeddable forms could use the same permission system and shared, configuration from the shareable form to then embed one of the shared forms. Right? That's kind of what I think that that would be a 2 step 2 step approach. Nope. I like that. So that's what you're seeing here. Right? So this is the current it's read only at the moment. Hard coded is read only. Even though we allow we've kind of plumbed this for role support in the future, it's currently read only. It's hard coded read only. So you get a read only form that looks like this, and it is to a degree, there are some permissionings. So the role does give access to the fields that are available and the relational content that's technically available and visible in the form. So you can see here my image isn't showing because I don't allow I haven't allowed the permissions correctly on that particular role. So you could have that kind of capability, And I believe we should I haven't tested this, actually. I because I'm logged in as an admin right now, but I think we can restrict the role list here based on the so the the allowed roles and permissions for the user. Permissions again? Yep. Exactly. So permissioning should control what's available in this list. So I think, again, I think the general plumbing is there for a shareable, editable form? The question becomes, what is it that we're sharing? You know, are you allowing them to create a an item from the form? What does that look like? Because right now, we are sharing an existing record. So there'd be work to be done around that, I think. Absolutely. As an embeddable I like the embeddable idea. Technically, you can kinda do that already. You know, we we see examples of that in the structures that, our good friend, Bryant, has set up where, you know, he set up these kinds of forms where Right. He's almost replicating our schema management capabilities of being able to create an editable form. So he's made it so that you can create a schema field, add whatever, you know, value type. This is a And as we're talking segue into, the second question I wanted to bring up, which is for shareable forms, are we sharing an existing form and you will still limit it down. Limit it down. Or is it effectively a separate form builder where you can create one of forms that you then connect the dots between that and your actual data model? Yeah. Similar to I think our our CRM has that kind of capability where you can build a form. Right? And then behind the scenes, the data gets stored wherever you direct those fields to store. Exactly. But you've got an and it's embeddable as a you know, you can get it as a link or you can direct them straight to the form or you can embed it as an embeddable link underneath the hood. Because the one thing I do recognize about the current share system is that it's a little bit a little very opaque. What's the right word? It's a little opaque to to know what you're sharing. I mean, by default, you're sharing what you're seeing. Right? It's like you're sharing the item that you're currently seeing. Yep. But what's actually gonna be shown to the user is different. Right? So you have to go check the link and see what it's gonna look like versus It's because it's based on the role that you then associate with the share. So if you use your own role, it's what you see is what you get. But other than that, it's a bit of a, you know, to your point, you have to create the share, pull it up, double check. If you're creating a dedicated form to share, be it read or write, that confusion is taken away immediately because it's the form that you created. It's the form that you're seeing. Right? I think the big question then becomes, how do we handle permissions if at all? Do we auto generate the permissions based on the stuff you put in the form? And therefore, you make it very explicit. Like, you put, an email address field, so therefore, you can see an email address. Or do we make it a little more opaque again by associating a role or multiple policies to TM to control the permissions for that shared item. Right? That's that's where it's a little finicky. So when when I meant that permissions, for example, if, where permissions become really important is for nested relationships. Right? So if you have a read item with a many to one field to a related category or something, what part of the category are you also supposed to be able to read from this entry point of the top level item? So having some sort of permission set there is gonna be required. Because otherwise, theoretically, if your relationships are a little complicated, you could pose a hell of a lot of data. Right? Because if we were to say, auto generate all of them, if you have a user created field because you just wanna show somebody's name, avatar, you could now theoretically go to that user record and you go to a direct to files record because you now have that connection through the user. Right? So that also, makes me wonder, there's another feature request that is completely unrelated to this, but it might actually directly be related now. One that I opened, I feel like 20 years. It's configuring access control permissions based on a parent child. So instead of saying, you have access to direct these files, you have access to direct these users. It's saying the permission, you can read a file if it's attached to a user if you're coming through the user and only then. Oh. Oh, yeah. Yeah. Yeah. Yeah. Yeah. That's, that would be very cool. That would be very cool. Top the clock. I think we need to need to start a new game. It's like, at what point do we get Jonathan to do that? It doesn't take much. It doesn't take much. Because because that would that would also potentially solve for this. Because then you could say, okay. If you have many to 1 on the record that you're sharing, you now have access to read just that one record from the related table, but nothing else from the related. Right? And for the record, that is how the current share system works actually under the hood. It is a hell of a lot more complicated, because what it does is it looks at the item that you're sharing and it checks what items are related, and then it makes a new permission set that says you can read just that one item from the related table. Right? But all of the other API ends work the same, which is interesting. But that's that's the way it does it right now. So it does actually, you know, specifically look up which items are related, which items are shared as per the role, but then lock it down to only allow you to ex that one particular item that is associated to the shared thing to make sure that we don't overexpose data in your system. Food for thought. But it it, you know, we're getting real quick into the weeds here again. Just from the question, is it sharing the existing form from your data model or are we sharing new one off forms? It sounds like and I've I've it it sounds like we probably wanna look into some sort of system. You can create individual forms and associate them back to your data model. Just in those cases where you wanna have multiple different forms with different fields that go to the same item. Commonly the case. Right? So if I was setting up a, you know, a a newsletter subscription, I might have very simple, but I still wanna register the contact. I still wanna be able to, you know, track their compliance or other things that I may wanna track or need to track versus the same contact information I would collect for a you know, you're signing up for a meeting or a webinar or something else. So the the forms can be storing data to the same places or to additional places. Follow-up question. What is that? One of these public forms, and I'll I'll get to Tim's question in the chat very soon because that's another level of complexity. But should we allow one of custom forms to save to multiple tables at the same time? Yes. Technically, yes. Form can one form create 5 different records in 5 different tables? Oh, I think it must. Right? Because of relations? Well, not even relations. Go Independent of relations. Right? Yeah. So if I'm if I'm setting up a form to collect, medical data, you know, to sign you up or set you up or do something or I'm collecting a survey, I might have survey information that I'm storing in the survey table, contact information I'm storing in the contact table. Just simple example. Right? Just 2 tables. But the contact information is in one place, the survey data is somewhere else. And I may from a from a compliance perspective, I may not be associating the user. I'm just tracking that the user responded, but the survey data has to be independent. Right? No relation at all. Here's one quick question. Good point, but Tim, wait beef before we go further further down the rabbit hole, there's another good point by Tim. It it it really sounds like a job for a flow or hook. And I think I agree, actually, because, like, the complexity then of setting it up and then the UI that has to be added for that and, stuff that could go wrong and stuff. Like, maybe, you know, just as a as a simple example. Okay. You have you just make one row in one table. That would that could be the cutoff that we decide on, maybe. I don't know. But it it really sounds like maybe a hook or a flow would then should be responsible for, you know, taking the the depending on the status, it takes the user's email and puts them also into the contacts table or the whatever table. I think I agree with that take. How do you guys feel about that? It's both ways because you could say you'd save all the data to a table and then run the flow based on that change or you save the form to a flow and then handle it yourself. I and I think there's a case to be made for both because for a simple contact us form that is always going through the same table in the same format and it matches your data model, it feels like flows could be a lot of, you know, complexity to configure just for that simple use case. But for everything else, I fully agree. Once you go, I wanna touch 5 different tables and I wanna submit to a different web, and all that kind of stuff. Yeah. Form to a flow, makes a lot of sense. Right? Right. So let's blow up this, let's blow up this discussion further because Tim also said, alright. How about, should public forms be able to save to a specific content version as well. If you call the first deal with the safety of a specific content version. Well, the nice thing is if we're going with this whole form safe to flow as idea, then sure do whatever you want. Right? That's that's kind of the beauty of the escape hatch that could be flows as the back end forms. Because at that point, if you wanna save it to a conversion, go for it. Right? What do we care? What when how when would you use that, though? Let's think about that for a second. So you have draft state basis for an item. I guess if you were updating existing content, you may wanna do that as a version, possibly. Typically, in shareable forms, I don't see it as a version necessarily. But if you were allowing someone, say, to update but even then revisions would track the the content changes over time if you were inclined. I I think yeah. What I was just about to say is what Tim again just put in the chat. Let's say you want to review and approve the changes that were made in pub. Right? So if you're running a sort of Wikipedia style, Wiki style, page Mhmm. And you wanna allow people to suggest edits, you could have a public form to update that one particular page, and then those updates go into a version that then can be reviewed and approved by the old person in charter, which is an interesting an interesting use case. That's a cool that's a cool freaking use case. Which actually would be very convenient for our own docs for that record. For example, that's what I was thinking about. I have the little button on the bottom here. Edit this page. Edit this line. That would be very cool. Hang on. Another use case from the audience in, in that updating existing thing from, Jay Shue says, another use case is a business directory and the users being able to suggest changes. Agreed. And the Durb saying we could actually use that fairly well as well. That's it. It could be implemented in flows. Right? Which is where it gets interesting again. Right? Because flows really become that sort of escape hatch for this type of stuff that, like, oh, you wanna save it to a version instead of to a table? You wanna save it to a different whatever you wanna do. Just use a flow. It it does also answer the question, is this just for create or is this also for update? And I think we've just concluded that also updates are important. Click updates. That's when you can do you can update an existing submission that you've already done, or you could, you know, the Wiki example or the business directory example or some of those. Yep. I think about, in particular, things like, you know, some of these online forms could be fairly complex. Right? I've I've done this. I've I've got you know, you're filling out something for a financial thing and you, you know, it's gonna take you an hour to do the form while you may be saving and coming back later. You can come and go from it. We do a lot with secured online security forms, you know, where we're filling out answers to complex questions that take hours or days to finish. And so, essentially, saving state and coming back and making updates and, oh, I mean, I I wanna fix that answer that I did, you know, 3 pages back in the form, and I wanna go make that adjustment. I think we found another use case for the saving it to a version. Mhmm. Because if you save it to a version, the validation of the database doesn't have yet because it only needs the saves to the database rather than to your stage to changes. Right? So the, what would you call it, plausible forms where you can enter a bunch of stuff, hit save as draft basically, and then come back later. That would be relying on content versioning. Good. Yep. Good very well. Doesn't have to, but it could. Right? You can manage that via state or status or other things as well. But, yeah. Unless you're thinking about validation in that case. Right? If you have data integrity rules that say the column cannot be So in your form, it has to be filled out. But you don't want the force to use the whole form once, you need to have an in been safe, which would be, you know, a version conversion version. I like it. It's Okay. Let's I need to switch to a slightly simpler question. Otherwise, my brain is gonna go What about deletes? Is Is that a thing you do publicly? My first gut reaction was no. Hell no. But, let's give it a little more thought. But I guess if it's user data, I don't know. I could see a use case for it. I don't I don't think from our side of things, if depending on how it's implemented, If you got compliance issues, GDPR, other kinds of things where the user has the right and choice to do that, that's that's gonna it's gonna be very use case specific. Because for the case we we try not to delete data in general. We put it in the soft archival state. You know, we use status or other things to handle that. But where you have compliance requirements where you must delete, But I don't know if that's a form. That that could be flows driven. That can be log business logic driven at that point as opposed to something to do with the form itself. I think you'd have to have a form that says I wanna I want my data to later. I wanna unsubscribe. And by doing that behind the scenes, the flows and data data management happen the way that you need them to happen. Right. Because I I could imagine that the because because deletes blank at least sound kind of insane. Because you would have what? You would show the user, here's all the records and go whichever delete whichever one you want. It that that feels like not something that you'd realistically want. But I could imagine that if we connect it to an account again, not not so much a a direct as app account, but, like, the moment you create a form submission, I could imagine that you maybe wanna do a public read of a layout. Here's a new question that we're gonna discuss in 5 minutes. Where you can just as a user as a temporary user all the submissions that you've done in the past and then delete a previous submission. To me, again, business logic. Right? That that tends to be not so much I I think you'd I think someone suggested it here. I think you'd do it as a delete request. You'd submit a request to delete and then confirm whatever mechanisms. Your your business logic, your flows, your your any additional code processing that you're doing on top of that would handle those things and send notifications accordingly. Feels very much like you would submit that as a specific form request to remove data, not the ability to delete data from the form. I think I agree in general that that shouldn't be allowed. You'd have to submit that as a separate form, maybe. I don't know. I'm sure there's a use case that I'm not thinking of. But Yeah. But to your point, if you create a new form that triggers a flow rather than saves to a table, that flow then just deletes it, whatever, based on your business logic, then prop solved. Right? You you don't necessarily go the mile to Yep. Have native victim delete support for that specific of a use case. Okay. Interesting. Interesting. Interesting. Interesting. Tricky. Tricky. Tricky questions. Tricky questions. Another another question in the chat here from user. So what about editable forms or relational data where items can be deleted after it's been saved and the user edits the data? We got it. Ladies and gentlemen, we got it. That's the real goal. If we can get right to do it, then we're then we're successful. What about editable foreign situational data where items can be deleted as it's been saved and use it as the data? I mean, I guess that kinda goes for any editable forms that it's like, user creates it, admin changes it, user tries to edit it, and that looks different. Which, yes, it will look different because you changed it. You changed somebody's submission. Right? I think that becomes becomes more of a workflow or a business process, thing where tell your staff don't touch, you know, don't go changing somebody submission. That's bad mojo. But I guess yes. What about resubmitting of shareable forms? We're kind of in the midst of thinking this through because, in the beginning, we said, okay. If you have a fixed link that you can send somebody and then they submit the thing, we could restrict that you can only submit once with that link. Or you can have a general link where, like, every single submission results in a new row every time. But then it's very use case dependent, I think. No. Like, that should be just configurable. Okay. Is this, will this result then in a on on my second visit to that link, will it show me the actual item, or is the form empty again, and can I resubmit it? I mean, that's, like, very dependent on on on the configuration, I think. Yeah. I think it should be doable, though. Some additional configurations here, potential validation checks. So, again, if it's an embeddable form or it's a shareable, editable form from our side, then this is gonna need some updating as well. Right? We'll need some additional parameters and things here. You'd have to potentially check the data, validate the data on save. Flows, again, can handle some of that, but to give the user feedback of you've already submitted or disabling the form because they've already made a submission. How do we check that? What does what does that look like? Because now you actually have to have something, you know, activity wise that says your device or whatever has been registered. We know that it was you, and you've already submitted the form. Yeah. That gets that's where I I don't know. It almost feels like that should just be front end dev work and get managed from that side of things. But Oh, here's here's the problem though, Jonathan, when it comes to the form that we're sharing, who's the front end dev doing the work? It's it's us. It's us. It's us. I know. So this needs more complex kinds of things because now max 5 uses, well, is that 5 users, or is that 5 you know, one person could submit all 5 or use all 5 values. Right? Is a user? What is a user? Right? What is the Are we getting deep? What am I I mean, that's that's kinda the question right now. I think about like same thing. We we track this on, you know, AppSight anyway, but now we've got this floating thing out there that would also have to track an activity record of who the IP and device and things are and be able to validate against that as part of this form configuration or this shareable form configuration. Now it's, you know, one time per user or per IP or, you know, whatever we consider that to be. There'd be something here, you know, max uses. So I want a 1,000 submissions, but then I wanna be able to also say per something. The the problem of the the how do you confirm the per something? Because you could say you could you could I mean, you could get away with it by just having a unique column. Right? That it's like you can only have one submission with this email address, and that's it. Done. It could be unique. Already exists. Can save it. Done. Right? But how do you prevent somebody, you know, with a Gmail account, for example, you can do the plus something something and it will come back to you anyways. You prevent somebody from submitting times with the same, you know, plus 1, plus 2, plus 3, that will work. And I can use all information still. Because there's no way for us to validate that. And then, you know, for email specifically, you can start thinking about, maybe we have some sort of email validation or we send an email and you have to click confirm or all that kind of stuff. But then what happens if you wanna use something else as the unique identifier? What if you're doing some of the phone numbers? Right? Where it's like, enter your phone number, we'll send you a text when it's your turn to to for for like reservations. Right? If you're doing a reservation at and it's it's that's that's very common around here. I don't know. Over in your parts of the world. But, you know, if you go to a restaurant here and it's full and it's like, oh, your your table's gonna be about 40 minutes and you your phone number, they'll send you a text when it's ready. Right? Mhmm. Or about 10 minutes before it's ready. So in that case, you wanna duplicate it on the phone number, but how can you confirm that? Right? You you can't really, there's no way for us to know that. A simpler a simple example would be if if you have first sorry, the delay delay is giving us. No, but but a simple example for, limiting that kind of, use would be, let's say you have a form that you can resubmit with, let's say, you have an online shop and then you want to use this for functionality for giving out promotion codes, and you only want to give out a 100 promotion codes, okay, Then it's just a matter of counting the rows, you know, so so we don't have to have a unique field or whatever. We just say, okay. This form can be submitted 100 times. That's it. I think there's like, it's a little different to your guys' use case, what you just described with the email and and phone and whatever. But, I mean, this is also a valid use case, I think. You know? I I want this form to just be usable for 100 submissions. Okay? Then it's just a matter of counting. Mhmm. Well, that's our that's already built in. Right? So we already support that max five uses. So and we keep track. Similarly, if we want this to be 1 per or 2 per source, right, then we have to actually track from a and, I guess, because it's an embeddable form or it's a, you know, we we have information and knowledge about the browser. Right? We we can track that. It just requires that we store the activity information and utilize that as part of the additional values here in a sense. There's still ways around. Right? There's always a way around. I've got 5 devices, and I wanna submit 5 submissions. You know, I can I can do that, but and and, you know, we can do things like enforcement of uniqueness on the values coming in and those things? That's already there. It's more about can I at least track to know that this user has already submitted a form because of their IP address slash device ID, that we track anyway from the browser cookie side of things? I think, I think I'm reaching the same conclusion as Tim. It's like we're going down the bot detection rabbit hole, which is like, can we fingerprint an individual user? No. There's no way. There's there's no way because IP address is shared with the location. So, therefore, everybody in the same household or the same business is gonna have a similar bound IP address. So that that doesn't work. I mean, this this fingerprint in question has been a cat and mouse between browser makers and, you know, back end implementers. It doesn't exist. The only way to do that is to require a sign through some sort of secondary authentication method, like send you an email with a magic link. So therefore, you prove you have access to the email, and that's it. Right? Before it submits or text with a phone number, that kind of stuff. Or log in through an SSO provide to confirm your, you know, your identity there, which actually is a different question I didn't even think about. But it would be kinda nice if you could sort of, like, connect the dots between what is your GitHub account click here to to o auth your way in to confirm, but that's not gonna be a 5 minute conversation, I don't think. Another question from the chat here, from from user and I'm gonna butcher your name. Sorry about that. Mama. That's what I'm gonna go with. How about the ability to show already submitted values to the user when filling out a form? Thinking about a sign up form for a party, and showing what food others already bring with them. Which is so this is an interesting question, which I think is not so much, the shareable, writable form. This is the question of readable lists of items. So right now, the share that we offer is just for a single item. You share that one. Right? What we don't allow you to do yet though, you can go to a layout and share the whole in a simple fashion. I could imagine that for this particular use case, what you would do is you would basically make a public share for your record of foodstuffs people bring to the party, long collection name, and then you can give people that link. Right? And then when they go there, they just see a layout like you would expect from directives with all of the stuff that has been previously entered with a click to to open an individual, I imagine, and then a, you know, a plug or something to go to the create page if you have create permissions through that public share. I think this is actually related to Hannes' question as well. More so because the food items being brought can be a many to many or a relational junction that's already there. So we'd show that in the current form. Right? Just like we did, you know, I only have translations in here right now, but equivalent kinds of things where you've got a a relational structure. The real question becomes when you're adding or removing relational items, this is considered potentially a delete operation under the hood. Right? So there there's there's a little bit of a tie between the delete conversation we were having and this ability to show or allow or not allow you to you know, you might be able to see what other people have brought, but you can't remove their food item. You can only add your own food item. Right? And or remove your own food item. I think role permissions generally work correctly for that, but it becomes a question of making sure that you test and set those things correctly. But is that considered a delete? Right? If you've got a cascade operation on, you know, removing a a relational item, well, that's potentially gonna cascade and cause a delete down the line. I think that would always be a deselect from the relational perspective. The Well, that depends on what you set your permissions for. Right? Oh, it's what you do. It's not permissions. The field oh, I guess it's what you set your field settings for. Right? If you set by default, yes, we set it to nullify so we don't actually delete any data. But if they've got cascade delete permissions, you know, if the cascade delete is turned on, that's going to actually delete data or contact. Point. Yeah. So the that's here's the security vulnerability way to happen. If you have an edit access to a simple item with a many the one many the one is configured to delete on select. If the user edit the field and they deselect, they now can theoretically delete stuff in your database, which is fun. Alright. Oh, jeez. It's already we're very we're already on on the dot here almost at 11. Oh, yeah. 11 for me. Times for everybody else. Just to to summarize all of this, because we went very much like this, but not a lot like that yet. We're running out of time. I think some some initial conclusions as far as I sort of take it now from this session. Right? It's like there's definitely a difference between shareable forms and embeddable forms. Shareable forms is part 1. Embeddable forms can then reuse whatever configuration that has for embedding stuff. I think that's conclusion number 1. I think to me, conclusion number 2, it's ideally you can create forms separately from the data model. Model. Although, that is quite a bit, you know, more involved to build and experiment with and etcetera etcetera. I think starting with create access is the most straightforward as you don't have problems with who can read what, how do you update previous submissions, how do people know what submissions they've previously done, etcetera. So in order of operations, shareable pages create first, then, read access for a listing would be very useful because then you have a way to click into an update item there. And then I think as a sort of your v 2, we should think about what do we form creation to look like in the first place and how does that tie into sharing? And a different question is, should sharing even be tied to collections and items, or is it just pages in the app altogether? Because I can also imagine that there's other places, like, folder in your file library that you might wanna share. Don't know. Like, another feature request for a different day, because I got skipped is, what about shareable dashboards from Insights? That'd be cool. But let's not do that right now. We'll save that for a different session. For now, Daniel, back to you to close it out. Thanks everybody for coming. If you enjoyed this discussion or are interested in other discussions, you can head over to directors. Iotv where you can find lots of other interesting shows and also this one. And, we hope to have you to see you again.","published",[139,150,160],{"people_id":140},{"id":141,"first_name":142,"last_name":143,"avatar":144,"bio":145,"links":146},"07ec688d-251d-4efe-bc17-73848402d43b","Daniel","Biegler","8897b70f-c524-460a-8990-58cc5c3be886","Engineer at Directus",[147],{"url":148,"service":149},"https://directus.io/team/daniel-biegler","website",{"people_id":151},{"id":152,"first_name":153,"last_name":154,"avatar":155,"bio":156,"links":157},"23ebcf2c-4374-4f5c-8198-f8ad497fd856","Rijk","van Zanten","7ef9652f-3835-432c-a43a-c5fe13001f31","CTO of Directus",[158],{"url":159,"service":149},"https://directus.io/team/rijk-van-zanten",{"people_id":161},{"id":162,"first_name":163,"last_name":164,"avatar":165,"bio":166,"links":167},"0d906492-75f0-45d9-abf7-ab779bf1ed08","Jonathan","Wagner","5062e4df-a198-4b40-af47-42362d3c0551","Sales Engineering Manager at Directus",[168],{"url":169,"service":149},"https://directus.io/team/jonathan-wagner",[],{"id":172,"number":173,"year":174,"episodes":175,"show":188},"6aa046f1-bd53-4510-9af0-c0f3daaf4415",1,"2024",[176,177,178,179,180,122,181,182,183,184,185,186,187],"daed2c08-703a-43d6-ac97-aacac61be4c0","86fa152b-6a8b-477e-94b5-bd91e1202d21","0b5f4343-1494-455b-b41a-25811c151242","b2b01569-d8c6-49a7-adaa-429fe84f204f","b63afbe1-6418-4e9e-b1da-4890979789f0","5c9c888c-f527-4608-a2f7-56f156d00980","243daa59-3772-4ebe-b212-c2a09a4a0b71","d66c1e46-cc57-49fe-a914-2e440bbc1576","12c8f72d-22fa-4ffa-a9d1-57047216fd1a","8896c934-aa2c-43b6-9342-8275682ab8b2","84c7b3ac-fd85-4539-8f39-3247118bcbf2","044b7c89-aaec-43b2-9d6d-6743a0fb5afd",{"title":189,"tile":190},"Request Review","73687d01-3734-4c28-aef7-e6fa8db4cf1e",{"title":8,"meta_description":8},{"id":181,"slug":193,"season":172,"vimeo_id":194,"description":195,"tile":196,"length":197,"resources":198,"people":8,"episode_number":202,"published":203,"title":204,"video_transcript_html":205,"video_transcript_text":206,"content":8,"seo":207,"status":137,"episode_people":208,"recommendations":212},"email-translations","944604881","In this recording of our live event on May 9 2024, Daniel, Jonathan, and Kevin discuss making email templates translatable","cf94e330-0c7e-4998-a002-a8df236def76",47,[199],{"name":200,"url":201},"Discussion","https://github.com/directus/directus/discussions/8239",7,"2024-05-16","Email Translations","\u003Cp>Speaker 0: Talk about what this feature is.\u003C/p>\u003Cp>Speaker 1: I'll I'll I'll in I'll intro because Daniel's gonna have to do all the hard hard work to do.\u003C/p>\u003Cp>Speaker 2: Oh, no.\u003C/p>\u003Cp>Speaker 1: So, we initially I think this was initially flagged as the make email templates translatable. So currently, especially for the system templates, not support translations on those. So things like your invite email, those are kind of hard coded as English only. You can do some things with the liquid templates, but even those are without some work are not really translatable. Mhmm.\u003C/p>\u003Cp>So the content, you have to do some variableization. Now with flows, I think with the advent of flows, you can do some things where you look up the data, pull your you know, based on content or other things, but be nice to make some modifications to the way that this platform is working to use either, the current translation strings or other capabilities, the translation solutions, interfaces on the platform itself, find a way to solve this problem so that emails can be multilingual more easily. So that's our goal. But I also saw that there I I found this that actually has an RFC spec. This was our our lovely CTO, mister Reich, creating this one liner, back in the day before we hardenforced RFCs.\u003C/p>\u003Cp>But then someone actually did a nice write up, and they referenced this particular ticket along with some other things. But they had some other capabilities on some event hooks and user invites and some things to actually extend the capabilities of the email solutions a little better. So we thought we'd use this as our our driving factor since it actually has RFC and it references the email translations. So that's the goal today, talk about how do we make the emails, the the platform emails, as well as other email things more easily translatable and easier to use and extend on the platform. Miss anything, Daniel?\u003C/p>\u003Cp>Anything here?\u003C/p>\u003Cp>Speaker 2: That's a nice, initial summary because, the pain of actually having a multilingual app, comes up quite quickly. As as soon as you got a couple different users from a couple different countries, you're you will run into this. So, this is largely only a problem for multilingual apps right now because, as of right now, you do have the ability to override our system email templates. So, technically, if you only have one language, you could just go into the, email template folder. And I even have looked up a link beforehand that I can share with the chat because I'm so organized, apparently, at least today.\u003C/p>\u003Cp>Speaker 1: Alright.\u003C/p>\u003Cp>Speaker 2: You may head on over to our docs under self hosted email templates, which will help you get started with how to do that. It's very, very simple. You have a template folder where you can put in the, the liquid template file, and you're basically done. Depending on what you want to do, of course, you know, you can make it more complicated. You can expand and expand on it, or add other functionality with your instance.\u003C/p>\u003Cp>But, technically, if you only have one language that you would like to serve, you can very easily do this. It's no problem. And even for the very, very, very brand new feature that was released this week, not sure how many of you guys have seen this because, I did a little thing with the help of the others, of course, because public registration also uses, an email template that you can override yourself. So that's the thing. You can expand on it, but as Jonathan said in the beginning, yeah, multi multilingual apps have a problem.\u003C/p>\u003Cp>Right? Like, how how do you do that as of right now? There's different, routes that you could go down on. Maybe just the the most most naive way would be to have a template per language that you just prefix with the ISO code of the language, for example. This would be the most naive way that I would not recommend, but, technically, we could do that just as a you know, to throw it in the room for discussion right now.\u003C/p>\u003Cp>So we could do that. I wouldn't do it that way, but, technically, we could.\u003C/p>\u003Cp>Speaker 0: One thing you mentioned, Jonathan, is you can kinda hack around with, if you build custom templates with, like, liquid tags. Do you have any more information about that? I'm not saying it would be an ideal approach, but how might that be approached now?\u003C/p>\u003Cp>Speaker 1: So liquid is just a, you know, a templating language, and you can you can grab templates in the flows as part of the email, service, that email notification service operation. And I believe if you supply variables, you can actually swap in the variables. So you could in in your Are you\u003C/p>\u003Cp>Speaker 0: using translation strings?\u003C/p>\u003Cp>Speaker 1: Look up the look up the multilingual contents, you know, store your your template data as a record using the current translations interface. So if we were to box here. I think in this particular demo, mail, settings, email templates. So if you were to set up, like, an email template like this. Right?\u003C/p>\u003Cp>So you can you could make this data driven, where instead of having this body here and the subject here and the name here, you could actually put those into a translation's interface, using the existing translations capabilities, then you manage your content. Now at this point, I can use a flow to grab this data. Now it doesn't work, I think, as Daniel's kind of referring to user invites. You'd have to do your own custom user invite and handle the, you know, on authentication or allow public registration kinds of things to do that. So to send a nonce you know, those are kind of system emails.\u003C/p>\u003Cp>Now we can override those with a liquid template. I'd have to play around. I think if we created a liquid template with variables in it, I think you could potentially use a flow to inject into that and swap in the multilingual from something like this, where I have the content lingually translated. But I don't have any testing.\u003C/p>\u003Cp>Speaker 0: I mean, you're talking about a naive way of doing this to be to have a template for each language, but why would we not simply store the contents of the email as a string in our translation files and then use that dynamic value? Surely, that's the the optimal way to do this. No?\u003C/p>\u003Cp>Speaker 1: That's That\u003C/p>\u003Cp>Speaker 2: would have been the better way that I wanted to to get into now.\u003C/p>\u003Cp>Speaker 0: Good.\u003C/p>\u003Cp>Speaker 2: So the like, in the beginning, I meant, like, the most naive way just to prefix every, email template with, like, enus.template. Liquid or whatever and then called it in every single language. Like, this is the most naive way that I could think of. But, as you might have guessed, by me emphasizing naive is it's very naive. It's not good because we have a very, very nice, crowd and integration for all of our translations for the app.\u003C/p>\u003Cp>So it would be very cool if we, instead of making every single template, store the languages directly, we would store like you suggested now, we would store every string inside that we want to translate very similar to our app translations. So we everybody from the community can what what's the what's the Crowded. Everybody can profit off of the, yeah, of the community's breadth and and width. Like, we have people coming from everywhere, every language. So it would be nice if we can do that.\u003C/p>\u003Cp>It's also for anyone that does not know this, head on over to no. I haven't. Oh, I have I have actually,\u003C/p>\u003Cp>Speaker 0: Locales. What what we're doing? Locales dot directors. Yeah.\u003C/p>\u003Cp>Speaker 2: Yes. If in case anybody did not know this, you can head over to locales.directors.io, and you'll see our app translations. You can contribute, can add your own. Take a look. Yeah.\u003C/p>\u003Cp>This would be a better solution to the email problem. So we can, automatically generate and pull in those, from user contributions. That would be very nice.\u003C/p>\u003Cp>Speaker 0: But there is something, you know, digging below the surface. That'd be fine for system emails. Like, for system emails, that's totally fine. Just use these. But scratching one level below the surface is the ability to act is to use translation strings maybe in custom templates.\u003C/p>\u003Cp>That's the one level on because I feel like the solution to make email tran make email templates translatable is fine for system emails. Like, that we have an approach. We have a you know, we have something. We just need to not hard code the values in English. But there's more than that, I suppose.\u003C/p>\u003Cp>Speaker 1: So I think that was one of the comments that was in the one of these tickets already. I think that was in here somewhere. Somebody mentioned that using the translation strings. I think it was the right somewhere along the way. But that is an option.\u003C/p>\u003Cp>Right? So to me, either something like this. Right? So you can do this yourself with flows for for anything non system email, whether we do the system emails in the translation strings here or whether it's in the actual crowd in files, because it's a system email, you could technically actually have that in all of the languages. I guess, technical question, how do I know what language to send the email in?\u003C/p>\u003Cp>So when I'm using a user invite, I guess, you set the language for the user, the default language for the user. Is that how you would manage that?\u003C/p>\u003Cp>Speaker 2: Yeah. For invites, I think it's a special case because you don't know the person. You could, under specific circumstances, not know what the person is speaking technically. But, like, for other system emails, we have the user. It's they are already registered, so you can just pick the language from the user or the default language of the instance.\u003C/p>\u003Cp>But for invites, I think we should fall back to the, default language of the instance Yeah. But also provide the opportunity to set a specific language inside of the, pop up. Yeah. Yeah. Exactly.\u003C/p>\u003Cp>Exactly. Yeah.\u003C/p>\u003Cp>Speaker 1: We'd add we'd add language here as well. Right? So not just the you know, you'd choose choose your role or whatever you're inviting this user to, but also have a language and set it to the default for the project as the initial. If If they wanna change it, they can choose from one of the languages. And, therefore, those things exist in the crowd inside, but that's part of the you don't have to do any translations inside the app for that.\u003C/p>\u003Cp>That's not a dynamic kind of thing necessarily. Although, if I'm overriding, then I still want. So that's something that we have to think about as well. Right? So where does this get managed, and how does this get managed?\u003C/p>\u003Cp>Crowdin is awesome for system, but the reality is I may want to customize the actual liquid tablet for this. And as soon as I do that, I'm now I now fall back outside of how do I manage the translations.\u003C/p>\u003Cp>Speaker 0: You know what would be really cool actually is if in settings, there was a a section called email templates, and our default ones were there and not deletable, and you could create new ones, and then use the built in director's translation interface to enable that. Like, that feels like a really nice flexible way to also potentially stop people needing to build their own liquid templates, like, as separate files and then load them into a directory. For many use cases, just being a just having a WYSIWYG with, well, a WYSIWYG would be plenty. Maybe with, like, a yield or, you know So\u003C/p>\u003Cp>Speaker 1: it it's this. This is fundamentally what you need is a subject and a body. That's all you really have to have for email. For the text, put this in as a, you know I I think again, the the trouble with making it a system side is I I also kind of want content users to be able to do this. So I'd I'd want my marketing teams or my whoever's to be able to manage the content in these.\u003C/p>\u003Cp>So in a sense, it would be a system user table, possibly, that would show up that you could make accessible to the content side. You could optionally make it as accessible maybe. We don't really we don't really do that with anything today. We don't we don't create anything here other than the languages table gets created if you haven't created it yet, for translations interface. I\u003C/p>\u003Cp>Speaker 0: I question that notion to a degree, though, because if you look at things like creating and editing flows, you can make exactly the same argument there. You wanna expose flows to more people in your organization, and we don't do that. I don't see why like, I think that that would be a bigger conversation about what is exposed versus what isn't and to what degree. So I I would be at peace with the idea that that is an admin setting, but I do get it. It feels a little more editorial perhaps.\u003C/p>\u003Cp>Speaker 1: Okay. That's a separate discussion then, really, I think. So one of because this actually came up this week. Somebody noted that if I make you know, I I'd like to be able to make some role editing capabilities accessible to a user, but not give them data model access or flow access or other things. So potentially being able to enable subsets of the settings for non admin users.\u003C/p>\u003Cp>So that's a separate discussion. But I do agree. I think email templates would be really awesome in here, so that I don't have to create liquid files or other things behind the scenes.\u003C/p>\u003Cp>Speaker 0: And you don't have access to the directory on professional cloud. That's the other big thing in my mind is, like, to really be a solution that works anywhere Directus is is hosted. It can't rely on dropping files in a persistent directory. It needs to be accessible via the data studio.\u003C/p>\u003Cp>Speaker 2: Some action in the chat. I envision being able to create custom email templates and sending it to a mailing service, specifically something something from directors. Could be separate thing, but would be good if it wasn't limited to settings page and flexible enough to support this.\u003C/p>\u003Cp>Speaker 1: The reality is, though, if I do want my own email templates, I could still create the user stuff for that, and I could mimic whatever was in the system. So, hopefully, over time, maybe there's additional system emails or things that we want for the platform. So we'd wanna be able to have those, and they could be manageable in the setting side if you wanted to replicate. Because Flows already supports, you know, grabbing things, you know, pull your variables, pull your data, pull your content. So, again, in this, like, agent c OS here, we have flows for, you know, sending the email.\u003C/p>\u003Cp>Right? So when you send the email, we're actually getting data from the trigger hooks and creates and posts and whatever, so we can pull in data from wherever. Right? So if there's data in a template or places that we wanna get it, we could do that. We can grab that ahead of the email.\u003C/p>\u003Cp>Speaker 0: Could you, show the drop down\u003C/p>\u003Cp>Speaker 2: link? Sorry.\u003C/p>\u003Cp>Speaker 0: Could you show the drop down again where it was marked down? What was the other option is attempt just in send email here. The other option is WYSIWYG or a template. Interesting. Because still in my mind, like, to be really flexible, you want templates to be able to have exactly data that is popped in there.\u003C/p>\u003Cp>So, yeah, I don't see why why you couldn't be authoring those indirectors.\u003C/p>\u003Cp>Speaker 2: You know?\u003C/p>\u003Cp>Speaker 1: I I think we should. I I think it would be awesome because having to go to liquid templates and have to have custom extension deployment capabilities or access to the server. Yeah. Not ideal. Right?\u003C/p>\u003Cp>So again, part of what I think this overall system flows discussion was about, in general. So moving away from the the simple thing that Raich put in here, this was a little bit more of handling this with some system flows and setups and management, being able to manage this from the front end as opposed to back end. So making it data driven. Right? The the things we enable for everyone else, let's enable this for ourselves and make this data driven.\u003C/p>\u003Cp>I love it.\u003C/p>\u003Cp>Speaker 2: Yeah. I I really want to go into that, issue as well, the system flows for, for the system actions. But, first, I wanna finish the other, message from the chat that was with the mailing service. Like, I'm not sure if I understand correctly because, like, this should be possible, right, with just the environment variables. You just define which SMTP server you want to use as an email service so you can actually connect to something else.\u003C/p>\u003Cp>And if you override the template, that is doing what you just said. Or maybe maybe am I missing something?\u003C/p>\u003Cp>Speaker 0: Maybe the ability to send them to custom places per run. Like, there's a few it depends what level of flexibility or abstraction you want to build in, but at its core, that's what happens with the email service In flows, at least.\u003C/p>\u003Cp>Speaker 1: In flows? I don't play with it much, but I don't think you get to choose your mail service here. Right?\u003C/p>\u003Cp>Speaker 0: No. No. But you configure that for the project. And then when emails are sent using this, that's how they get\u003C/p>\u003Cp>Speaker 1: sent. But they get sent with 1 service, not multiple services. Right? Single services.\u003C/p>\u003Cp>Speaker 0: I'm not I'm not sure I see I mean, maybe I'm missing it, but I'm not sure I see the value in being able to set set up multiple. I don't even think you can. I'm not sure you can. It'll be in config options.\u003C/p>\u003Cp>Speaker 2: I mean, technically, because, like, most email services have specific rest APIs that you can just call. So you can probably just set up a webhook event Use a web. Operation thingy. Yep. Send over the the specific payload, and then the email service should take over.\u003C/p>\u003Cp>So, yeah, technically, should be doable.\u003C/p>\u003Cp>Speaker 1: Nice. But I think we're single email service Yeah. On the scenes or\u003C/p>\u003Cp>Speaker 2: Yes.\u003C/p>\u003Cp>Speaker 1: And I I don't actually know.\u003C/p>\u003Cp>Speaker 0: Hello. The hello. Hello. Hello, Duff. We could should talk because I also built my wedding website with, with Directus and built a set of automations around that.\u003C/p>\u003Cp>So how funny is that? I wrote a whole blog post about this. It's one of the earliest blog posts on the developer blog. If you wanna go take a look in our docs. Yeah.\u003C/p>\u003Cp>That's fun. Gosh. Nerds really do like to overcomplicate weddings. Then don't they slash we.\u003C/p>\u003Cp>Speaker 1: Developers are as bad as some of our I\u003C/p>\u003Cp>Speaker 0: mean, I have to deal with\u003C/p>\u003Cp>Speaker 1: complicating things. Right?\u003C/p>\u003Cp>Speaker 0: That's amazing. Yeah. That's so funny. Why should\u003C/p>\u003Cp>Speaker 2: I spend 15 minutes to do the thing that I need to do when I could spend 3 hours to automate the thing.\u003C/p>\u003Cp>Speaker 0: Oh, no. No. It was good. We used it for I mean, a quick aside, but I will explain. So weddings have, like, quite a lot of variability to them.\u003C/p>\u003Cp>So we had if you consider a ticket. Right? A ticket. Right? An RSVP.\u003C/p>\u003Cp>So the first thing is you don't generally send, a ticket per person. You'll send it a group and the group will RSVP for individuals and they might not RSVP the same way, then we, at least, our ceremony could only hold like 80 people, but our reception had like 200 people at it. So, we had variable ticket types and then some ticket types allowed a plus one, some didn't, so all this variability. So backing that with data was really useful. So you had people, then you had invites of multiple people, and then you had RSVPs against the invite.\u003C/p>\u003Cp>And then we also used it for comms, so like blasting out emails or texts to everyone. That's how we did it. And we also used it to manage the shopping list as, because we DIY'd the wedding as people RSVP. So that's that's why it needed hours and hours and hours of, of time.\u003C/p>\u003Cp>Speaker 2: Just like Benny said, you just have to get married a couple times, then the effort was totally worse.\u003C/p>\u003Cp>Speaker 1: I mean, I'm never doing that again. One time was enough.\u003C/p>\u003Cp>Speaker 2: So, yeah, I think it's it's regarding the This is\u003C/p>\u003Cp>Speaker 1: year 30 for us.\u003C/p>\u003Cp>Speaker 2: Oh, damn. Nice.\u003C/p>\u003Cp>Speaker 1: My partner's been a long time. Congratulations.\u003C/p>\u003Cp>Speaker 2: So, Alright. Let's summarize a little bit because we have, you know, 2 issues. So the first one with the general email translatability is not that complex in itself, but should be doable also. And with Kevin's mentioned, like, translation strings, if we could use those, that would be very cool, very nice. With for the system emails, if we could reuse the crowd in, stuff or, like, the static hosting of the string so we can reuse, you know, services and stuff, that would also be very nice.\u003C/p>\u003Cp>And now I think like, if nobody has anything else regarding that\u003C/p>\u003Cp>Speaker 0: Could I just add could I could I add a question? Very interesting. Which is simply Sure. Of course. Can you not use translation strings in custom templates and custom liquid templates today?\u003C/p>\u003Cp>It feels like you should be able to. No. You can't. Okay. Fine.\u003C/p>\u003Cp>Speaker 2: I don't think you can.\u003C/p>\u003Cp>Speaker 1: That's not what I know of.\u003C/p>\u003Cp>Speaker 0: No. No. No. I I defer to you. I've not tried to do it.\u003C/p>\u003Cp>I made an assumption that it was supported. So, yeah, good to know.\u003C/p>\u003Cp>Speaker 2: As far as I know, like, the the only thing that you can do in there is, like, use data that's get passed in, you know, with the keys. So, you could do that with flows. Right? Like, if you would send if you could fetch some data or decide in a flow, like, what that specific e will hold. So, like, for an English user, it will hold hello, and for a German user, it would say, like, or something.\u003C/p>\u003Cp>Then you could reuse the same key, and it works, you know, for multiple languages. But you can't actually use the language thingies, the other thingies. Oh, yeah. And and another nice point from Tim. What about right to left languages?\u003C/p>\u003Cp>Speaker 0: Oh, they don't exist. We're gonna forget about right to left lang I mean, sure. But, you know, that that is a nuance in an implementation, I think. I think don't you set it on the HTML attributes? So you would just set it in the email.\u003C/p>\u003Cp>Speaker 2: I mean, it it look. I'm I'm really not sure because I don't speak or read languages that go from right to left.\u003C/p>\u003Cp>Speaker 0: But more but more than anything, we need to think about that.\u003C/p>\u003Cp>Speaker 2: Yeah. Like like a button, like like a, verification button or something. Should it also be on the other side, for example, in the email template? So, like, not only text, but also, like, buttons. Do the does the language affect those as well?\u003C/p>\u003Cp>I think so. Right?\u003C/p>\u003Cp>Speaker 0: I think my my very limp with pleading complete ignorance here, I'm pretty sure basically whole UIs flip accordingly. But, yes, I think Tim Tim makes a good point though in that it would not simply be a translation string, but you would intrinsically need to know is this email a right to left or left to right email. And, you know, change the I think I genuinely think it's just an attribute in the HTML tag, but, you know, change that\u003C/p>\u003Cp>Speaker 2: accordingly. Yeah. But but in the HTML tag, for example, like, it would need to with, like, c s like, CSS in emails is always very tricky. Like, it's very nitpicky. Something works in an email client, something doesn't, and that's, like, super archaic.\u003C/p>\u003Cp>If if anybody had to deal with this, I'm sorry for you.\u003C/p>\u003Cp>Speaker 0: We support some right to left languages though. Right? Like, in the data studio.\u003C/p>\u003Cp>Speaker 2: I believe so. I have never used them, to be honest. So please don't look at me for further info in the context.\u003C/p>\u003Cp>Speaker 0: Given given that the default language collection gets created with We do.\u003C/p>\u003Cp>Speaker 1: We do.\u003C/p>\u003Cp>Speaker 2: Yep. Definitely.\u003C/p>\u003Cp>Speaker 1: So if you look, we have Arabic Yeah. For 1. So if you scroll where's my language Uh-oh. I don't know what\u003C/p>\u003Cp>Speaker 2: Don't lose the button.\u003C/p>\u003Cp>Speaker 1: I'm good enough navigating around. Worst case, I have DirecTV access to this guy. Fix it. But it's all good. So you get your Arabic.\u003C/p>\u003Cp>So we do have the translations for it.\u003C/p>\u003Cp>Speaker 0: It's individual strings, though. Yeah. Yeah. Exactly. Exactly.\u003C/p>\u003Cp>As Tim said here in the chat, I'm not convinced this is a true right to left implementation for languages. It likely will do, but will do is not necessarily the best or optimal. But in any case, that's just worth noticing too.\u003C/p>\u003Cp>Speaker 1: Would the reality actually be that this this should flip over here in the right to left? Like, the module bar, like, the whole screen would, like, invert? Oh, that makes my head hurt.\u003C/p>\u003Cp>Speaker 0: I I am not sure that's correct. So I I feel the need to add, I believe, the 3 of us here, plus Tim and the child Oh, Benny said, yes. Okay. Someone had a degree of confidence because I was like, if we've not done it, we don't know and there are degrees of implementation. Right?\u003C/p>\u003Cp>But, at the very least, consider the way people read left to right in terms of priority and flow. They would wanna be flipped.\u003C/p>\u003Cp>Speaker 2: Yeah. But we also have to keep in mind that, Benny is from Australia, so his layout is also different. His navigation is on the bottom, and everything appears on the top. It's flipped.\u003C/p>\u003Cp>Speaker 0: You know what would be so funny if, yeah, everything was upside down or, like, even subtle things like like the the spinner stand in the other direction like the toilet water.\u003C/p>\u003Cp>Speaker 2: Yeah. Oh, that would be good. Alrighty. I think I think that's for for now, enough about emails because the other issues are also very interesting, and I think we should we should look into them.\u003C/p>\u003Cp>Speaker 1: Definitely. So sounds like we have a couple of solutions to think through on how we'd wanna implement this. I was looking, Kevin, with regards to your question. It does look like if you use a custom template, so so my custom template so if you have a custom liquid template, you can define variables inside that template. So first name, you then pass that as data from a flow.\u003C/p>\u003Cp>Now this is flow implementation of that template. But, technically\u003C/p>\u003Cp>Speaker 0: Yeah. I mean, technically, being able to and it being in any way optimal. There's a very, very wide chasm between the 2, and I think this is up on one end. Right?\u003C/p>\u003Cp>Speaker 1: Yeah. So once again, what you would do is you would have a body and a subject here that you were looking up from that translation user side content translation. So you'd have a user table with a translations interface, that has your subject and your body and just simply translate the whole thing. You could variabilize or anything that you wanted inside that template itself. Flows would have to handle these, you know, use a run script.\u003C/p>\u003Cp>I did something like this recently for page templates. So defining a page template, content gets built in the user tables, and then when the user's ready to say, you know, for my my location page template, generate the location page, substitute in. I've got a flow that looks for those variables, substitutes them in, generates the page instance for that location, and I'm standing for that. So you could do those kinds of things. But again, it's a lot of work upfront, for the developers and the, you know, the administrators.\u003C/p>\u003Cp>So Yeah. Figuring out a way to make this I think, again, the system making it accessible via the admin in some way, shape, or form, I think is the ideal solution. Like it. Agreed. Cool.\u003C/p>\u003Cp>Speaker 2: And check.\u003C/p>\u003Cp>Speaker 1: Alright. System flows. What do you wanna talk about there, mister Daniel?\u003C/p>\u003Cp>Speaker 2: Oh, this this one is very cool. This is very interesting. It's, the idea and I'm I'm I I'm always very in favor of dogfooding, like, our application. So if we could use like, integrate flows deeper into our app itself, it would, like, in a way, force us to actually improve flows a little bit for ourselves. And so we got it's not I mean, really like them.\u003C/p>\u003Cp>Speaker 1: I know. We we we talked about flows 2.0 a little while back. Right? But yes. Go ahead.\u003C/p>\u003Cp>Speaker 2: Yeah. And, yeah. So this one is pretty interesting. So, the idea is that you replace our current, like, internal behavior of, like, what even happens if somebody presses, forgot password. You know, like like, for example, maybe I would like to send a couple emails.\u003C/p>\u003Cp>I would like to send one email to the to the admin and say, like, oh, warning. This user has, requested a password request or something, you know, just as a random example. You can also do, like,\u003C/p>\u003Cp>Speaker 1: more product updates. Record above and beyond what's in the system already. Maybe you've got soft compliance or ISO compliance things where you get that logged to a system somewhere. Yeah. That's not our app.\u003C/p>\u003Cp>Interesting.\u003C/p>\u003Cp>Speaker 2: Exactly. So maybe you want to customize this. And, I think, I haven't read the entire issue yet, but I think the idea was just to start with, like, invites and password, resets. But we can expand on this a little bit. And, you know, like, depending on how we structure this, how the user experience is, like, how do you override that?\u003C/p>\u003Cp>We have to have a fallback. What happens in the UI? And and you're not allowed to delete the thing. What happens if somebody deletes the thing? You know, like, there's there's a couple things that can go wrong, but, technically, I think this is very exciting and a very smart idea.\u003C/p>\u003Cp>I I really like this.\u003C/p>\u003Cp>Speaker 1: Clever. Well written too. Well defined. Well thought through. Linking to related concepts and tickets.\u003C/p>\u003Cp>David David Zacharias. Excellent. Excellent work. I love the\u003C/p>\u003Cp>Speaker 0: Yeah. Read only read only flows. Must have read only flows AKA system flows. Additional which kinda makes sense here. You have system collections and you can extend system collections as well.\u003C/p>\u003Cp>So it could be that thing where it's like, hey, you know what? These first two steps or the first and last, you can't change those. You can either put stuff in the middle or stuff at the end, kind of like you can do with fields today in collections. So Mhmm. The core behavior stays exactly the same that you can tack on.\u003C/p>\u003Cp>I would be more inclined then to just have an event, though, that an event based hook can hook into.\u003C/p>\u003Cp>Speaker 2: I don't know. No. That's a good point, actually.\u003C/p>\u003Cp>Speaker 0: Because if you have read only flows and you have these new additional scopes, then they kind of negate the need for one another, I think.\u003C/p>\u003Cp>Speaker 2: Now that that's a good point. Yeah. That is a good point.\u003C/p>\u003Cp>Speaker 0: And our paradigm today is\u003C/p>\u003Cp>Speaker 2: because, like, oh, let me based. Even if somebody wants to just break the flow, for example, maybe somebody doesn't want the, like, even the functionality to to be there. You know? Like, maybe you want to forbid actually password requests, like, reset requests.\u003C/p>\u003Cp>Speaker 0: Yeah. Or you just want it to come to the internal team and never go back out to them automatically. Like, that is a a managed process. Yeah. Interesting.\u003C/p>\u003Cp>Yep.\u003C/p>\u003Cp>Speaker 2: Yeah. Also Disabling your Reasonable to me.\u003C/p>\u003Cp>Speaker 1: Disabling a password reset? Interesting.\u003C/p>\u003Cp>Speaker 2: Yeah. I mean, for you know, it's it's always such a, you know, contrived example and stuff, but take like, there's so many different environments and and regulations and\u003C/p>\u003Cp>Speaker 0: Get in touch with your system administrator. Managers and Your IT team\u003C/p>\u003Cp>Speaker 2: or whatever. For example. Yeah. So I can definitely see the use case there. And and this is, like like, super interesting to me.\u003C/p>\u003Cp>Speaker 0: The the the lowest\u003C/p>\u003Cp>Speaker 2: Like, I have not thought about this.\u003C/p>\u003Cp>Speaker 0: Neither have I. The lowest hanging fruit version of this is additional scopes that allow you to execute additional logic on top of the core logic for things like inviting and password resets. These I I almost feel like that is a separate thing, which is smaller and much easier to to implement. Pop that to the side. The system flows is is diff is the thing here.\u003C/p>\u003Cp>I just find that in that addition interesting.\u003C/p>\u003Cp>Speaker 1: Yep. Nope. And so, again, it was extensible, you know, in the sense of it'd be nice to have the translation capability, but also, again, move. We're gonna touch some of these things, potentially moving some of that logic to where it's more accessible or modifiable.\u003C/p>\u003Cp>Speaker 0: Oh, to modify the business logic, users can duplicate the flow and adapt to their needs. The system flow would then be inactive, but could be activated anytime to restore the default functionality. That UX, for me, does not feel good, but it is an interesting way to think about it.\u003C/p>\u003Cp>Speaker 2: Yeah. I I think\u003C/p>\u003Cp>Speaker 1: Well, the system side scope\u003C/p>\u003Cp>Speaker 2: in the event yeah. If you can just, like, have a filter hook, and that would do the thing. Like, you can then cancel. Like, if you throw, the hook will be canceled, and then the email won't be sent out. And if you just pass it through, the normal behavior will take place, which is just sending an email.\u003C/p>\u003Cp>Right? Like, and you can do stuff in between. Yeah. I feel like this would be a way better solution than having, like, read only flows and copying and then, you know, fallbacks and something is missing and whatever. Like, maybe just\u003C/p>\u003Cp>Speaker 0: And the And the critical thing is it matches the paradigms we have today. We have event based, event based triggers, and then we have actions and filters which run before or after the the operation happens, the the database operation happens. And yeah. So that feels that feels kinda better to me. And, yeah, you can always find a way to break it out of completing.\u003C/p>\u003Cp>And if you're if it's blocking, then the end part never happens.\u003C/p>\u003Cp>Speaker 2: Yeah. Oh, this is cool. If somebody could work on this, that would be nice. This is pretty cool.\u003C/p>\u003Cp>Speaker 1: Well, that's why we're reviewing so we can Could we determine, does it make sense and what additional things do we need to think through. Right?\u003C/p>\u003Cp>Speaker 0: Can we split this into 2 feature requests? Because that core nugget we've discussed is feeling very viable. Also, it feels like not a huge lift. And it is not system. It is not system flows.\u003C/p>\u003Cp>It is the introduction of new events, and then system flows is is something in and of its own. Right. I suppose.\u003C/p>\u003Cp>Speaker 2: But, like, if we have that event, like, do we even need system flows then?\u003C/p>\u003Cp>Speaker 0: I I I would argue not. I I would argue not. But that isn't what this. It's hard because I don't feel inclined to change people's feature requests into the 10% one liner that they've introduced, in it. But that nugget can be dealt with in isolation.\u003C/p>\u003Cp>Speaker 1: Yeah.\u003C/p>\u003Cp>Speaker 0: Yeah. Saw that.\u003C/p>\u003Cp>Speaker 2: Okay. So so that that's that's pretty neat. That would be nice. Yeah. Very cool.\u003C/p>\u003Cp>Yeah. Then okay. So for the events, then there would be a password request reset request. I always\u003C/p>\u003Cp>Speaker 0: It's a reset it's a reset request and then a reset.\u003C/p>\u003Cp>Speaker 2: Yeah. And a oh, oh, right. Those are 2 things. Okay. The the request and the actual reset.\u003C/p>\u003Cp>Maybe you want to act on that too. Okay. Those 2. The invite would be the 3rd.\u003C/p>\u003Cp>Speaker 0: Oh, I'm hang on. So I can just tell you because I've just written this section of our new documentation. So there is invite request and invite accept. Right, actually creating a user off the back of an invite. Then there is, password reset request and password reset.\u003C/p>\u003Cp>And then there's a set maybe around SSO specifically, but maybe not. They are that out. And then if we're talking about if we're thinking about the whole breadth of kind of off, there is also 2fa on off. Like, they are the that is the set of kind of operations that exist beyond just logging in, locking out, logging out, refreshing.\u003C/p>\u003Cp>Speaker 2: And since this week, there will be maybe coming then, register request and register request accepted, maybe?\u003C/p>\u003Cp>Speaker 0: Yes.\u003C/p>\u003Cp>Speaker 2: Something. Ah, and the email verification might also be interesting. Somebody might need that.\u003C/p>\u003Cp>Speaker 0: I would sooner add a a a, you know, like, a bundle of new events and go, well, there's the bit the biggest degree of flexibility for\u003C/p>\u003Cp>Speaker 2: That would be neat. Okay. Yeah. This this this sounds very exciting. This sounds actually very cool to me.\u003C/p>\u003Cp>Because we introduced to also new events for the content versioning. There was the promotion Promotion. Or promote or promotion, which is also useful. So this doesn't sound that far and unreasonable. This sounds very reasonable, actually.\u003C/p>\u003Cp>Speaker 0: So, Jonathan, so while you're typing, there's a there's a couple more. So there is invite, and then there's invite accept. There's password reset request and password reset, And there is 2 FA on and off. And they are the only 2 in my mind that I'm not sure how what like, I'm not sure what the impact of adding those in particular are, but they are there as well. And then I don't I don't have enough knowledge around single sign on to be confident in in listing events around that.\u003C/p>\u003Cp>Speaker 2: Cool.\u003C/p>\u003Cp>Speaker 1: Yep.\u003C/p>\u003Cp>Speaker 2: Yeah.\u003C/p>\u003Cp>Speaker 1: Yeah. And, again, being able to extend being able to extend these would be really powerful. Right? Because if we've got a lot of clients that run us as a SaaS, we operate as a SaaS. There are system and service emails that, again, we do it through user templates and other things today, the way that we define and the way we've talked about.\u003C/p>\u003Cp>But making this kind of built in where you can create and manage your own system emails and service emails, would love it.\u003C/p>\u003Cp>Speaker 0: Yeah. And the the thing is we already because we this only were basically, taking this feature request around or the other feature request rather, which is, oh, sorry. I see you're in this issue. Sorry. We're in the wrong one.\u003C/p>\u003Cp>Sorry. So emails that go out are not all of those. Sorry. Emails are just the, the yes. The password reset request and the invite.\u003C/p>\u003Cp>They are the only 2 system emails. Sorry. They are the auth events, though. Or the the potential auth you know, they are the points at which we could implement events. The fact that we already have filters and actions as blocking and non blocking, you know, code, you know, logic business logic means immediately you can effectively extend Directus' core functionality without needing to do anything else but expose these new events, which is really cool.\u003C/p>\u003Cp>Speaker 2: Yes. Agreed.\u003C/p>\u003Cp>Speaker 0: It's nice when you have a system that kind of already has the building blocks. Right? There's no new building blocks that need to be built for this one.\u003C/p>\u003Cp>Speaker 2: Yes. Only the integration and making sure that we can actually, like, cancel, for example, like, what happens if if the thing canceled and stuff. But other than that, you're completely right. Yes. So just as a reminder for everybody else in the chat because there's still a couple people here, the show will be over very soon.\u003C/p>\u003Cp>So if you have any questions that you would like to ask, now is the time. Now is the time.\u003C/p>\u003Cp>Speaker 1: Quiet group today.\u003C/p>\u003Cp>Speaker 0: Nothing wrong with that at all.\u003C/p>\u003Cp>Speaker 2: Alright. Yeah.\u003C/p>\u003Cp>Speaker 1: Means maybe we did our job right.\u003C/p>\u003Cp>Speaker 0: And and not right any other\u003C/p>\u003Cp>Speaker 1: time.\u003C/p>\u003Cp>Speaker 0: Yeah. That's really cool. I like the idea of system system flows. I, ultimately, like the idea of that, of exposing a set of functionality as flows in a UI that could be extended on the end. But I I, personally believe it's just simply unnecessary.\u003C/p>\u003Cp>It's just exposing the new events. And with actions and filters, it facilitates, I think, the goals of this.\u003C/p>\u003Cp>Speaker 2: Yep. Yeah. Exactly. I fully agree. So people let your let your questions out in last minute.\u003C/p>\u003Cp>1, 2. Yeah. If you have enjoyed this, or want to partake in the next one, you take a look in Discord in the events. You will see that we will be doing another episode on the 23rd May Yeah. Will be about configurable API errors.\u003C/p>\u003Cp>So errors are always very important. You might wanna let your voice be heard there. So please join in. Tune in if you like. And if you enjoyed this and want to revisit this or other episodes, head on over to directors.iotv.\u003C/p>\u003Cp>And, there will be lots of other shows as well, which are quite interesting and fun. So please check it out. Let's say it again, directors.io/tv.\u003C/p>\u003Cp>Speaker 0: Yep. We hope\u003C/p>\u003Cp>Speaker 2: you enjoyed. Oh, there's the link.\u003C/p>\u003Cp>Speaker 0: Thank you. And all other episodes of request review bar the last one because I messed up the recording, you can find right there.\u003C/p>","Talk about what this feature is. I'll I'll I'll in I'll intro because Daniel's gonna have to do all the hard hard work to do. Oh, no. So, we initially I think this was initially flagged as the make email templates translatable. So currently, especially for the system templates, not support translations on those. So things like your invite email, those are kind of hard coded as English only. You can do some things with the liquid templates, but even those are without some work are not really translatable. Mhmm. So the content, you have to do some variableization. Now with flows, I think with the advent of flows, you can do some things where you look up the data, pull your you know, based on content or other things, but be nice to make some modifications to the way that this platform is working to use either, the current translation strings or other capabilities, the translation solutions, interfaces on the platform itself, find a way to solve this problem so that emails can be multilingual more easily. So that's our goal. But I also saw that there I I found this that actually has an RFC spec. This was our our lovely CTO, mister Reich, creating this one liner, back in the day before we hardenforced RFCs. But then someone actually did a nice write up, and they referenced this particular ticket along with some other things. But they had some other capabilities on some event hooks and user invites and some things to actually extend the capabilities of the email solutions a little better. So we thought we'd use this as our our driving factor since it actually has RFC and it references the email translations. So that's the goal today, talk about how do we make the emails, the the platform emails, as well as other email things more easily translatable and easier to use and extend on the platform. Miss anything, Daniel? Anything here? That's a nice, initial summary because, the pain of actually having a multilingual app, comes up quite quickly. As as soon as you got a couple different users from a couple different countries, you're you will run into this. So, this is largely only a problem for multilingual apps right now because, as of right now, you do have the ability to override our system email templates. So, technically, if you only have one language, you could just go into the, email template folder. And I even have looked up a link beforehand that I can share with the chat because I'm so organized, apparently, at least today. Alright. You may head on over to our docs under self hosted email templates, which will help you get started with how to do that. It's very, very simple. You have a template folder where you can put in the, the liquid template file, and you're basically done. Depending on what you want to do, of course, you know, you can make it more complicated. You can expand and expand on it, or add other functionality with your instance. But, technically, if you only have one language that you would like to serve, you can very easily do this. It's no problem. And even for the very, very, very brand new feature that was released this week, not sure how many of you guys have seen this because, I did a little thing with the help of the others, of course, because public registration also uses, an email template that you can override yourself. So that's the thing. You can expand on it, but as Jonathan said in the beginning, yeah, multi multilingual apps have a problem. Right? Like, how how do you do that as of right now? There's different, routes that you could go down on. Maybe just the the most most naive way would be to have a template per language that you just prefix with the ISO code of the language, for example. This would be the most naive way that I would not recommend, but, technically, we could do that just as a you know, to throw it in the room for discussion right now. So we could do that. I wouldn't do it that way, but, technically, we could. One thing you mentioned, Jonathan, is you can kinda hack around with, if you build custom templates with, like, liquid tags. Do you have any more information about that? I'm not saying it would be an ideal approach, but how might that be approached now? So liquid is just a, you know, a templating language, and you can you can grab templates in the flows as part of the email, service, that email notification service operation. And I believe if you supply variables, you can actually swap in the variables. So you could in in your Are you using translation strings? Look up the look up the multilingual contents, you know, store your your template data as a record using the current translations interface. So if we were to box here. I think in this particular demo, mail, settings, email templates. So if you were to set up, like, an email template like this. Right? So you can you could make this data driven, where instead of having this body here and the subject here and the name here, you could actually put those into a translation's interface, using the existing translations capabilities, then you manage your content. Now at this point, I can use a flow to grab this data. Now it doesn't work, I think, as Daniel's kind of referring to user invites. You'd have to do your own custom user invite and handle the, you know, on authentication or allow public registration kinds of things to do that. So to send a nonce you know, those are kind of system emails. Now we can override those with a liquid template. I'd have to play around. I think if we created a liquid template with variables in it, I think you could potentially use a flow to inject into that and swap in the multilingual from something like this, where I have the content lingually translated. But I don't have any testing. I mean, you're talking about a naive way of doing this to be to have a template for each language, but why would we not simply store the contents of the email as a string in our translation files and then use that dynamic value? Surely, that's the the optimal way to do this. No? That's That would have been the better way that I wanted to to get into now. Good. So the like, in the beginning, I meant, like, the most naive way just to prefix every, email template with, like, enus.template. Liquid or whatever and then called it in every single language. Like, this is the most naive way that I could think of. But, as you might have guessed, by me emphasizing naive is it's very naive. It's not good because we have a very, very nice, crowd and integration for all of our translations for the app. So it would be very cool if we, instead of making every single template, store the languages directly, we would store like you suggested now, we would store every string inside that we want to translate very similar to our app translations. So we everybody from the community can what what's the what's the Crowded. Everybody can profit off of the, yeah, of the community's breadth and and width. Like, we have people coming from everywhere, every language. So it would be nice if we can do that. It's also for anyone that does not know this, head on over to no. I haven't. Oh, I have I have actually, Locales. What what we're doing? Locales dot directors. Yeah. Yes. If in case anybody did not know this, you can head over to locales.directors.io, and you'll see our app translations. You can contribute, can add your own. Take a look. Yeah. This would be a better solution to the email problem. So we can, automatically generate and pull in those, from user contributions. That would be very nice. But there is something, you know, digging below the surface. That'd be fine for system emails. Like, for system emails, that's totally fine. Just use these. But scratching one level below the surface is the ability to act is to use translation strings maybe in custom templates. That's the one level on because I feel like the solution to make email tran make email templates translatable is fine for system emails. Like, that we have an approach. We have a you know, we have something. We just need to not hard code the values in English. But there's more than that, I suppose. So I think that was one of the comments that was in the one of these tickets already. I think that was in here somewhere. Somebody mentioned that using the translation strings. I think it was the right somewhere along the way. But that is an option. Right? So to me, either something like this. Right? So you can do this yourself with flows for for anything non system email, whether we do the system emails in the translation strings here or whether it's in the actual crowd in files, because it's a system email, you could technically actually have that in all of the languages. I guess, technical question, how do I know what language to send the email in? So when I'm using a user invite, I guess, you set the language for the user, the default language for the user. Is that how you would manage that? Yeah. For invites, I think it's a special case because you don't know the person. You could, under specific circumstances, not know what the person is speaking technically. But, like, for other system emails, we have the user. It's they are already registered, so you can just pick the language from the user or the default language of the instance. But for invites, I think we should fall back to the, default language of the instance Yeah. But also provide the opportunity to set a specific language inside of the, pop up. Yeah. Yeah. Exactly. Exactly. Yeah. We'd add we'd add language here as well. Right? So not just the you know, you'd choose choose your role or whatever you're inviting this user to, but also have a language and set it to the default for the project as the initial. If If they wanna change it, they can choose from one of the languages. And, therefore, those things exist in the crowd inside, but that's part of the you don't have to do any translations inside the app for that. That's not a dynamic kind of thing necessarily. Although, if I'm overriding, then I still want. So that's something that we have to think about as well. Right? So where does this get managed, and how does this get managed? Crowdin is awesome for system, but the reality is I may want to customize the actual liquid tablet for this. And as soon as I do that, I'm now I now fall back outside of how do I manage the translations. You know what would be really cool actually is if in settings, there was a a section called email templates, and our default ones were there and not deletable, and you could create new ones, and then use the built in director's translation interface to enable that. Like, that feels like a really nice flexible way to also potentially stop people needing to build their own liquid templates, like, as separate files and then load them into a directory. For many use cases, just being a just having a WYSIWYG with, well, a WYSIWYG would be plenty. Maybe with, like, a yield or, you know So it it's this. This is fundamentally what you need is a subject and a body. That's all you really have to have for email. For the text, put this in as a, you know I I think again, the the trouble with making it a system side is I I also kind of want content users to be able to do this. So I'd I'd want my marketing teams or my whoever's to be able to manage the content in these. So in a sense, it would be a system user table, possibly, that would show up that you could make accessible to the content side. You could optionally make it as accessible maybe. We don't really we don't really do that with anything today. We don't we don't create anything here other than the languages table gets created if you haven't created it yet, for translations interface. I I question that notion to a degree, though, because if you look at things like creating and editing flows, you can make exactly the same argument there. You wanna expose flows to more people in your organization, and we don't do that. I don't see why like, I think that that would be a bigger conversation about what is exposed versus what isn't and to what degree. So I I would be at peace with the idea that that is an admin setting, but I do get it. It feels a little more editorial perhaps. Okay. That's a separate discussion then, really, I think. So one of because this actually came up this week. Somebody noted that if I make you know, I I'd like to be able to make some role editing capabilities accessible to a user, but not give them data model access or flow access or other things. So potentially being able to enable subsets of the settings for non admin users. So that's a separate discussion. But I do agree. I think email templates would be really awesome in here, so that I don't have to create liquid files or other things behind the scenes. And you don't have access to the directory on professional cloud. That's the other big thing in my mind is, like, to really be a solution that works anywhere Directus is is hosted. It can't rely on dropping files in a persistent directory. It needs to be accessible via the data studio. Some action in the chat. I envision being able to create custom email templates and sending it to a mailing service, specifically something something from directors. Could be separate thing, but would be good if it wasn't limited to settings page and flexible enough to support this. The reality is, though, if I do want my own email templates, I could still create the user stuff for that, and I could mimic whatever was in the system. So, hopefully, over time, maybe there's additional system emails or things that we want for the platform. So we'd wanna be able to have those, and they could be manageable in the setting side if you wanted to replicate. Because Flows already supports, you know, grabbing things, you know, pull your variables, pull your data, pull your content. So, again, in this, like, agent c OS here, we have flows for, you know, sending the email. Right? So when you send the email, we're actually getting data from the trigger hooks and creates and posts and whatever, so we can pull in data from wherever. Right? So if there's data in a template or places that we wanna get it, we could do that. We can grab that ahead of the email. Could you, show the drop down link? Sorry. Could you show the drop down again where it was marked down? What was the other option is attempt just in send email here. The other option is WYSIWYG or a template. Interesting. Because still in my mind, like, to be really flexible, you want templates to be able to have exactly data that is popped in there. So, yeah, I don't see why why you couldn't be authoring those indirectors. You know? I I think we should. I I think it would be awesome because having to go to liquid templates and have to have custom extension deployment capabilities or access to the server. Yeah. Not ideal. Right? So again, part of what I think this overall system flows discussion was about, in general. So moving away from the the simple thing that Raich put in here, this was a little bit more of handling this with some system flows and setups and management, being able to manage this from the front end as opposed to back end. So making it data driven. Right? The the things we enable for everyone else, let's enable this for ourselves and make this data driven. I love it. Yeah. I I really want to go into that, issue as well, the system flows for, for the system actions. But, first, I wanna finish the other, message from the chat that was with the mailing service. Like, I'm not sure if I understand correctly because, like, this should be possible, right, with just the environment variables. You just define which SMTP server you want to use as an email service so you can actually connect to something else. And if you override the template, that is doing what you just said. Or maybe maybe am I missing something? Maybe the ability to send them to custom places per run. Like, there's a few it depends what level of flexibility or abstraction you want to build in, but at its core, that's what happens with the email service In flows, at least. In flows? I don't play with it much, but I don't think you get to choose your mail service here. Right? No. No. But you configure that for the project. And then when emails are sent using this, that's how they get sent. But they get sent with 1 service, not multiple services. Right? Single services. I'm not I'm not sure I see I mean, maybe I'm missing it, but I'm not sure I see the value in being able to set set up multiple. I don't even think you can. I'm not sure you can. It'll be in config options. I mean, technically, because, like, most email services have specific rest APIs that you can just call. So you can probably just set up a webhook event Use a web. Operation thingy. Yep. Send over the the specific payload, and then the email service should take over. So, yeah, technically, should be doable. Nice. But I think we're single email service Yeah. On the scenes or Yes. And I I don't actually know. Hello. The hello. Hello. Hello, Duff. We could should talk because I also built my wedding website with, with Directus and built a set of automations around that. So how funny is that? I wrote a whole blog post about this. It's one of the earliest blog posts on the developer blog. If you wanna go take a look in our docs. Yeah. That's fun. Gosh. Nerds really do like to overcomplicate weddings. Then don't they slash we. Developers are as bad as some of our I mean, I have to deal with complicating things. Right? That's amazing. Yeah. That's so funny. Why should I spend 15 minutes to do the thing that I need to do when I could spend 3 hours to automate the thing. Oh, no. No. It was good. We used it for I mean, a quick aside, but I will explain. So weddings have, like, quite a lot of variability to them. So we had if you consider a ticket. Right? A ticket. Right? An RSVP. So the first thing is you don't generally send, a ticket per person. You'll send it a group and the group will RSVP for individuals and they might not RSVP the same way, then we, at least, our ceremony could only hold like 80 people, but our reception had like 200 people at it. So, we had variable ticket types and then some ticket types allowed a plus one, some didn't, so all this variability. So backing that with data was really useful. So you had people, then you had invites of multiple people, and then you had RSVPs against the invite. And then we also used it for comms, so like blasting out emails or texts to everyone. That's how we did it. And we also used it to manage the shopping list as, because we DIY'd the wedding as people RSVP. So that's that's why it needed hours and hours and hours of, of time. Just like Benny said, you just have to get married a couple times, then the effort was totally worse. I mean, I'm never doing that again. One time was enough. So, yeah, I think it's it's regarding the This is year 30 for us. Oh, damn. Nice. My partner's been a long time. Congratulations. So, Alright. Let's summarize a little bit because we have, you know, 2 issues. So the first one with the general email translatability is not that complex in itself, but should be doable also. And with Kevin's mentioned, like, translation strings, if we could use those, that would be very cool, very nice. With for the system emails, if we could reuse the crowd in, stuff or, like, the static hosting of the string so we can reuse, you know, services and stuff, that would also be very nice. And now I think like, if nobody has anything else regarding that Could I just add could I could I add a question? Very interesting. Which is simply Sure. Of course. Can you not use translation strings in custom templates and custom liquid templates today? It feels like you should be able to. No. You can't. Okay. Fine. I don't think you can. That's not what I know of. No. No. No. I I defer to you. I've not tried to do it. I made an assumption that it was supported. So, yeah, good to know. As far as I know, like, the the only thing that you can do in there is, like, use data that's get passed in, you know, with the keys. So, you could do that with flows. Right? Like, if you would send if you could fetch some data or decide in a flow, like, what that specific e will hold. So, like, for an English user, it will hold hello, and for a German user, it would say, like, or something. Then you could reuse the same key, and it works, you know, for multiple languages. But you can't actually use the language thingies, the other thingies. Oh, yeah. And and another nice point from Tim. What about right to left languages? Oh, they don't exist. We're gonna forget about right to left lang I mean, sure. But, you know, that that is a nuance in an implementation, I think. I think don't you set it on the HTML attributes? So you would just set it in the email. I mean, it it look. I'm I'm really not sure because I don't speak or read languages that go from right to left. But more but more than anything, we need to think about that. Yeah. Like like a button, like like a, verification button or something. Should it also be on the other side, for example, in the email template? So, like, not only text, but also, like, buttons. Do the does the language affect those as well? I think so. Right? I think my my very limp with pleading complete ignorance here, I'm pretty sure basically whole UIs flip accordingly. But, yes, I think Tim Tim makes a good point though in that it would not simply be a translation string, but you would intrinsically need to know is this email a right to left or left to right email. And, you know, change the I think I genuinely think it's just an attribute in the HTML tag, but, you know, change that accordingly. Yeah. But but in the HTML tag, for example, like, it would need to with, like, c s like, CSS in emails is always very tricky. Like, it's very nitpicky. Something works in an email client, something doesn't, and that's, like, super archaic. If if anybody had to deal with this, I'm sorry for you. We support some right to left languages though. Right? Like, in the data studio. I believe so. I have never used them, to be honest. So please don't look at me for further info in the context. Given given that the default language collection gets created with We do. We do. Yep. Definitely. So if you look, we have Arabic Yeah. For 1. So if you scroll where's my language Uh-oh. I don't know what Don't lose the button. I'm good enough navigating around. Worst case, I have DirecTV access to this guy. Fix it. But it's all good. So you get your Arabic. So we do have the translations for it. It's individual strings, though. Yeah. Yeah. Exactly. Exactly. As Tim said here in the chat, I'm not convinced this is a true right to left implementation for languages. It likely will do, but will do is not necessarily the best or optimal. But in any case, that's just worth noticing too. Would the reality actually be that this this should flip over here in the right to left? Like, the module bar, like, the whole screen would, like, invert? Oh, that makes my head hurt. I I am not sure that's correct. So I I feel the need to add, I believe, the 3 of us here, plus Tim and the child Oh, Benny said, yes. Okay. Someone had a degree of confidence because I was like, if we've not done it, we don't know and there are degrees of implementation. Right? But, at the very least, consider the way people read left to right in terms of priority and flow. They would wanna be flipped. Yeah. But we also have to keep in mind that, Benny is from Australia, so his layout is also different. His navigation is on the bottom, and everything appears on the top. It's flipped. You know what would be so funny if, yeah, everything was upside down or, like, even subtle things like like the the spinner stand in the other direction like the toilet water. Yeah. Oh, that would be good. Alrighty. I think I think that's for for now, enough about emails because the other issues are also very interesting, and I think we should we should look into them. Definitely. So sounds like we have a couple of solutions to think through on how we'd wanna implement this. I was looking, Kevin, with regards to your question. It does look like if you use a custom template, so so my custom template so if you have a custom liquid template, you can define variables inside that template. So first name, you then pass that as data from a flow. Now this is flow implementation of that template. But, technically Yeah. I mean, technically, being able to and it being in any way optimal. There's a very, very wide chasm between the 2, and I think this is up on one end. Right? Yeah. So once again, what you would do is you would have a body and a subject here that you were looking up from that translation user side content translation. So you'd have a user table with a translations interface, that has your subject and your body and just simply translate the whole thing. You could variabilize or anything that you wanted inside that template itself. Flows would have to handle these, you know, use a run script. I did something like this recently for page templates. So defining a page template, content gets built in the user tables, and then when the user's ready to say, you know, for my my location page template, generate the location page, substitute in. I've got a flow that looks for those variables, substitutes them in, generates the page instance for that location, and I'm standing for that. So you could do those kinds of things. But again, it's a lot of work upfront, for the developers and the, you know, the administrators. So Yeah. Figuring out a way to make this I think, again, the system making it accessible via the admin in some way, shape, or form, I think is the ideal solution. Like it. Agreed. Cool. And check. Alright. System flows. What do you wanna talk about there, mister Daniel? Oh, this this one is very cool. This is very interesting. It's, the idea and I'm I'm I I'm always very in favor of dogfooding, like, our application. So if we could use like, integrate flows deeper into our app itself, it would, like, in a way, force us to actually improve flows a little bit for ourselves. And so we got it's not I mean, really like them. I know. We we we talked about flows 2.0 a little while back. Right? But yes. Go ahead. Yeah. And, yeah. So this one is pretty interesting. So, the idea is that you replace our current, like, internal behavior of, like, what even happens if somebody presses, forgot password. You know, like like, for example, maybe I would like to send a couple emails. I would like to send one email to the to the admin and say, like, oh, warning. This user has, requested a password request or something, you know, just as a random example. You can also do, like, more product updates. Record above and beyond what's in the system already. Maybe you've got soft compliance or ISO compliance things where you get that logged to a system somewhere. Yeah. That's not our app. Interesting. Exactly. So maybe you want to customize this. And, I think, I haven't read the entire issue yet, but I think the idea was just to start with, like, invites and password, resets. But we can expand on this a little bit. And, you know, like, depending on how we structure this, how the user experience is, like, how do you override that? We have to have a fallback. What happens in the UI? And and you're not allowed to delete the thing. What happens if somebody deletes the thing? You know, like, there's there's a couple things that can go wrong, but, technically, I think this is very exciting and a very smart idea. I I really like this. Clever. Well written too. Well defined. Well thought through. Linking to related concepts and tickets. David David Zacharias. Excellent. Excellent work. I love the Yeah. Read only read only flows. Must have read only flows AKA system flows. Additional which kinda makes sense here. You have system collections and you can extend system collections as well. So it could be that thing where it's like, hey, you know what? These first two steps or the first and last, you can't change those. You can either put stuff in the middle or stuff at the end, kind of like you can do with fields today in collections. So Mhmm. The core behavior stays exactly the same that you can tack on. I would be more inclined then to just have an event, though, that an event based hook can hook into. I don't know. No. That's a good point, actually. Because if you have read only flows and you have these new additional scopes, then they kind of negate the need for one another, I think. Now that that's a good point. Yeah. That is a good point. And our paradigm today is because, like, oh, let me based. Even if somebody wants to just break the flow, for example, maybe somebody doesn't want the, like, even the functionality to to be there. You know? Like, maybe you want to forbid actually password requests, like, reset requests. Yeah. Or you just want it to come to the internal team and never go back out to them automatically. Like, that is a a managed process. Yeah. Interesting. Yep. Yeah. Also Disabling your Reasonable to me. Disabling a password reset? Interesting. Yeah. I mean, for you know, it's it's always such a, you know, contrived example and stuff, but take like, there's so many different environments and and regulations and Get in touch with your system administrator. Managers and Your IT team or whatever. For example. Yeah. So I can definitely see the use case there. And and this is, like like, super interesting to me. The the the lowest Like, I have not thought about this. Neither have I. The lowest hanging fruit version of this is additional scopes that allow you to execute additional logic on top of the core logic for things like inviting and password resets. These I I almost feel like that is a separate thing, which is smaller and much easier to to implement. Pop that to the side. The system flows is is diff is the thing here. I just find that in that addition interesting. Yep. Nope. And so, again, it was extensible, you know, in the sense of it'd be nice to have the translation capability, but also, again, move. We're gonna touch some of these things, potentially moving some of that logic to where it's more accessible or modifiable. Oh, to modify the business logic, users can duplicate the flow and adapt to their needs. The system flow would then be inactive, but could be activated anytime to restore the default functionality. That UX, for me, does not feel good, but it is an interesting way to think about it. Yeah. I I think Well, the system side scope in the event yeah. If you can just, like, have a filter hook, and that would do the thing. Like, you can then cancel. Like, if you throw, the hook will be canceled, and then the email won't be sent out. And if you just pass it through, the normal behavior will take place, which is just sending an email. Right? Like, and you can do stuff in between. Yeah. I feel like this would be a way better solution than having, like, read only flows and copying and then, you know, fallbacks and something is missing and whatever. Like, maybe just And the And the critical thing is it matches the paradigms we have today. We have event based, event based triggers, and then we have actions and filters which run before or after the the operation happens, the the database operation happens. And yeah. So that feels that feels kinda better to me. And, yeah, you can always find a way to break it out of completing. And if you're if it's blocking, then the end part never happens. Yeah. Oh, this is cool. If somebody could work on this, that would be nice. This is pretty cool. Well, that's why we're reviewing so we can Could we determine, does it make sense and what additional things do we need to think through. Right? Can we split this into 2 feature requests? Because that core nugget we've discussed is feeling very viable. Also, it feels like not a huge lift. And it is not system. It is not system flows. It is the introduction of new events, and then system flows is is something in and of its own. Right. I suppose. But, like, if we have that event, like, do we even need system flows then? I I I would argue not. I I would argue not. But that isn't what this. It's hard because I don't feel inclined to change people's feature requests into the 10% one liner that they've introduced, in it. But that nugget can be dealt with in isolation. Yeah. Yeah. Saw that. Okay. So so that that's that's pretty neat. That would be nice. Yeah. Very cool. Yeah. Then okay. So for the events, then there would be a password request reset request. I always It's a reset it's a reset request and then a reset. Yeah. And a oh, oh, right. Those are 2 things. Okay. The the request and the actual reset. Maybe you want to act on that too. Okay. Those 2. The invite would be the 3rd. Oh, I'm hang on. So I can just tell you because I've just written this section of our new documentation. So there is invite request and invite accept. Right, actually creating a user off the back of an invite. Then there is, password reset request and password reset. And then there's a set maybe around SSO specifically, but maybe not. They are that out. And then if we're talking about if we're thinking about the whole breadth of kind of off, there is also 2fa on off. Like, they are the that is the set of kind of operations that exist beyond just logging in, locking out, logging out, refreshing. And since this week, there will be maybe coming then, register request and register request accepted, maybe? Yes. Something. Ah, and the email verification might also be interesting. Somebody might need that. I would sooner add a a a, you know, like, a bundle of new events and go, well, there's the bit the biggest degree of flexibility for That would be neat. Okay. Yeah. This this this sounds very exciting. This sounds actually very cool to me. Because we introduced to also new events for the content versioning. There was the promotion Promotion. Or promote or promotion, which is also useful. So this doesn't sound that far and unreasonable. This sounds very reasonable, actually. So, Jonathan, so while you're typing, there's a there's a couple more. So there is invite, and then there's invite accept. There's password reset request and password reset, And there is 2 FA on and off. And they are the only 2 in my mind that I'm not sure how what like, I'm not sure what the impact of adding those in particular are, but they are there as well. And then I don't I don't have enough knowledge around single sign on to be confident in in listing events around that. Cool. Yep. Yeah. Yeah. And, again, being able to extend being able to extend these would be really powerful. Right? Because if we've got a lot of clients that run us as a SaaS, we operate as a SaaS. There are system and service emails that, again, we do it through user templates and other things today, the way that we define and the way we've talked about. But making this kind of built in where you can create and manage your own system emails and service emails, would love it. Yeah. And the the thing is we already because we this only were basically, taking this feature request around or the other feature request rather, which is, oh, sorry. I see you're in this issue. Sorry. We're in the wrong one. Sorry. So emails that go out are not all of those. Sorry. Emails are just the, the yes. The password reset request and the invite. They are the only 2 system emails. Sorry. They are the auth events, though. Or the the potential auth you know, they are the points at which we could implement events. The fact that we already have filters and actions as blocking and non blocking, you know, code, you know, logic business logic means immediately you can effectively extend Directus' core functionality without needing to do anything else but expose these new events, which is really cool. Yes. Agreed. It's nice when you have a system that kind of already has the building blocks. Right? There's no new building blocks that need to be built for this one. Yes. Only the integration and making sure that we can actually, like, cancel, for example, like, what happens if if the thing canceled and stuff. But other than that, you're completely right. Yes. So just as a reminder for everybody else in the chat because there's still a couple people here, the show will be over very soon. So if you have any questions that you would like to ask, now is the time. Now is the time. Quiet group today. Nothing wrong with that at all. Alright. Yeah. Means maybe we did our job right. And and not right any other time. Yeah. That's really cool. I like the idea of system system flows. I, ultimately, like the idea of that, of exposing a set of functionality as flows in a UI that could be extended on the end. But I I, personally believe it's just simply unnecessary. It's just exposing the new events. And with actions and filters, it facilitates, I think, the goals of this. Yep. Yeah. Exactly. I fully agree. So people let your let your questions out in last minute. 1, 2. Yeah. If you have enjoyed this, or want to partake in the next one, you take a look in Discord in the events. You will see that we will be doing another episode on the 23rd May Yeah. Will be about configurable API errors. So errors are always very important. You might wanna let your voice be heard there. So please join in. Tune in if you like. And if you enjoyed this and want to revisit this or other episodes, head on over to directors.iotv. And, there will be lots of other shows as well, which are quite interesting and fun. So please check it out. Let's say it again, directors.io/tv. Yep. We hope you enjoyed. Oh, there's the link. Thank you. And all other episodes of request review bar the last one because I messed up the recording, you can find right there.","8fb596c2-af4e-4a21-b22b-b5da736ee51a",[209,210,211],"c7f329c8-1566-48d9-bdd5-5dbd9238c097","6c66580b-883c-4b84-9825-7111ec9dcd42","01c1e460-1c3b-49ee-84b0-b6366cbe81ad",[],{"reps":214},[215,271],{"name":216,"sdr":8,"link":217,"countries":218,"states":220},"John Daniels","https://meet.directus.io/meetings/john2144/john-contact-form-meeting",[219],"United States",[221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270],"Michigan","Indiana","Ohio","West Virginia","Kentucky","Virginia","Tennessee","North Carolina","South Carolina","Georgia","Florida","Alabama","Mississippi","New York","MI","IN","OH","WV","KY","VA","TN","NC","SC","GA","FL","AL","MS","NY","Connecticut","CT","Delaware","DE","Maine","ME","Maryland","MD","Massachusetts","MA","New Hampshire","NH","New Jersey","NJ","Pennsylvania","PA","Rhode Island","RI","Vermont","VT","Washington DC","DC",{"name":272,"link":273,"countries":274},"Michelle Riber","https://meetings.hubspot.com/mriber",[275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,252,463,464],"Albania","ALB","Algeria","DZA","Andorra","AND","Angola","AGO","Austria","AUT","Belgium","BEL","Benin","BEN","Bosnia and Herzegovina","BIH","Botswana","BWA","Bulgaria","BGR","Burkina Faso","BFA","Burundi","BDI","Cameroon","CMR","Cape Verde","CPV","Central African Republic","CAF","Chad","TCD","Comoros","COM","Côte d'Ivoire","CIV","Croatia","HRV","Czech Republic","CZE","Democratic Republic of Congo","COD","Denmark","DNK","Djibouti","DJI","Egypt","EGY","Equatorial Guinea","GNQ","Eritrea","ERI","Estonia","EST","Eswatini","SWZ","Ethiopia","ETH","Finland","FIN","France","FRA","Gabon","GAB","Gambia","GMB","Ghana","GHA","Greece","GRC","Guinea","GIN","Guinea-Bissau","GNB","Hungary","HUN","Iceland","ISL","Ireland","IRL","Italy","ITA","Kenya","KEN","Latvia","LVA","Lesotho","LSO","Liberia","LBR","Libya","LBY","Liechtenstein","LIE","Lithuania","LTU","Luxembourg","LUX","Madagascar","MDG","Malawi","MWI","Mali","MLI","Malta","MLT","Mauritania","MRT","Mauritius","MUS","Moldova","MDA","Monaco","MCO","Montenegro","MNE","Morocco","MAR","Mozambique","MOZ","Namibia","NAM","Niger","NER","Nigeria","NGA","North Macedonia","MKD","Norway","NOR","Poland","POL","Portugal","PRT","Republic of Congo","COG","Romania","ROU","Rwanda","RWA","San Marino","SMR","São Tomé and Príncipe","STP","Senegal","SEN","Serbia","SRB","Seychelles","SYC","Sierra Leone","SLE","Slovakia","SVK","Slovenia","SVN","Somalia","SOM","South Africa","ZAF","South Sudan","SSD","Spain","ESP","Sudan","SDN","Sweden","SWE","Tanzania","TZA","Togo","TGO","Tunisia","TUN","Uganda","UGA","United Kingdom","GBR","Vatican City","VAT","Zambia","ZMB","Zimbabwe","ZWE","UK","Germany","Netherlands","Switzerland","CH","NL",1773850445319]