feat!: monorepo landing page (#1868)

## Description

Monorepos the [landing website](https://photonvision.org)

## Meta

Merge checklist:
- [x] @mcm001 migrates all the secrets over to this repo
- [x] Add label for website stuff
- [ ] Archive the old website repo
- [x] Website gets cleaned up
This commit is contained in:
Sam Freund
2025-04-10 22:03:37 -05:00
committed by GitHub
parent c26a7cc5ac
commit 163dbe58e4
20 changed files with 7091 additions and 0 deletions

28
.github/workflows/website.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
name: Website Build
on:
push:
# For now, run on all commits to main
branches: [ main ]
# and also all tags starting with v
tags:
- 'v*'
jobs:
rsync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
- name: Install packages
run: npm ci
- name: Build project
run: npm run build
- uses: up9cloud/action-rsync@v1.4
env:
HOST: ${{ secrets.WEBMASTER_SSH_HOST }}
USER: ${{ secrets.WEBMASTER_SSH_USERNAME }}
KEY: ${{secrets.WEBMASTER_SSH_KEY}}
SOURCE: /website/dist/*
TARGET: /var/www/html/photonvision-website

View File

@@ -19,6 +19,9 @@ modifiableFileExclude {
\.webp$
\.ico$
\.rknn$
\.mp4$
\.ttf$
\.woff2$
gradlew
photon-lib/py/photonlibpy/generated/
photon-targeting/src/main/native/cpp/photon/constrained_solvepnp/generate/

3
website/README.md Executable file
View File

@@ -0,0 +1,3 @@
# photovision-website
PhotonVision's landing page!

23
website/favicon.svg Normal file
View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 508 507" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-1279,0)">
<g id="PhotonVision-Icon-BG" transform="matrix(0.264062,0,0,0.469444,1279.5,0)">
<rect x="0" y="0" width="1920" height="1080" style="fill:none;"/>
<clipPath id="_clip1">
<rect x="0" y="0" width="1920" height="1080"/>
</clipPath>
<g clip-path="url(#_clip1)">
<g transform="matrix(4.27015,0,0,2.40196,-20444.8,-3235.56)">
<circle cx="5012.55" cy="1571.77" r="224.918" style="fill:rgb(0,100,146);"/>
</g>
<g transform="matrix(4.95901,0,0,2.78944,-13955,-10313.5)">
<path d="M3055.09,3977.51C3050.3,3984.25 3045,3990.56 3039.21,3996.35C2987.91,4047.65 2917.1,4038.77 2881.16,3976.54C2845.23,3914.3 2857.71,3822.13 2909.01,3770.83C2960.31,3719.53 3031.13,3728.41 3067.06,3790.64C3069.85,3795.48 3072.35,3800.49 3074.56,3805.67L3039.78,3811.64C3012.82,3769.64 2962.9,3764.58 2926.45,3801.04C2888.89,3838.59 2879.76,3906.07 2906.07,3951.63C2932.37,3997.19 2984.22,4003.69 3021.77,3966.14L3021.89,3966.01L3055.09,3977.51ZM3085.02,3841.47C3090.86,3875.56 3086.6,3912.35 3073.22,3944.57L3043.91,3934.42C3056.74,3907.59 3060.53,3875.54 3054.13,3846.78L3085.02,3841.47Z" style="fill:white;"/>
</g>
<g transform="matrix(4.95901,0,0,2.78944,-13955,-3827.86)">
<path d="M2906.78,1571.77L3111.02,1642.48L3116.61,1626.34L3147.2,1664.74L3099.42,1675.99L3105,1659.86L2910.03,1592.35C2908.25,1585.69 2907.18,1578.77 2906.78,1571.77ZM2917.45,1517.07L3114.77,1483.17L3111.88,1466.34L3157.2,1485.21L3120.78,1518.13L3117.88,1501.3L2910.22,1536.97C2911.99,1530.09 2914.41,1523.4 2917.45,1517.07Z" style="fill:rgb(255,216,67);"/>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
website/images/demo.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

338
website/index.html Executable file
View File

@@ -0,0 +1,338 @@
<!doctype html>
<html lang="en-US">
<!-- TODO: We need more images and videos to improve quality of the site- if you can see this and have PhotonVision, take a screenshot of yourself using it and send it to the #media channel in Discord!-->
<head>
<title>PhotonVision</title>
<link rel="icon" href="favicon.svg" type="image/svg+xml" />
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="src/css/main.css" />
<link rel="stylesheet" href="src/css/fontawesome.min.css" />
<link rel="stylesheet" href="src/css/brands.min.css" />
<link rel="stylesheet" href="src/css/solid.min.css" />
<meta name="title" content="PhotonVision" />
<meta
name="description"
content="PhotonVision is the free, fast, and easy-to-use computer vision solution for the FIRST Robotics Competition."
/>
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website" />
<meta property="og:url" content="https://photonvision.org/" />
<meta property="og:title" content="PhotonVision" />
<meta
property="og:description"
content="PhotonVision is the free, fast, and easy-to-use computer vision solution for the FIRST Robotics Competition."
/>
<meta
property="og:image"
content="https://photonvision.org/images/PhotonVision-Icon-BG_2.png"
/>
</head>
<body class="home bg-zinc-900 font-light text-white w-screen">
<div id="page-wrapper" class="h-screen overflow-y-auto scroll-smooth">
<!-- Header -->
<header
id="header"
class="bg-zinc-800 flex md:justify-end sticky top-0 w-full z-10"
>
<button
class="header-btn hover:bg-zinc-700 cursor-pointer flex md:!hidden"
popovertarget="mobile-nav"
aria-label="Open mobile navigation menu"
>
<i class="fa-solid fa-bars !leading-[24px]"></i>
</button>
<div class="relative">
<div
popover
id="mobile-nav"
class="h-screen starting:open:-translate-x-50 open:translate-0 transition-transform -translate-x-50 relative duration-400 transition-discrete bg-zinc-700 open:flex open:flex-col md:open:hidden"
>
<a
href="https://docs.photonvision.org/en/latest/"
class="header-btn"
>Documentation</a
>
<a href="https://discord.gg/wYxTwym" class="header-btn">Discord</a>
<a
href="https://github.com/PhotonVision/photonvision/"
class="header-btn"
>GitHub</a
>
<a
href="https://my-store-cec24b.creator-spring.com/"
class="header-btn"
>Merch</a
>
<a
href="https://demo.photonvision.org"
class="header-btn bg-primary"
>Demo</a
>
</div>
</div>
<nav id="nav" class="hidden md:flex">
<a href="https://docs.photonvision.org/en/latest/" class="header-btn"
>Documentation</a
>
<a href="https://discord.gg/wYxTwym" class="header-btn">Discord</a>
<a
href="https://github.com/PhotonVision/photonvision/"
class="header-btn"
>GitHub</a
>
<a
href="https://my-store-cec24b.creator-spring.com/"
class="header-btn"
>Merch</a
>
<a href="https://demo.photonvision.org" class="header-btn bg-primary"
>Demo</a
>
</nav>
</header>
<!-- One -->
<section
class="flex flex-col h-[calc(100vh_-_56px)] justify-center items-center p-8 md:p-0 relative"
>
<div class="flex justify-center md:justify-end flex-col md:flex-row">
<header
class="flex flex-col gap-4 items-center md:items-end justify-center text-center md:text-end"
>
<h2 class="text-4xl">PhotonVision</h2>
<div class="text-xl max-w-128">
PhotonVision is the free, fast, and easy-to-use computer vision
solution for the FIRST® Robotics Competition. Teams can download
a PhotonVision image for select coprocessors and start tracking
targets in minutes.
</div>
<a
href="https://docs.photonvision.org/en/latest/docs/quick-start/quick-install.html"
class="bg-primary py-4 px-8 rounded grow-0 self-center md:self-end"
>Get Started</a
>
</header>
<span class="self-center md:self-initial mt-8 md:ms-8 shrink"
><img
src="images/PhotonVision-Icon-BG.png"
alt="PhotonVision Logo"
class="max-w-64"
/></span>
</div>
<a href="#two" class="absolute bottom-0 p-4">
<i class="fa-solid fa-chevron-down"></i>
</a>
</section>
<!-- Two -->
<section
id="two"
class="h-[calc(100vh_-_56px)] relative justify-center flex items-center"
>
<span class="image fit"
><img
src="images/demo.png"
alt="Demo of PhotonVision UI"
loading="lazy"
/></span>
<a href="#three" class="absolute bottom-0 p-4"
><i class="fa-solid fa-chevron-down"></i
></a>
</section>
<!-- Three -->
<section
id="three"
class="min-h-[calc(100vh_-_56px)] flex flex-col gap-4 items-center justify-center px-4 md:px-14 lg:px-28 relative"
>
<header
class="flex flex-col gap-4 justify-center items-center text-center"
>
<h2 class="text-3xl">The Future is in Sight</h2>
<p class="text-2xl">
PhotonVision is a powerful, open-source vision system for FRC. It's
designed to be fast and easy to use, regardless of your team's
financial or technical resources.
</p>
<hr class="border-brand-yellow border-2 w-64 mb-4" />
</header>
<div class="mb-8 lg:mb-0">
<div
class="grid max-w-xl grid-cols-1 gap-x-8 gap-y-10 lg:max-w-none lg:grid-cols-2 lg:gap-y-16"
>
<section class="relative pl-16">
<div class="features-icon">
<i class="fa-solid fa-location-arrow"></i>
</div>
<h3 class="text-lg mb-2">First-Class AprilTag Support</h3>
<p>FRC Target tracking, out of the box.</p>
</section>
<section class="relative pl-16">
<div class="features-icon">
<i class="icon alt major fa-solid fa-chess-board"></i>
</div>
<h3 class="text-lg mb-2">Built-In Camera Calibration</h3>
<p>
Per-camera intrinsics calibration maximizes accuracy of
homography
</p>
</section>
<section class="relative pl-16">
<div class="features-icon">
<i class="icon alt major fa-solid fa-brain"></i>
</div>
<h3 class="text-lg mb-2">Machine Learning</h3>
<p>Hardware-accelerated inferencing for gamepiece detection</p>
</section>
<section class="relative pl-16">
<div class="features-icon">
<i class="icon alt major fa-solid fa-eye"></i>
</div>
<h3 class="text-lg mb-2">Driver Mode Integration</h3>
<p>You can use the same camera for driving and robot vision</p>
</section>
<section class="relative pl-16">
<div class="features-icon">
<i class="icon alt major fa-solid fa-camera"></i>
</div>
<h3 class="text-lg mb-2">Simultaneous Multi-Camera Operation</h3>
<p>
PhotonVision can run as many cameras as your hardware can handle
</p>
</section>
<section class="relative pl-16">
<div class="features-icon">
<i class="icon alt major fa-solid fa-layer-group"></i>
</div>
<h3 class="text-lg mb-2">Multi-Tag Pose Estimation</h3>
<p>Fuse all your available data for peak robot performance</p>
</section>
</div>
</div>
<a href="#four" class="absolute bottom-0 p-4"
><i class="fa-solid fa-chevron-down"></i
></a>
</section>
<!-- Four -->
<section id="four">
<div class="">
<video
src="images/in-action.mp4"
playsinline
autoplay
loop
muted
loading="lazy"
class="w-full h-[calc(100vh_-_56px)] object-cover bottom-0 relative"
></video>
</div>
</section>
<section
id="five"
class="flex flex-col md:flex-row items-center justify-between relative mt-8 py-8 px-28 gap-8 bg-primary"
>
<header
class="flex flex-col gap-4 justify-center items-center text-center"
>
<h2 class="text-3xl">Champs 2024 Talk</h2>
<div class="flex gap-2 mb-4">
<a
href="https://docs.google.com/presentation/d/1Gh5InslM5p7aDxjzK8DHoEorpATOl-MQWWixY5GjGgs/edit#slide=id.p"
class="bg-brand-blue py-4 px-8 rounded grow-0 text-nowrap"
>Slide Deck</a
>
<a
href="https://github.com/PhotonVision/champs_2024"
class="bg-brand-blue py-4 px-8 rounded grow-0 text-nowrap"
>Code</a
>
</div>
</header>
<div class="self-stretch contents">
<iframe
src="https://www.youtube-nocookie.com/embed/iV2v7F_9GwE?si=4wgaT1IrZBpA71dF"
title="YouTube video player"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerpolicy="strict-origin-when-cross-origin"
allowfullscreen
class="max-w-256 aspect-video"
></iframe>
</div>
</section>
<!-- Eight -->
<section
id="six"
class="min-h-[calc(100vh_-_56px)] flex flex-col gap-4 items-center justify-center px-14 lg:px-28"
>
<header
class="flex flex-col gap-4 justify-center items-center text-center"
>
<h2 class="text-3xl">FOSS</h2>
<p class="text-2xl">
PhotonVision is an open-source, community based vision system
designed for use within the FIRST® Robotics Competition that aims
to provide easy and inexpensive vision tracking to teams.
</p>
<hr class="border-brand-yellow border-2 w-64 mb-4" />
</header>
<div>
<div
class="grid max-w-xl grid-cols-1 gap-x-8 gap-y-10 lg:max-w-none lg:grid-cols-2 lg:gap-y-16"
>
<section class="relative pl-16">
<div class="features-icon">
<i class="icon alt major fa-solid fa-check"></i>
</div>
<h3 class="text-lg mb-2">Open Source</h3>
<p>
PhotonVision is the largest FOSS FRC Vision project to date,
constantly being updated with new features and bug fixes.
</p>
</section>
<section class="relative pl-16">
<div class="features-icon">
<i class="icon alt major fa-solid fa-balance-scale"></i>
</div>
<h3 class="text-lg mb-2">GNU GPL v3</h3>
<p>
The GNU GPL v3 license allows you to download, modify and share
source code.
</p>
</section>
<section class="relative pl-16">
<div class="features-icon">
<i class="icon alt major fab fa-github"></i>
</div>
<h3 class="text-lg mb-2">We're on GitHub</h3>
<p>
We do all of our development openly on GitHub. Transparency is
key for every contributor of PhotonVision.
</p>
</section>
</div>
</div>
</section>
<!-- Footer -->
<footer
id="footer"
class="p-14 bg-zinc-700 flex flex-col items-center gap-8"
>
<img
src="images/PhotonVision-Icon-BG.png"
style="width: 50px; height: 50px"
alt="PhotonVision logo"
/>
<ul class="text-sm">
<li>&copy;2025 PhotonVision. All rights reserved.</li>
</ul>
</footer>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

1445
website/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

20
website/package.json Normal file
View File

@@ -0,0 +1,20 @@
{
"name": "photonvision-website",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview"
},
"devDependencies": {
"prettier": "^3.5.3",
"typescript": "~5.7.2",
"vite": "^6.2.0"
},
"dependencies": {
"@tailwindcss/vite": "^4.1.3",
"tailwindcss": "^4.1.3"
}
}

6
website/src/css/brands.min.css vendored Normal file

File diff suppressed because one or more lines are too long

5165
website/src/css/fontawesome.min.css vendored Normal file

File diff suppressed because it is too large Load Diff

23
website/src/css/main.css Executable file
View File

@@ -0,0 +1,23 @@
@import "tailwindcss";
@theme {
--color-primary: #006492;
--color-brand-yellow: #ffd842;
--color-brand-blue: #39a4d6;
}
.header-btn {
@apply hover:text-brand-yellow text-white flex p-4 transition-colors;
}
.features-icon {
@apply absolute top-0 left-0 flex size-10 items-center justify-center rounded-lg bg-brand-blue;
}
.fas::before,
.far::before,
.fab::before,
.fa-solid::before,
.fa-regular::before,
.fa-brands::before,
.fa::before {
content: var(--fa);
}

6
website/src/css/solid.min.css vendored Normal file
View File

@@ -0,0 +1,6 @@
/*!
* Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* Copyright 2024 Fonticons, Inc.
*/
:host,:root{--fa-style-family-classic:"Font Awesome 6 Free";--fa-font-solid:normal 900 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}.fa-solid,.fas{font-weight:900}

1
website/src/main.ts Executable file
View File

@@ -0,0 +1 @@

1
website/src/vite-env.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
/// <reference types="vite/client" />

Binary file not shown.

Binary file not shown.

24
website/tsconfig.json Normal file
View File

@@ -0,0 +1,24 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["src"]
}

5
website/vite.config.ts Normal file
View File

@@ -0,0 +1,5 @@
import { defineConfig } from "vite";
import tailwindcss from "@tailwindcss/vite";
export default defineConfig({
plugins: [tailwindcss()],
});