docs(showcase): add 74 new showcase sites (#8010)

This commit is contained in:
Sébastien Lorber 2022-08-31 14:28:02 +02:00 committed by GitHub
parent ab73d86cb4
commit 97c9710ce3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 674 additions and 12 deletions

View file

@ -7,6 +7,7 @@
import fs from 'fs-extra'; import fs from 'fs-extra';
import path from 'path'; import path from 'path';
import _ from 'lodash';
import imageSize from 'image-size'; import imageSize from 'image-size';
import {Joi} from '@docusaurus/utils-validation'; import {Joi} from '@docusaurus/utils-validation';
import {TagList, sortedUsers, type User} from '../users'; import {TagList, sortedUsers, type User} from '../users';
@ -62,6 +63,7 @@ describe('users data', () => {
// The preview should be jest/emptyModule // The preview should be jest/emptyModule
preview: Joi.object({default: Joi.any()}) preview: Joi.object({default: Joi.any()})
.unknown(false) .unknown(false)
.allow(null)
.required() .required()
.messages({ .messages({
'object.base': 'object.base':
@ -87,6 +89,65 @@ describe('users data', () => {
); );
} }
}); });
it('does not contain duplicates', () => {
function normalizeUrl(url: string | null) {
if (url === null) {
return null;
}
if (!url.endsWith('/')) {
return `${url}/`;
}
return url;
}
function duplicatesBy(mapper: (user: User) => string | null) {
const grouped: {[key: string]: User[]} = _.groupBy(sortedUsers, (user) =>
mapper(user),
);
return Object.fromEntries(
Object.entries(grouped).filter((entry) => entry[1].length > 1),
);
}
let duplicatesLog = '';
const duplicatesByTitle = duplicatesBy((user) =>
user.title.trim().toLowerCase(),
);
Object.entries(duplicatesByTitle).forEach(([title, users]) => {
duplicatesLog += `Showcase site title '${title}' is used ${users.length} times! Duplicates are not allowed!\n`;
});
const duplicatesByDescription = duplicatesBy((user) =>
user.description.trim().toLowerCase(),
);
Object.entries(duplicatesByDescription).forEach(([description, users]) => {
duplicatesLog += `Showcase site description '${description}' is used ${users.length} times! Duplicates are not allowed!\n`;
});
const duplicatesByWebsite = duplicatesBy((user) =>
normalizeUrl(user.website),
);
Object.entries(duplicatesByWebsite).forEach(([website, users]) => {
duplicatesLog += `Showcase site website url '${website}' is used ${users.length} times! Duplicates are not allowed!\n`;
});
const duplicatesBySource = duplicatesBy((user) =>
normalizeUrl(user.source),
);
Object.entries(duplicatesBySource).forEach(([source, users]) => {
// source is allowed to be null for multiple sites
// "null", see Lodash groupBy issue: https://github.com/lodash/lodash/issues/3060
if (source && source !== 'null') {
duplicatesLog += `Showcase site source url '${source}' is used ${users.length} times! Duplicates are not allowed!\n`;
}
});
if (duplicatesLog) {
throw new Error(duplicatesLog);
}
});
}); });
describe('preview images', () => { describe('preview images', () => {

View file

@ -100,8 +100,7 @@ const Users: User[] = [
'The best search experience for docs, integrates in minutes, for free', 'The best search experience for docs, integrates in minutes, for free',
preview: require('./showcase/algolia.png'), preview: require('./showcase/algolia.png'),
website: 'https://docsearch.algolia.com/', website: 'https://docsearch.algolia.com/',
source: source: 'https://github.com/algolia/docsearch/tree/main/packages/website',
'https://github.com/algolia/docsearch/tree/main/packages/website',
tags: ['favorite', 'opensource', 'product'], tags: ['favorite', 'opensource', 'product'],
}, },
{ {
@ -445,7 +444,8 @@ const Users: User[] = [
}, },
{ {
title: 'difranca | Tech-Notes', title: 'difranca | Tech-Notes',
description: 'This documentation aims to comprise my learning notes on various tech subjects.', description:
'This documentation aims to comprise my learning notes on various tech subjects.',
preview: require('./showcase/difranca-technotes.png'), preview: require('./showcase/difranca-technotes.png'),
website: 'https://difranca.github.io/', website: 'https://difranca.github.io/',
source: 'https://github.com/difranca/difranca.github.io', source: 'https://github.com/difranca/difranca.github.io',
@ -1185,8 +1185,7 @@ const Users: User[] = [
}, },
{ {
title: 'Mixcore CMS', title: 'Mixcore CMS',
description: description: 'Fully Open Source ASP.Net Core / Dotnet Core CMS UI Toolkit',
'Fully Open Source ASP.Net Core / Dotnet Core CMS UI Toolkit',
preview: require('./showcase/mixcore.png'), preview: require('./showcase/mixcore.png'),
website: 'https://docs.mixcore.org/', website: 'https://docs.mixcore.org/',
source: 'https://github.com/mixcore/docs/tree/master/website', source: 'https://github.com/mixcore/docs/tree/master/website',
@ -1833,7 +1832,7 @@ const Users: User[] = [
title: 'Resoto', title: 'Resoto',
description: description:
'Open-source cloud infrastructure management tool—find leaky resources, manage quota limits, detect drift, and clean up!', 'Open-source cloud infrastructure management tool—find leaky resources, manage quota limits, detect drift, and clean up!',
preview: require('./showcase/resoto.png'), preview: null,
website: 'https://resoto.com', website: 'https://resoto.com',
source: 'https://github.com/someengineering/resoto.com', source: 'https://github.com/someengineering/resoto.com',
tags: ['opensource', 'product', 'design'], tags: ['opensource', 'product', 'design'],
@ -2195,7 +2194,7 @@ const Users: User[] = [
preview: require('./showcase/tauri.png'), preview: require('./showcase/tauri.png'),
website: 'https://tauri.app/', website: 'https://tauri.app/',
source: 'https://github.com/tauri-apps/tauri-docs', source: 'https://github.com/tauri-apps/tauri-docs',
tags: ['opensource', 'i18n', 'product', 'design'] tags: ['opensource', 'i18n', 'product', 'design'],
}, },
{ {
title: 'TechHarvesting', title: 'TechHarvesting',
@ -2259,12 +2258,11 @@ const Users: User[] = [
}, },
{ {
title: 'Tremor', title: 'Tremor',
description: description: 'Tremor Event Processing Engine',
'Early-stage event processing system for unstructured data with structural pattern-matching, filtering and transformation',
preview: require('./showcase/tremor.png'), preview: require('./showcase/tremor.png'),
website: 'https://www.tremor.rs/', website: 'https://www.tremor.rs/',
source: 'https://github.com/tremor-rs/tremor-www', source: 'https://github.com/tremor-rs/tremor-www',
tags: ['opensource', 'versioning'], tags: ['opensource', 'versioning','large'],
}, },
{ {
title: 'TRPG Engine', title: 'TRPG Engine',
@ -2433,6 +2431,599 @@ const Users: User[] = [
source: 'https://github.com/7Wate/wiki', source: 'https://github.com/7Wate/wiki',
tags: ['opensource', 'personal'], tags: ['opensource', 'personal'],
}, },
{
title: 'Discord API Types',
description: 'Discord API Types',
preview: null,
website: 'https://discord-api-types.dev/',
source: 'https://github.com/discordjs/discord-api-types/tree/main/website',
tags: ['opensource', 'versioning', 'large'],
},
{
title: 'Hanabi',
description: 'A list of Hanabi card game strategies',
preview: null,
website: 'https://hanabi.github.io/',
source: 'https://github.com/hanabi/hanabi.github.io',
tags: ['opensource'],
},
{
title: 'IsaacScript',
description: 'Write Binding of Isaac: Repentance mods with TypeScript',
preview: null,
website: 'https://isaacscript.github.io/',
source: 'https://github.com/IsaacScript/isaacscript/tree/main/packages/docs',
tags: ['opensource'],
},
{
title: 'Jest Preview',
description: 'Debug your Jest tests. Effortlessly.',
preview: null,
website: 'https://www.jest-preview.com/',
source: 'https://github.com/nvh95/jest-preview/tree/main/website',
tags: ['opensource'],
},
{
title: 'Paweł Kosiec',
description: 'Personal website and blog of Paweł Kosiec, Full-stack Cloud Developer.',
preview: null,
website: 'https://kosiec.dev/',
source: 'https://github.com/pkosiec/website',
tags: ['opensource','personal'],
},
{
title: 'Homarr',
description: 'Homarr is a simple and lightweight homepage for your server.',
preview: null,
website: 'https://homarr.vercel.app/',
source: 'https://github.com/ajnart/homarr/tree/docs',
tags: ['opensource'],
},
{
title: 'Wings',
description: 'Wings is a modern website-as-service for progressive campaigns',
preview: null,
website: 'https://wings.dev/',
source: null,
tags: ['product','i18n'],
},
{
title: 'Kishan Gajera',
description: 'Personal portfolio and blog of Kishan Gajera',
preview: null,
website: 'https://www.kgajera.com/',
source: 'https://github.com/kgajera/blog',
tags: ['opensource','personal'],
},
{
title: 'Harvest CLI',
description: 'A CLI for Harvest\'s time tracking software',
preview: null,
website: 'https://kgajera.github.io/hrvst-cli/',
source: 'https://github.com/kgajera/hrvst-cli/tree/main/website',
tags: ['opensource'],
},
{
title: 'TSEI.JP',
description: 'TSEI.JP personal website, articles and docs',
preview: null,
website: 'https://tsei.jp/',
source: null,
tags: ['personal'],
},
{
title: 'Brobot',
description: 'Testable state-based GUI automation.',
preview: null,
website: 'https://jspinak.github.io/brobot/',
source: 'https://github.com/jspinak/brobot/tree/main/docs',
tags: ['opensource'],
},
{
title: 'Fathym Blog',
description: 'Fathym deploys, hosts and integrates your favorite tech stacks.',
preview: null,
website: 'https://www.fathym.com/blog',
source: 'https://github.com/lowcodeunit/public-web-blog',
tags: ['opensource'],
},
{
title: 'Tech Interview Handbook',
description: 'Free curated tech interview preparation materials for busy software engineers.',
preview: null,
website: 'https://www.techinterviewhandbook.org/',
source: 'https://github.com/yangshun/tech-interview-handbook',
tags: ['opensource','personal'],
},
{
title: 'Front End Interview Handbook',
description: 'Free curated tech interview preparation materials for busy software engineers',
preview: null,
website: 'https://www.frontendinterviewhandbook.com/',
source: 'https://github.com/yangshun/front-end-interview-handbook',
tags: ['opensource','personal'],
},
{
title: 'WIZnet',
description: 'Documentation for various WIZnet products',
preview: null,
website: 'https://docs.wiznet.io/',
source: 'https://github.com/Wiznet/document_framework',
tags: ['opensource','product'],
},
{
title: 'Xiaohai\'s Mind Palace',
description: 'A place for organizing notes, writing blogs, and showcasing projects.',
preview: null,
website: 'https://xiaohai.wiki/',
source: 'https://github.com/xiaohai-huang/learning-notes',
tags: ['opensource','personal'],
},
{
title: 'Cho.sh',
description: 'Sunghyun Sho\'s Second Brain on the Web.',
preview: null,
website: 'https://cho.sh/',
source: 'https://github.com/anaclumos/www',
tags: ['opensource','personal','i18n'],
},
{
title: 'i18n-tools',
description: 'CLI to make common operations around i18n files simpler',
preview: null,
website: 'https://jy95.github.io/i18n-tools/',
source: 'https://github.com/jy95/i18n-tools/tree/master/website',
tags: ['opensource'],
},
{
title: 'Pure.css',
description: 'A set of small, responsive CSS modules that you can use in every web project.',
preview: null,
website: 'https://purecss.io/',
source: 'https://github.com/pure-css/pure',
tags: ['opensource','design'],
},
{
title: 'Moodle Developer Resources',
description: 'Moodle - the world\'s open source learning platform',
preview: null,
website: 'https://moodledev.io/',
source: 'https://github.com/moodle/devdocs',
tags: ['opensource','product','large'],
},
{
title: 'Toggle',
description: 'Open Source real-time feature flags deployment without need of a server with SDK',
preview: null,
website: 'https://www.togglee.com/',
source: 'https://github.com/togglee/togglee-web',
tags: ['opensource','product'],
},
{
title: 'Barklarm',
description: 'Open Source multiplatform alarm and build status monitoring application',
preview: null,
website: 'https://www.barklarm.com/',
source: 'https://github.com/kanekotic/barklarm-website',
tags: ['opensource','product'],
},
{
title: 'Nikita\'s Everything I Know Wiki',
description: 'Digital wiki with notes/links.',
preview: null,
website: 'https://wiki.nikiv.dev/',
source: 'https://github.com/nikitavoloboev/knowledge',
tags: ['opensource','personal','large'],
},
{
title: 'Infinity Works Company Handbook',
description: 'An online company handbook, acting as a one-stop shop for all relevant information needed for colleagues.',
preview: null,
website: 'https://handbook.infinityworks.com/',
source: null,
tags: ['design'], // TODO need a tag for company's corporate websites?
},
{
title: 'Neo Blockchain Developer Portal',
description: 'A collection of tools and resources to help you build outstanding applications on Neo',
preview: null,
website: 'https://developers.neo.org/',
source: 'https://github.com/neo-project/neo-dev-portal',
tags: ['opensource'], // TODO create crypto/web3 tag?
},
{
title: 'Yew',
description: 'Documentation of Yew web framework',
preview: null,
website: 'https://yew.rs/',
source: 'https://github.com/yewstack/yew/tree/master/website',
tags: ['opensource','versioning','i18n','large'],
},
{
title: 'Sensory Percussion help',
description: 'On-line manual for Sensory Percussion, a music production tool for electronic drums.',
preview: null,
website: 'https://help.sunhou.se/',
source: null,
tags: ['product'],
},
{
title: 'The Fundraising Lore',
description: 'A guide to help founders successfully raise early-stage VC financing',
preview: null,
website: 'https://www.lore.vc/',
source: 'https://github.com/dvitanov/lorevc',
tags: ['opensource','personal'], // TODO find better tag?
},
{
title: 'LifeOmic PHC Documentation',
description: 'Help and information for LifeOmic PHC',
preview: null,
website: 'https://phc.docs.lifeomic.com/',
source: null,
tags: ['product'],
},
{
title: 'Kanekotic\'s Page',
description: 'List of open-source projects and blog',
preview: null,
website: 'https://www.kanekotic.com/',
source: 'https://github.com/kanekotic/kanekotic-page',
tags: ['opensource','personal'],
},
{
title: 'DevTomek',
description: 'A Polish blog about programming, electronics and IoT',
preview: null,
website: 'https://devtomek.pl/',
source: null,
tags: ['personal'],
},
{
title: 'Vantevo Analytics',
description: 'The most complete and secure Google Analytics alternative.',
preview: null,
website: 'https://vantevo.io/docs/',
source: null,
tags: ['product','i18n'],
},
{
title: 'lsfusion platform documentation',
description: 'A declarative open-source language-based platform for information systems development',
preview: null,
website: 'https://docs.lsfusion.org/',
source: 'https://github.com/lsfusion/docusaurus',
tags: ['opensource','i18n','versioning'],
},
{
title: 'Rokt Docs',
description: 'Rokt\'s product documentation',
preview: null,
website: 'https://docs.rokt.com/',
source: null,
tags: ['product'],
},
{
title: 'Harmonoid',
description: 'A beautiful material-design cross platform music player',
preview: null,
website: 'https://harmonoid.com/',
source: null,
tags: ['product','design'],
},
{
title: 'Mentorship Guide',
description: 'Making mentorship accessible to all, for mentors and mentees.',
preview: null,
website: 'https://mentorship.guide/',
source: 'https://github.com/mentorship-sponsorship/mentorship-guide-docs',
tags: ['opensource','design'],
},
{
title: 'Vishal Gandhi',
description: 'The Data Column - Blog by Vishal Gandhi',
preview: null,
website: 'https://vishalgandhi.in/',
source: null,
tags: ['personal'],
},
{
title: 'Daily.dev Documentation',
description: 'Official product documentation for daily.dev',
preview: null,
website: 'https://docs.daily.dev/',
source: 'https://github.com/dailydotdev/docs',
tags: ['opensource','product','design'],
},
{
title: 'Formiz',
description: 'React forms with ease! Composable, headless & with built-in multi steps',
preview: null,
website: 'https://formiz-react.com/',
source: 'https://github.com/ivan-dalmet/formiz/tree/master/documentation',
tags: ['opensource'],
},
{
title: 'Wener Live & Life',
description: 'Notes, Stories, Awesomes',
preview: null,
website: 'https://wener.me/',
source: 'https://github.com/wenerme/wener/tree/master/site',
tags: ['opensource','personal'],
},
{
title: 'Modrinth Documentation',
description: 'The documentation for Modrinth, an open source Minecraft modding platform',
preview: null,
website: 'https://docs.modrinth.com/',
source: 'https://github.com/modrinth/docs',
tags: ['opensource'],
},
{
title: 'Codiga Documentation',
description: 'Documentation for Codiga, your Code Analysis & Coding Assistant',
preview: null,
website: 'https://doc.codiga.io/',
source: 'https://github.com/codiga/doc.codiga.io/tree/main/website',
tags: ['opensource','product'],
},
{
title: 'Takken.io',
description: 'Webber\'s personal website',
preview: null,
website: 'https://takken.io/',
source: 'https://github.com/webbertakken/takken.io',
tags: ['opensource','personal'],
},
{
title: 'GameCI',
description: 'Open source continuous integration for games',
preview: null,
website: 'https://game.ci/',
source: 'https://github.com/game-ci/documentation',
tags: ['opensource','product','versioning'],
},
{
title: 'Batect',
description: 'The fast, consistent way to run your development and testing tasks everywhere.',
preview: null,
website: 'https://batect.dev/',
source: 'https://github.com/batect/batect.dev',
tags: ['opensource'],
},
{
title: 'Boyka-Framework',
description: 'Ultimate test automation for testing any application on any platform',
preview: null,
website: 'https://wasiqbhamla.github.io/boyka-framework/',
source: 'https://github.com/WasiqBhamla/boyka-framework/tree/main/website',
tags: ['opensource'],
},
{
title: 'Nango',
description: 'Open-source infrastructure for native integrations in SaaS products',
preview: null,
website: 'https://docs.nango.dev/',
source: 'https://github.com/NangoHQ/nango/tree/main/docs',
tags: ['opensource','product'],
},
{
title: 'YepCode Docs',
description: 'Docs for the all-in-one platform that connects your services and APIs',
preview: null,
website: 'https://docs.yepcode.io/',
source: null,
tags: ['product'],
},
{
title: 'YepCode Recipes',
description: 'Recipes for the all-in-one platform that connects your services and APIs',
preview: null,
website: 'https://yepcode.io/recipes/',
source: null,
tags: ['product','large'],
},
{
title: 'Appcircle Docs',
description: 'Appcircle is an easy-to-setup mobile CI/CD platform.',
preview: null,
website: 'https://docs.appcircle.io/',
source: 'https://github.com/appcircleio/appcircle-docusaurus/tree/master/',
tags: ['opensource','product'],
},
{
title: 'Rowy Docs',
description: 'Open-source low-code platform for Firebase, Cloud Functions and GCP',
preview: null,
website: 'https://docs.rowy.io/',
source: 'https://github.com/rowyio/docs',
tags: ['opensource','product','design'],
},
{
title: 'Keebio Documentation',
description: 'Mechanical keyboard build guides and keyboard reprogramming info',
preview: null,
website: 'https://docs.keeb.io/',
source: 'https://github.com/keebio/keebio-docs',
tags: ['opensource','product'],
},
{
title: 'SR50 Finance',
description: 'Reference handbook for personal finance',
preview: null,
website: 'https://sr50.finance/',
source: 'https://github.com/tpascarella/sr50',
tags: ['opensource'],
},
{
title: '前端大刘',
description: 'Record and share to make progress every day!',
preview: null,
website: 'https://lzwdot.com/',
source: 'https://github.com/lzwdot/lzwdot.github.io',
tags: ['opensource','personal'],
},
{
title: 'DipScope',
description: 'Open source tools to develop high quality software',
preview: null,
website: 'https://dipscope.com/',
source: null,
tags: ['versioning'],
},
{
title: 'MutableSecurity',
description: 'Platform for automating the lifecycle of cybersecurity solutions',
preview: null,
website: 'https://www.mutablesecurity.io/',
source: 'https://github.com/MutableSecurity/website',
tags: ['opensource','product'],
},
{
title: 'Atlas',
description: 'Atlas CLI helps developers manage their database schemas by applying DevOps principles.',
preview: null,
website: 'https://atlasgo.io/',
source: 'https://github.com/ariga/atlas',
tags: ['opensource','product'],
},
{
title: 'Ent',
description: 'An entity framework for Go',
preview: null,
website: 'https://entgo.io/',
source: 'https://github.com/ent/ent/tree/master/doc/website',
tags: ['opensource','i18n'],
},
{
title: 'NAYAtel ',
description: 'Documentation for TAC Department',
preview: null,
website: 'https://nayatel.shoaibsajid.com/',
source: null,
tags: [], // TODO not sure which tag to use here
},
{
title: 'WPShop',
description: 'Docs site for the ShopWP WordPress plugin',
preview: null,
website: 'https://docs.wpshop.io/',
source: null,
tags: ['product'],
},
{
title: 'Polkadot Wiki',
description: 'The central source of truth for Polkadot Network',
preview: null,
website: 'https://wiki.polkadot.network/',
source: 'https://github.com/w3f/polkadot-wiki/tree/master/polkadot-wiki',
tags: ['opensource'], // TODO add web3 tag?
},
{
title: 'CodingHabits',
description: 'An interactive learning environment for developers',
preview: null,
website: 'https://www.codinghabits.online/',
source: null,
tags: ['product'],
},
{
title: 'Crawlee',
description: 'Scalable web crawling, scraping and automation library for JS/Node.js',
preview: null,
website: 'https://crawlee.dev/',
source: 'https://github.com/apify/crawlee/tree/master/website',
tags: ['opensource','versioning'],
},
{
title: 'codehooks',
description: 'Fast Serverless Backend made Easy',
preview: null,
website: 'https://codehooks.io/',
source: null,
tags: ['product'],
},
{
title: 'HiCA',
description: 'Free SSL Certificate Provider, supports ACME',
preview: null,
website: 'https://www1.hi.cn/',
source: null,
tags: ['product'],
},
{
title: 'Ouch1978',
description: 'Personal site of @Ouch1978',
preview: null,
website: 'https://ouch1978.github.io/',
source: 'https://github.com/Ouch1978/ouch1978.github.io',
tags: ['opensource','personal'],
},
{
title: 'Dojo Documentation',
description: 'Take faster card payments with Dojo.',
preview: null,
website: 'https://docs.dojo.tech/',
source: null,
tags: ['product'],
},
{
title: 'Computer Science Turkish Resource',
description: 'A Computer Science portal for enthusiasts.',
preview: null,
website: 'https://bb-tr-kaynak.netlify.app/',
source: 'https://github.com/Fire-Oceann/bb-tr-kaynak/',
tags: ['opensource'],
},
{
title: 'OKP4',
description: 'Documentation portal for the OKP4 blockchain',
preview: null,
website: 'https://docs.okp4.network/',
source: 'https://github.com/okp4/docs',
tags: ['opensource','product','design'], // TODO add web3 tag
},
{
title: 'Konkatsu Strategy Guide',
description: 'Support konkatsu (marriage hunting) in Japan',
preview: null,
website: 'https://hikonkatsu.com/',
source: null,
tags: ['personal'],
},
{
title: 'Zondax Documentation',
description: 'Building back-end tech solutions for the Web3 Space.',
preview: null,
website: 'https://docs.zondax.ch/',
source: null,
tags: ['product','design'], // TODO add web3 tag
},
{
title: 'Embedded IDE',
description: 'A c/c++ development environment for microcontrollers',
preview: null,
website: 'https://em-ide.com/',
source: 'https://github.com/github0null/eide-docs',
tags: ['opensource','i18n'],
},
{
title: 'ShellHub Documentation',
description: 'A centralized SSH server for the the edge and cloud computing',
preview: null,
website: 'https://docs.shellhub.io/',
source: 'https://github.com/shellhub-io/docs',
tags: ['opensource','product'],
},
{
title: 'Dynamoose',
description: 'A modeling tool for Amazon\'s DynamoDB',
preview: null,
website: 'https://dynamoosejs.com/',
source: 'https://github.com/dynamoose/dynamoose/tree/main/docs',
tags: ['opensource'],
},
/* /*
Pro Tip: add your site in alphabetical order. Pro Tip: add your site in alphabetical order.
Appending your site here (at the end) is more likely to produce Git conflicts. Appending your site here (at the end) is more likely to produce Git conflicts.
@ -2442,7 +3033,7 @@ const Users: User[] = [
export type User = { export type User = {
title: string; title: string;
description: string; description: string;
preview: string; preview: string | null; // null = use our serverless screenshot service
website: string; website: string;
source: string | null; source: string | null;
tags: TagType[]; tags: TagType[];

View file

@ -58,11 +58,21 @@ function ShowcaseCardTag({tags}: {tags: TagType[]}) {
); );
} }
function getCardImage(user: User): string {
return (
user.preview ??
`https://slorber-api-screenshot.netlify.app/${encodeURIComponent(
user.website,
)}/showcase`
);
}
function ShowcaseCard({user}: {user: User}) { function ShowcaseCard({user}: {user: User}) {
const image = getCardImage(user);
return ( return (
<li key={user.title} className="card shadow--md"> <li key={user.title} className="card shadow--md">
<div className={clsx('card__image', styles.showcaseCardImage)}> <div className={clsx('card__image', styles.showcaseCardImage)}>
<Image img={user.preview} alt={user.title} /> <Image img={image} alt={user.title} />
</div> </div>
<div className="card__body"> <div className="card__body">
<div className={clsx(styles.showcaseCardHeader)}> <div className={clsx(styles.showcaseCardHeader)}>