diff --git a/bun.lockb b/bun.lockb
index 895d5db..aa18124 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/package.json b/package.json
index b212b70..3ab3afd 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
"prismjs": "^1.29.0",
"react": "^18",
"react-dom": "^18",
+ "react-icons": "^5.4.0",
"react-use-measure": "^2.1.1"
},
"devDependencies": {
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 8670d40..cd1fcbd 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -5,10 +5,12 @@ import { Container } from '@/components/container'
import { Footer } from '@/components/footer'
import { Gradient } from '@/components/gradient'
import { InterstateRows } from '@/components/interstate-rows'
+import LeftCodeTabs from '@/components/left-code-tabs'
import { Link } from '@/components/link'
import { LogoCluster } from '@/components/logo-cluster'
import { Map } from '@/components/map'
import { Navbar } from '@/components/navbar'
+import RightCodeTabs from '@/components/right-code-tabs'
import { Testimonials } from '@/components/testimonials'
import { Heading, Subheading } from '@/components/text'
import { ChevronRightIcon } from '@heroicons/react/16/solid'
@@ -75,54 +77,7 @@ function BentoSection() {
eyebrow="Free"
title="Open Source"
description="Built by the community, for the community. Always free and open source."
- graphic={
-
-
-
-
-
-
-
- playlistService.jsx
-
-
- artistService.jsx
-
-
-
-
- {
- try {
- const response = await fetch("https://api.spotify.com/v1/me/playlists", {
- headers: {
- Authorization: \`Bearer \${accessToken}\`,
- },
- });
- if (response.ok) {
- const data = await response.json();
- const validPlaylists = data.items.filter(item => item && item.id);
- if (validPlaylists.length > 0) {
- const imageUrl = validPlaylists[0].images[0]?.url;
- if (imageUrl) {
- localStorage.setItem("libraryImage", imageUrl);
- updateGradientColors(imageUrl, "library");
- }
- }
- setPlaylists(validPlaylists);
- } else {
- console.error("Error fetching user playlists:", response.status);
- }
- } catch (error) {
- console.error("Error fetching user playlists:", error.message);
- }
-};`}
- />
-
-
-
-
- }
+ graphic={}
fade={['bottom']}
className="max-lg:rounded-t-4xl lg:col-span-3 lg:rounded-tl-4xl"
/>
@@ -130,49 +85,7 @@ function BentoSection() {
eyebrow="Simple"
title="Easy Setup"
description="Get up and running in minutes with our step-by-step installation guide and community support."
- graphic={
-
-
-
-
-
-
-
- setup_hotspot.py
-
-
- README.md
-
-
-
-
-
- If you haven't already, download superbird-tool and run
- the setup process detailed here.
-
-
- Download and unzip the latest image from Releases, connect
- Car Thing to your computer in USB Mode (hold preset
- buttons 1 and 4 while connecting), and run the following
- from your command line:
-
-
- # Go into the superbird-tool repository
-
-
- $ cd C:\path\to\superbird-tool-main
-
-
- # Find device
-
-
- $ python superbird_tool.py --find_device
-
-
-
-
-
- }
+ graphic={}
fade={['bottom']}
className="lg:col-span-3 lg:rounded-tr-4xl"
/>
diff --git a/src/components/left-code-tabs.tsx b/src/components/left-code-tabs.tsx
new file mode 100644
index 0000000..f59a373
--- /dev/null
+++ b/src/components/left-code-tabs.tsx
@@ -0,0 +1,180 @@
+import dynamic from 'next/dynamic'
+import { useEffect, useState } from 'react'
+import { FaJsSquare, FaReact } from 'react-icons/fa'
+
+const CodeBlock = dynamic(() => import('@/components/code-block'), {
+ ssr: false,
+})
+
+type TabKey = 'playlist' | 'artist'
+
+interface TabContent {
+ title: string
+ code: string
+}
+
+interface TabsData {
+ playlist: TabContent
+ artist: TabContent
+}
+
+const LeftCodeTabs = () => {
+ const [activeTab, setActiveTab] = useState('playlist')
+ const [isMounted, setIsMounted] = useState(false)
+ const [isChanging, setIsChanging] = useState(false)
+
+ useEffect(() => {
+ setIsMounted(true)
+ }, [])
+
+ const handleTabChange = (newTab: TabKey) => {
+ if (newTab === activeTab) return
+
+ setIsChanging(true)
+ setTimeout(() => {
+ setActiveTab(newTab)
+ setIsChanging(false)
+ }, 150)
+ }
+
+ const tabs: TabsData = {
+ playlist: {
+ title: 'playlistService.js',
+ code: `export const fetchUserPlaylists = async (
+ accessToken,
+ setPlaylists,
+ updateGradientColors,
+ handleError
+) => {
+ try {
+ const response = await fetch("https://api.spotify.com/v1/me/playlists", {
+ headers: {
+ Authorization: \`Bearer \${accessToken}\`,
+ },
+ });
+ if (response.ok) {
+ const data = await response.json();
+ const validPlaylists = data.items.filter((item) => item && item.id);
+ if (validPlaylists.length > 0) {
+ const imageUrl = validPlaylists[0].images?.[0]?.url;
+ if (imageUrl) {
+ localStorage.setItem("libraryImage", imageUrl);
+ updateGradientColors(imageUrl, "library");
+ }
+ }
+ setPlaylists(validPlaylists);
+ } else {
+ console.error("Error fetching user playlists:", response.status);
+ }
+ } catch (error) {
+ console.error("Error fetching user playlists:", error.message);
+ }
+};`,
+ },
+ artist: {
+ title: 'AuthSelection.jsx',
+ code: `const enableBluetoothDiscovery = async () => {
+ try {
+ setIsBluetoothDiscovering(true);
+ const response = await fetch(
+ "http://localhost:5000/bluetooth/discover/on",
+ {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ );
+
+ if (!response.ok) {
+ throw new Error("Failed to enable bluetooth discovery");
+ }
+
+ setTimeout(() => {
+ setIsBluetoothDiscovering(false);
+ fetch("http://localhost:5000/bluetooth/discover/off", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }).catch(console.error);
+ }, 120000);
+ } catch (error) {
+ console.error("Error enabling bluetooth discovery:", error);
+ setIsBluetoothDiscovering(false);
+ }
+};`,
+ },
+ }
+
+ return (
+
+
+
+
+
+
+
handleTabChange('playlist')}
+ className="relative cursor-pointer"
+ >
+
+
+
+ {tabs.playlist.title}
+
+
+
+
+
handleTabChange('artist')}
+ className="relative cursor-pointer"
+ >
+
+
+
+ {tabs.artist.title}
+
+
+
+
+
+
+
+ {isMounted && (
+
+
+
+ )}
+
+
+
+
+ )
+}
+
+export default LeftCodeTabs
diff --git a/src/components/right-code-tabs.tsx b/src/components/right-code-tabs.tsx
new file mode 100644
index 0000000..4abdb6f
--- /dev/null
+++ b/src/components/right-code-tabs.tsx
@@ -0,0 +1,172 @@
+import dynamic from 'next/dynamic'
+import { useEffect, useState } from 'react'
+import { FaPython } from 'react-icons/fa'
+import { RiMarkdownFill } from 'react-icons/ri'
+
+const CodeBlock = dynamic(() => import('@/components/code-block'), {
+ ssr: false,
+})
+
+type TabKey = 'setup' | 'readme'
+
+interface TabContent {
+ title: string
+ code: string
+}
+
+interface TabsData {
+ setup: TabContent
+ readme: TabContent
+}
+
+const RightCodeTabs = () => {
+ const [activeTab, setActiveTab] = useState('readme')
+ const [isMounted, setIsMounted] = useState(false)
+ const [isChanging, setIsChanging] = useState(false)
+
+ useEffect(() => {
+ setIsMounted(true)
+ }, [])
+
+ const handleTabChange = (newTab: TabKey) => {
+ if (newTab === activeTab) return
+
+ setIsChanging(true)
+ setTimeout(() => {
+ setActiveTab(newTab)
+ setIsChanging(false)
+ }, 150)
+ }
+
+ const tabs: TabsData = {
+ setup: {
+ title: 'setup_hotspot.py',
+ code: `def setup_hotspot():
+ # Check if WiFi is available
+ wifi_status = check_wifi_status()
+ if not wifi_status:
+ print("Error: WiFi hardware not detected")
+ return False
+
+ # Create hotspot configuration
+ config = {
+ "ssid": "Car_Thing_Setup",
+ "wpa_passphrase": generate_password(),
+ "ip_range": "192.168.4.0/24"
+ }
+
+ # Apply configuration
+ success = apply_hotspot_config(config)
+ if not success:
+ print("Error: Failed to configure hotspot")
+ return False
+
+ # Start hotspot service
+ if start_hotspot_service():
+ print("Hotspot started successfully")
+ print(f"SSID: {config['ssid']}")
+ print(f"Password: {config['wpa_passphrase']}")
+ return True
+ else:
+ print("Error: Failed to start hotspot")
+ return False`,
+ },
+ readme: {
+ title: 'README.md',
+ code: `# Car Thing Setup Guide
+
+1. Download superbird-tool and run the setup process detailed here.
+
+2. Download and unzip the latest image from Releases.
+
+3. Connect Car Thing to your computer in USB Mode:
+ - Hold preset buttons 1 and 4 while connecting
+ - Wait for device recognition
+
+4. Open your command line and run:
+
+ # Go into the superbird-tool repository
+ $ cd C:\\path\\to\\superbird-tool-main
+
+ # Find device
+ $ python superbird_tool.py --find_device
+
+ # Flash the new image
+ $ python superbird_tool.py --flash path/to/nocturne.img
+
+5. Wait for the process to complete.
+ Do not disconnect the device during flashing.`,
+ },
+ }
+
+ return (
+
+
+
+
+
+
+
handleTabChange('setup')}
+ className="relative cursor-pointer"
+ >
+
+
+
+ {tabs.setup.title}
+
+
+
+
+
handleTabChange('readme')}
+ className="relative cursor-pointer"
+ >
+
+
+
+ {tabs.readme.title}
+
+
+
+
+
+
+
+ {isMounted && (
+
+
+
+ )}
+
+
+
+
+ )
+}
+
+export default RightCodeTabs