Jump to content

Search the Community

Showing results for 'video'.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • Welcome to ProcessWire
    • News & Announcements
    • Showcase
    • Wishlist & Roadmap
  • Community Support
    • Getting Started
    • Tutorials
    • FAQs
    • General Support
    • API & Templates
    • Modules/Plugins
    • Themes and Profiles
    • Multi-Language Support
    • Security
    • Jobs
  • Off Topic
    • Pub
    • Dev Talk

Product Groups

  • Form Builder
  • ProFields
  • ProCache
  • ProMailer
  • Login Register Pro
  • ProDrafts
  • ListerPro
  • ProDevTools
  • Likes
  • Custom Development

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


AIM


MSN


Website URL


ICQ


Yahoo


Jabber


Skype


Location


Interests

  1. For all who are interested in this module: I have been a tester in the past and this module is excellent. I am using it now in every project at it makes asset handling (not only images but think of pdf, mp3, video, etc.) a breeze. This module acts as a missing link for global media management in ProcessWire.
  2. Iโ€™ve been using `TextformatterVideoEmbed` for YouTube/Vimeo embeds and made a small local patch that seems generally useful for generated iframe output. The change adds two attributes to generated iframe embeds when they are not already present: ```html loading="lazy" referrerpolicy="strict-origin-when-cross-origin" ``` This is independent of any consent/privacy module. It simply improves the default iframe markup produced by `TextformatterVideoEmbed`. The intended behavior is: - add `loading="lazy"` to iframe embeds by default - add `referrerpolicy="strict-origin-when-cross-origin"` by default - do not override either attribute if it already exists in the iframe markup - keep existing embed behavior unchanged otherwise Example implementation pattern: ```php if(stripos($embedCode, ' loading=') === false) { $embedCode = preg_replace('/<iframe\b/i', '<iframe loading="lazy"', $embedCode, 1); } if(stripos($embedCode, ' referrerpolicy=') === false) { $embedCode = preg_replace('/<iframe\b/i', '<iframe referrerpolicy="strict-origin-when-cross-origin"', $embedCode, 1); } ``` Reasoning: - Native iframe lazy loading is now widely supported and helps avoid loading off-screen video embeds unnecessarily. - `strict-origin-when-cross-origin` is also the modern browser default in many contexts, but making it explicit gives generated third-party embeds a safer baseline. - The change is low risk because it only applies to iframe markup and skips attributes already present. Would this be suitable as a small PR to the module? If preferred, it could also be exposed as module config options rather than hardcoded defaults.
  3. Thanks, @millipedia. I used Audio Embed Textformatter in the past, in another site, together with Video Embed and so on (pdf, etc.). But it would be much simpler and more elegant to use a universal "insert media..." in TinyMCE. As a last resource, while I wait for a uniform solution, I'm using a Hanna code to embed the audio without forcing the person who is editing to deal with code. But I'm not completely satisfied with this partial solution, I confess.
  4. With all of the advancements in AI, and other technologies not slowing down, it's getting even harder to feel like I'm staying relevant. Add to that the pressure to exercise and stay fit, work outside or around the home, and to be sure to retain some amount of leisure... How do you all do it? I see my gaming buddy logging hours of a video game. He works in defensive cybersecurity, so he makes quite a bit and is on-call. Thankfully for him, he works remote (I do not). But he has a family with tweeny triplets (!). He's just this past week mentioned ripping up carpet, last week he ran a trench to run electrical for a man-made pond he's installed with boulders that he moved by hand. Meanwhile I want to learn about n8n, take some AI courses (someone mentioned faster.dev here in the forums), work on personal (dev) projects, but also get things done around the house, and make sure to spend time with the girlfriend and make sure she's happy. I have not figured out a good time management scenario to balance these all out: House/property work. Friends and family time. Leisure time. Exerciise Paid work (job / income). Professional improvement and advancement. What are your tricks, or boundaries, to set time aside for each of these? Are you struggling like I am to properly afford time to each thing and not allow them to thoroughly overtake another's time commitment? Looking for revelations that some of you may have had during your careers or lifetimes to help you sort these things out! ๐Ÿ™ƒ
  5. Hi Ryan, I'll do my best to explain this, but keep in mind my experience with queues / background jobs is only 2 years old. But in short, inspiration would be best taken from the classic, "batteries included" big web application frameworks like Laravel (as Teppo pointed out) and Rails. I like the Laravel page I linked because it gets very in-depth (I've read that page at least 10 times). Let's use a classic example like this: Let's say someone wants to upload a video to a field and we want it to be converted to a different file format (let's say that's being handled by ffmpeg). That's a time intensive task that wouldn't be able to be done within a standard max limit 30 second web request, or even with the memory available to php via php-fpm. It might take minutes or even hours, and even then, things can go wrong and it might fail. So, instead we'd want this to happen independent of the web request, therefore a background job dedicated to that task would have to be made and scheduled to be processed. It could happen immediately, or maybe it can be scheduled for 30 minutes later. This is not related to cron jobs which are a different concept. (Another example is for example in an ecommerce checkout; it's generally better practice to send the order notification email as a background job instead of inline with the code that processes the order after it's submitted). With that, queue systems are typically powered by a different dedicated database or system, with Redis being a popular choice. The reason for this is to limit load on the primary database; many large systems may have millions of jobs per day so offloading that to a separate database saves resources. However the big web application frameworks I mentioned also allow the option for the main database itself to store the jobs (Rails enabled this in Nov 2024), which is typically fast enough and probably good enough for a ProcessWire-based solution. You then have workers which act on the jobs. You can define there to be one or multiple workers. Let's say you have a powerful server and want to transcode multiple videos at a time, then having multiple workers would allow more jobs to be done in parallel and take advantage of your system resources. Obviously you don't want a worker to act on a job more than once, or two different workers to act on the same job. So this gets into jobs have statuses, being locked, and avoiding race conditions. The Laravel documentation gets into all of that, but I think reading up on queues/background jobs/workers and experimenting with it would be tremendously helpful. In regards to my print-on-demand system, I'm not using a queue system as I described above and I did experiment with WireQueue and IftRunner a while ago, but it didn't really... fit? It was a while ago and I was still wrapping my head around queues; also I came to realize that what I needed was even deeper than that (ie, durable workflows, but that's unrelated to what we're talking about here). I eventually put something together that relies on "fake" jobs using cron jobs and progressing through a durable workflow; it's not the most efficient way to do it, but I got it working. I've been meaning to rewrite that part of the system one day and having a native / first-party queue system (which dovetails with the CLI commands), would be the best approach.
  6. Hi I think Analytics for MH would be really useful addition for power users. Some of you mentioned you mange thousands of images. Maybe with MH that might be less given the shared image concept. Iโ€™ll be starting shortly so if you have any requests, just add them here. Phase 1 will be an emphasis on data vs big dashboards etc. Metrics we could surfaceโ€ฆ # MediaHub Analytics โ€” Metric Ideas ## Asset Inventory & Volume - Total asset count (all time) - Asset count by type (image, video, document, audio, etc.) - Coloured storage usage bar by type (like the iCloud bar) - Total storage consumed, broken down by type - Average file size by type - Largest single assets (top 10) - Assets exceeding a defined file size threshold ## Usage & Engagement - Top 1 and top 9 most-used assets (by placement count) - Assets used on the most pages - Assets used more than once (vs. unique placements) - Most-used asset by type (e.g. most-used video) - Assets referenced in TinyMCE/rich text fields vs. structured fields - Pages with the most assets total - Pages with the most images specifically - Pages with the highest asset variety (mixed types) ## Waste & Orphan Detection - Unused assets (uploaded but placed nowhere) - Assets uploaded but never used in a TinyMCE field specifically - Assets that were used but the page/entry has since been deleted - Duplicate or near-duplicate filenames - Assets with no alt text or metadata ## Crops & Transforms - Images with the most crop variants - Images with crops defined but never rendered - Images with no crops defined at all - Most common crop ratios/dimensions used across the hub ## Age & Freshness - Recently added (last 7, 30, 90 days) - Oldest assets in the hub - Oldest assets that have never been used - Assets not updated or replaced in over X months - Upload velocity over time (assets added per week/month) ## Content Quality & Hygiene - Assets missing required metadata (title, alt text, caption, tags) - Images below recommended resolution for their usage context - Assets with broken or missing source files - Assets with no focal point set (if supported) - Untagged or uncategorised assets ## People & Process - Assets uploaded per user/author - Which users upload the most unused assets - Upload activity by day of week or time of day - Most active uploaders in the last 30 days ## Search & Filter Behaviour - Most searched terms (by frequency) - Most searched terms with zero results - Most used filters (type, date, tag, label, etc.) - Filter combinations used most often together - Searches that result in no action (user searches but doesnโ€™t select anything) - Most abandoned searches (searched, filtered, then left) ## Collections & Folders - Largest collections by asset count - Largest collections by total storage size - Most nested / deepest folder structures - Collections with the most unused assets inside them - Empty collections (created but never populated) - Collections that havenโ€™t been updated in over X months - Most viewed or accessed collections - Collections with assets shared across the most pages ## Labels (Library / Storage Organisation) - Asset count per label - Storage volume per label - Labels with the most unused assets - Labels with no assets assigned (orphan labels) - Most combined labels (which labels appear together most) - Unlabelled assets (no label assigned at all) ## Tags (Display / Website Facing) - Most used tags by asset count - Tags applied to assets that are never actually used on the website - Assets with the most tags applied - Untagged assets - Tags that are never searched or filtered by visitors - Tag overlap โ€” assets sharing the same tag cluster (useful for spotting redundancy) - Most used tag per asset type (e.g. most common image tag vs. video tag) ----- **Other high-value metrics for power users:** duplicate detection, metadata completeness scoring, upload velocity trends, and per-user waste ratios (whoโ€™s uploading assets that never get used). The type of useful info that might surface process problems rather than just content problems.
  7. @BitPoet Thank you for info ๐Ÿ™‚ I updated video
  8. The video uses the HEVC codec (h.265). Firefox on Windows doesn't support h.265 due to licensing issues. A workaround is to download the video and open it with whatever video viewer is associated with mp4 files.
  9. @Ivan Gretsky I don't know why but video is there and I can see ๐Ÿ™‚
  10. Iโ€™m worried about you, @ryan. You talk about Claude like a person. Pretty soon youโ€™ll be in your basement in your underwear, unshaven for weeks and your family is going to be wondering what happened to the family man they knew. And please donโ€™t accidentally call Claude Claudette because your wife will truly think something is going on with this newfound friend of yours. Hopefully we can rely on one weekly post from you. Just to let us know youโ€™re ok. But even then, how do we know Claude isnโ€™t writing for you. We may have to start doing weekly Zoom updates (yes, with video on!).
  11. Hi @Juergen Thank you very much, I updated the module but there are some issues. If I try to valid a form with a required field (InputFile) without filling it (and without calling setErrorMessageToField()): It's not happening with the previous version I was using (2.2.55). I'm trying the method to set an error on a given field, it's working but message text color is still green at top of form: Strange error management when submitting the form several times using setErrorMessageToField() (video to make it clear) : I fill the InputFile required field and an optional one. I submit. setErrorMessageToField() triggers the error. The InputFile required field has been emptied (was already the case in previous version, is it expected?). I submit again. Issues: the form is fully emptied. setErrorMessageToField() has no effect the second time. InputFile required field is empty but no error. (if I had filled it again, the 2 points above are still there) I also have a request, could you make the setErrorMessageToField() first parameter a string, so I can pass a field name? Or supporting both name and field reference if you prefer. Usually the form fields are created in a form class and are not stored as class members, it's why it's more convenient to use field names, like with getValue() method. Thank you. ๐Ÿ™‚
  12. This week I worked with Claude Code on refactoring the core WireHooks class to improve it in various ways. I do this work because I like to code, so am of course handling that part. But Claude has been very helpful in finding issues as well as reviewing all my code before it gets committed. In this case, Claude found several bugs that are now fixed, and also saved me from introducing more when I added new features. Working with Claude Code reminds me of 1989 when I was in high school learning Turbo Pascal and building a BBS, and getting help from a neighbor and good friend that was doing the same. I learned so much then and now it feels like that time again. But man have things come a long way since then. I asked Claude about helping with the ProcessWire issues and requests GitHub repos, and now it's solving issue reports, replying to them and committing fixes. For simple fixes that involve a line or two, I'm going to let it handle the the whole thing. It's posting under my GitHub account, but it identifies itself as Claude in replies and and in commits. That way it's easy to tell what it does under my account. I had it just cover a couple of issue reports today as a test (see 2195 and 2192), but will be having it do a lot more going forward. Back to the WireHooks class, I asked Claude about writing a commit message for the WireHooks updates, and wow, check this out: Bug fixes in WireHooks: - conditionalArgMatch(): Fix Selector mutation bug where the shared Selector object stored in hook options was permanently mutated after the first call, causing argMatch hooks (e.g. addHook('WireLog::save(=errors)')) to stop matching after their first invocation. - getHooks(): Remove key variable from foreach to prevent shadowing $method param. - getHooks(): Replace array_merge() in loops with direct array append. - addHook(): Prevent 'noAddHooks' option from leaking into stored hook options. - isHookedOrParents(): Use $className string consistently in cache key writes, rather than $class which may be a Wire object. - runHooks(): Scope $useHookReturnValue inside foreach so it resets per hook. - runHooks(): Use strict null comparison ($toObject === null). Bug fixes in HookEvent: - arguments(): Allow setting an argument value to null (use func_num_args() > 1 instead of $value !== null check). - arguments(): Use array_key_exists() instead of isset() for null-correct lookup. - getArgumentNames(): Guard ReflectionMethod instantiation with method_exists() to avoid uncaught ReflectionException for dynamically-added hook methods. - __toString(): Fix argument list building (was appending to string instead of array), add null/bool display, avoid PHP fatal for objects without __toString(). New features in WireHooks: - cancelHooks: Now accepts string values 'before' or 'after' (in addition to boolean true) to cancel only hooks of a given type. For example, a before hook can set $event->cancelHooks = 'after' to cancel remaining after hooks without affecting the hooked method call. - Custom event data carry-forward: Custom data set on a HookEvent (via $event->customKey = $value) is now carried forward to subsequent HookEvent instances within the same runHooks() call. This allows before hooks to pass data to after hooks without using external variables. - getHooks('*'): Supports wildcard method to return all hooks for all objects. Available in debug mode only (uses allStaticHooks/allLocalHooks aggregates). - allStaticHooks: Now tracked alongside allLocalHooks when debug mode is on. - addHooks() comment fix: "If there is a parenthesis" corrected to "no parenthesis". - addHook() exception messages improved with additional context. - runHooks() docblock updated to include 'either' type. - hookTimer() PHPDoc: @param String corrected to lowercase string. New features in HookEvent: - $defaults static property: Defines the canonical set of standard HookEvent fields, used to distinguish custom data from built-in event properties. - $eid property: Each HookEvent instance gets a unique sequential event ID. - set() override: Tracks non-default keys set on the event in $customKeys. - getCustomData(): Returns only the custom (non-default) data set on the event, used internally by runHooks() for the carry-forward feature. - cancelHooks property updated to support bool|string type. Anyway, I know a lot of you here are deep into the AI stuff, and I'm just getting started, so none of this is surprising. But it sure is a pleasure collaborating with Claude Code on this stuff and it brings back that coding wonder and excitement from 1989. Some Claude and Claude Code podcasts I've enjoyed listening to or watching this week include one from AI for Humans Claude is Cooking, Wednesday's AI Daily Brief on How to use Claude's new upgrades, and the Get Educated AI video of how to setup Claude to use your computer and web browser, etc. (though I've not tried this just yet!). Lastly, last week I put together a ProcessWire powered JSON feed of bike tours, and the client prompted that they wanted a map and look what Claude Code did, I'm impressed!
  13. Is Vimeo or a dedicated video host not an option?
  14. Iโ€™ve faced a lot of headache with video logistics too, especially when you have all sorts of different formats and sizes from clients who just want it to โ€œwork.โ€ Self-hosting was never smooth for me, and every time bitrate or compatibility issues popped up, it just ate up hours. I know some folks set up ffmpeg pipelines, but honestly, I like to keep things simple and user-friendly. Anything that automates the heavy-lifting or even provides presets for common exports makes my life easier, especially if less techy people are involved. Whatโ€™s helped in my personal workflow is relying on tools that streamline editing and automatic conversion, so I can focus on the content rather than the nitty-gritty of formats and uploads. Iโ€™ve been experimenting with movavi for this reason, it handles a lot of these basic headaches in a lightweight way and makes prepping files less technical for the rest of the team.
  15. The content owner of this video that I randomly chose from the YouTube homepage had marked this particular video content as not-embeddable, so the JSON response from the oembed provider of YouTube responded with "Unauthorized" which the Essence library doesn't really handle (it just returns nothingness, which in this case is kind of appropriate). Once I tracked that down, I tried another YouTube video URL and it worked as expected. ๐Ÿคฆ
  16. Hey all, MediaHub is ready! Thanks for the kind words and the questions about availability. I've been replying to a few people privately, but here's the latest.. It has been given a thorough kicking on my own site(s) and 2 client sites. I'm opening up a waitlist for those interested in purchasing early access. I want to limit it initially to the first 5-10-ish people. IE small batches so I can make sure the purchase and licensing flow works smoothly hear how the setup goes across different environments provide proper support to each person. If you're interested, DM me here. Early access members will get a discount on the first year of updates as a thank you for feedback. I'll post a walkthrough video here shortly, but the screenshots earlier in the thread should give you a pretty good picture of things. Cheers everyone, Peter
  17. Is anyone using this recently? I have had this installed as a "just in case" type of module, and when originally developing, it worked. In trying to audit my code for accessibility practices a little more thoroughly, this module is currently not working (and I unfortunately hadn't used it for any saved data embeds as of yet). I'm getting the error message of, "No oembed data or provider found," and no error logs seem to be generated in ProcessWire, and PHP deprecation notices for the essence library on the webserver logs (PHP 8.2). My test embed was a YouTube video as a simple check: https://www.youtube.com/watch?v=-cdrVNfngo0 Haven't yet tried to track down the issue, only just noticed and thought I'd ask other users first. ๐Ÿ™‚
  18. Hey guys. I'm looking to implement something a bit more tricky than the usual tags/authors/themes things we usually solve with the page selector. Imagine 3 sections: projects / news / videos. A item in any of these sections can be related to content from the others. What's bugging me is that there isn't one that's central, and relations should work both ways, so that when a video is added and related to a news item, that news item gets related back. I mean we can be adding a news article and there is already a related video, or we can be adding a video and relate it to a news article (or many). This presents challenges on where to centralise, how to collect relations on the frontend, and even how this is all managed by the admin. How can we do this and keep some sanity?
  19. I am sure many of you have seen @Ex-user's comments about AI data centres in the in the ProcessWire 3.0.257 โ€“ Core updates thread. It seems like we have lost them from the community, but I do think a Pub topic about the darker side of AI is worthwhile. I have watched the video that was posted and here is another one worth a watch. I must admit that Claude code is making me much more productive, so it's a strange situation to be in. I do worry about all of the environmental and human health concerns posted in that other video and all of the societal ones in this video and so I think it's important that we are at least aware of these things when we talk about AI in ProcessWire. Let's keep the dialog respectful and productive.
  20. @mattgs Like Adrian, I also consider myself very environmentally conscious. I've not spent much time learning AI in part because I thought it was problematic for a lot of reasons. But I don't think we're likely to stop these AI companies so that's why I thought I should try things out with a company that seems to have more ethics than the others. Anthropic seems to have a mission for AI safety and sustainability. I hope it's legit. And as far as I can tell, the other companies don't, which I find concerning. But I'm also not as up-to-speed as you are on the on the issues you brought up, so I'll have to look closer as well as check out the video you mentioned (do you have a link?). I'm also aware that a project like ProcessWire gets executed millions upon millions of times every month (or day?) throughout the world, and every execution consumes energy. So I've always been very interested in optimization and making ProcessWire use as little time and energy as possible to do its work. The updates that we've been focusing on here are aimed directly at that. So perhaps AI is using a little energy to find optimizations and bugs in PW, but that single brief code review session reduces the energy usage of every ProcessWire execution going forward. This is a case where AI is likely saving a lot more energy than it consumes, indirectly by making ProcessWire use less energy. Some of the optimizations and bugs its found have been there since the beginning, and likely would have never been identified otherwise.
  21. You do you. I completely disagree with your take on every level, and I can't possibly understand how you're able to square that circle about being environmetally conscious and using AI, which is burning energy, wasting water, driving hardware and energy prices, causing real physical harm (see Benn Jordan's video on datacenters) and not to mention, starting actual wars over precious resources. But I'm not going to argue about this. This community has moved in a direction where I have no longer a place in. And I for one can't in good conscience recommend or use a project I see as using unethical, harmful and environmentally and technically unsustainable practices anymore. Good luck and good-bye.
  22. It's good to see Cursor getting a bit of airtime and some mentions. Been using it since around 2024, and it's improving rapidly. The latest AI models too are impressive. It helps me with development, some UI design, SEO and pretty much is across 90% of my daily work these days apart from some design work. One of the best things about AI Agents is they can run in the cloud. So I'll often fire up a Cusror AI agent while I'm out for a walk or at the gym. I get home and the development work is ready for review and merge. I have yet to use Claude Code yet but I also see people speak highly of it. It's more terminal-based. Worth a look. Especially with Claude's new skills. Here's a good video from a Meta Engineer using CC.
  23. @bernhard thanks for sharing the video. And exciting journey you had there :-) Eventually this is where things are going, I guess. Would be great to know who in this community is working on similar stuff. I'm currently creating a collection of skills that can be plugged-in to PW projects here: https://github.com/gebeer/processwire-ai-docs Would love to collaborate with others on that and exchange ideas.
  24. It's a bit over a year since I started this post and it's crazy how far AI and cursor got! Huge shoutout to @gebeer who is my main source of wisdom when it comes to AI related stuff ๐Ÿ™‚ I wanted to share a video that I watched recently. It is quite lengthy, but I was looking for exactly that to make sure I don't miss any basics. For me it was eye opening, so I wanted to share it: My personal takeaways/learnings: I have thought for a long time that AI is great to read/understand/explain or help me find something in my codebase but for actual coding it's not very helpful most of the time (other than cursor tab, which is awesome!) You can run multiple agents in cursor at once, and you can run multiple models at once, which is crazy The better you setup your environment, the better the results (obviously...) AI can write all your RockPageBuilder blocks with RockMigrations code easily You can actually TALK to cursor in the chat, which is a lot quicker than typing. You can even TALK to it in german and it will translate it to english on the fly, which is crazy. This is just the beginning So the question for me was is it really worth the effort of setting up your environment so that AI does the work for you and then in the end you spend more time debugging than if you just went ahead and coded it from scratch? I'm not sure yet, and I asked that question today @gebeer. He said clearly yes, and my gut said I can imagine he is right, but I did not really experience it myself. Today that changed. I took some time to try a new workflow for a client request. Usually I would have added code by hand, as that's a lot quicker. Why? Because you either start prompting and get bad results or you have to invest a lot of time upfront. But I know how it feels to invest some time upfront and then have superpowers forever ๐Ÿ™‚ So I gave it a try and after a quick emergency rescue session with @gebeer I got very good results in actually very little time. And once I started to adopt that workflow it started to make sense more and more and I started to answer the question to myself: Is the effort worth it? Clear answer: YES So I want to encourage everyone to watch the video, try it out, ask for help if you hit any roadblocks. So why do I think it's worth it? Simple example: I asked AI to implement a new RockPageBuilder block. It did the backend for me quickly and easily. Then it did the frontend for me. The frontend needed more time and debugging, but I then added the uikit docs to my project and told cursor to add the docs to my cursor rules/skills/whatever (still confused, but cursor knows what to do). Then results seemed to get even better and it even fixed an issue in a way that I would have never thought of (because I didn't know this option was there). So I even learned something new. Finally I saw an issue in my .latte file, which is quite a common mistake: AI forgot to add |noescape to the {$page->headline} output, which made the headline "Foo & Bar" show up as "Foo &amp; Bar". I guess every latte user knows that problem ๐Ÿ™‚ The solution: Tell AI to fix the issue and to also add that info to the frontend-dev skill/rules. That means it will likely never make this mistake again! This is a really powerful approach. I'm quite impressed. And I think I'll need a more expensive subscription soon ^^ Which is one of the downsides. You have been warned! ๐Ÿ˜„๐Ÿ˜‰ PS: The initial setup is also quite easy. All I did is to talk to cursor: A bit messy instructions and lots of mistakes, but it doesn't matter as long as cursor understands you. I'm quite sure the results are not perfect, but from what I read in the instructions for the AI it's a quite good overview of the project! And it's something to build upon and grow ๐Ÿ™‚
ร—
ร—
  • Create New...