mirror of
https://github.com/ruisaraiva19/favycon.git
synced 2026-09-12 19:51:07 +05:00
feat(seo): declare the author and add llms.txt
The about modal is lazily mounted, so the credits and contact address are not in the server-rendered HTML and no crawler ever sees them. Authorship therefore goes in the head, where it is always present: a meta author, a rel=author link to ruisaraiva.dev, and SoftwareApplication JSON-LD. The structured data names Rui as author and Augusto and Miguel as contributors, because the modal credits three people and the markup should not tell a machine a tidier story than the page tells a reader. Also adds public/llms.txt: accepted input formats, the 310px and 512px minimums, and exactly what the zip contains, including that favicon.svg only appears for SVG input and manifest.json only with the PWA option. It is written from utils/favicon.ts and the route handler rather than from memory. Note it is a static file, so it is the one thing here that can drift from the sizes it documents. Two hardcoded favycon.vercel.app strings become the SITE_URL constant the rest of the file now uses.
This commit is contained in:
parent
3588ab0506
commit
78c9508195
@ -1,43 +1,78 @@
|
||||
import Head from 'next/head'
|
||||
|
||||
const SITE_URL = 'https://favycon.vercel.app'
|
||||
|
||||
const AUTHOR = { name: 'Rui Saraiva', url: 'https://ruisaraiva.dev' }
|
||||
|
||||
// The tool credits three people in its About modal, so the structured data says
|
||||
// the same thing rather than a tidier untruth: Rui as author, the other two as
|
||||
// contributors, linked where the modal links them.
|
||||
const CONTRIBUTORS = [
|
||||
{ name: 'Augusto Lopes', url: 'https://twitter.com/aboutaugusto' },
|
||||
{ name: 'Miguel Teixeira', url: 'https://github.com/miguellteixeira' },
|
||||
]
|
||||
|
||||
type SEOProps = {
|
||||
title: string
|
||||
description: string
|
||||
}
|
||||
|
||||
const SEO = ({ title, description }: SEOProps) => (
|
||||
<Head>
|
||||
<title>{title}</title>
|
||||
<meta name="description" content={description} />
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="/favicon-57x57.png" />
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="/favicon-60x60.png" />
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="/favicon-72x72.png" />
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="/favicon-76x76.png" />
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="/favicon-114x114.png" />
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="/favicon-120x120.png" />
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="/favicon-144x144.png" />
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="/favicon-152x152.png" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/favicon-180x180.png" />
|
||||
<meta name="apple-mobile-web-app-title" content="Favycon" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
||||
<link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png" />
|
||||
<link rel="icon" type="image/png" sizes="192x192" href="/favicon-192x192.png" />
|
||||
<meta name="msapplication-TileColor" content="#ffffff" />
|
||||
<meta name="msapplication-TileImage" content="/favicon-144x144.png" />
|
||||
<meta name="msapplication-config" content="/browserconfig.xml" />
|
||||
<meta property="og:title" content={title} />
|
||||
<meta property="og:description" content={description} />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:site_name" content={title} />
|
||||
<meta property="og:url" content="https://favycon.vercel.app" />
|
||||
<meta property="og:image" content="https://favycon.vercel.app/share.png?v5" />
|
||||
<meta property="og:image:type" content="image/png" />
|
||||
<meta property="og:image:width" content="1200" />
|
||||
<meta property="og:image:height" content="630" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
</Head>
|
||||
)
|
||||
const SEO = ({ title, description }: SEOProps) => {
|
||||
const structuredData = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'SoftwareApplication',
|
||||
name: 'Favycon',
|
||||
description,
|
||||
url: SITE_URL,
|
||||
applicationCategory: 'DeveloperApplication',
|
||||
operatingSystem: 'Any',
|
||||
browserRequirements: 'Requires JavaScript',
|
||||
image: `${SITE_URL}/share.png`,
|
||||
license: 'https://opensource.org/licenses/MIT',
|
||||
// It is genuinely free, and Google wants the price stated to believe it.
|
||||
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
||||
author: { '@type': 'Person', ...AUTHOR },
|
||||
contributor: CONTRIBUTORS.map((person) => ({ '@type': 'Person', ...person })),
|
||||
codeRepository: 'https://github.com/ruisaraiva19/favycon',
|
||||
}
|
||||
|
||||
return (
|
||||
<Head>
|
||||
<title>{title}</title>
|
||||
<meta name="description" content={description} />
|
||||
<meta name="author" content={AUTHOR.name} />
|
||||
<link rel="author" href={AUTHOR.url} />
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="/favicon-57x57.png" />
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="/favicon-60x60.png" />
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="/favicon-72x72.png" />
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="/favicon-76x76.png" />
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="/favicon-114x114.png" />
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="/favicon-120x120.png" />
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="/favicon-144x144.png" />
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="/favicon-152x152.png" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/favicon-180x180.png" />
|
||||
<meta name="apple-mobile-web-app-title" content="Favycon" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
||||
<link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png" />
|
||||
<link rel="icon" type="image/png" sizes="192x192" href="/favicon-192x192.png" />
|
||||
<meta name="msapplication-TileColor" content="#ffffff" />
|
||||
<meta name="msapplication-TileImage" content="/favicon-144x144.png" />
|
||||
<meta name="msapplication-config" content="/browserconfig.xml" />
|
||||
<meta property="og:title" content={title} />
|
||||
<meta property="og:description" content={description} />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:site_name" content={title} />
|
||||
<meta property="og:url" content={SITE_URL} />
|
||||
<meta property="og:image" content={`${SITE_URL}/share.png?v5`} />
|
||||
<meta property="og:image:type" content="image/png" />
|
||||
<meta property="og:image:width" content="1200" />
|
||||
<meta property="og:image:height" content="630" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(structuredData) }} />
|
||||
</Head>
|
||||
)
|
||||
}
|
||||
|
||||
export { SEO }
|
||||
|
||||
48
public/llms.txt
Normal file
48
public/llms.txt
Normal file
@ -0,0 +1,48 @@
|
||||
# Favycon
|
||||
|
||||
> A free online tool that turns one image into a complete set of favicons, in
|
||||
> every size and format a site needs, as a downloadable zip.
|
||||
|
||||
Drag and drop an image and Favycon returns `favicons.zip` plus the markup to
|
||||
paste into your `<head>`. Nothing is stored: the image is converted in the
|
||||
request and the zip is streamed straight back.
|
||||
|
||||
Site: https://favycon.vercel.app
|
||||
|
||||
## Input
|
||||
|
||||
- Accepted formats: JPEG, PNG, SVG.
|
||||
- Minimum dimensions: 310x310. SVG input is exempt, since it is rescaled from
|
||||
vector.
|
||||
- With the PWA option enabled the minimum is 512x512, again except for SVG.
|
||||
|
||||
## What the zip contains
|
||||
|
||||
- `icons/favicon-<size>.png` at 16x16, 32x32, 57x57, 60x60, 70x70, 72x72,
|
||||
76x76, 96x96, 114x114, 120x120, 144x144, 150x150, 152x152, 180x180, 192x192
|
||||
and 310x310.
|
||||
- `icons/favicon.ico`, rendered from a 256x256 master.
|
||||
- `icons/favicon.svg`, only when the uploaded image was itself an SVG.
|
||||
- `icons/browserconfig.xml` for IE10+ tiles.
|
||||
- `icons/manifest.json`, only when the PWA option is on. That option also adds
|
||||
128x128, 384x384 and 512x512 PNGs.
|
||||
- `readme.txt` with the HTML to add, written to match the options chosen.
|
||||
|
||||
## Facts
|
||||
|
||||
- Author: Rui Saraiva (https://ruisaraiva.dev)
|
||||
- Contributors: Augusto Lopes (product design), Miguel Teixeira
|
||||
- Built in 2020
|
||||
- Licence: MIT
|
||||
- Source: https://github.com/ruisaraiva19/favycon
|
||||
- Price: free, no account, no upload limit published
|
||||
- Contact: hello@ruisaraiva.dev
|
||||
|
||||
## Notes
|
||||
|
||||
- This is a single-page tool. There is no blog, docs site or API documentation
|
||||
to crawl beyond this file and the repository.
|
||||
- There is a public HTTP endpoint at `POST /api/favycon`. It takes a multipart
|
||||
body with an `icon` file field and an optional `pwa` field set to `1`, and
|
||||
responds with `application/zip`. It is what the page itself calls; it is not
|
||||
a documented or versioned public API.
|
||||
Loading…
Reference in New Issue
Block a user