// site/extras.jsx — nav, download, faq, contact, support, footer const SURFACES = [ { value: 'clay', color: '#C84500', label: 'Clay' }, { value: 'grass', color: '#196B1E', label: 'Grass' }, { value: 'hard', color: '#1A44B0', label: 'Hard' }, ]; function SunIcon() { return ( ); } function MoonIcon() { return ( ); } function Nav({ mode, setMode, palette, setPalette }) { const [scrolled, setScrolled] = React.useState(false); React.useEffect(() => { const h = () => setScrolled(window.scrollY > 60); window.addEventListener('scroll', h, { passive: true }); h(); return () => window.removeEventListener('scroll', h); }, []); const isDark = mode === 'dark'; return ( ); } function WordmarkBand() { return (
SETLY · TENNIS · ATP · WIDGETS · SETLY
); } function Download() { return (
14:09
Wednesday, May 20
03Download

Run it
on your
phone.

Setly is in private TestFlight — currently invite-only while we tune the live activity backbone for the clay swing. Spots open weekly.

βf
TestFlight
iOS 17 or later · ~12 MB · Italian / English
Request invite
{['iPhone 12+', 'iOS 17+', 'StandBy ready', 'Live Activities', 'Lock screen'].map(t => (
· {t}
))}
); } function FAQ() { const [open, setOpen] = React.useState(0); const items = [ { q: "Is Setly free?", a: "Yes — Setly is free during the beta and the v1 launch. A small one-time tip jar (PayPal, Apple Pay) keeps it sustainable." }, { q: "Does it cover WTA?", a: "Yes. Setly covers both ATP and WTA singles. Doubles support is on the way." }, { q: "Where do scores come from?", a: "Setly aggregates publicly available scoring feeds. There can be a 30–90 second delay versus broadcast." }, { q: "What devices are supported?", a: "Any iPhone running iOS 17 or later. iPadOS support arrives in v2.0. The watchOS complication is on the roadmap." }, { q: "Is my data tracked?", a: "No analytics SDKs, no tracking. The app has a login option reserved for future features — it's there for when it's needed, not to collect anything now." }, ]; return (
04Questions

Service
line.

Most questions arrive in the same shape. Here are the answers we keep on the locker-room wall.

{items.map((it, i) => (
setOpen(open === i ? -1 : i)}>
{it.q} +
{it.a}
))}
); } function CTABands() { const [name, setName] = React.useState(""); const [email, setEmail] = React.useState(""); const [device, setDevice] = React.useState(""); const mailto = React.useMemo(() => { const subject = encodeURIComponent("Setly · Beta tester request"); const body = encodeURIComponent(`Ciao Federico!\n\nName: ${name}\nDevice: ${device}\n\nWhy I want in:\n…\n\n— ${email || "(your email)"}`); return `mailto:federico.deduro@gmail.com?subject=${subject}&body=${body}`; }, [name, device, email]); return (
— BETA TESTERS WANTED

Be on the
service line.

We're letting in ~30 testers a week. Tell us who you are and what you watch — we'll send a TestFlight code by email.

{ e.preventDefault(); window.location.href = mailto; }} style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12, marginTop: 28, maxWidth: 560 }}> setName(e.target.value)} style={{ padding: '14px 16px', borderRadius: 12, border: 'none', background: 'rgba(255,255,255,0.18)', color: '#fff', fontSize: 15, fontFamily: 'inherit', outline: 'none' }} /> setDevice(e.target.value)} style={{ padding: '14px 16px', borderRadius: 12, border: 'none', background: 'rgba(255,255,255,0.18)', color: '#fff', fontSize: 15, fontFamily: 'inherit', outline: 'none' }} /> setEmail(e.target.value)} style={{ gridColumn: 'span 2', padding: '14px 16px', borderRadius: 12, border: 'none', background: 'rgba(255,255,255,0.18)', color: '#fff', fontSize: 15, fontFamily: 'inherit', outline: 'none' }} />
Or write directly to federico.deduro@gmail.com
— SUPPORT THE PROJECT

Buy us
a new
string set.

Setly is a one-developer side project. A small tip pays the Apple developer fee, the data feed, and an espresso between match days.

Tip on PayPal
paypal.me/setlyFDD
); } function Footer() { return ( ); } Object.assign(window, { Nav, Download, FAQ, CTABands, Footer, WordmarkBand });