Generate dynamic manifest/meta/favicons
4
.env
@ -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
@ -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-*
|
||||
|
||||
|
35
README.md
@ -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.
|
||||
|
87
index.html
@ -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>
|
||||
|
10
package.json
@ -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",
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 15 KiB |
@ -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>
|
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 4.6 KiB |
@ -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
@ -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],
|
||||
})
|
@ -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>
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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))
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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",
|
||||
|
@ -1,12 +1,30 @@
|
||||
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({
|
||||
dotenv.config({path: '.env.local'})
|
||||
dotenv.config({path: '.env'})
|
||||
|
||||
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,
|
||||
},
|
||||
@ -23,18 +41,82 @@ export default defineConfig({
|
||||
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: "Nostr, your way.",
|
||||
theme_color: "#EB5E28",
|
||||
protocol_handlers: [{protocol: "web+nostr", url: "/%s"}],
|
||||
description: process.env.VITE_APP_DESCRIPTION,
|
||||
theme_color: accentColor,
|
||||
protocol_handlers: [
|
||||
{protocol: "web+nostr", url: "/%s"},
|
||||
{protocol: "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"},
|
||||
{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"},
|
||||
],
|
||||
},
|
||||
}),
|
||||
@ -48,4 +130,5 @@ export default defineConfig({
|
||||
},
|
||||
}),
|
||||
],
|
||||
}
|
||||
})
|
||||
|