Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions .github/workflows/deploy-frontend.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: Deploy Frontend to Cloudflare Pages

on:
push:
branches:
- main
paths:
- 'frontend/**'
- '.github/workflows/deploy-frontend.yml'
pull_request:
branches:
- main
paths:
- 'frontend/**'

jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
cache-dependency-path: frontend/package-lock.json

- name: Install dependencies
working-directory: frontend
run: npm ci

- name: Build
working-directory: frontend
run: npm run build

- name: Deploy to Cloudflare Pages
id: deploy
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy dist --project-name=workmate
workingDirectory: frontend

- name: Comment preview URL on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const body = `🚀 **Cloudflare Pages Preview**\n\nDeployed to: ${process.env.DEPLOYMENT_URL}`;
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const existing = comments.find(c => c.body.includes('Cloudflare Pages Preview'));
if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body,
});
}
env:
DEPLOYMENT_URL: ${{ steps.deploy.outputs.deployment-url }}
41 changes: 15 additions & 26 deletions frontend/src/app/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Routes, Route } from "react-router-dom";
import { LoginPage } from "./pages/LoginPage";
import { ChatPage } from "./pages/ChatPage";
import { AdminPage } from "./pages/AdminPage";
import { SettingsPage } from "./pages/SettingsPage";
Expand All @@ -9,12 +8,11 @@ import { Sidebar } from "./components/Sidebar";

export default function App() {
return (
<Routes>
<Route path="/login" element={<LoginPage />} />
<Route
path="/admin"
element={
<ProtectedRoute>
<ProtectedRoute>
<Routes>
<Route
path="admin"
element={
<AdminRoute>
<div className="flex h-screen overflow-hidden bg-white dark:bg-slate-900">
<Sidebar
Expand All @@ -25,13 +23,11 @@ export default function App() {
<AdminPage />
</div>
</AdminRoute>
</ProtectedRoute>
}
/>
<Route
path="/settings"
element={
<ProtectedRoute>
}
/>
<Route
path="settings"
element={
<div className="flex h-screen overflow-hidden bg-white dark:bg-slate-900">
<Sidebar
activeConversationId={null}
Expand All @@ -40,17 +36,10 @@ export default function App() {
/>
<SettingsPage />
</div>
</ProtectedRoute>
}
/>
<Route
path="/*"
element={
<ProtectedRoute>
<ChatPage />
</ProtectedRoute>
}
/>
</Routes>
}
/>
<Route path="*" element={<ChatPage />} />
</Routes>
</ProtectedRoute>
);
}
16 changes: 8 additions & 8 deletions frontend/src/app/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -270,14 +270,14 @@ export function Sidebar({
<div className="space-y-1.5">
{workspaces.length === 0 ? (
<Link
to="/settings"
to="/app/settings"
className="block text-xs text-slate-400 hover:text-purple-500 text-center py-3 transition-colors"
>
Connect a Notion workspace
</Link>
) : (
workspaces.map((workspace) => (
<Link key={workspace.id} to="/settings">
<Link key={workspace.id} to="/app/settings">
<Card
className="p-2.5 hover:bg-white dark:hover:bg-slate-800 transition-colors cursor-pointer border-slate-200 dark:border-slate-700"
>
Expand Down Expand Up @@ -309,9 +309,9 @@ export function Sidebar({
{/* Navigation Links */}
<div className="space-y-1 flex-shrink-0">
<Link
to="/"
to="/app"
className={`flex items-center gap-2 rounded-md px-3 py-2 text-sm font-medium transition-colors ${
location.pathname === '/'
location.pathname === '/app'
? 'bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300'
: 'text-slate-700 dark:text-slate-300 hover:bg-slate-200 dark:hover:bg-slate-800'
}`}
Expand All @@ -320,9 +320,9 @@ export function Sidebar({
Chat
</Link>
<Link
to="/settings"
to="/app/settings"
className={`flex items-center gap-2 rounded-md px-3 py-2 text-sm font-medium transition-colors ${
location.pathname === '/settings'
location.pathname === '/app/settings'
? 'bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300'
: 'text-slate-700 dark:text-slate-300 hover:bg-slate-200 dark:hover:bg-slate-800'
}`}
Expand All @@ -332,9 +332,9 @@ export function Sidebar({
</Link>
{isAdmin && (
<Link
to="/admin"
to="/app/admin"
className={`flex items-center gap-2 rounded-md px-3 py-2 text-sm font-medium transition-colors ${
location.pathname === '/admin'
location.pathname === '/app/admin'
? 'bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300'
: 'text-slate-700 dark:text-slate-300 hover:bg-slate-200 dark:hover:bg-slate-800'
}`}
Expand Down
30 changes: 27 additions & 3 deletions frontend/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,40 @@
import { createRoot } from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { ThemeProvider } from "next-themes";
import { AuthProvider } from "./app/contexts/AuthContext";
import { Toaster } from "./app/components/ui/sonner";
import App from "./app/App.tsx";
import App from "./app/App";
import { PublicLayout } from "./public/layouts/PublicLayout";
import { LandingPage } from "./public/pages/LandingPage";
import { AboutPage } from "./public/pages/AboutPage";
import { PricingPage } from "./public/pages/PricingPage";
import { DocsPage } from "./public/pages/DocsPage";
import { DemoPage } from "./public/pages/DemoPage";
import { ContactPage } from "./public/pages/ContactPage";
import { LoginPage } from "./app/pages/LoginPage";
import "./styles/index.css";

createRoot(document.getElementById("root")!).render(
<BrowserRouter>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
<AuthProvider>
<App />
<Routes>
{/* Public marketing site */}
<Route element={<PublicLayout />}>
<Route index element={<LandingPage />} />
<Route path="about" element={<AboutPage />} />
<Route path="pricing" element={<PricingPage />} />
<Route path="docs" element={<DocsPage />} />
<Route path="demo" element={<DemoPage />} />
<Route path="contact" element={<ContactPage />} />
</Route>

{/* Auth */}
<Route path="login" element={<LoginPage />} />

{/* Authenticated app */}
<Route path="app/*" element={<App />} />
</Routes>
<Toaster position="bottom-right" richColors />
</AuthProvider>
</ThemeProvider>
Expand Down
26 changes: 26 additions & 0 deletions frontend/src/public/components/ComingSoon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Link } from "react-router-dom";
import type { LucideIcon } from "lucide-react";

interface ComingSoonProps {
icon: LucideIcon;
title: string;
description: string;
}

export function ComingSoon({ icon: Icon, title, description }: ComingSoonProps) {
return (
<div className="flex min-h-[60vh] flex-col items-center justify-center px-6 text-center">
<div className="mb-6 flex h-16 w-16 items-center justify-center rounded-2xl bg-purple-600/[0.08] border border-purple-600/20">
<Icon className="h-7 w-7 text-purple-500" />
</div>
<h1 className="text-2xl font-bold text-white">{title}</h1>
<p className="mt-2 text-sm text-white/40">{description}</p>
<Link
to="/"
className="mt-6 text-sm text-purple-500 transition-colors hover:text-purple-400"
>
&larr; Back to Home
</Link>
</div>
);
}
44 changes: 44 additions & 0 deletions frontend/src/public/components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Link } from "react-router-dom";

const footerLinks = [
{ label: "About", href: "/about" },
{ label: "Pricing", href: "/pricing" },
{ label: "Docs", href: "/docs" },
{ label: "Contact", href: "/contact" },
{ label: "GitHub", href: "https://github.com/RubyRyn/WorkMate" },
];

export function Footer() {
return (
<footer className="border-t border-white/[0.06] px-6 py-8">
<div className="mx-auto flex max-w-7xl flex-col items-center justify-between gap-4 sm:flex-row">
<p className="text-xs text-white/30">
&copy; 2026 WorkMate. Built at SFBU.
</p>
<div className="flex gap-6">
{footerLinks.map((link) =>
link.href.startsWith("http") ? (
<a
key={link.label}
href={link.href}
target="_blank"
rel="noopener noreferrer"
className="text-xs text-white/30 transition-colors hover:text-white/60"
>
{link.label}
</a>
) : (
<Link
key={link.label}
to={link.href}
className="text-xs text-white/30 transition-colors hover:text-white/60"
>
{link.label}
</Link>
)
)}
</div>
</div>
</footer>
);
}
Loading
Loading