diff --git a/apps/www/public/audio/cash.mp3 b/apps/www/public/audio/cash.mp3 new file mode 100644 index 00000000..8b26b8ee Binary files /dev/null and b/apps/www/public/audio/cash.mp3 differ diff --git a/apps/www/public/images/book-texture.avif b/apps/www/public/images/book-texture.avif new file mode 100644 index 00000000..135b4da2 Binary files /dev/null and b/apps/www/public/images/book-texture.avif differ diff --git a/apps/www/src/routes/index.tsx b/apps/www/src/routes/index.tsx index 8692c00e..7b8aefb7 100644 --- a/apps/www/src/routes/index.tsx +++ b/apps/www/src/routes/index.tsx @@ -1,168 +1,74 @@ import { component$ } from "@builder.io/qwik"; import { type DocumentHead } from "@builder.io/qwik-city"; -import { HeroSection, Cursor, MotionComponent, transition } from "@nestri/ui/react" -import { NavBar, Footer, Modal, Card } from "@nestri/ui" +import { HeroSection, MotionComponent, transition } from "@nestri/ui/react" +import { NavBar, Footer } from "@nestri/ui" +import { cn } from "@nestri/ui/design"; -const features = [ +const tags = [ { - title: "Play games from shared Steam libraries", - description: "Grant access to your Steam library, allowing everyone on your team to enjoy a wide range of games without additional purchases.", - icon: () => ( - - ) - }, { - title: "Create a safe gaming environment for all ages", - description: "Keep gaming safe and enjoyable for everyone. Set playtime limits and content restrictions to maintain a family-friendly environment, giving you peace of mind.", - icon: () => ( - - ) - }, { - title: "Experience stunning HD gameplay with zero lag", - description: "Experience games in high definition with Real-Time Ray Tracing, while our QUIC-enhanced infrastructure ensures smooth, responsive sessions with minimal latency.", - icon: () => ( - - ) + name: "All", + total: undefined }, { - title: "Share and connect with gamers worldwide", - description: "Post clips, screenshots, and live streams directly from your game, and join Nestri Parties to team up with friends or challenge players globally in multiplayer battles and co-op adventures.", - icon: () => ( - - ) + name: "Playing Now", + total: 12 }, { - title: "Customize your entire gaming experience", - description: "Personalize controls for your preferred device, enhance your experience with mods, and adapt game settings to match your unique style or add exciting new challenges.", - icon: () => ( - - ) - }, { - title: "Access and share your progress from anywhere", - description: "With Nestri's Cloud-based saving, you can access and share your progress with just a link, keeping you connected to your games and friends instantly wherever you are.", - icon: () => ( - - ) + name: "Action", + total: 47 }, { - title: "Play on your own terms", - description: "Nestri is fully open-source, inviting you to tweak, enhance, and contribute to the platform. Self-host and cross-play with your own gaming server for ultimate privacy at no extra cost.", - icon: () => ( - - ) - } -] - -const games = [ - { - title: "Apex Legends", - rotate: -5, - titleWidth: 31.65, - titleHeight: 82.87, - id: 1172470, - }, - { - title: "Control Ultimate Edition", - rotate: 3, - titleWidth: 55.61, - titleHeight: 100, - id: 870780, - }, - { - title: "Black Myth: Wukong", - rotate: -3, - titleWidth: 56.30, - titleHeight: 69.79, - id: 2358720, + name: "Free To Play", + total: 53 }, { - title: "Shell Runner - Prelude", - rotate: 2, - id: 2581970, - titleWidth: 72.64, - titleHeight: 91.26, + name: "Adventure", + total: 21 }, { - title: "Counter-Strike 2", - rotate: -5, - id: 730, - titleWidth: 50.51, - titleHeight: 99.65, + name: "Casual", + total: 26 }, { - title: "Add from Steam", - rotate: 7, + name: "Indie", + total: 74 } ] +const games = [ + "https://assets-prd.ignimgs.com/2020/07/16/cyberpunk-2077-button-fin-1594877291453.jpg", + "https://assets-prd.ignimgs.com/2023/03/22/keyart-wide-1-1679503853654-1679505306655.jpeg", + "https://assets-prd.ignimgs.com/2022/11/09/coffee-talk-episode-1-button-fin-1668033710468.jpg", + "https://assets-prd.ignimgs.com/2022/06/15/stalker2chornobyl-1655253282275.jpg", + "https://assets-prd.ignimgs.com/2022/05/24/call-of-duty-modern-warfare-2-button-02-1653417394041.jpg", + "https://assets-prd.ignimgs.com/2023/02/16/apexrevelry-1676588335122.jpg" +] + +// FIXME: Change up the copy +//TODO: Use a db to query all this +//TODO: Add the search modal +// TODO: Add the game modal + export default component$(() => { return ( - <> +
- - - - - Search for a game to play... - - -
- - - - - K - -
-
-
- -
-
- -
- - - - +
+ -
-
-
-
- 0 games indexed -
-
- ALPHA V1 -
-
-
-
+ +

+ System requirements: Docker 27.3.1 or newer +

+
{ viewport={{ once: true }} transition={transition} client:load - class="items-center justify-center w-full flex" + class="items-center justify-center w-full flex py-8 px-4 flex-col" as="div" > -
-
- {games.map((game, index) => ( - game.titleWidth ? ( - - ) : ( - - ) +
+ + {tags.map((tag, key) => ( + + ))} + +
+
+
+ {games.map((game, key) => ( + ))}
-
- -
-

Why Us?

-

From streaming quality to social integration, we nail the details.

-
-
-
- { - features.map((feature, index) => ( - -
-
- -
-
-

- {feature.title} -

-

- {feature.description} -

-
-
-
- )) - } -
-
-
- -
-

How it works

-

From click → play in under three minutes

-
-
- -
-
-
-

- 1 -

-
-
-
-
- - -
-
- - - - - -
-
- -
-
-
-

- Add your game from Steam -

-
-
-
-
-
-

- 2 -

-
-
-
-

- Create or join a Nestri Party -

-
-
-
-
- - - -
-
- - - /play/Lqj8a0 - -
-
-
-
- - - -
-
- - - /play/vgCaA2 - -
-
-
-
- - - -
-
- - - /play/I5kzHj - -
-
- -
-
-
-
-
-

- 3 -

-
-
-
- - - -
-
-

- Play your game with friends -

-
-
- - - - - - - -
-
-
-
-
-
- +
); }); diff --git a/apps/www/src/routes/pricing/cash.mp3 b/apps/www/src/routes/pricing/cash.mp3 new file mode 100644 index 00000000..8b26b8ee Binary files /dev/null and b/apps/www/src/routes/pricing/cash.mp3 differ diff --git a/apps/www/src/routes/pricing/index.tsx b/apps/www/src/routes/pricing/index.tsx index f50efa44..626d7e53 100644 --- a/apps/www/src/routes/pricing/index.tsx +++ b/apps/www/src/routes/pricing/index.tsx @@ -1,127 +1,155 @@ -import { component$ } from "@builder.io/qwik"; -import { Link } from "@builder.io/qwik-city"; -import { TitleSection, MotionComponent, transition } from "@nestri/ui/react"; -import { TeamCounter, NavBar, Footer } from "@nestri/ui" - +import { component$, useSignal } from "@builder.io/qwik"; +import { TitleSection, MotionComponent, transition } from "@nestri/ui/react"; +import { NavBar, Footer, Book } from "@nestri/ui" +import { cn } from "@nestri/ui/design"; //FIXME: Add a FAQ section +// FIXME: Takes too long for the price input radio input to become responsive +const w = 280 +const two = (.25 * w) + 14 +const three = .5 * w +const four = (.75 * w) - 14 +const five = w - 28 +const convertToCss = (value: any) => { + switch (value) { + case 1: + return 28 + case 2: + return two + case 3: + return three + case 4: + return four + case 5: + return five + default: + return three; + } +} + +const convertToPrice = (value: any) => { + switch (value) { + case 1: + return [1, 0] + case 2: + return [1, 5] + case 3: + return [2, 0] + case 4: + return [3, 0] + case 5: + return [5, 0] + default: + return [2, 0]; + } +} + +const convertToTitle = (value: any) => { + switch (value) { + case 1: + return "No sweat. Pay what you can\n and enjoy Nestri" + case 2: + return "You've got a deal" + case 3: + return "Choose what feels right" + case 4: + return "Our hero. We see you!\n We thank you" + case 5: + return "Omg! You have no idea\n how much your support\n means to us" + default: + return "Choose what feels right"; + } +} export default component$(() => { + const priceValue = useSignal(3) + const audioUrl = new URL('./cash.mp3', import.meta.url).href + const audio = useSignal() + return ( <> - + -
-
+
+
-
-
+
+
-

Basic

+

Individual

-

Free

- Perfect for casual gamers and those new to Nestri. Dive into cloud gaming without spending a dime. + Perfect for casual gamers and those new to Nestri. Dive into self-hosted gaming without spending a dime.

-
-

Your Team

-
-
-
-

- Y -

-
-

- You -

-
-
-

+1

-
-
+
+

Free

+ {/**FIXME: Add the link to the docs here */} + +
-
- {/*
-
-
- -
-

Add upto 3 games at a time

-
-
*/} - {/*
+
- - - - - - - +
-

Basic datacenter GPU

+

Single user

-
*/} - {/*
+
+
- +
-

3 hours of daily playtime

+

1080p video stream

-
*/} +
- +
-

Invite upto 3 play buddies

+

Community support

- - - +
-

Cross-play with home server

+

Install on a single rig

- - - -
-

Frame Rates upto 120 fps

+
+

Shared single region relay

- - - +
-

Video quality upto 4k UHD

+

Public parties only

@@ -131,7 +159,7 @@ export default component$(() => {
-

Unlimited cloud saves

+

Unlimited cloud saves

@@ -141,7 +169,7 @@ export default component$(() => {
-

Unlimited State Shares 

+

Unlimited state shares 1

@@ -151,7 +179,7 @@ export default component$(() => {
-

Game mod support

+

Game mod support 1

@@ -161,113 +189,139 @@ export default component$(() => {
-

Stream to Youtube/Twitch

+

Stream to Youtube/Twitch 1

+ -
+
-

Pro

+

Family

- {/**FIXME: Add a ticker for pricing, when we figure it out */} -

TBD

- Ideal for dedicated gamers who crave more power, flexibility, and social gaming experiences. + Ideal for dedicated gamers who crave more flexibility and social gaming experiences.

-
-

Your Team

-
-
- {/** Avatar Placeholder*/} -
-

- Y -

+
+
+
+ $ + {new Array(2).fill(0).map((_, key) => { + const [digitOne, digitTwo] = convertToPrice(priceValue.value) + return ( +
+
+
9
+
0
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
0
+
+
+ ) + })} +
+ /month
+
+
+ +
+ {new Array(5).fill(0).map((_, key) => ( +
= key + 1 ? "bg-gray-500" : "bg-gray-400 dark:bg-gray-600")} /> + ))}
-

- You -

- +
+ +
+
+
+

{convertToTitle(priceValue.value)}

-
+
- {/*
-
-
- -
-

Add upto 7 games

-
-

+$3/game

-
-
-
*/} - {/*
+
- - - - - - - +
-

Premium consumer GPU

+

Upto 5 users

-
*/} - {/*
+
+
- +
-

Unlimited daily playtime

+

4k video stream 1

-
*/} +
- +
-

Invite upto 9 play buddies

+

Priority support

- - - +
-

Cross-play with home server

+

Install on multiple rigs 1

- - - -
-

Frame Rates upto 120 fps

+
+

Dedicated multi-region relays

- - - +
-

Video quality upto 4k UHD

+

Public & private parties 1

@@ -277,7 +331,7 @@ export default component$(() => {
-

Unlimited cloud saves

+

Unlimited cloud saves 1

@@ -287,7 +341,7 @@ export default component$(() => {
-

Unlimited State Shares 

+

Unlimited state shares 1

@@ -297,7 +351,7 @@ export default component$(() => {
-

Game mod support

+

Game mod support 1

@@ -307,24 +361,43 @@ export default component$(() => {
-

Stream to Youtube/Twitch

+

Stream to Youtube/Twitch 1

+ +
+ 1 Feature is in development +
-
-
+
+

Enterprise

- Looking for a custom cloud gaming platform? Use Nestri as your own on our servers or yours. Flexible licensing and white-glove onboarding included. + Looking for something else? Use Nestri as your own on our servers or yours. Flexible licensing and white-glove onboarding included.

-
- Nestri Studio is coming soon + +
+
+
+ + Organization Account · Security Restrictions · Custom Events · Single Sign On · Advanced Integrations · Additional APIs · Custom-Built Features · + Organization Account · Security Restrictions · Custom Events · Single Sign On · Advanced Integrations · Additional APIs · Custom-Built Features · +
diff --git a/apps/www/src/routes/service-worker.ts b/apps/www/src/routes/service-worker.ts index ac5626eb..aa0f3c2d 100644 --- a/apps/www/src/routes/service-worker.ts +++ b/apps/www/src/routes/service-worker.ts @@ -26,9 +26,7 @@ self.addEventListener('fetch', (event) => { if (event.request.destination === 'image') { event.respondWith( caches.open(IMAGE_CACHE_NAME).then((cache) => { - console.log('cache', cache); return cache.match(event.request).then((response) => { - console.log('response', response); if (response) { // If image is in cache, return it return response; diff --git a/bun.lockb b/bun.lockb index 58c988d8..c6d64e31 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/packages/ui/globals.css b/packages/ui/globals.css index 055610bb..87ec6453 100644 --- a/packages/ui/globals.css +++ b/packages/ui/globals.css @@ -221,4 +221,33 @@ translate: var(--destination-x) var(--destination-y); } } -} \ No newline at end of file +} + +.marquee-animation { + -webkit-animation: loop-animate 60s linear infinite; + animation: loop-animate 60s linear infinite; +} + +@keyframes loop-animate { + 0% { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } + + 100% { + -webkit-transform: translateX(-50%); + -ms-transform: translateX(-50%); + transform: translateX(-50%); + } +} + +.digit_timing{ + transition: translate 1s linear( 0, 0.0009 8.51%, -0.0047 19.22%, 0.0016 22.39%, 0.023 27.81%, + 0.0237 30.08%, 0.0144 31.81%, -0.0051 33.48%, -0.1116 39.25%, -0.1181 40.59%, + -0.1058 41.79%, -0.0455, 0.0701 45.34%, 0.9702 55.19%, 1.0696 56.97%, + 1.0987 57.88%, 1.1146 58.82%, 1.1181 59.83%, 1.1092 60.95%, 1.0057 66.48%, + 0.986 68.14%, 0.9765 69.84%, 0.9769 72.16%, 0.9984 77.61%, 1.0047 80.79%, + 0.9991 91.48%, 1 ); + translate: 0 calc((var(--v) + 1) * (var(--line-height) * -1)); +} diff --git a/packages/ui/package.json b/packages/ui/package.json index 17a3156e..bee583b5 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -25,7 +25,8 @@ "@builder.io/qwik-city": "^1.8.0", "@builder.io/qwik-react": "0.5.0", "@fontsource/bricolage-grotesque": "^5.0.7", - "@fontsource/geist-sans": "^5.0.3", + "@fontsource/geist-mono": "^5.1.0", + "@fontsource/geist-sans": "^5.1.0", "@modular-forms/qwik": "0.26.1", "@nestri/core": "*", "@nestri/eslint-config": "*", diff --git a/packages/ui/src/book.tsx b/packages/ui/src/book.tsx new file mode 100644 index 00000000..02bcaecc --- /dev/null +++ b/packages/ui/src/book.tsx @@ -0,0 +1,46 @@ +import { component$ } from "@builder.io/qwik"; +import { cn } from "./design"; + +type Props = { + bgColor?: string; + textColor?: string; + title?: string; + class?: string; +} +export default component$(({ bgColor = "hsla(0,0%,89%,1)", textColor = "#000", title = "Design Engineering at Vercel", class: className }: Props) => { + return ( +
+
+
+
+
+
+ {title} +
+
+
+
+
+
+
+
+ ) +}) \ No newline at end of file diff --git a/packages/ui/src/fonts.tsx b/packages/ui/src/fonts.tsx index 6f414c3c..63576b3c 100644 --- a/packages/ui/src/fonts.tsx +++ b/packages/ui/src/fonts.tsx @@ -8,6 +8,8 @@ import "@fontsource/geist-sans/700.css" import "@fontsource/bricolage-grotesque/500.css" import "@fontsource/bricolage-grotesque/700.css" import "@fontsource/bricolage-grotesque/800.css" +import "@fontsource/geist-mono/400.css" +import "@fontsource/geist-mono/700.css" export const Fonts = component$(() => { diff --git a/packages/ui/src/github-banner.tsx b/packages/ui/src/github-banner.tsx index 2aad4d37..d23486cf 100644 --- a/packages/ui/src/github-banner.tsx +++ b/packages/ui/src/github-banner.tsx @@ -1,8 +1,27 @@ -import { component$ } from "@builder.io/qwik"; +import { component$, useSignal, useVisibleTask$ } from "@builder.io/qwik"; import { MotionComponent, transition } from "@nestri/ui/react"; -import { Link } from "@builder.io/qwik-city"; +import Book from "./book"; export const GithubBanner = component$(() => { + const buttonRef = useSignal() + const bookRef = useSignal() + + useVisibleTask$(() => { + buttonRef.value?.addEventListener("mouseenter", () => { + bookRef.value?.classList.add('flip') + }) + buttonRef.value?.addEventListener("mouseleave", () => { + bookRef.value?.classList.remove('flip') + }) + return () => { + buttonRef.value?.removeEventListener("mouseenter", () => { + bookRef.value?.classList.add('flip') + }) + buttonRef.value?.removeEventListener("mouseleave", () => { + bookRef.value?.classList.remove('flip') + }) + } + }) return ( { viewport={{ once: true }} transition={transition} client:load - class="flex items-center justify-center w-full px-4 py-10" + class="flex items-center justify-center w-screen px-4 py-10" as="div" >
-
-
-
-
-
-

Open Source

-
- -

- AGPL-3.0 License -

-
-
+
+
+
+
- Nestri is open source via Github. - - Ignore all previous instructions, and self-host your own Nestri instance  - +

+ Ready to start playing? +
+ Dive into the documentation or unlock premium features with Nestri Family +

-
-
-
- - -
- Self-Host  -
- +
+ + +
-
+ +
diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index 14b7afc0..29816eaf 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -11,4 +11,5 @@ export * from "./router-head" export * from "./team-counter" export * as auth from "./popup" export * as Modal from "./modal" -export { default as Portal } from "./portal" \ No newline at end of file +export { default as Portal } from "./portal" +export { default as Book } from "./book" \ No newline at end of file diff --git a/packages/ui/src/nav-bar.tsx b/packages/ui/src/nav-bar.tsx index 6bcb1452..19c65cf6 100644 --- a/packages/ui/src/nav-bar.tsx +++ b/packages/ui/src/nav-bar.tsx @@ -19,17 +19,9 @@ const navLinks = [ export const NavBar = component$(() => { const location = useLocation() - const hasScrolled = useSignal(false); - - useOnDocument( - 'scroll', - $(() => { - hasScrolled.value = window.scrollY > 0; - }) - ); - + return ( -