Generate dynamic manifest/meta/favicons

This commit is contained in:
Jon Staab 2024-03-06 15:01:57 -08:00
parent cf074bd222
commit b5ede0b883
47 changed files with 201 additions and 192 deletions

4
.env
View File

@ -13,8 +13,10 @@ VITE_PLATFORM_PUBKEY=8ec86ac9e10979998652068ee6b00223b8e3265aabb3fe28fb6b3b6e294
VITE_FORCE_GROUP=
VITE_PLATFORM_RELAYS=
VITE_ENABLE_ZAPS=true
VITE_LOGO_URL=
VITE_APP_NAME=Coracle
VITE_APP_URL=https://app.coracle.social
VITE_APP_LOGO=/images/logo.png
VITE_APP_DESCRIPTION="A nostr client for regular people"
VITE_CLIENT_NAME=Coracle
VITE_CLIENT_ID=31990:97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322:1685968093690
VITE_BUGSNAG_API_KEY=

8
.gitignore vendored
View File

@ -30,3 +30,11 @@ ssl
scratch.md
psql-tmux.json
sandbox.sql
# Generated on build
public/icons
public/images/apple-touch-icon-180x180.png
public/images/favicon.ico
public/images/maskable-icon-512x512.png
public/images/pwa-*

View File

@ -2,8 +2,6 @@
Coracle is a web client for the Nostr protocol focused on pushing the boundaries of what's unique about nostr, including relay selection and management, web-of-trust based moderation and content recommendations, and privacy protection. Check it out at [coracle.social](https://coracle.social).
[Dufflepud](https://github.com/coracle-social/dufflepud) is a companion server which you can self-host. It helps Coracle with things like link previews and image uploads.
If you like Coracle and want to support its development, you can donate sats via [Geyser](https://geyser.fund/project/coracle).
# Features
@ -56,5 +54,36 @@ You can find a more complete changelog [here](./CHANGELOG.md).
- Clone the project repository: `git clone https://github.com/coracle-social/coracle.git`
- Navigate to the project directory: `cd coracle`
- Install dependencies: `yarn`
- Customize configuration in `.env` (optional)
- Customize configuration in `.env` (optional, see below)
- Start the development server: `yarn dev`
# Customization
Coracle is intended to be fully white-labeled by groups of various kinds. The following environment variables can be set in `.env.local` to customize Coracle's appearance and behavior:
- `VITE_DARK_THEME` and `VITE_LIGHT_THEME` are comma-separate lists of key/value pairs defining theme colors.
- `VITE_DVM_RELAYS` is a comma-separated list of relays to use when making requests against DVMs.
- `VITE_SEARCH_RELAYS` is a comma-separated list of relays to use when using NIP 50 search.
- `VITE_DEFAULT_RELAYS` is a comma-separated list of relays to use as defaults/fallbacks.
- `VITE_DEFAULT_FOLLOWS` is a comma-separated list of hex pubkeys to fetch content from when the user isn't following anyone.
- `VITE_ONBOARDING_LISTS` is a comma-separated list of `kind:30003` person lists to populate onboarding with.
- `VITE_NIP96_URLS` is a comma-separated list of default upload providers.
- `VITE_IMGPROXY_URL` is an [imgproxy](https://imgproxy.net) instance url for protecting user privacy and reducing bandwidth use.
- `VITE_DUFFLEPUD_URL` is a [Dufflepud](https://github.com/coracle-social/dufflepud) instance url, which helps Coracle with things like link previews and image uploads.
- `VITE_PLATFORM_ZAP_SPLIT` is a decimal between 0 and 1 defining the default zap split percent.
- `VITE_PLATFORM_PUBKEY` is the pubkey of the platform owner. This gets zapped when using the platform zap split.
- `VITE_FORCE_GROUP` is an optional `kind:34550` or `kind:35834` address. If provided, the home page of Coracle will be the home page for the group, and most views will be filtered down to the group's scope.
- `VITE_PLATFORM_RELAYS` is an optional comma-separated list of relay urls to use for feeds. If provided, most UI components related to relay selection will be hidden from the user.
- `VITE_ENABLE_ZAPS` can be set to `false` to disable zaps.
- `VITE_APP_NAME` is the app's name.
- `VITE_APP_URL` is the app's url. Used to generate open graph meta tags.
- `VITE_APP_LOGO` is the path for the app's logo relative to the `public` directory, starting with a trailing slash. Used to generate favicons and manifest.
- `VITE_APP_DESCRIPTION` is the app's description.
- `VITE_CLIENT_NAME` is the client's name. Only change this if you have forked Coracle.
- `VITE_CLIENT_ID` is the client's NIP 89 handler id. Only change this if you have forked Coracle.
- `VITE_BUGSNAG_API_KEY` is your [bugsnag](https://www.bugsnag.com/) api key.
- `VITE_BUILD_HASH` can be set during build to indicate the software version on the about page.
- `VITE_LOG_LEVEL` can be set to `info`, `warn`, or `error`. This controls how much shows up in the console.
- `VITE_ENABLE_MARKET` can be set to `false` to disable the marketplace tab.
See `.env` for default values.

View File

@ -5,94 +5,7 @@
<meta
http-equiv="Content-Security-Policy"
content="script-src 'self'; worker-src 'self'; style-src 'self' 'unsafe-inline'; frame-src open.spotify.com; child-src 'none'; form-action 'none';" />
<link
rel="apple-touch-icon"
sizes="57x57"
href="/images/favicon/apple-icon-57x57.png"
/>
<link
rel="apple-touch-icon"
sizes="60x60"
href="/images/favicon/apple-icon-60x60.png"
/>
<link
rel="apple-touch-icon"
sizes="72x72"
href="/images/favicon/apple-icon-72x72.png"
/>
<link
rel="apple-touch-icon"
sizes="76x76"
href="/images/favicon/apple-icon-76x76.png"
/>
<link
rel="apple-touch-icon"
sizes="114x114"
href="/images/favicon/apple-icon-114x114.png"
/>
<link
rel="apple-touch-icon"
sizes="120x120"
href="/images/favicon/apple-icon-120x120.png"
/>
<link
rel="apple-touch-icon"
sizes="144x144"
href="/images/favicon/apple-icon-144x144.png"
/>
<link
rel="apple-touch-icon"
sizes="152x152"
href="/images/favicon/apple-icon-152x152.png"
/>
<link
rel="apple-touch-icon"
sizes="180x180"
href="/images/favicon/apple-icon-180x180.png"
/>
<link
rel="icon"
type="image/png"
sizes="192x192"
href="/images/favicon/android-icon-192x192.png"
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="/images/favicon/favicon-32x32.png"
/>
<link
rel="icon"
type="image/png"
sizes="96x96"
href="/images/favicon/favicon-96x96.png"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="/images/favicon/favicon-16x16.png"
/>
<link rel="mask-icon" href="/images/logo.svg" color="#FFFFFF" />
<meta name="msapplication-TileColor" content="#EB5E28" />
<meta
name="msapplication-TileImage"
content="/images/favicon/ms-icon-144x144.png"
/>
<meta name="theme-color" content="#EB5E28" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta property="description" content="Nostr, your way." />
<meta property="og:title" content="Coracle" />
<meta property="og:type" content="website" />
<meta property="og:description" content="Nostr, your way." />
<meta property="og:image" content="/images/banner.png" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Coracle" />
<meta name="twitter:description" content="Nostr, your way." />
<meta name="twitter:image" content="/images/banner.png" />
<meta property="og:url" content="https://app.coracle.social" />
<title>Coracle</title>
</head>
<body class="w-full">
<div id="app"></div>

View File

@ -5,8 +5,7 @@
"type": "module",
"scripts": {
"dev": "vite --host",
"build": "vite build",
"preview": "vite preview",
"build": "yarn add sharp -D --ignore-engines && pwa-assets-generator && vite build",
"check:es": "eslint 'src/**/*.{js,ts,svelte}' --quiet",
"check:ts": "svelte-check --tsconfig ./tsconfig.json --threshold error",
"check:fmt": "prettier --check $(git diff head --name-only --diff-filter d | grep -E '(js|ts|svelte)$' | xargs)",
@ -27,19 +26,24 @@
"@types/throttle-debounce": "^5.0.2",
"@typescript-eslint/eslint-plugin": "^6.13.1",
"@typescript-eslint/parser": "^6.13.1",
"@vite-pwa/assets-generator": "^0.2.4",
"autoprefixer": "^10.4.16",
"cypress": "^13.6.0",
"dotenv": "^16.4.5",
"eslint": "^8.54.0",
"eslint-plugin-svelte3": "^4.0.0",
"favicons": "^7.1.5",
"madge": "^6.1.0",
"postcss": "^8.4.31",
"prettier": "^3.1.0",
"prettier-plugin-svelte": "^3.1.2",
"prettier-plugin-tailwindcss": "^0.5.11",
"sharp": "^0.33.2",
"svelte-preprocess": "^5.1.1",
"tailwindcss": "^3.3.5",
"typescript": "^5.3.2",
"vite": "^5.0.4",
"vite-plugin-html-config": "^1.0.11",
"vite-plugin-mkcert": "^1.17.1",
"vite-plugin-node-polyfills": "^0.17.0",
"vite-plugin-pwa": "^0.17.2"
@ -65,7 +69,7 @@
"normalize-url": "^8.0.0",
"nostr-tools": "^2.1.5",
"npm-run-all": "^4.1.5",
"paravel": "^0.5.0",
"paravel": "^0.5.1",
"qr-scanner": "^1.4.2",
"qrcode": "^1.5.3",
"ramda": "^0.29.1",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -1,12 +0,0 @@
<svg width="189" height="189" viewBox="0 0 189 189" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_753_289)">
<path d="M43.7937 12.5298C0.57938 44.8609 0.342815 92.8076 16.3236 126.458C33.6361 162.913 75.9226 184.525 117.769 173.613C156.42 163.534 183.82 122.549 182.358 95.8221" stroke="#EB5E28" stroke-width="12" stroke-linecap="round"/>
<path d="M78.6923 75.6945C50.8177 86.6612 44.0155 112.559 47.9751 133.172C52.2646 155.502 72.1284 173.572 96.2818 173.985C118.59 174.366 139.116 156.332 142.045 141.655" stroke="#EB5E28" stroke-width="12" stroke-linecap="round"/>
<path d="M43.5856 12.4047C17.9702 31.569 17.83 59.9895 27.3026 79.936C37.5646 101.545 62.6301 114.355 87.4348 107.887C110.345 101.913 126.587 77.6188 125.72 61.7764" stroke="#EB5E28" stroke-width="12" stroke-linecap="round"/>
</g>
<defs>
<clipPath id="clip0_753_289">
<rect width="189" height="189" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 937 B

10
pwa-assets.config.js Normal file
View File

@ -0,0 +1,10 @@
import dotenv from 'dotenv'
import {defineConfig, minimalPreset as preset} from '@vite-pwa/assets-generator/config'
dotenv.config({path: '.env.local'})
dotenv.config({path: '.env'})
export default defineConfig({
preset,
images: ['public' + process.env.VITE_APP_LOGO],
})

View File

@ -54,8 +54,8 @@
class="mb-4 mt-4 flex items-center gap-2 pl-6"
external
href="https://info.coracle.social">
<img alt="App Logo" src={import.meta.env.VITE_LOGO_URL || "/images/logo.png"} class="w-12" />
<h1 class="staatliches -mb-[0.1em] leading-none" style={`font-size: ${appName.length / 5}em`}>
<img alt="App Logo" src={import.meta.env.VITE_APP_LOGO} class="w-12" />
<h1 class="staatliches -mb-[0.1em] leading-none" style={`font-size: ${appName.length / 3}em`}>
{appName}
</h1>
</Anchor>

View File

@ -1,10 +1,10 @@
<script lang="ts">
import {Tags, matchFilters} from "paravel"
import {isChildOf, getIdOrAddress, Tags, matchFilters} from "paravel"
import {reject, whereEq, uniqBy, prop} from "ramda"
import {onMount, onDestroy} from "svelte"
import {quantify, ensurePlural, batch} from "hurdak"
import {fly, slide} from "src/util/transition"
import {getIdOrAddress, isChildOf, isLike, isGiftWrap} from "src/util/nostr"
import {isLike, isGiftWrap} from "src/util/nostr"
import {formatTimestamp} from "src/util/misc"
import Popover from "src/partials/Popover.svelte"
import AltColor from "src/partials/AltColor.svelte"

View File

@ -1,7 +1,7 @@
<script lang="ts">
import {onMount} from "svelte"
import {decodeAddress} from "paravel"
import {getIdOrAddress, noteKinds} from "src/util/nostr"
import {getIdOrAddress, decodeAddress} from "paravel"
import {noteKinds} from "src/util/nostr"
import {fly} from "src/util/transition"
import FlexColumn from "src/partials/FlexColumn.svelte"
import Spinner from "src/partials/Spinner.svelte"

View File

@ -1,8 +1,8 @@
<script lang="ts">
import {onMount} from "svelte"
import {defer} from "hurdak"
import {getIdOrAddress} from "paravel"
import {isMobile} from "src/util/html"
import {getIdOrAddress} from "src/util/nostr"
import {fly} from "src/util/transition"
import Spinner from "src/partials/Spinner.svelte"
import Note from "src/app/shared/Note.svelte"

View File

@ -1,6 +1,5 @@
import {Tags} from "paravel"
import {Tags, getIdAndAddress} from "paravel"
import {whereEq, groupBy, find} from "ramda"
import {getIdAndAddress} from "src/util/nostr"
import {derived, DerivedCollection} from "src/engine/core/utils"
import {pubkey} from "src/engine/session/state"
import {settings} from "src/engine/session/derived"

View File

@ -1,15 +1,9 @@
import {partition, concat, prop, uniqBy, identity, without, assoc} from "ramda"
import {ensurePlural, doPipe, batch} from "hurdak"
import {now, Tags} from "paravel"
import {now, Tags, getIdOrAddress, getIdAndAddress} from "paravel"
import {race} from "src/util/misc"
import {info} from "src/util/logger"
import {
getIdOrAddress,
getIdAndAddress,
noteKinds,
reactionKinds,
repostKinds,
} from "src/util/nostr"
import {noteKinds, reactionKinds, repostKinds} from "src/util/nostr"
import type {DisplayEvent} from "src/engine/notes/model"
import type {Event} from "src/engine/events/model"
import {sortEventsDesc, unwrapRepost} from "src/engine/events/utils"

View File

@ -1,7 +1,6 @@
import {decodeAddress, addressToFilter, getAddress, isContextAddress} from "paravel"
import {decodeAddress, isReplaceable, addressToFilter, getAddress, isContextAddress} from "paravel"
import {omit, without, find, prop, groupBy, uniq} from "ramda"
import {shuffle, randomId, seconds, avg} from "hurdak"
import {isAddressable} from "src/util/nostr"
import {env} from "src/engine/session/state"
import {follows, network} from "src/engine/people/derived"
import {hints} from "src/engine/relays/utils"
@ -66,7 +65,7 @@ export const getReplyFilters = (events, filter) => {
for (const event of events) {
e.push(event.id)
if (isAddressable(event)) {
if (isReplaceable(event)) {
a.push(getAddress(event))
}

View File

@ -1,10 +1,10 @@
import EventEmitter from "events"
import {createEvent, asEvent, Tags} from "paravel"
import {createEvent, getIdAndAddress, asEvent, Tags} from "paravel"
import {omit, uniqBy} from "ramda"
import {defer, union, difference} from "hurdak"
import {info} from "src/util/logger"
import {parseContent} from "src/util/notes"
import {getIdAndAddress, generatePrivateKey} from "src/util/nostr"
import {generatePrivateKey} from "src/util/nostr"
import type {Event, NostrEvent} from "src/engine/events/model"
import {hints, forcePlatformRelays} from "src/engine/relays/utils"
import {env, pubkey} from "src/engine/session/state"

View File

@ -1,7 +1,6 @@
import {uniqBy, identity, prop, sortBy} from "ramda"
import {batch} from "hurdak"
import {Tags} from "paravel"
import {getIdOrAddress, getIdAndAddress} from "src/util/nostr"
import {Tags, getIdOrAddress, getIdAndAddress} from "paravel"
import type {DisplayEvent} from "src/engine/notes/model"
import type {Event} from "src/engine/events/model"
import {writable} from "src/engine/core/utils"

View File

@ -1,4 +1,4 @@
import {getIdAndAddress} from "src/util/nostr"
import {getIdAndAddress} from "paravel"
import {hints} from "src/engine/relays/utils"
import {createAndPublish} from "src/engine/network/utils"

View File

@ -1,9 +1,9 @@
import {fromNostrURI, getAddress, Tags} from "paravel"
import {fromNostrURI, Tags} from "paravel"
import {schnorr} from "@noble/curves/secp256k1"
import {bytesToHex} from "@noble/hashes/utils"
import {nip05, nip19, generateSecretKey, getEventHash, getPublicKey as getPk} from "nostr-tools"
import {identity} from "ramda"
import {between, avg} from "hurdak"
import {avg} from "hurdak"
import type {Event} from "src/engine"
export const fromHex = k => Uint8Array.from(Buffer.from(k, "hex"))
@ -73,23 +73,6 @@ export const getAvgRating = (events: Event[]) => avg(events.map(getRating).filte
export const isHex = x => x?.length === 64 && x?.match(/^[a-f0-9]{64}$/)
export const isReplaceable = e => between(9999, 20000, e.kind)
export const isParameterizedReplaceable = e => between(29999, 40000, e.kind)
export const isAddressable = e => isReplaceable(e) || isParameterizedReplaceable(e)
export const getIdOrAddress = e => (isAddressable(e) ? getAddress(e) : e.id)
export const getIdAndAddress = e => (isAddressable(e) ? [e.id, getAddress(e)] : [e.id])
export const isChildOf = (a, b) => {
const {roots, replies} = Tags.fromEvent(a).ancestors()
const parentIds = (replies.exists() ? replies : roots).values().valueOf()
return Boolean(getIdAndAddress(b).find(x => parentIds.includes(x)))
}
const WARN_TAGS = new Set([
"nsfw",
"nude",

View File

@ -1,51 +1,134 @@
import fs from 'fs'
import dotenv from 'dotenv'
import * as path from "path"
import {defineConfig} from "vite"
import {VitePWA} from "vite-plugin-pwa"
import mkcert from "vite-plugin-mkcert"
import {favicons} from 'favicons'
import htmlPlugin from "vite-plugin-html-config"
import sveltePreprocess from "svelte-preprocess"
import {svelte} from "@sveltejs/vite-plugin-svelte"
import {nodePolyfills} from "vite-plugin-node-polyfills"
export default defineConfig({
server: {
https: false,
},
build: {
sourcemap: true,
},
resolve: {
alias: {
src: path.resolve(__dirname, "src"),
},
},
plugins: [
mkcert(),
nodePolyfills({
protocolImports: true,
}),
VitePWA({
registerType: "autoUpdate",
injectRegister: "auto",
manifest: {
name: process.env.VITE_APP_NAME,
short_name: process.env.VITE_APP_NAME,
description: "Nostr, your way.",
theme_color: "#EB5E28",
protocol_handlers: [{protocol: "web+nostr", url: "/%s"}],
icons: [
{type: "image/png", sizes: "192x192", src: "/images/favicon/android-icon-192x192.png"},
{type: "image/png", sizes: "512x512", src: "/images/favicon/android-icon-512x512.png"},
],
},
}),
svelte({
preprocess: sveltePreprocess(),
onwarn: (warning, handler) => {
if (warning.code.startsWith("a11y-")) return
if (warning.filename.includes("node_modules")) return
dotenv.config({path: '.env.local'})
dotenv.config({path: '.env'})
handler(warning)
const accentColor = process.env.VITE_LIGHT_THEME.match(/accent:(#\w+)/)[1]
export default defineConfig(async () => {
const icons = await favicons('public' + process.env.VITE_APP_LOGO)
if (!fs.existsSync('public/icons')) fs.mkdirSync('public/icons')
for (const {name, contents} of icons.images) {
fs.writeFileSync(`public/icons/${name}`, contents, "binary")
}
return {
server: {
https: false,
},
build: {
sourcemap: true,
},
resolve: {
alias: {
src: path.resolve(__dirname, "src"),
},
}),
],
},
plugins: [
mkcert(),
nodePolyfills({
protocolImports: true,
}),
htmlPlugin({
title: process.env.VITE_APP_NAME,
metas: [
{name: "description", content: process.env.VITE_APP_DESCRIPTION},
{name: "theme-color", content: accentColor},
{name: "og:title", content: process.env.VITE_APP_NAME},
{name: "og:type", content: "website"},
{name: "og:description", content: process.env.VITE_APP_DESCRIPTION},
{name: "og:image", content: "/images/banner.png"},
{name: "twitter:card", content: "summary_large_image"},
{name: "twitter:title", content: process.env.VITE_APP_NAME},
{name: "twitter:description", content: process.env.VITE_APP_DESCRIPTION},
{name: "twitter:image", content: "/images/banner.png"},
{property: "og:url", content: process.env.VITE_APP_URL},
{name: "msapplication-TileColor", content: accentColor},
{name: "msapplication-TileImage", content: "/icons/mstile-144x144.png"},
],
links: [
{rel: "icon", href: "/icons/favicon.ico", sizes: "48x48"},
{rel: "icon", href: "/icons/favicon-16x16.png", sizes: "any", type: "image/png"},
{rel: "icon", href: "/icons/favicon-32x32.png", sizes: "any", type: "image/png"},
{rel: "icon", href: "/icons/favicon-48x48.png", sizes: "any", type: "image/png"},
{rel: "apple-touch-icon", sizes: "57x57", href: "/icons/apple-touch-icon-57x57.png"},
{rel: "apple-touch-icon", sizes: "60x60", href: "/icons/apple-touch-icon-60x60.png"},
{rel: "apple-touch-icon", sizes: "72x72", href: "/icons/apple-touch-icon-72x72.png"},
{rel: "apple-touch-icon", sizes: "76x76", href: "/icons/apple-touch-icon-76x76.png"},
{rel: "apple-touch-icon", sizes: "114x114", href: "/icons/apple-touch-icon-114x114.png"},
{rel: "apple-touch-icon", sizes: "120x120", href: "/icons/apple-touch-icon-120x120.png"},
{rel: "apple-touch-icon", sizes: "144x144", href: "/icons/apple-touch-icon-144x144.png"},
{rel: "apple-touch-icon", sizes: "152x152", href: "/icons/apple-touch-icon-152x152.png"},
{rel: "apple-touch-icon", sizes: "180x180", href: "/icons/apple-touch-icon-180x180.png"},
{rel: "icon", type: "image/png", sizes: "192x192", href: "/icons/android-icon-192x192.png"},
{rel: "icon", type: "image/png", sizes: "32x32", href: "/icons/favicon-32x32.png"},
{rel: "icon", type: "image/png", sizes: "96x96", href: "/icons/favicon-96x96.png"},
{rel: "icon", type: "image/png", sizes: "16x16", href: "/icons/favicon-16x16.png"},
{rel: "mask-icon", href: "/images/logo.svg", color: "#FFFFFF"},
{rel: "icon", type: "image/png", sizes: "144x144", href: "/icons/android-chrome-144x144.png"},
{rel: "icon", type: "image/png", sizes: "192x192", href: "/icons/android-chrome-192x192.png"},
{rel: "icon", type: "image/png", sizes: "256x256", href: "/icons/android-chrome-256x256.png"},
{rel: "icon", type: "image/png", sizes: "36x36", href: "/icons/android-chrome-36x36.png"},
{rel: "icon", type: "image/png", sizes: "384x384", href: "/icons/android-chrome-384x384.png"},
{rel: "icon", type: "image/png", sizes: "48x48", href: "/icons/android-chrome-48x48.png"},
{rel: "icon", type: "image/png", sizes: "512x512", href: "/icons/android-chrome-512x512.png"},
{rel: "icon", type: "image/png", sizes: "72x72", href: "/icons/android-chrome-72x72.png"},
{rel: "icon", type: "image/png", sizes: "96x96", href: "/icons/android-chrome-96x96.png"},
{rel: "apple-touch-icon", sizes: "1024x1024", href: "apple-touch-icon-1024x1024.png"},
{rel: "apple-touch-icon", sizes: "114x114", href: "apple-touch-icon-114x114.png"},
{rel: "apple-touch-icon", sizes: "120x120", href: "apple-touch-icon-120x120.png"},
{rel: "apple-touch-icon", sizes: "144x144", href: "apple-touch-icon-144x144.png"},
{rel: "apple-touch-icon", sizes: "152x152", href: "apple-touch-icon-152x152.png"},
{rel: "apple-touch-icon", sizes: "167x167", href: "apple-touch-icon-167x167.png"},
{rel: "apple-touch-icon", sizes: "180x180", href: "apple-touch-icon-180x180.png"},
{rel: "apple-touch-icon", sizes: "57x57", href: "apple-touch-icon-57x57.png"},
{rel: "apple-touch-icon", sizes: "60x60", href: "apple-touch-icon-60x60.png"},
{rel: "apple-touch-icon", sizes: "72x72", href: "apple-touch-icon-72x72.png"},
{rel: "apple-touch-icon", sizes: "76x76", href: "apple-touch-icon-76x76.png"},
],
}),
VitePWA({
registerType: "autoUpdate",
injectRegister: "auto",
manifest: {
name: process.env.VITE_APP_NAME,
short_name: process.env.VITE_APP_NAME,
description: process.env.VITE_APP_DESCRIPTION,
theme_color: accentColor,
protocol_handlers: [
{protocol: "web+nostr", url: "/%s"},
{protocol: "nostr", url: "/%s"},
],
icons: [
{src: "images/pwa-64x64.png", sizes: "64x64", type: "image/png"},
{src: "images/pwa-192x192.png", sizes: "192x192", type: "image/png"},
{src: "images/pwa-512x512.png", sizes: "512x512", type: "image/png", purpose: "any"},
{src: "images/maskable-icon-512x512.png", sizes: "512x512", type: "image/png", purpose: "maskable"},
],
},
}),
svelte({
preprocess: sveltePreprocess(),
onwarn: (warning, handler) => {
if (warning.code.startsWith("a11y-")) return
if (warning.filename.includes("node_modules")) return
handler(warning)
},
}),
],
}
})

BIN
yarn.lock

Binary file not shown.