23 January 2023by Jack McGregor
Payload is great but sometimes it can be difficult to visualize your app in all its multi-user glory when you have to keep populating everything by hand. Fortunately, we can leverage Payload's awesome constructor and models, along with the new-and-improved FakerJS to create rich linked documents that will help you to hit the ground running!
For this demo, we're going to create Users, Posts & Pages with Media, and some Tags and Categories for our sprinkles. You can obviously use what models you want, you maverick.
So let's start with the configuration. The gist here is that we initialize an instance of Payload using a separate seed script. This script will use the same Collections, database and config as our actual app but will have a start and finish. For this reason, we will declare our seed directory outside of our src directory, so we will need a slightly different tsconfig.seed.js file
So we have our tsconfig, our script (note how similar it is to the normal dev script), now we need the entry point file:
If you were to now run yarn seed it wouldn't do much other than initialize the payload config and then shut down. To do actual seeding, I'm going to use a class as I love their abilities to store and share state in a simple object.
For educational purposes I've stripped out the logic for now and just left the method names so you can get a high-level view of the logic we'll be writing. But in case you can't be arsed to read the code, the script will seed the information in the following order:
- Media (because we want our other collections to have media objects)
- Users (Admins & Editors)
- Pages (requires Users and Media)
- Categories
- Tags
- Posts (requires Media, Users, Categories and Tags)
You'll also notice that after the class we do two things:
- We wrap the class in a function that initializes, drops previous data, seeds and then shuts down
- We call that function in a promise chain. This part isn't strictly necessary but it helps with debugging and keeping it clean
Hopefully it's not too much and you can see where we're going.
Media
Let's start with our media. Not going to lie, I over complicated this one enormously when I first tried this, then I spent longer than I would care to admit trying to get it to store media on Amazon's S3 buckets. I'm not going to go into details on how to do that in here though. Sorry. The trick is, however, to use S3
So we have our Media Collection, let's import it into our seed file and hook it up, but before we do this you will need to create a local file for the images you wish to use.
I've done this within seed/media, so will look a bit like this:
- seed/
- media/
- pic-1.jpg
- pic-2.jpg
- etc
Now, after running your script, you should see the logs and if everything is set up properly then you will see your images appear in your Amazon S3 Bucket and their reference IDs in your database in the Media collection.
As a bonus, why not try modelling, creating and storing different types of media like gifs, documents, videos and music? It's a good exercise to practice what you've learned.
Users
Every app needs users, both administrative (provided by Payload) and business-use (created by us). Here's a simple User Collection; yours will probably look much different
Once we have a User, we'll create our SuperAdmin user first; this just makes it easier for us to go into the app to check our progress
You can probably see where this is going, but its where we first get to use Faker!
When we run the script, we use the default user values (2 admin and 10 editors) to create 2 admins & 10 editors with fake names, emails, passwords (that we can actually use to log in as them), but also a Super Admin who's details stay the same and you can grant any executive privileges to should you choose to.
Pages
We now have Media and Users, so we can start making content. We'll start with the simpler Collection, Pages.
See the simple Page Collection below:
Pretty simple. The Media field will save the image itself in our bucket but the ID in Mongo and reference it in this collection.
However, since we want to generate Rich Text to mimic the Rich Text Editor with which I'm writing this post, we need to replicate its structure.
We could create another method within the class to handle this but we might as well utilize inheritance.
In this example, I've created two more classes:
- SeedHelper
- Generic helpers eg. shuffle
- Will be inherited by our Seed class
- Will in turn inherit...
- RichTextHelper
- Will create structures like headers, paragraphs, lists etc
In a nutshell, we randomly generate arrays of Rich Text blocks in order (headers then lists then paragraphs etc) and then shuffle the array at the end using another helper method defined in the helper class.
Once you have your helpers, you can create the main methods. Each Page needs and author which we grab randomly from `this.users`
Also important to note that the way the methods are configured you can consistently create the same pages every time (eg About, Contact, Clients, whatever), as well as random ones. This is useful if you have both static pages and dynamic pages.
Excellent! Running your script now should drop then populate Media, Users and Pages with relations to each other.
Categories and Tags
Since these are very simple I'm going to write them up together. Basically, we want to include these for our Post documents.
In my example, a Category would be more general, like Development, Testing or Deployment, whereas a Tag would be more specific, like AWS, Payload, Docker, Typescript or Jest. Again, just an example. Go crazy.
Cool. Now for the seeding method. I chose to create the same tags each time but you're under no obligation to do that. Fill your boots with Faker data!
Run your script to check it works. If it does, awesome. If not then put on your debugger hat. This post doesn't have comments. Sorry
Posts
Finally onto the main event: creating a Post that utilizes our Media, Users, Categories and Tags!
Here's our Collection:
And our method:
And there you have it!
A very rough seed file with 5 related collections, Media in S3, Rich Text maker and Faker and a smidge of inheritance. No doubt some people will look at this with horror but who cares - its just a rough guide to help you with the general direction. Hope you enjoyed it!
Playwright ID scraper31 January 2023Rendering languages in code blocks17 January 2023Creating dynamic test IDs for Jest and Playwright17 January 2023