WordPress Images

WordPress Media Library Folders: Why There Are None, and What Actually Works

WordPress stores every upload as a post, not as a file in a folder, which is why the media library has no directories to organise. Here is what the uploads folder really is, why moving files by hand breaks images everywhere, and how taxonomy-based folders solve it without touching the disk.

WordPress Media Library Folders: Why There Are None, and What Actually Works

A client hands over a site with 4,200 items in the media library. Somewhere in there are the eleven product photos you need. You open Media, scroll, and give up after two screens of hero images, favicons and a decade of blog thumbnails.

The obvious fix is folders. Put the product photos in a folder called Products. WordPress does not offer this, has never offered it, and the reason is not neglect.

There are two separate questions hiding inside “can I have folders”. One is about directories on the server. The other is about how the library is arranged inside wp-admin. Most of the confusion in this topic comes from treating those as the same question. They are not, and the answers are different.

Table showing where each part of a WordPress attachment lives, from the wp_posts row to the file path and sub-size metadata, and what breaks if each is changed by hand

What an attachment actually is

Every upload creates a row in wp_posts with post_type set to attachment and post_status set to inherit. Core registers that post type in create_initial_post_types() with 'hierarchical' => false and support for only title, author and comments. There is no parent directory field, because there is no directory concept in a post table.

The fields you fill in on the attachment details panel map onto ordinary post columns. Title is post_title, caption is post_excerpt, description is post_content. Alt text is the odd one out: it lives in postmeta under _wp_attachment_image_alt, which matters later.

The file itself is referenced by a single meta value, _wp_attached_file, holding a path relative to the uploads base directory, such as 2025/03/oak-dining-table.jpg. Every URL you ever see for that image is rebuilt from that string. get_attached_file() prepends wp_get_upload_dir()['basedir'] to it, and wp_get_attachment_url() does the same with the base URL. The generated sizes live in a second meta value, _wp_attachment_metadata, whose file key holds that same relative path while each entry under sizes stores a bare filename, resolved against the directory of the original. If you want the full picture of how one upload becomes eight or more files, that is covered in how WordPress turns a single upload into a set of sized files.

Nothing in that record says what the image is for. The only location data is a path, and the path describes where the bytes sit, not what the picture belongs to.

The uploads folder is a date structure, not an organisation system

The wp-content/uploads/2025/03/ layout comes from one option, uploads_use_yearmonth_folders, which a fresh install sets to 1 in populate_options(). It is exposed as a single checkbox at Settings, Media, labelled “Organize my uploads into month- and year-based folders”. wp_upload_dir() reads that option and builds a subdirectory of /$y/$m, nothing more.

There is a detail here that surprises people. The year and month are not always today’s. When you upload into an existing post, media_handle_upload() uses that post’s post_date as the timestamp instead, so an image dragged into a post published in 2019 lands in uploads/2019/. Core skips this backdating when the parent is a page, and the REST attachments controller repeats the same rule, so the block editor behaves identically. That is core working as designed, and it is one more reason the disk layout tells you nothing useful about your content.

Turning the checkbox off does not give you control. It gives you a single flat wp-content/uploads directory holding every file the site has ever had, which on a busy site means tens of thousands of entries in one directory and a slower time for anything that lists it. The date structure exists precisely to stop that.

You can change where files are written through the upload_dir filter, which receives the path, url, subdir, basedir and baseurl values as an array. That is how plugins put uploads into per-user or per-post-type directories. Two honest caveats. The filter runs on every call to wp_upload_dir(), not only during an upload, so a rule that fires unconditionally will also change how existing files are resolved, which is its own way of breaking things. And even done carefully, you have written a rule, not built an interface. Nobody in wp-admin will see a folder tree because of it.

Moving files by hand is the one thing that genuinely breaks

This is the single most damaging idea in this whole topic. Somebody connects over SFTP, sees a mess of month folders, creates uploads/products/, drags the images in, and every one of them dies.

The database never noticed. _wp_attached_file still says 2025/03/oak-dining-table.jpg, so wp_get_attachment_url() still builds a URL pointing at a file that is no longer there. The generated sizes go with it, because wp_calculate_image_srcset() resolves each size’s bare filename against the directory of the original, so the thumbnails and every entry in the srcset attribute break in the same instant. If you want the mechanics of how those srcset entries are assembled, see how WordPress builds srcset and why images look soft on dense screens.

It gets worse than the attachment record. Image blocks store the literal URL in post_content, so those are now pointing at nothing either, and attachment_url_to_postid() looks for an exact match on the stored _wp_attached_file value, so nothing can map the new URL back to the attachment.

Moving a single file correctly means moving the original and every generated size, updating _wp_attached_file, updating the file key inside _wp_attachment_metadata, and rewriting every stored URL in post content, widgets, options and theme mods. WordPress core does none of that for you, and there is no admin screen that offers to. If you want to see what the database currently believes about a given image before you touch anything, WP-CLI will tell you.

wp post meta get 1234 _wp_attached_file
wp post meta get 1234 _wp_attachment_metadata

The practical rule: treat wp-content/uploads as machine-owned storage. Read it, back it up, never rearrange it.

Step by step diagram of how tidying the WordPress uploads folder over FTP leaves the database pointing at old paths and breaks every derived image size

What core actually gives you instead

There are four real mechanisms, and each is worth knowing for what it is not as much as for what it is.

post_parent records which post an upload came in through. media_handle_upload() sets it, and the block editor sends the current post ID as a post parameter to the REST attachments endpoint, which assigns it there too. That is the “Uploaded to” column in list mode, and the “Unattached” filter is nothing more than a query for post_parent = 0. It is useful for tracing where a file came from. It is useless as organisation, because a file has exactly one parent, that parent is whichever post you happened to upload through, and an image used on ten pages still shows one. Anything uploaded through Media, Add New has a parent of zero forever.

The date dropdown, rendered by months_dropdown(), filters by upload month. It answers “what did I add in June”, which is occasionally the right question and usually not.

The title, caption, description and alt fields are free text you control. Core fills the title in for you: media_handle_upload() takes the uploaded filename, strips the extension, runs it through sanitize_text_field() and stores that as post_title. For images it will prefer an embedded EXIF or IPTC title if the file carries one, and pull the caption and alt from that metadata too, but most files coming off a phone or a camera carry nothing usable. Upload IMG_4471.JPG and the title of that attachment is IMG_4471. That is the whole reason so many libraries are unsearchable.

Search is the mechanism people actually use, and it is better than its reputation. WP_Query searches post_title, post_excerpt and post_content, and it hard-restricts the search columns to exactly those three: even the post_search_columns filter is intersected back against that list. For attachments, core adds one more thing. When a search term is present, wp_edit_attachments_query_vars() for list mode, wp_ajax_query_attachments() for the media modal and the REST attachments controller each switch on the wp_allow_query_attachment_by_filename filter, which is off by default. That joins wp_postmeta on _wp_attached_file and adds the stored path to the search. So media search covers title, caption, description and filename. It does not cover alt text, because alt lives in meta and meta is not one of those three columns. Alt text is still worth writing properly, for the reasons in writing alt text people can actually use, but do not expect it to help you find anything.

How media folder plugins really work

Essentially every plugin that adds folders to the media library implements them as a custom taxonomy registered for the attachment post type. A “folder” is a term in wp_terms, and putting an image in it writes one row into wp_term_relationships. Core even has a dedicated helper, get_taxonomies_for_attachments(), for discovering them.

The consequences are all good ones. Files never move, so _wp_attached_file stays valid and nothing breaks. The organisation lives in the database, so it survives a migration to a host with a completely different directory path, and it travels with an export. Rename a folder and no image is touched.

Core cooperates more than you would expect. The media list table renders any attachment taxonomy as a column when it is registered with show_admin_column, and links each term to upload.php?taxonomy=...&term=.... The admin menu adds a term management screen under Media for any attachment taxonomy with show_ui and show_in_menu. And wp_ajax_query_attachments() explicitly allows a registered taxonomy’s query var through to WP_Query, which is how a plugin’s folder sidebar filters the grid without core knowing anything about folders.

WunderPaint’s media library manager implements folders and tags as real WordPress taxonomies with drag and drop, so what gets written is the same term relationships described here.

Now the honest limitation. Term relationships are many-to-many. Nothing in the data model stops an attachment from carrying five folder terms at once. Exclusivity is a rule the plugin’s interface chooses to enforce, not a property of the storage. “Move to folder” is really “remove term A, add term B”, and when that logic is missing, or a bulk operation goes sideways, or a second plugin writes terms of its own, an image sits in two folders and shows up twice. If exclusive folders matter to you, test it: put an image in one folder, then drag it to another, then check whether the first folder still lists it.

The second consequence is a pleasant one. Deactivate the plugin and the folders vanish from the screen while the terms stay in the database, untouched. The images are exactly where they always were. Reactivate and the structure comes back. Compare that with the failure mode of any approach that moves files.

A basic version you can write yourself

If you want to understand what you are buying, build the skeleton first. One call to register_taxonomy() against the attachment post type gives you real folders in the database. This belongs in a small plugin or your child theme’s functions file, and if you are unsure where that is, where custom code belongs and how to edit it safely covers it.

add_action( 'init', 'wpie_register_media_folders' );

function wpie_register_media_folders() {
	register_taxonomy(
		'media_folder',
		'attachment',
		array(
			'labels'                => array(
				'name'          => 'Media Folders',
				'singular_name' => 'Media Folder',
				'menu_name'     => 'Folders',
				'all_items'     => 'All Folders',
				'edit_item'     => 'Edit Folder',
				'add_new_item'  => 'Add New Folder',
				'search_items'  => 'Search Folders',
			),
			'hierarchical'          => true,
			'public'                => true,
			'publicly_queryable'    => false,
			'show_ui'               => true,
			'show_admin_column'     => true,
			'show_in_nav_menus'     => false,
			'show_in_rest'          => true,
			'rewrite'               => false,
			// Attachments carry the 'inherit' status, and the default counter
			// only counts one when its parent post is published. Without this,
			// every folder holding unattached images reports zero.
			'update_count_callback' => '_update_generic_term_count',
		)
	);
}

Two of those arguments are doing quiet work. public stays true because get_attachment_fields_to_edit() skips any attachment taxonomy that is not both public and show_ui, so setting it false removes the field from the media modal entirely. publicly_queryable is false so you do not accidentally create front-end archive URLs for your internal filing system. WP_Taxonomy only strips the query var when the taxonomy is not publicly queryable and you are not in wp-admin, which is exactly what makes the filtered admin views keep working.

What you get for those thirty lines:

  • A Folders screen under Media for creating, renaming and nesting terms.
  • A checklist meta box on the full attachment edit screen, added by register_and_do_post_meta_boxes() like any other hierarchical taxonomy.
  • A Media Folders column in list mode, with each term linking to a filtered view of the library.
  • The taxonomy exposed in the REST API, so anything you build later can read and write it.

What you do not get: drag and drop, a folder tree beside the grid, or any filter control in grid mode at all. Grid mode is the default view, and it renders two dropdowns. One mixes the media types with All media items, Unattached and Mine. The other is the date filter. Neither knows your taxonomy exists. In the media modal, your folder appears as a plain text field holding a comma-separated list of term slugs, because that is how get_attachment_fields_to_edit() renders attachment taxonomies. It works. It is not pretty.

List mode you can improve cheaply. The media list table fires restrict_manage_posts, so a dropdown is one function away.

add_action( 'restrict_manage_posts', 'wpie_media_folder_filter' );

function wpie_media_folder_filter( $post_type ) {
	if ( 'attachment' !== $post_type ) {
		return;
	}

	$selected = isset( $_GET['media_folder'] )
		? sanitize_text_field( wp_unslash( $_GET['media_folder'] ) )
		: '0';

	wp_dropdown_categories(
		array(
			'taxonomy'        => 'media_folder',
			'name'            => 'media_folder',
			'id'              => 'media_folder_filter',
			'value_field'     => 'slug',
			'show_option_all' => 'All folders',
			'hierarchical'    => true,
			'hide_empty'      => false,
			'selected'        => $selected,
		)
	);
}

The submitted value is a term slug. upload.php hands the whole query string to WP_Query, and parse_tax_query() picks up the taxonomy’s query var and turns it into a slug-based tax query. The admin column links take a slightly different route, the generic taxonomy and term pair, but both end up as the same kind of query. This only applies to list mode, since grid mode never renders the control, but for a working library it is often enough.

Folders and tags answer different questions

A folder answers “where does this belong”, and the useful version of that question has exactly one answer. A tag answers “what is this about”, and that question has as many answers as you like. Confusing the two produces a folder tree with sixty leaves and nothing in most of them.

The structure that survives is a small number of folders that match how the site is actually built. Products. Team. Blog. Brand assets. Client supplied. Five or six, one level deep, maybe two where a genuine split exists. Then tags for everything else, applied generously, because terms are additive and an extra tag costs nothing: hero, transparent-background, needs-replacing, autumn-2025, photographer-name.

Deep hierarchies get abandoned for a reason worth stating plainly. The cost of filing is paid at upload time, by whoever is uploading, and the benefit is collected later, often by somebody else. Most uploads happen inside the post editor, in the media modal, in the middle of writing, where the folder interface is either absent or one click further than anyone will go. So the file lands in the default bucket. A structure that is only correct when every person remembers to be careful is not a structure, it is a hope. Two levels is the practical ceiling for most sites, and one level is fine for a lot of them.

Comparison of folders and tags for a WordPress media library, showing which question each answers and where each one stops working

Naming is what pays off regardless

Folders help you browse. Names are what let you find. And since search covers the filename, the title, the caption and the description, a well-named file is findable on any WordPress site, with any plugin set, in five years, after two migrations.

Know what sanitize_file_name() does to your name on the way in. It removes accents, strips a defined list of special characters including brackets, quotes, ampersands, parentheses and percent signs, collapses runs of spaces, tabs and hyphens into a single hyphen, and trims stray dots, hyphens and underscores from the ends. So Oak Dining Table (Front).jpg arrives as Oak-Dining-Table-Front.jpg. Note that core does not lowercase the name: wp_unique_filename() only lowercases the extension. Lowercasing is your habit to keep, not something WordPress does for you. Since the title is derived from that same original filename, one good name seeds two searchable fields at once.

Two things to avoid. Do not put dimensions in the name, because WordPress appends its own -1024x683 style suffixes to generated sizes and you end up reading product-800x600-1024x768.jpg. In fact wp_unique_filename() deliberately forces a number onto any uploaded name ending in a -000x000, -scaled or -rotated pattern, to keep it from colliding with a generated file. And do not rely on uniqueness across the library: wp_unique_filename() only checks the target directory, so logo.png uploaded in March and again in January sits happily in two month folders under the same name, with nothing anywhere recording that they are the same picture. That is one of the ways duplicate bloat accumulates, along with the others covered in cleaning up a WordPress media library.

A convention that holds up: subject, then variant, then context. oak-dining-table-walnut-front.jpg. team-priya-nair-headshot.jpg. logo-white-transparent.png. Boring, lowercase, hyphenated, no dates unless the date is the identity of the thing.

Since naming is the part that pays off, it is worth deciding the scheme once and then holding to it.

The builder below assembles one from the pieces you actually need, project, area, subject, date, sequence, and shows what a name will look like as you go. Then paste in the names you already have and it tells you which ones do not fit, what they would be called under the scheme, and which pairs would collide once WordPress has sanitised them. It also recognises the suffixes core adds itself, so nobody renames a generated size by accident.

Media naming scheme

WordPress has no folders for media, so the file name and a taxonomy are the only order there is. Build a naming scheme here, then check your own file names against it. If you drop files on the box, only their names are read: nothing is opened, nothing is uploaded, nothing leaves this browser tab.

1. Build the scheme
Blocks, in order
Example name
acme-blog-kitchen-tap-2026-08-hero-01.jpg

41 characters

The scheme in one line
acme-{area}-{topic}-YYYY-MM-{purpose}-NN.jpg
  • WordPress runs every upload through sanitize_file_name. It strips ? [ ] / \ = < > : ; , ' " & $ # * ( ) | ~ ` ! { } % +, turns runs of spaces and hyphens into a single hyphen, and trims dots, hyphens and underscores off both ends.
  • It folds accents through remove_accents, and the table it uses depends on the site language. On an English installation Küche.jpg is stored as Kuche.jpg and Straße Foto.JPG as Strase-Foto.JPG. On a German one the same two become Kueche.jpg and Strasse-Foto.JPG. Set the language above to match your site, because it decides which names collide.
  • A middle extension that WordPress does not allow gets an underscore, so photo.php.jpg is stored as photo.php_.jpg. That is a security rule, not a typo.
  • Case is kept, but Linux servers treat Foto.jpg and foto.jpg as two different files while Windows and macOS do not. Lower case only is the setting that never surprises anyone.
  • WordPress adds its own endings after the name: -1200x800 for each registered size, -scaled, -rotated, and -1, -2 when a name is taken. They are not part of your scheme and must never be renamed by hand.
WordPress stores it as
2. Check your own names
Or drop files here
Drop files here
or press Enter to pick some. Only the names are taken, the files themselves stay on your disk.
Nothing checked yet
NameVerdictSuggested name

Nothing is renamed for you. WordPress keeps the file name in the database and in every size it has already made, so renaming an uploaded file by hand breaks the links to it. Use the list for the files you have not uploaded yet, and for a fresh library.

Team rules, the second file in the download

  
3. What works instead of folders
  • A taxonomy on attachments. An attachment is a post type, so it can carry terms like any post. One flat taxonomy with ten to twenty terms covers what people actually look for. It gives you a column in the list view and a filter through the URL, for example upload.php?media_topic=kitchen.
  • Know what the media search reads. It searches the title, the caption, the description and the file name. It does not search the alt text, which lives in post meta, and it does not search your taxonomy terms. A term you can only filter by is worth less than a word you can search for.
  • So use the caption and the description as search fields. Put the words your team would type into the description when you upload: the room, the client, the campaign. That is the one field the search reads and nobody ever fills in.
  • A folder plugin moves nothing. Almost all of them register a taxonomy and draw a tree over it. The files stay in uploads/2026/08, which is the good news: removing the plugin breaks no URL and loses no file. It loses the tree, because the tree was only terms. Check that the plugin uses a real taxonomy before you sort ten thousand files into it.
  • The name still carries the load. Search, backups, the browser download folder and every export see the file name and nothing else. That is why the scheme above comes first and the taxonomy second.
A taxonomy for attachments, ready to paste into a small plugin
<?php
add_action( 'init', function () {
    register_taxonomy( 'media_topic', 'attachment', array(
        'label'             => 'Topics',
        'hierarchical'      => false,
        'public'            => false,
        'show_ui'           => true,
        'show_admin_column' => true,
        'show_in_rest'      => true,
        'rewrite'           => false,
    ) );
} );
Put it in a small plugin, not in the theme, so the terms survive a theme change.
WunderPaint
The Dynamic Design and Automation Studio
WunderPaint is a layered image editor for your WordPress media library. WunderPaint Studio is the same thing in any browser, free and without an account.

When this stops being optional

There is no magic file count, but there is a mechanic. Grid mode requests attachments in batches of 80 and appends more as you scroll. List mode shows 20 per page unless you change it, from the upload_per_page user option. Browsing works while the thing you want is in the first batch. Past that, you are searching, and searching only works if the text is good.

Which means the real threshold is not how many files you have, it is how many of them look alike at thumbnail size. Three thousand obviously different photographs are easier to work with than eighty product shots of similar objects on white. If your library is visually distinctive, you can go a long way on scrolling and a decent filename. If it is repetitive, the pain starts at a few hundred.

Three other triggers are worth watching for, independent of size. More than one person uploading, because two naming habits produce no naming habit. A site you will hand to a client, because the person inheriting it has none of your context. And any library where the same asset exists in several crops or versions, because that is exactly the case where a filename alone stops disambiguating.

Symptom and cause

Images disappeared after you tidied the uploads folder over FTP. The database still holds the old relative path in _wp_attached_file, and every URL is rebuilt from it. Put the files back exactly where they were and everything returns, which is why you never delete the original directories until you have checked.

The folders vanished when you deactivated the plugin, but the images are fine. The folders were terms in a custom taxonomy. Deactivating removed the interface, not the data. The relationships are still sitting in wp_term_relationships waiting for something to read them.

Media search finds nothing, even though you wrote careful alt text. Search covers title, caption, description and the stored file path. Alt text lives under the _wp_attachment_image_alt meta key, and WP_Query restricts its search columns to post_title, post_excerpt and post_content.

Everything says Unattached. post_parent is zero, which is normal for anything uploaded through Media, Add New rather than from inside a post. It is not a warning, and it says nothing at all about whether the image is used somewhere.

An image shows up in two folders at once. Term relationships are many-to-many, so the plugin’s “move” either failed to remove the old term or was never exclusive to begin with. Check the attachment’s terms directly before blaming the interface.

Where that leaves you

The absence of folders is a consequence of the data model, not an oversight somebody forgot to fix. Attachments are posts, and posts do not live in directories. Anything that looks like a folder in wp-admin is a term in your database applied to a post, and that is exactly why it is safe to use and safe to remove.

If you install a folder plugin, you are adopting a taxonomy somebody else designed. That is a perfectly good decision. Just know what you are getting: portable, non-destructive, reversible, and only as exclusive as the plugin’s interface chooses to make it. Test the move behaviour on day one rather than discovering it on day two hundred.

And if you do nothing else, name files before you upload them. It takes three seconds, it survives every plugin change, every theme change and every migration, and it feeds the one retrieval tool that is always present. Folders make a library browsable. Names make it findable, and findable is the thing you actually needed.

WordPress Media Library Folders: Why There Are None, and What Actually Works

Table of Contents

Learn it by building something

Every week one thing you can make the same afternoon, from dynamic templates to 3D type. Written down step by step.

One mail a week, and then it ends.
Unsubscribe in one click.

WordPress Development

Dynamic Templates: Build the Design Once, Let Your Posts Fill It In

You build the layout once, tell a few layers where to get their content, and from then on every post, product or page renders its own version.

WordPress Development

Why Should a Design Become a File at All?

Every static graphic on a page is a snapshot of what was true when somebody exported it. There is a whole category of quiet wrongness that follows from that.

WordPress Images

WordPress SVG Upload: Why It Is Blocked and How to Fix It

WordPress refuses SVG uploads out of the box, and the snippet everyone pastes works on some servers and not on others. Here is the vector case for wanting one, the exact core check that rejects it, and the sizing bug you inherit once the upload finally succeeds.

WordPress Development

WordPress Child Themes: When You Need One and When You Don’t

A child theme is the right answer to one problem: overriding template files in a theme that still receives updates. For CSS tweaks and a few PHP snippets, it is overhead you maintain forever for no benefit.

Troubleshooting

HTTP Error When Uploading Images to WordPress: The Real Causes

The red bar reading HTTP error is not a verdict on your image. It is the uploader reporting that the POST to async-upload.php came back unusable, and six unrelated failures produce exactly that. Here is how to tell them apart in about ten seconds.

WordPress Images

Working Out the Image Size Your Theme Actually Wants

A slot measured in CSS pixels needs a file measured in image pixels, and on a Retina screen the second number is twice the first. Here is how to measure the slot, choose a ratio without losing half the photograph, and check that WordPress will actually generate the size you need.

Download the free WunderPaint Plugin for WordPress

The WunderPaint workspace with the layers panel, adjustment sliders, text style presets and the asset library along the bottom

The Image Editor & Design Studio

Everything described here can be done in the browser, on your own site. The live demo runs the full editor with nothing to install.

Free

Chaos Art

Autonomous painters make one-of-a-kind abstract art in 3D space - gestures, art movements, painterly media, and embeds that paint a new original for every visitor.

Pro

Particle Strokes

Paint with swarms of light: twenty-two movements, a stamp you draw yourself, and curves that give a stroke a shape - the swarm keeps painting for a few seconds after you let go.

Pro

City Diorama

Any place on earth as a miniature you could hold: real streets, water and building footprints raised into a 3D diorama - or wrapped around a sphere as your own tiny planet.

Free

Papercut Art

Layered paper pictures with real depth - a photo sliced along its actual depth into up to twenty layers, parametric landscapes, animals and clouds you can shape, letters with real counters, and a look that runs on three dials.

Pro

3D Earth Studio

A hyperrealistic globe - day and night with city lights, live clouds, atmosphere halo, country borders and highlights, click-to-place markers with flight-route arcs, satellite orbits, seamless rotation video and a live website embed.

Free

Mystic Studio

Turn a birth date into wall art - a real natal chart with houses and aspects, the moon of that night, zodiac and Chinese zodiac posters, numerology cards and a synastry wheel for two, in eight artful themes.

Free

Marble Bath

Marble paper on a virtual water bath - drop, rake and comb real Ebru patterns with gestures, flowers and classic recipes, razor-sharp at any size and re-editable as a layer.

Free

Day Ring

Turn a day into a beautiful circular schedule - colour-coded time blocks as arcs around a 24-hour clock, with concentric rings for overlaps, emoji, templates and a legend.

Free

Code Shot

Turn code into a gorgeous, share-ready image - syntax highlighting, editor themes, window frames and diff highlighting - then drop it into your design as a re-editable layer.

Pro

3D Solar System Studio

Build a date-accurate 3D solar system - real planet positions for any date, photoreal textures and one slider from artistic to true scale - then drop it into your design as an editable layer.

Pro

3D Molecule Studio

Build a real 3D molecule - from a curated library, the periodic table or a SMILES string - then style it, measure it and drop it into your design as an editable layer.

Pro

3D Textile Studio

Drop your design onto cloth that behaves like the material you pick: silk falls soft, felt holds its shape, flag fabric snaps in the wind. Hang it, blow it and drape it, then lay the finished drape back into your document as a picture.

Pro

3D Particle Studio

Point the engine at any layer and it becomes a cloud of particles that keeps its colours, flowing through a sphere, a galaxy or your own outline. Keep the frame you like as a still, or embed the running engine so it keeps moving on your page.

Free

Origami

Put your own picture on the paper and watch that very sheet fold itself into a crane or a box. Every step is a station you can stop at and turn around in 3D, which is exactly where printed diagrams leave you alone.

Pro

3D Flip Studio

A hardcover you can leaf through, a limp magazine, a strewn pile of sheets, a sticker peeling off its backing. The curl is real geometry, so the print never slides across the paper.

Free

Handwriting Fonts

Draw the alphabet here or fill in a printed sheet and photograph it. What comes out is a genuine font family, installed into your site and available in every picker.

Pro

Step Guides

Turn any picture into an instruction. Every mark is pinned to a place in the image, so arrows still point at the right thing after the callout has been dragged somewhere else.

Free

Text Art

One studio, sixteen art types: ASCII and emoji art, brick, dice, cube, sticky-note, LED, ceramic and keycap mosaics, word portraits, text flows, silhouettes, element tiles and more.