diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md deleted file mode 100644 index f0d2201..0000000 --- a/DEVELOPMENT.md +++ /dev/null @@ -1,117 +0,0 @@ -# CodeRED-Astra Development Guide - -## Project Structure - -This is a hackathon-ready project with a clean separation between frontend and backend: - -- **React Frontend** (`web-app/`): Modern React app with Vite and Tailwind CSS -- **Rust Engine** (`rust-engine/`): High-performance backend API server -- **Database**: MySQL 8.0 with phpMyAdmin for management - -## Quick Start - -### Prerequisites -- Docker & Docker Compose -- Node.js 20+ (for local development) -- Rust 1.82+ (for local development) - -### Development Setup - -1. **Clone and setup environment**: -```bash -cp .env.example .env -# Edit .env with your database passwords and API keys -``` - -2. **Start the entire stack**: -```bash -docker-compose up --build -``` - -3. **Access the application**: -- Frontend: http://localhost (port 80) -- Rust API: http://localhost:8000 -- phpMyAdmin: http://127.0.0.1:8080 - -### Local Development (Recommended for Hackathon) - -**Frontend Development**: -```bash -cd web-app -npm install -npm run dev # Starts on http://localhost:5173 -``` - -**Backend Development**: -```bash -cd rust-engine -cargo run # Starts on http://localhost:8000 -``` - -## Team Workflow - -### Frontend Team (React) -- Work in `web-app/src/` -- Main entry: `src/App.jsx` -- Add new components in `src/components/` -- API calls go through `/api/*` (auto-proxied to Rust engine) -- Use Tailwind CSS for styling -- Hot reload enabled with Vite - -### Backend Team (Rust) -- Work in `rust-engine/src/` -- Main server: `src/main.rs` -- Add new modules in `src/` -- API endpoints start with `/api/` -- Database connection via SQLx -- CORS enabled for frontend communication - -## API Communication - -The frontend communicates with the Rust engine via: -```javascript -// This automatically proxies to http://rust-engine:8000 in Docker -// or http://localhost:8000 in local development -fetch('/api/health') - .then(response => response.json()) - .then(data => console.log(data)); -``` - -## Database Schema - -Edit `rust-engine/src/main.rs` to add database migrations and models as needed. - -## Environment Variables - -Required in `.env`: -``` -MYSQL_DATABASE=astra -MYSQL_USER=astraadmin -MYSQL_PASSWORD=your_secure_password -MYSQL_ROOT_PASSWORD=your_root_password -GEMINI_API_KEY=your_gemini_key -``` - -## Deployment - -The project is containerized and ready for deployment: -- Frontend: Static files served via Vite preview -- Backend: Optimized Rust binary -- Database: Persistent MySQL data volume - -## Hackathon Tips - -1. **Frontend team**: Start with the existing App.jsx and build your UI components -2. **Backend team**: Add new API endpoints in the Rust main.rs file -3. **Database**: Use phpMyAdmin at http://127.0.0.1:8080 to manage data -4. **Testing**: The app shows connection status between frontend and backend -5. **Hot reload**: Both frontend and backend support hot reload during development - -## Common Issues - -- **CORS errors**: Already configured, but check Rust engine CORS settings if needed -- **Database connection**: Engine gracefully handles DB offline state for initial development -- **Port conflicts**: Web runs on 80, API on 8000, phpMyAdmin on 8080 -- **Build failures**: Check Node.js and Rust versions match requirements - -Happy hacking! 🚀 \ No newline at end of file diff --git a/eslint.config.js b/eslint.config.js deleted file mode 100644 index 777fe18..0000000 --- a/eslint.config.js +++ /dev/null @@ -1,29 +0,0 @@ -import js from "@eslint/js"; -import globals from "globals"; -import reactHooks from "eslint-plugin-react-hooks"; -import reactRefresh from "eslint-plugin-react-refresh"; -import { defineConfig, globalIgnores } from "eslint/config"; - -export default defineConfig([ - globalIgnores(["dist"]), - { - files: ["**/*.{js,jsx}"], - extends: [ - js.configs.recommended, - reactHooks.configs["recommended-latest"], - reactRefresh.configs.vite, - ], - languageOptions: { - ecmaVersion: 2020, - globals: globals.browser, - parserOptions: { - ecmaVersion: "latest", - ecmaFeatures: { jsx: true }, - sourceType: "module", - }, - }, - rules: { - "no-unused-vars": ["error", { varsIgnorePattern: "^[A-Z_]" }], - }, - }, -]); diff --git a/package.json b/package.json deleted file mode 100644 index 198e9c6..0000000 --- a/package.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "codered-astra", - "private": true, - "scripts": { - "build": "vite build", - "dev": "vite", - "host": "vite host", - "format": "prettier --write \"**/*.{ts,tsx,md}\"", - "clean-dist": "find apps/ -type d -name 'dist' -print0 | xargs -r0 -- rm -r", - "clean-all": "find apps/ -type d -name 'dist' -print0 | xargs -r0 -- rm -r && find . -path ./node_modules -prune -o -name 'node_modules' | xargs rm -rf " - }, - "license": "ISC", - "dependencies": { - "@google/genai": "^1.25.0", - "@tailwindcss/postcss": "^4.1.14", - "@tailwindcss/vite": "^4.1.14", - "@vitejs/plugin-react": "^5.0.4", - "bootstrap": "^5.3.8", - "bootstrap-icons": "^1.13.1", - "cors": "^2.8.5", - "dotenv": "^17.2.3", - "express": "^5.1.0", - "helmet": "^8.1.0", - "lucide-react": "^0.546.0", - "pg": "^8.16.3", - "react": "^19.2.0", - "react-bootstrap": "^2.10.10", - "react-dom": "^19.2.0", - "react-router": "^7.9.4", - "react-router-dom": "^7.9.4", - "vite-jsconfig-paths": "^2.0.1" - }, - "packageManager": ">=npm@10.9.0", - "devDependencies": { - "eslint": "^9.38.0", - "eslint-plugin-import": "^2.32.0", - "eslint-plugin-react": "^7.37.5", - "eslint-plugin-react-hooks": "^7.0.0", - "eslint-plugin-react-refresh": "^0.4.24", - "nodemon": "^3.1.10", - "prettier": "^3.6.2", - "tailwindcss": "^4.1.14", - "vite": "^7.1.10" - } -} diff --git a/src/index.css b/src/index.css deleted file mode 100644 index 9895c36..0000000 --- a/src/index.css +++ /dev/null @@ -1,24 +0,0 @@ -@import "tailwindcss/preflight"; -@import "tailwindcss/utilities"; - -:root { - --color-primary: 15 40 98; - --color-secondary: 79 95 118; - --color-accent: 158 54 58; - --color-paragraph: 255 255 255; - --color-background: 9 31 54; -} - -body { - margin: 0; - background-color: rgb(var(--color-background)); - color: rgb(var(--color-paragraph)); - font-family: - ui-sans-serif, - system-ui, - -apple-system, - "Segoe UI", - Roboto, - "Helvetica Neue", - Arial; -} diff --git a/src/main.jsx b/src/main.jsx deleted file mode 100644 index e054df6..0000000 --- a/src/main.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import { StrictMode } from "react"; -import { createRoot } from "react-dom/client"; -import "./index.css"; -import App from "./app/index.jsx"; - -createRoot(document.getElementById("root")).render( - - - -); diff --git a/vite.config.js b/vite.config.js deleted file mode 100644 index db0ad28..0000000 --- a/vite.config.js +++ /dev/null @@ -1,14 +0,0 @@ -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react"; -import jsconfigPaths from "vite-jsconfig-paths"; -import tailwindcss from "@tailwindcss/vite"; - -// https://vite.dev/config/ -export default defineConfig({ - plugins: [tailwindcss(), react(), jsconfigPaths()], - resolve: { - alias: { - src: "/src", - }, - }, -}); diff --git a/web-app/Dockerfile b/web-app/Dockerfile index 4d1e34d..a39f697 100644 --- a/web-app/Dockerfile +++ b/web-app/Dockerfile @@ -1,22 +1,15 @@ -# web-app/Dockerfile -FROM node:20-alpine +FROM node:23-alpine -WORKDIR /app +COPY . /codered-astra -# Copy package files first to leverage Docker's build cache -COPY package*.json ./ +WORKDIR /codered-astra -# Install dependencies -RUN npm ci --only=production=false +RUN npm i -# Copy the rest of your application code -COPY . . - -# Build the React application -RUN npm run build - -# Expose the port EXPOSE 3000 -# Use preview mode for production-like serving -CMD ["npm", "run", "preview"] \ No newline at end of file +RUN npm run format + +RUN npm run build + +CMD ["npm", "run", "host"] diff --git a/web-app/README.md b/web-app/README.md new file mode 100644 index 0000000..18bc70e --- /dev/null +++ b/web-app/README.md @@ -0,0 +1,16 @@ +# React + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## React Compiler + +The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project. diff --git a/web-app/eslint.config.js b/web-app/eslint.config.js index 777fe18..af876ec 100644 --- a/web-app/eslint.config.js +++ b/web-app/eslint.config.js @@ -1,7 +1,5 @@ import js from "@eslint/js"; import globals from "globals"; -import reactHooks from "eslint-plugin-react-hooks"; -import reactRefresh from "eslint-plugin-react-refresh"; import { defineConfig, globalIgnores } from "eslint/config"; export default defineConfig([ diff --git a/web-app/jsconfig.json b/web-app/jsconfig.json index 8fd87b4..c48ffbb 100644 --- a/web-app/jsconfig.json +++ b/web-app/jsconfig.json @@ -1,8 +1,6 @@ { "compilerOptions": { - "baseUrl": "web-app/src" + "baseUrl": "./" }, - "include": [ - "web-app/src" - ] + "include": ["src"] } diff --git a/web-app/package.json b/web-app/package.json index d275cee..198e9c6 100644 --- a/web-app/package.json +++ b/web-app/package.json @@ -1,37 +1,45 @@ { "name": "codered-astra", "private": true, - "type": "module", "scripts": { - "dev": "vite", "build": "vite build", - "preview": "vite preview", - "host": "vite --host 0.0.0.0 --port 3000", - "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", - "format": "prettier --write \"**/*.{js,jsx,md}\"" + "dev": "vite", + "host": "vite host", + "format": "prettier --write \"**/*.{ts,tsx,md}\"", + "clean-dist": "find apps/ -type d -name 'dist' -print0 | xargs -r0 -- rm -r", + "clean-all": "find apps/ -type d -name 'dist' -print0 | xargs -r0 -- rm -r && find . -path ./node_modules -prune -o -name 'node_modules' | xargs rm -rf " }, "license": "ISC", "dependencies": { - "@google/generative-ai": "^0.21.0", - "axios": "^1.7.7", + "@google/genai": "^1.25.0", + "@tailwindcss/postcss": "^4.1.14", + "@tailwindcss/vite": "^4.1.14", + "@vitejs/plugin-react": "^5.0.4", + "bootstrap": "^5.3.8", + "bootstrap-icons": "^1.13.1", + "cors": "^2.8.5", + "dotenv": "^17.2.3", + "express": "^5.1.0", + "helmet": "^8.1.0", "lucide-react": "^0.546.0", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-router-dom": "^6.28.0" - }, - "devDependencies": { - "@types/react": "^18.3.12", - "@types/react-dom": "^18.3.1", - "@vitejs/plugin-react": "^4.3.3", - "autoprefixer": "^10.4.20", - "eslint": "^9.14.0", - "eslint-plugin-react": "^7.37.2", - "eslint-plugin-react-hooks": "^5.0.0", - "eslint-plugin-react-refresh": "^0.4.14", - "postcss": "^8.4.47", - "prettier": "^3.3.3", - "tailwindcss": "^3.4.14", - "vite": "^5.4.10", + "pg": "^8.16.3", + "react": "^19.2.0", + "react-bootstrap": "^2.10.10", + "react-dom": "^19.2.0", + "react-router": "^7.9.4", + "react-router-dom": "^7.9.4", "vite-jsconfig-paths": "^2.0.1" + }, + "packageManager": ">=npm@10.9.0", + "devDependencies": { + "eslint": "^9.38.0", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-react": "^7.37.5", + "eslint-plugin-react-hooks": "^7.0.0", + "eslint-plugin-react-refresh": "^0.4.24", + "nodemon": "^3.1.10", + "prettier": "^3.6.2", + "tailwindcss": "^4.1.14", + "vite": "^7.1.10" } } diff --git a/web-app/postcss.config.js b/web-app/postcss.config.js deleted file mode 100644 index e99ebc2..0000000 --- a/web-app/postcss.config.js +++ /dev/null @@ -1,6 +0,0 @@ -export default { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -} \ No newline at end of file diff --git a/web-app/src/App.jsx b/web-app/src/App.jsx deleted file mode 100644 index 7f203e5..0000000 --- a/web-app/src/App.jsx +++ /dev/null @@ -1,137 +0,0 @@ -import { useState, useEffect } from "react"; -import { Cpu, Database, Zap, Activity } from "lucide-react"; - -function App() { - const [engineStatus, setEngineStatus] = useState(null); - const [loading, setLoading] = useState(true); - - useEffect(() => { - checkEngineHealth(); - }, []); - - const checkEngineHealth = async () => { - try { - const response = await fetch('/api/health'); - const data = await response.json(); - setEngineStatus(data); - } catch (error) { - console.error('Engine health check failed:', error); - setEngineStatus({ success: false, message: 'Engine offline' }); - } finally { - setLoading(false); - } - }; - - return ( -
-
- {/* Header */} -
-
- -

- CodeRED-Astra -

-
-

- Hackathon Project - React Frontend + Rust Engine -

-
- - {/* Status Cards */} -
- {/* React App Status */} -
-
- -

React Frontend

-
-
✓ Online
-

- Vite + React development environment ready -

-
- - {/* Rust Engine Status */} -
-
- -

Rust Engine

-
-
- {loading ? '⏳ Checking...' : engineStatus?.success ? '✓ Online' : '✗ Offline'} -
-

- {loading ? 'Connecting to engine...' : - engineStatus?.success ? 'Engine responding normally' : - 'Engine may still be starting up'} -

-
-
- - {/* Engine Details */} - {engineStatus?.success && ( -
-
- -

Engine Status

-
-
-
- Status: - {engineStatus.data?.status} -
-
- Last Check: - - {engineStatus.data?.timestamp ? new Date(engineStatus.data.timestamp).toLocaleTimeString() : 'N/A'} - -
-
- {engineStatus.message && ( -
- {engineStatus.message} -
- )} -
- )} - - {/* Quick Actions */} -
-

Quick Actions

-
- - - -
-
- - {/* Development Notes */} -
-

🚀 Ready for hackathon development!

-

- Frontend team: Work in web-app/src/ | - Backend team: Work in rust-engine/src/ -

-
-
-
- ); -} - -export default App; diff --git a/src/app/index.jsx b/web-app/src/app/index.jsx similarity index 77% rename from src/app/index.jsx rename to web-app/src/app/index.jsx index 86327c4..9d0b576 100644 --- a/src/app/index.jsx +++ b/web-app/src/app/index.jsx @@ -1,5 +1,5 @@ import React from "react"; -import ChatLayout from "src/components/ui/ChatLayout"; +import ChatLayout from "src/components/layouts/chat-layout"; function App() { return ( diff --git a/src/components/ui/ChatLayout.jsx b/web-app/src/components/layouts/chat-layout.jsx similarity index 81% rename from src/components/ui/ChatLayout.jsx rename to web-app/src/components/layouts/chat-layout.jsx index 060c0cd..fbfb5f0 100644 --- a/src/components/ui/ChatLayout.jsx +++ b/web-app/src/components/layouts/chat-layout.jsx @@ -1,7 +1,7 @@ import React, { useState } from "react"; -import ChatHeader from "./ChatHeader"; -import ChatWindow from "./ChatWindow"; -import MessageInput from "./MessageInput"; +import ChatHeader from "src/components/ui/chat/chat-header"; +import ChatWindow from "src/components/ui/chat/chat-window"; +import MessageInput from "src/components/ui/chat/message-input"; export default function ChatLayout() { const [messages, setMessages] = useState([ diff --git a/src/components/layouts/dashboard-layout.jsx b/web-app/src/components/layouts/dashboard-layout.jsx similarity index 100% rename from src/components/layouts/dashboard-layout.jsx rename to web-app/src/components/layouts/dashboard-layout.jsx diff --git a/src/components/ui/Button/DeleteButton.jsx b/web-app/src/components/ui/Button/DeleteButton.jsx similarity index 100% rename from src/components/ui/Button/DeleteButton.jsx rename to web-app/src/components/ui/Button/DeleteButton.jsx diff --git a/src/components/ui/Button/NewChatButton.css b/web-app/src/components/ui/Button/NewChatButton.css similarity index 100% rename from src/components/ui/Button/NewChatButton.css rename to web-app/src/components/ui/Button/NewChatButton.css diff --git a/src/components/ui/Button/NewChatButton.jsx b/web-app/src/components/ui/Button/NewChatButton.jsx similarity index 100% rename from src/components/ui/Button/NewChatButton.jsx rename to web-app/src/components/ui/Button/NewChatButton.jsx diff --git a/src/components/ui/ChatHeader.jsx b/web-app/src/components/ui/chat/chat-header.jsx similarity index 100% rename from src/components/ui/ChatHeader.jsx rename to web-app/src/components/ui/chat/chat-header.jsx diff --git a/src/components/ui/ChatWindow.jsx b/web-app/src/components/ui/chat/chat-window.jsx similarity index 100% rename from src/components/ui/ChatWindow.jsx rename to web-app/src/components/ui/chat/chat-window.jsx diff --git a/src/components/ui/MessageInput.jsx b/web-app/src/components/ui/chat/message-input.jsx similarity index 100% rename from src/components/ui/MessageInput.jsx rename to web-app/src/components/ui/chat/message-input.jsx diff --git a/web-app/src/index.css b/web-app/src/index.css index ec9640b..9895c36 100644 --- a/web-app/src/index.css +++ b/web-app/src/index.css @@ -1,33 +1,24 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; +@import "tailwindcss/preflight"; +@import "tailwindcss/utilities"; :root { - font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; - line-height: 1.5; - font-weight: 400; - color-scheme: dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + --color-primary: 15 40 98; + --color-secondary: 79 95 118; + --color-accent: 158 54 58; + --color-paragraph: 255 255 255; + --color-background: 9 31 54; } body { margin: 0; - display: flex; - place-items: center; - min-width: 320px; - min-height: 100vh; -} - -#root { - width: 100%; - margin: 0; -} - -code { - font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono", Menlo, monospace; + background-color: rgb(var(--color-background)); + color: rgb(var(--color-paragraph)); + font-family: + ui-sans-serif, + system-ui, + -apple-system, + "Segoe UI", + Roboto, + "Helvetica Neue", + Arial; } diff --git a/src/styles/theme.css b/web-app/src/styles/theme.css similarity index 100% rename from src/styles/theme.css rename to web-app/src/styles/theme.css diff --git a/web-app/tailwind.config.js b/web-app/tailwind.config.js deleted file mode 100644 index 5b480dc..0000000 --- a/web-app/tailwind.config.js +++ /dev/null @@ -1,19 +0,0 @@ -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: ["./src/**/*.{js,ts,jsx,tsx}"], - theme: { - extend: { - colors: { - background: "rgba(var(--background))", - paragraph: "rgba(var(--paragraph))", - primary: "rgba(var(--primary))", - secondary: "rgba(var(--secondary))", - accent: "rgba(var(--accent))", - }, - flex: { - 0: "0 0 100%", - }, - }, - }, - plugins: [], -}; diff --git a/web-app/vite.config.js b/web-app/vite.config.js index 226be7d..db0ad28 100644 --- a/web-app/vite.config.js +++ b/web-app/vite.config.js @@ -1,26 +1,14 @@ import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; import jsconfigPaths from "vite-jsconfig-paths"; +import tailwindcss from "@tailwindcss/vite"; // https://vite.dev/config/ export default defineConfig({ - plugins: [react(), jsconfigPaths()], - server: { - host: '0.0.0.0', - port: 3000, - proxy: { - '/api': { - target: process.env.RUST_ENGINE_URL || 'http://localhost:8000', - changeOrigin: true, - rewrite: (path) => path.replace(/^\/api/, '') - } - } + plugins: [tailwindcss(), react(), jsconfigPaths()], + resolve: { + alias: { + src: "/src", + }, }, - preview: { - host: '0.0.0.0', - port: 3000 - }, - build: { - outDir: 'dist' - } });