initial template

Seto Elkahfi committed Jul 31, 2024 at 00:17 UTC 1967bad27b599c1592737e2c36ca04cdb26b5848
15 files changed +183 -200
frontend/splitfire-desktop/README.md
+5 -1
@@ -4,11 +4,15 @@ SplitFire AI is an artificial intelligence app for music enthusiasts. This repo
4
5 ## Bazel
6
7 -Run under bazel for more faster iteration:
7 +Run Tauri project under bazel for more faster iteration:
8 ```bash
9 bazel run //frontend/splitfire-desktop:dev
10 ```
11
12 +Run frontend from the local node:
13 +```bash
14 +npm run next-dev
15 +```
16 ## Local development
17
18 Run only the web target:
frontend/splitfire-desktop/app/_lib/menus.ts
+4 -4
@@ -8,12 +8,12 @@ export const menus: { items: Item[] }[] = [
8 {
9 items: [
10 {
11 - name: 'Play',
12 - slug: 'play',
11 + name: 'Home',
12 + slug: '',
13 },
14 {
15 - name: 'Chat 🤖',
16 - slug: 'chat',
15 + name: 'Play',
16 + slug: 'play',
17 },
18 ],
19 },
frontend/splitfire-desktop/app/_ui/address-bar.tsx
+3 -28
@@ -45,34 +45,9 @@ export function AddressBar() {
45 <HomeIcon width={16} />
46 </div>
47 <div className="flex gap-x-1 text-sm font-medium">
48 - {pathname ? (
49 - <>
50 - <span className="text-gray-600">/</span>
51 - {pathname
52 - .split('/')
53 - .slice(1)
54 - .map((segment) => {
55 - return (
56 - <React.Fragment key={segment}>
57 - <span>
58 - <span
59 - key={segment}
60 - className="animate-[highlight_1s_ease-in-out_1] rounded-full px-1.5 py-0.5 text-gray-100"
61 - >
62 - {segment}
63 - </span>
64 - </span>
65 -
66 - <span className="text-gray-600">/</span>
67 - </React.Fragment>
68 - );
69 - })}
70 - </>
71 - ) : null}
72 -
73 - <Suspense>
74 - <Params />
75 - </Suspense>
48 + <span className="animate-[highlight_1s_ease-in-out_1] text-gray-100">
49 + {pathname.replaceAll("/", "").toUpperCase()}
50 + </span>
51 </div>
52 </div>
53 );
frontend/splitfire-desktop/app/_ui/global-nav.tsx
+10 -2
@@ -21,11 +21,11 @@ export function GlobalNav() {
21 onClick={close}
22 >
23 <div className="h-7 w-7 rounded-sm border border-white/30 group-hover:border-white/50">
24 - <Image src="/logo192.png" alt="Tauri on Bazel" width={40} height={40} />
24 + <Image src="/logo192.png" alt="SplitFire" width={40} height={40} />
25 </div>
26
27 <h3 className="font-semibold tracking-wide text-gray-400 group-hover:text-gray-50">
28 - Tauri on Bazel
28 + SplitFire
29 </h3>
30 </Link>
31 </div>
@@ -60,9 +60,17 @@ export function GlobalNav() {
60 <GlobalNavItem key={item.slug} item={item} close={close} />
61 ))}
62 </div>
63 +
64 </div>
65 );
66 })}
67 + <div className="mb-2 px-3 text-xs font-semibold uppercase tracking-wider text-gray-400/80">
68 + <div>{"Account"}</div>
69 + </div>
70 +
71 + <div className="space-y-1">
72 + <GlobalNavItem key={"login"} item={{name: "Login", slug: "login"}} close={close} />
73 + </div>
74 </nav>
75 </div>
76 </div>
frontend/splitfire-desktop/app/layout.tsx
+8 -2
@@ -1,8 +1,14 @@
1 -'use client'
2 -
1 +import { Metadata } from 'next';
2 import { AddressBar } from './_ui/address-bar';
3 import { GlobalNav } from './_ui/global-nav';
4 import './globals.css';
5 +import { cn } from '@/lib/utils';
6 +
7 +
8 +export const metadata: Metadata = {
9 + title: "SplitFire",
10 + description: "an intelligent exression engine.",
11 +};
12
13 export default function RootLayout({
14 children,
frontend/splitfire-desktop/app/login/page.tsx new
+21
@@ -0,0 +1,21 @@
1 +import Link from "next/link";
2 +
3 +export default function Page() {
4 + return (
5 + <div className="space-y-8">
6 + <h1 className="text-xl font-medium text-gray-300">Login</h1>
7 + <div className="h-screen w-screen flex justify-center items-center bg-slate-100">
8 + <div className="sm:shadow-xl px-8 pb-8 pt-12 sm:bg-white rounded-xl space-y-12">
9 + <h1 className="font-semibold text-2xl">Login</h1>
10 +
11 + <p className="text-center">
12 + Need to create an account?{' '}
13 + <Link className="text-indigo-500 hover:underline" href="/register">
14 + Create Account
15 + </Link>{' '}
16 + </p>
17 + </div>
18 + </div>
19 + </div>
20 + );
21 +}
frontend/splitfire-desktop/app/play/(checkout)/checkout/page.tsx deleted
-15
@@ -1,15 +0,0 @@
1 -export async function generateStaticParams() {
2 - const posts = [
3 - { slug: "post-1" },
4 - { slug: "post-2" },
5 - { slug: "post-3" },
6 - ];
7 -
8 - return posts.map((post) => ({
9 - slug: post.slug,
10 - }))
11 -}
12 -
13 -export default function Page() {
14 - return <h1 className="text-xl font-medium text-gray-400/80">Checkout</h1>;
15 -}
frontend/splitfire-desktop/app/play/(checkout)/layout.tsx deleted
-23
@@ -1,23 +0,0 @@
1 -import { Boundary } from '@/app/_ui/boundary';
2 -import { TabNavItem } from '@/app/_ui/tab-nav-item';
3 -import React from 'react';
4 -
5 -export default function Layout({ children }: { children: React.ReactNode }) {
6 - return (
7 - <Boundary
8 - labels={['checkout layout']}
9 - color="blue"
10 - animateRerendering={false}
11 - >
12 - <div className="space-y-9">
13 - <div className="flex items-center justify-between">
14 - <div className="flex items-center gap-x-4">
15 - <TabNavItem href="/play">Back</TabNavItem>
16 - </div>
17 - </div>
18 -
19 - <div>{children}</div>
20 - </div>
21 - </Boundary>
22 - );
23 -}
frontend/splitfire-desktop/app/play/(checkout)/template.tsx deleted
-6
@@ -1,6 +0,0 @@
1 -import { Boundary } from '@/app/_ui/boundary';
2 -import React from 'react';
3 -
4 -export default function Template({ children }: { children: React.ReactNode }) {
5 - return <Boundary>{children}</Boundary>;
6 -}
frontend/splitfire-desktop/app/play/layout.tsx
+5 -9
@@ -1,16 +1,12 @@
1 +import { Metadata } from 'next';
2 import React from 'react';
3
3 -const title = 'Nested Layouts';
4 -
5 -export const metadata = {
6 - metadataBase: new URL('https://splitfire.ai'),
7 - title,
8 - openGraph: {
9 - title,
10 - images: [`/api/og?title=${title}`],
11 - },
4 +export const metadata: Metadata = {
5 + title: "Play",
6 + description: "an intelligent exression engine.",
7 };
8
9 +
10 export default async function Layout({
11 children,
12 }: {
frontend/splitfire-desktop/package-lock.json
+20 -2
@@ -10,6 +10,7 @@
10 "license": "MIT",
11 "dependencies": {
12 "@heroicons/react": "1.0.6",
13 + "@radix-ui/react-icons": "^1.3.0",
14 "@radix-ui/react-slot": "^1.0.2",
15 "@radix-ui/react-tooltip": "^1.0.7",
16 "@sentry/react": "^7.12.1",
@@ -24,7 +25,7 @@
25 "axios": "^0.25.0",
26 "bootstrap": "5.1.3",
27 "class-variance-authority": "^0.7.0",
27 - "clsx": "1.2.1",
28 + "clsx": "^1.2.1",
29 "dexie": "^3.2.0",
30 "dexie-observable": "^3.0.0-beta.11",
31 "eslint": "8.32.0",
@@ -44,7 +45,8 @@
45 "react-textarea-autosize": "^8.5.3",
46 "react-transition-group": "4.x",
47 "react-youtube": "^7.14.0",
47 - "tailwind-merge": "^2.2.1",
48 + "tailwind-merge": "^2.4.0",
49 + "tailwindcss-animate": "^1.0.7",
50 "tone": "^14.7.77",
51 "tslog": "^4.9.2",
52 "typescript": "4.9.4",
@@ -3455,6 +3457,14 @@
3457 }
3458 }
3459 },
3460 + "node_modules/@radix-ui/react-icons": {
3461 + "version": "1.3.0",
3462 + "resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.0.tgz",
3463 + "integrity": "sha512-jQxj/0LKgp+j9BiTXz3O3sgs26RNet2iLWmsPyRz2SIcR4q/4SbazXfnYwbAr+vLYKSfc7qxzyGQA1HLlYiuNw==",
3464 + "peerDependencies": {
3465 + "react": "^16.x || ^17.x || ^18.x"
3466 + }
3467 + },
3468 "node_modules/@radix-ui/react-id": {
3469 "version": "1.1.0",
3470 "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz",
@@ -16493,6 +16503,14 @@
16503 "node": ">=14.0.0"
16504 }
16505 },
16506 + "node_modules/tailwindcss-animate": {
16507 + "version": "1.0.7",
16508 + "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz",
16509 + "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==",
16510 + "peerDependencies": {
16511 + "tailwindcss": ">=3.0.0 || insiders"
16512 + }
16513 + },
16514 "node_modules/tailwindcss/node_modules/postcss-selector-parser": {
16515 "version": "6.1.1",
16516 "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz",
frontend/splitfire-desktop/package.json
+22 -20
@@ -4,46 +4,48 @@
4 "version": "0.3.4",
5 "private": true,
6 "dependencies": {
7 + "@heroicons/react": "1.0.6",
8 + "@radix-ui/react-icons": "^1.3.0",
9 + "@radix-ui/react-slot": "^1.0.2",
10 + "@radix-ui/react-tooltip": "^1.0.7",
11 "@sentry/react": "^7.12.1",
12 "@sentry/tracing": "^7.12.1",
13 + "@tauri-apps/api": "^1.5.3",
14 "@types/actioncable": "^5.2.7",
15 "@types/jest": "^27.4.0",
16 + "@types/node": "18.17.0",
17 + "@types/react": "18.2.78",
18 + "@types/react-dom": "18.2.25",
19 "actioncable": "^5.2.6",
20 "axios": "^0.25.0",
21 "bootstrap": "5.1.3",
22 + "class-variance-authority": "^0.7.0",
23 + "clsx": "^1.2.1",
24 "dexie": "^3.2.0",
25 "dexie-observable": "^3.0.0-beta.11",
26 + "eslint": "8.32.0",
27 + "eslint-config-next": "14.1.0",
28 "lodash.debounce": "^4.0.8",
29 + "next": "14.2.5",
30 + "react": "18.2.0",
31 "react-bootstrap": "^2.1.1",
32 "react-dnd": "^16.0.1",
33 "react-dnd-html5-backend": "^16.0.1",
34 + "react-dom": "18.2.0",
35 + "react-hot-toast": "^2.4.1",
36 "react-icons": "^4.3.1",
37 "react-intl": "^5.24.4",
38 "react-router-dom": "6",
39 "react-scripts": "5.0.0",
40 + "react-textarea-autosize": "^8.5.3",
41 "react-transition-group": "4.x",
42 "react-youtube": "^7.14.0",
43 + "tailwind-merge": "^2.4.0",
44 + "tailwindcss-animate": "^1.0.7",
45 "tone": "^14.7.77",
46 "tslog": "^4.9.2",
28 - "web-vitals": "^2.1.3",
29 - "@heroicons/react": "1.0.6",
30 - "@radix-ui/react-slot": "^1.0.2",
31 - "@radix-ui/react-tooltip": "^1.0.7",
32 - "@tauri-apps/api": "^1.5.3",
33 - "@types/node": "18.17.0",
34 - "@types/react": "18.2.78",
35 - "@types/react-dom": "18.2.25",
36 - "class-variance-authority": "^0.7.0",
37 - "clsx": "1.2.1",
38 - "eslint": "8.32.0",
39 - "eslint-config-next": "14.1.0",
40 - "next": "14.2.5",
41 - "react": "18.2.0",
42 - "react-hot-toast": "^2.4.1",
43 - "react-textarea-autosize": "^8.5.3",
44 - "react-dom": "18.2.0",
47 "typescript": "4.9.4",
46 - "tailwind-merge": "^2.2.1"
48 + "web-vitals": "^2.1.3"
49 },
50 "scripts": {
51 "next-dev": "next dev",
@@ -73,10 +75,10 @@
75 "mini-css-extract-plugin": "2.4.5"
76 },
77 "devDependencies": {
76 - "@tauri-apps/cli": "^1.5.14",
77 - "@types/lodash.debounce": "^4.0.7",
78 "@tailwindcss/forms": "0.5.3",
79 "@tailwindcss/typography": "0.5.9",
80 + "@tauri-apps/cli": "^1.5.14",
81 + "@types/lodash.debounce": "^4.0.7",
82 "autoprefixer": "^10.4.19",
83 "postcss": "^8.4.38",
84 "tailwindcss": "^3.4.3"
frontend/splitfire-desktop/public/grid.svg new
+5
@@ -0,0 +1,5 @@
1 +
2 +<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
3 + <path d="M96,95h4v1H96v4H95V96H86v4H85V96H76v4H75V96H66v4H65V96H56v4H55V96H46v4H45V96H36v4H35V96H26v4H25V96H16v4H15V96H0V95H15V86H0V85H15V76H0V75H15V66H0V65H15V56H0V55H15V46H0V45H15V36H0V35H15V26H0V25H15V16H0V15H15V0h1V15h9V0h1V15h9V0h1V15h9V0h1V15h9V0h1V15h9V0h1V15h9V0h1V15h9V0h1V15h9V0h1V15h4v1H96v9h4v1H96v9h4v1H96v9h4v1H96v9h4v1H96v9h4v1H96v9h4v1H96v9h4v1H96Zm-1,0V86H86v9ZM85,95V86H76v9ZM75,95V86H66v9ZM65,95V86H56v9ZM55,95V86H46v9ZM45,95V86H36v9ZM35,95V86H26v9ZM25,95V86H16v9ZM16,85h9V76H16Zm10,0h9V76H26Zm10,0h9V76H36Zm10,0h9V76H46Zm10,0h9V76H56Zm10,0h9V76H66Zm10,0h9V76H76Zm10,0h9V76H86Zm9-10V66H86v9ZM85,75V66H76v9ZM75,75V66H66v9ZM65,75V66H56v9ZM55,75V66H46v9ZM45,75V66H36v9ZM35,75V66H26v9ZM25,75V66H16v9ZM16,65h9V56H16Zm10,0h9V56H26Zm10,0h9V56H36Zm10,0h9V56H46Zm10,0h9V56H56Zm10,0h9V56H66Zm10,0h9V56H76Zm10,0h9V56H86Zm9-10V46H86v9ZM85,55V46H76v9ZM75,55V46H66v9ZM65,55V46H56v9ZM55,55V46H46v9ZM45,55V46H36v9ZM35,55V46H26v9ZM25,55V46H16v9ZM16,45h9V36H16Zm10,0h9V36H26Zm10,0h9V36H36Zm10,0h9V36H46Zm10,0h9V36H56Zm10,0h9V36H66Zm10,0h9V36H76Zm10,0h9V36H86Zm9-10V26H86v9ZM85,35V26H76v9ZM75,35V26H66v9ZM65,35V26H56v9ZM55,35V26H46v9ZM45,35V26H36v9ZM35,35V26H26v9ZM25,35V26H16v9ZM16,25h9V16H16Zm10,0h9V16H26Zm10,0h9V16H36Zm10,0h9V16H46Zm10,0h9V16H56Zm10,0h9V16H66Zm10,0h9V16H76Zm10,0h9V16H86Z" fill="rgba(255,255,255,0.2)" fill-rule="evenodd" opacity="0.2"/>
4 + <path d="M6,5V0H5V5H0V6H5v94H6V6h94V5Z" fill="rgba(255,255,255,0.075)" fill-rule="evenodd"/>
5 +</svg>
frontend/splitfire-desktop/tailwind.config.js deleted
-88
@@ -1,88 +0,0 @@
1 -import colors from 'tailwindcss/colors';
2 -import { Config } from 'tailwindcss';
3 -
4 -export default {
5 - content: [
6 - './app/**/*.{js,ts,jsx,tsx,mdx}',
7 - ],
8 - future: {
9 - hoverOnlyWhenSupported: true,
10 - },
11 - darkMode: 'class',
12 - theme: {
13 - extend: {
14 - // https://vercel.com/design/color
15 - colors: {
16 - gray: colors.zinc,
17 - 'gray-1000': 'rgb(17,17,19)',
18 - 'gray-1100': 'rgb(10,10,11)',
19 - vercel: {
20 - pink: '#FF0080',
21 - blue: '#0070F3',
22 - cyan: '#50E3C2',
23 - orange: '#F5A623',
24 - violet: '#7928CA',
25 - },
26 - },
27 - backgroundImage: ({ theme }) => ({
28 - 'vc-border-gradient': `radial-gradient(at left top, ${theme(
29 - 'colors.gray.500',
30 - )}, 50px, ${theme('colors.gray.800')} 50%)`,
31 - }),
32 - keyframes: ({ theme }) => ({
33 - rerender: {
34 - '0%': {
35 - ['border-color']: theme('colors.vercel.pink'),
36 - },
37 - '40%': {
38 - ['border-color']: theme('colors.vercel.pink'),
39 - },
40 - },
41 - highlight: {
42 - '0%': {
43 - background: theme('colors.vercel.pink'),
44 - color: theme('colors.white'),
45 - },
46 - '40%': {
47 - background: theme('colors.vercel.pink'),
48 - color: theme('colors.white'),
49 - },
50 - },
51 - loading: {
52 - '0%': {
53 - opacity: '.2',
54 - },
55 - '20%': {
56 - opacity: '1',
57 - transform: 'translateX(1px)',
58 - },
59 - to: {
60 - opacity: '.2',
61 - },
62 - },
63 - shimmer: {
64 - '100%': {
65 - transform: 'translateX(100%)',
66 - },
67 - },
68 - translateXReset: {
69 - '100%': {
70 - transform: 'translateX(0)',
71 - },
72 - },
73 - fadeToTransparent: {
74 - '0%': {
75 - opacity: '1',
76 - },
77 - '40%': {
78 - opacity: '1',
79 - },
80 - '100%': {
81 - opacity: '0',
82 - },
83 - },
84 - }),
85 - },
86 - },
87 - plugins: [require('@tailwindcss/typography'), require('@tailwindcss/forms')],
88 -} satisfies Config;
frontend/splitfire-desktop/tailwind.config.ts new
+80
@@ -0,0 +1,80 @@
1 +import type { Config } from "tailwindcss"
2 +
3 +const config = {
4 + darkMode: ["class"],
5 + content: [
6 + './pages/**/*.{ts,tsx}',
7 + './components/**/*.{ts,tsx}',
8 + './app/**/*.{ts,tsx}',
9 + './src/**/*.{ts,tsx}',
10 + ],
11 + prefix: "",
12 + theme: {
13 + container: {
14 + center: true,
15 + padding: "2rem",
16 + screens: {
17 + "2xl": "1400px",
18 + },
19 + },
20 + extend: {
21 + colors: {
22 + border: "hsl(var(--border))",
23 + input: "hsl(var(--input))",
24 + ring: "hsl(var(--ring))",
25 + background: "hsl(var(--background))",
26 + foreground: "hsl(var(--foreground))",
27 + primary: {
28 + DEFAULT: "hsl(var(--primary))",
29 + foreground: "hsl(var(--primary-foreground))",
30 + },
31 + secondary: {
32 + DEFAULT: "hsl(var(--secondary))",
33 + foreground: "hsl(var(--secondary-foreground))",
34 + },
35 + destructive: {
36 + DEFAULT: "hsl(var(--destructive))",
37 + foreground: "hsl(var(--destructive-foreground))",
38 + },
39 + muted: {
40 + DEFAULT: "hsl(var(--muted))",
41 + foreground: "hsl(var(--muted-foreground))",
42 + },
43 + accent: {
44 + DEFAULT: "hsl(var(--accent))",
45 + foreground: "hsl(var(--accent-foreground))",
46 + },
47 + popover: {
48 + DEFAULT: "hsl(var(--popover))",
49 + foreground: "hsl(var(--popover-foreground))",
50 + },
51 + card: {
52 + DEFAULT: "hsl(var(--card))",
53 + foreground: "hsl(var(--card-foreground))",
54 + },
55 + },
56 + borderRadius: {
57 + lg: "var(--radius)",
58 + md: "calc(var(--radius) - 2px)",
59 + sm: "calc(var(--radius) - 4px)",
60 + },
61 + keyframes: {
62 + "accordion-down": {
63 + from: { height: "0" },
64 + to: { height: "var(--radix-accordion-content-height)" },
65 + },
66 + "accordion-up": {
67 + from: { height: "var(--radix-accordion-content-height)" },
68 + to: { height: "0" },
69 + },
70 + },
71 + animation: {
72 + "accordion-down": "accordion-down 0.2s ease-out",
73 + "accordion-up": "accordion-up 0.2s ease-out",
74 + },
75 + },
76 + },
77 + plugins: [require("tailwindcss-animate")],
78 +} satisfies Config
79 +
80 +export default config
\ No newline at end of file