Real head: link previews, brand icons, and the font that never loaded
1036
_expo/static/js/web/entry-0378b3b321364495a1241c81b00660ae.js
Normal file
BIN
apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
badge-96.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
favicon-16.png
Normal file
|
After Width: | Height: | Size: 384 B |
BIN
favicon-32.png
Normal file
|
After Width: | Height: | Size: 674 B |
BIN
favicon.ico
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
5
favicon.svg
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32" fill="none">
|
||||||
|
<title>Pull Up — favicon</title>
|
||||||
|
<desc>Pull Up — generated by design/brand/build.mjs. Do not edit; edit the generator. Small cut: this file is only ever seen at tab size.</desc>
|
||||||
|
<rect width="32" height="32" rx="0" ry="0" fill="#0C0C0E"/><g transform="translate(1.389 1.778) scale(1.218)"><path d="M2.6 19.6c3.6.6 7-.6 9.6-3.4 2.6-2.8 5.2-4.2 8.6-3.8" fill="none" stroke="#EDEDEF" stroke-width="2.6" stroke-linecap="round"/><circle cx="18.4" cy="7.4" r="3.75" fill="#8FE388"/></g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 593 B |
BIN
icon-192.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
icon-512.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
icon-maskable-192.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
icon-maskable-512.png
Normal file
|
After Width: | Height: | Size: 9.8 KiB |
154
index.html
|
|
@ -1,10 +1,110 @@
|
||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
|
<!--
|
||||||
|
The document shell. THIS is the file that ships — `app/app/+html.tsx` is the
|
||||||
|
obvious place to put a meta tag and under `web.output: "single"` it is never
|
||||||
|
evaluated. All the reasoning lives in `+html.tsx`, which is not served to
|
||||||
|
anybody; keep the two in sync and keep this comment short, because every byte
|
||||||
|
of it is downloaded by every visitor.
|
||||||
|
|
||||||
|
Three things must not change. Keep `<div id="root">`. Keep the two
|
||||||
|
substitution tokens below exactly where they are. And do not quote a
|
||||||
|
substitution token, or a closing head or body tag, anywhere in this comment:
|
||||||
|
the CLI fills the template with first-match `String.replace` calls, so a
|
||||||
|
comment that names one swallows it — which the first draft of this file did,
|
||||||
|
putting the literal title token in the tab and the bundle script in the middle
|
||||||
|
of this paragraph.
|
||||||
|
-->
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||||
<title>Pull Up</title>
|
|
||||||
|
<title>Pull Up — Pickup sports at UF</title>
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
content="Post a pickup game at UF, or ask to join one. Fifteen sports on the courts and fields you already walk past. Free, nothing to install, and the host approves everyone who plays."
|
||||||
|
/>
|
||||||
|
<link rel="canonical" href="https://pullup.onetouch.studio/" />
|
||||||
|
<meta name="robots" content="index, follow, max-image-preview:large" />
|
||||||
|
|
||||||
|
<!-- Open Graph. iMessage, WhatsApp, Slack, Discord, Instagram DMs and
|
||||||
|
Facebook all read these; Twitter falls back to them for anything its
|
||||||
|
own namespace does not define. Absolute URLs are not optional here —
|
||||||
|
a relative og:image is dropped by most of them. -->
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:site_name" content="Pull Up" />
|
||||||
|
<meta property="og:title" content="Pull Up — Pickup sports at UF" />
|
||||||
|
<meta
|
||||||
|
property="og:description"
|
||||||
|
content="Post a pickup game at UF, or ask to join one. Fifteen sports on the courts and fields you already walk past. Free, nothing to install, and the host approves everyone who plays."
|
||||||
|
/>
|
||||||
|
<meta property="og:url" content="https://pullup.onetouch.studio/" />
|
||||||
|
<meta property="og:locale" content="en_US" />
|
||||||
|
<meta property="og:image" content="https://pullup.onetouch.studio/og.png" />
|
||||||
|
<meta property="og:image:type" content="image/png" />
|
||||||
|
<!-- Declared dimensions let a client lay out the card before the image has
|
||||||
|
downloaded, which is the difference between a preview that appears with
|
||||||
|
the message and one that pops in a second later. -->
|
||||||
|
<meta property="og:image:width" content="1200" />
|
||||||
|
<meta property="og:image:height" content="630" />
|
||||||
|
<meta
|
||||||
|
property="og:image:alt"
|
||||||
|
content="The Pull Up mark on a near-black field, above the line: There is a game on tonight."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
|
<meta name="twitter:title" content="Pull Up — Pickup sports at UF" />
|
||||||
|
<meta
|
||||||
|
name="twitter:description"
|
||||||
|
content="Post a pickup game at UF, or ask to join one. Fifteen sports on the courts and fields you already walk past. Free, nothing to install, and the host approves everyone."
|
||||||
|
/>
|
||||||
|
<meta name="twitter:image" content="https://pullup.onetouch.studio/og.png" />
|
||||||
|
<meta
|
||||||
|
name="twitter:image:alt"
|
||||||
|
content="The Pull Up mark on a near-black field, above the line: There is a game on tonight."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- Icons. Every one of these is a fixed path in `public/`, because Metro
|
||||||
|
content-hashes anything it bundles and a manifest cannot point at a
|
||||||
|
name that changes each build. Placed by design/web-assets.mjs from the
|
||||||
|
cuts in design/brand/. The .ico goes first with `sizes="any"`: that is
|
||||||
|
the ordering that makes a browser which understands SVG take the SVG
|
||||||
|
and one which does not fall back cleanly. -->
|
||||||
|
<link rel="icon" href="/favicon.ico" sizes="any" />
|
||||||
|
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png" />
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16.png" />
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||||
|
<link rel="manifest" href="/site.webmanifest" />
|
||||||
|
|
||||||
|
<meta name="theme-color" content="#0C0C0E" />
|
||||||
|
<meta name="color-scheme" content="dark" />
|
||||||
|
|
||||||
|
<!-- Add-to-home-screen. This is not decoration: iOS will not deliver a web
|
||||||
|
push at all unless the site has been added to the home screen, so the
|
||||||
|
standalone metadata is load-bearing for notifications, not just for
|
||||||
|
looks. `black` rather than `black-translucent` because the viewport is
|
||||||
|
not `viewport-fit=cover` — translucent without cover leaves a white
|
||||||
|
band above a near-black app. -->
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
|
<meta name="mobile-web-app-capable" content="yes" />
|
||||||
|
<meta name="apple-mobile-web-app-title" content="Pull Up" />
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||||
|
<meta name="application-name" content="Pull Up" />
|
||||||
|
|
||||||
|
<!-- Archivo, the app's face. `lib/theme.ts` asks every screen for it and
|
||||||
|
until this line shipped nothing ever loaded it, so the whole product
|
||||||
|
rendered in the system UI font. It belongs in the document rather than
|
||||||
|
in the JS bundle: a font requested by a chunk that has not parsed yet
|
||||||
|
starts downloading a second too late. -->
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@75..125,400..900&display=swap"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
|
||||||
<!-- The `react-native-web` recommended style reset: https://necolas.github.io/react-native-web/docs/setup/#root-element -->
|
<!-- The `react-native-web` recommended style reset: https://necolas.github.io/react-native-web/docs/setup/#root-element -->
|
||||||
<style id="expo-reset">
|
<style id="expo-reset">
|
||||||
/* These styles make the body full-height */
|
/* These styles make the body full-height */
|
||||||
|
|
@ -23,7 +123,53 @@
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<link rel="icon" href="/favicon.ico"/></head>
|
|
||||||
|
<style id="pullup-base">
|
||||||
|
html, body { background: #0C0C0E; color-scheme: dark; }
|
||||||
|
body { font-family: Archivo, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }
|
||||||
|
|
||||||
|
/* One soft light source behind everything so large dark areas have
|
||||||
|
depth instead of reading as a flat void. Fixed, so it does not
|
||||||
|
travel with the scroll. */
|
||||||
|
body::before {
|
||||||
|
content: "";
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
/* Barely there. Enough that a large dark area is not flat,
|
||||||
|
not enough to read as a coloured glow. */
|
||||||
|
background:
|
||||||
|
radial-gradient(60rem 40rem at 82% -10%, rgba(143,227,136,0.045), transparent 60%),
|
||||||
|
radial-gradient(50rem 36rem at 4% 106%, rgba(255,255,255,0.02), transparent 58%);
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
#root { position: relative; z-index: 1; }
|
||||||
|
|
||||||
|
::selection { background: rgba(143,227,136,0.25); }
|
||||||
|
|
||||||
|
/* The default scrollbar on a dark page is a bright grey slab. */
|
||||||
|
* { scrollbar-width: thin; scrollbar-color: rgba(255,255,255,0.16) transparent; }
|
||||||
|
*::-webkit-scrollbar { width: 10px; height: 10px; }
|
||||||
|
*::-webkit-scrollbar-thumb {
|
||||||
|
background: rgba(255,255,255,0.14);
|
||||||
|
border-radius: 99px;
|
||||||
|
border: 3px solid transparent;
|
||||||
|
background-clip: content-box;
|
||||||
|
}
|
||||||
|
*::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.24); background-clip: content-box; }
|
||||||
|
*::-webkit-scrollbar-track { background: transparent; }
|
||||||
|
|
||||||
|
input, textarea { font-family: inherit; }
|
||||||
|
/* Autofill repaints Chrome inputs white, which looks broken here. */
|
||||||
|
input:-webkit-autofill,
|
||||||
|
input:-webkit-autofill:hover,
|
||||||
|
input:-webkit-autofill:focus {
|
||||||
|
-webkit-text-fill-color: #EDEDEF;
|
||||||
|
-webkit-box-shadow: 0 0 0 1000px #141417 inset;
|
||||||
|
transition: background-color 9999s ease-in-out 0s;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<!-- Use static rendering with Expo Router to support running without JavaScript. -->
|
<!-- Use static rendering with Expo Router to support running without JavaScript. -->
|
||||||
|
|
@ -32,6 +178,6 @@
|
||||||
</noscript>
|
</noscript>
|
||||||
<!-- The root element for your Expo app. -->
|
<!-- The root element for your Expo app. -->
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<script src="/_expo/static/js/web/entry-87229ee88c358aff8c4dc06b2c66745f.js" defer></script>
|
<script src="/_expo/static/js/web/entry-0378b3b321364495a1241c81b00660ae.js" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
BIN
og.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
21
site.webmanifest
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"id": "/",
|
||||||
|
"name": "Pull Up — Pickup sports at UF",
|
||||||
|
"short_name": "Pull Up",
|
||||||
|
"description": "Post a pickup game at UF, or ask to join one. Fifteen sports on the courts and fields you already walk past. Free, nothing to install, and the host approves everyone who plays.",
|
||||||
|
"lang": "en-US",
|
||||||
|
"dir": "ltr",
|
||||||
|
"start_url": "/",
|
||||||
|
"scope": "/",
|
||||||
|
"display": "standalone",
|
||||||
|
"background_color": "#0C0C0E",
|
||||||
|
"theme_color": "#0C0C0E",
|
||||||
|
"categories": ["sports", "social"],
|
||||||
|
"icons": [
|
||||||
|
{ "src": "/icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any" },
|
||||||
|
{ "src": "/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any" },
|
||||||
|
{ "src": "/icon-maskable-192.png", "sizes": "192x192", "type": "image/png", "purpose": "maskable" },
|
||||||
|
{ "src": "/icon-maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" },
|
||||||
|
{ "src": "/apple-touch-icon.png", "sizes": "180x180", "type": "image/png", "purpose": "any" }
|
||||||
|
]
|
||||||
|
}
|
||||||
15
sw.js
|
|
@ -68,9 +68,18 @@ async function handlePush(event) {
|
||||||
|
|
||||||
await self.registration.showNotification(title, {
|
await self.registration.showNotification(title, {
|
||||||
body,
|
body,
|
||||||
// The maskable icon already in the export. No emoji anywhere in this app.
|
/* Both of these must be fixed paths in this same public/ folder. They used
|
||||||
icon: '/assets/icon.png',
|
* to point at `/assets/icon.png`, which has never existed in an export —
|
||||||
badge: '/assets/icon.png',
|
* Metro content-hashes everything it bundles, so nothing it produces has a
|
||||||
|
* stable name, and every notification this app has ever shown fell back to
|
||||||
|
* the browser's own generic glyph. Verify with a HEAD request against a
|
||||||
|
* deployed build before changing either.
|
||||||
|
*
|
||||||
|
* Android reduces `badge` to a monochrome silhouette, so it gets the
|
||||||
|
* white-on-transparent cut rather than the full icon, which would come back
|
||||||
|
* as an unreadable grey blob. No emoji anywhere in this app. */
|
||||||
|
icon: '/icon-192.png',
|
||||||
|
badge: '/badge-96.png',
|
||||||
/* Collapse by conversation. Five chat messages from one game should be one
|
/* Collapse by conversation. Five chat messages from one game should be one
|
||||||
* line on the lock screen, not five -- `renotify` still buzzes for each so
|
* line on the lock screen, not five -- `renotify` still buzzes for each so
|
||||||
* nothing is silently swallowed. A notification with no session falls back
|
* nothing is silently swallowed. A notification with no session falls back
|
||||||
|
|
|
||||||