diff --git a/web/.storybook/stories-category-doc-pages/Images.stories.mdx b/web/.storybook/stories-category-doc-pages/Images.stories.mdx
new file mode 100644
index 000000000..42d843033
--- /dev/null
+++ b/web/.storybook/stories-category-doc-pages/Images.stories.mdx
@@ -0,0 +1,16 @@
+import { Canvas, Meta, Story } from '@storybook/addon-docs';
+import { Image, ImageRow } from './ImageAsset';
+
+
+
+# Images
+
+
+
diff --git a/web/.storybook/stories-category-doc-pages/SocialPlatformImages.stories.mdx b/web/.storybook/stories-category-doc-pages/SocialPlatformImages.stories.mdx
new file mode 100644
index 000000000..7758aff36
--- /dev/null
+++ b/web/.storybook/stories-category-doc-pages/SocialPlatformImages.stories.mdx
@@ -0,0 +1,41 @@
+import { Canvas, Meta, Story } from '@storybook/addon-docs';
+import { Image, ImageRow } from './ImageAsset';
+
+
+
+# Social Platform Images
+
+
+
diff --git a/web/.storybook/tools/Images.stories.mdx b/web/.storybook/tools/Images.stories.mdx
new file mode 100644
index 000000000..3d6391169
--- /dev/null
+++ b/web/.storybook/tools/Images.stories.mdx
@@ -0,0 +1,12 @@
+import { Canvas, Meta, Story } from '@storybook/addon-docs';
+import { Image, ImageRow } from './ImageAsset';
+
+
+
+# {{capitalize title}}
+
+
diff --git a/web/.storybook/tools/generate-image-story.mjs b/web/.storybook/tools/generate-image-story.mjs
new file mode 100644
index 000000000..3ae81b945
--- /dev/null
+++ b/web/.storybook/tools/generate-image-story.mjs
@@ -0,0 +1,35 @@
+import fs from 'fs';
+import path, { resolve } from 'path';
+
+import { readdirSync, lstatSync } from 'fs';
+import handlebars from 'handlebars';
+
+handlebars.registerHelper('capitalize', function (str) {
+ return str.charAt(0).toUpperCase() + str.slice(1);
+});
+
+const args = process.argv;
+const dir = args[2];
+const title = args[3];
+if (args.length < 4) {
+ console.error('Usage: generate-image-story.mjs
');
+ process.exit(1);
+}
+
+const relativeDir = path.relative('../../public/', dir);
+
+const images = readdirSync(dir)
+ .map(img => {
+ const resolvedPath = path.resolve(dir, img);
+ if (lstatSync(resolvedPath).isDirectory()) {
+ return;
+ }
+
+ return { name: img, src: `${relativeDir}/${img}` };
+ })
+ .filter(Boolean);
+
+const template = fs.readFileSync('./Images.stories.mdx', 'utf8');
+let t = handlebars.compile(template);
+let output = t({ images, title });
+console.log(output);
diff --git a/web/.storybook/tools/generate-stories.sh b/web/.storybook/tools/generate-stories.sh
index 67dbfded2..7b363502a 100755
--- a/web/.storybook/tools/generate-stories.sh
+++ b/web/.storybook/tools/generate-stories.sh
@@ -8,3 +8,8 @@ node generate-emoji-story.mjs >../stories-category-doc-pages/Emoji.stories.mdx
# Pull down the doc about development
curl -s https://raw.githubusercontent.com/owncast/owncast.github.io/master/content/development.md >/tmp/development.md
node generate-document-stories.mjs
+
+# Project image assets
+
+node generate-image-story.mjs ../../public/img/ Images >../stories-category-doc-pages/Images.stories.mdx
+node generate-image-story.mjs ../../public/img/platformlogos/ "Social Platform Images" >../stories-category-doc-pages/SocialPlatformImages.stories.mdx