diff --git a/README.md b/README.md index cc86b0c..a65c95b 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,19 @@

+ +

License

+ +![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg) +

This project is licensed under the MIT License.

+
+
+ +
+

Flowpilot is a one of a kind n8n workflow generator.Generation of production ready, deployable and testable workflows is what Flowpilot strives in.Flowpilot helps coders @@ -12,40 +22,13 @@


+ +
- +
- - - - - - -
- React Logo -

Frontend

-

React

-
- Laravel Logo -

Backend

-

Laravel

-
- React Logo -

Database

-

MySQL

-
+
+

General Communication Flow



-

Copilot Communication Flow

FlowPilot Communication Flow Diagram @@ -75,11 +57,7 @@ n8n Generation workflow between the frontend, backend, generation module, LLM, vector-db and an open SSE connection.

- -

Sequence Diagram

-Start -

ER Diagram

Start @@ -87,9 +65,13 @@

+

+

+ +

+

Main Features

-

AI Copilot

@@ -102,11 +84,7 @@
  • Server-sent events (SSE) connection for live updates
  • -
    - AI Copilot Demo -
    -

    Community Hub

    @@ -119,11 +97,7 @@
  • Engage with other builders in the n8n ecosystem
  • -
    - Community Hub Demo -
    -

    User Profiles

    @@ -137,9 +111,6 @@
  • Download workflow content and history
  • -
    - User Profiles Demo -

    @@ -148,6 +119,53 @@

    +

    Landing

    + + + + + +
    + + + +
    +
    +
    +

    Login

    + + + + + +
    + + + +
    +

    + +

    +
    +
    +

    Signup

    + + + + + +
    + + + +
    +

    + +

    +
    +
    + +

    Copilot

    Simple workflow generation

    @@ -175,14 +193,101 @@
    -

    -
    - +

    Community Hub

    + + + + + +
    + + + +
    +
    +
    +

    Profile

    + + + + + +
    + + + +
    +
    +
    +

    Settings

    + + + + + +
    + + + +
    + + + + + +
    + + + +
    +


    + +
    +
    +

    This project was built using a test-driven and validation-first mindset. +Every major feature was developed alongside tests to ensure reliability, prevent regressions, and maintain production-grade stability as the system evolved.

    +
    +
    + +

    Frontend

    + + + + + + + + + + + +
    Folder StructureCentralized Error HandlerAPI Interceptor
    +

    Backend

    + + + + + + + + + + + +
    ControllerServiceCentralized Error Handler
    +
    +
    +
    +

    Github Actions

    + +
    +
    +

    Git Philosophy

    This project follows a structured Git workflow designed to keep the codebase clean, scalable, and production-ready at all times. @@ -239,146 +344,141 @@ docs/readme-update ``` --- - -

    Commit Philosophy

    - -Each commit should represent one logical change. - -We follow the Conventional Commits standard: - -``` -type(scope): short description -``` - -Examples: -```bash -feat(auth): add JWT login endpoint -fix(api): prevent crash on null response -refactor(db): extract query builder -docs(readme): add deployment guide -``` - ---- - -

    Development Loop

    - -Here’s the exact workflow cycle used in this project: - -```bash -# Start from dev -git checkout dev -git pull - -# Create a feature branch -git checkout -b feature/follow-system - -# Work and commit in small logical steps -git commit -m "feat(db): add follows table" -git commit -m "feat(api): add follow endpoints" - -# Merge back into dev -git checkout dev -git merge feature/follow-system -git push -``` - -When the release is stable: - -```bash -# Release to production -git checkout main -git pull -git merge dev -git push - -# Sync dev with production -git checkout dev -git merge main -git push -``` - -## Graph Example: - -``` -main - ↑ - │ (merge when dev is stable) - │ -dev - ├── chore/project-scaffold - ├── chores/DeploymentPreperation - ├── feat/Microservices - │ └── feat/Microservices-SchemaExtractor-AST - │ - ↑ (merge back to main) - │ - ├── feature/Client - │ ├── feature/Client-copilot - │ └── feature/Client-landingPage - ├── feature/Copilot - │ └── feature/Copilot-langChain - ├── feature/Server-Client/Posting-workflows - │ - ↑ (merge back to main) - │ - ├── feature/Server-Client/userProfile - ├── refactor/Server-Client/cleaning - └── refactor/Server-copilot -``` ---- - -

    Why This Workflow?

    - -This structure ensures: - -- Clean and readable commit history -- Safe collaboration and easier debugging -- `main` is always deployable -- Features never break production -- Scalable long-term development - ---- - -

    - In short: build on dev, ship from main, and keep commits clean and meaningful. -

    -
    -
    -
    -
    -

    This project was built using a test-driven and validation-first mindset. -Every major feature was developed alongside tests to ensure reliability, prevent regressions, and maintain production-grade stability as the system evolved.


    +

    Tests

    +

    Feature tests

    +
    +
    + Testing 1 + Testing 2 + Testing 3 + Testing 4 +
    +
    + +

    Unit tests

    - Testing 1 + Testing 8
    +
    +
    + +
    +

    Deployment Architecture

    + +
    -

    Feature tests

    -
    -
    - Testing 1 - Testing 2 - Testing 3 - Testing 4 -
    -
    +

    FlowPilot uses Docker to containerize the frontend, backend, and database components, ensuring consistent deployment across development, staging, and production environments.

    -## 📄 License +

    Database Configuration

    +

    Database setup and initialization using Docker:

    +Database Build -![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg) -This project is licensed under the MIT License. +
    +
    +

    Frontend Deployment

    +

    The frontend is containerized separately for both development and production environments:

    + + + + + + + + + +
    Development FrontendRoot Docker Frontend Config
    Frontend DockerRoot Frontend Config
    + +
    +
    + +

    Backend Deployment

    +

    The backend services are containerized with appropriate configurations for both development and production:

    + + + + + + + + + +
    Development BackendRoot Docker Backend Config
    Backend DockerRoot Backend Config
    + +
    +
    + +

    Development vs Production Separation

    +

    FlowPilot maintains a clear separation between development and production environments using Docker Compose configurations:

    + +

    Development Environment

    +

    Command: docker compose -f docker-compose.dev.yml up --build

    + + +

    Production Environment

    +

    Command: docker compose -f docker-compose.prod.yml up --build -d

    + + +

    Key Architectural Differences

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    AspectDevelopmentProduction
    Build StrategyLightweight, includes dev dependenciesMulti-stage, optimized for size and performance
    Code MountingLive volumes for hot reloadCopied into image at build time
    PersistenceEphemeral (data lost on container stop)Named volumes for database durability
    DebuggingEnabled with verbose loggingDisabled for security and performance
    Auto-RecoveryManual restart requiredAutomatic via restart policy
    diff --git a/client/src/App.tsx b/client/src/App.tsx index d25e41a..1a25307 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -10,33 +10,13 @@ import ProfilePage from './Pages/profile/Profile' import AboutPage from './Pages/AboutUs' import SettingsPage from './Pages/Settings/Settings' -// day 22 I am fucked beyond comprehension -// Test tracing and generation -// Add the abiilty to send a workflow -// Clean the copilot frontend / backend files -// merge to main -// fix CV -// For after 12 am -// Deploy the website -// Create CI / CD -// push to main -// victory dance - -// big objectives must start at 24th to give myself a chance of finishing them +// big objectives // ADD THE ABILITY TO SEND USER WORKFLOWS TO ADD ON IT/FIX IT - HARD - BACKEND HEAVY // ADD THE ABILITY TO CREATE CUSTOM NODES - VERY HARD - F/B HEAVY ON BOTH // ADD THE ABILITY TO SAVE CREDENTIALS OR FIGURE OUT A WAY TO DO IT AUTOMATICALLY - HARD F/B HEAVY ON BOTH -// USE LANGCHAIN // white screen appearing on reload then page appears -// objectives for today: -/** - * - * Create Tests for everything except copilot - */ - - function App() { return ( diff --git a/client/src/Pages/community/components/PostCard.tsx b/client/src/Pages/community/components/PostCard.tsx index b31a438..b512cc5 100644 --- a/client/src/Pages/community/components/PostCard.tsx +++ b/client/src/Pages/community/components/PostCard.tsx @@ -36,7 +36,11 @@ const PostCard: React.FC = ({ const likeMutation = useToggleLike(userId); const exportContent = useExportPost(); - const imageUrl = post.photo ? `${BASE_URL}/${post.photo}` : null; + const imageUrl = post.photo + ? post.photo.startsWith('blob:') + ? post.photo + : `${BASE_URL}/${post.photo}` + : null; return ( <> diff --git a/client/src/Pages/community/hook/useCreatePost.ts b/client/src/Pages/community/hook/useCreatePost.ts index 84da499..70d050f 100644 --- a/client/src/Pages/community/hook/useCreatePost.ts +++ b/client/src/Pages/community/hook/useCreatePost.ts @@ -26,6 +26,9 @@ export const useCreatePost = () => { const previousData = queryClient.getQueryData(["community-posts"]); + // Create temporary photo URL if image exists + const tempPhotoUrl = inputs.image ? URL.createObjectURL(inputs.image) : ""; + const optimisticPost: PostDto = { id: Date.now(), // Temporary ID author: `${user?.first_name} ${user?.last_name}`.trim(), @@ -33,7 +36,7 @@ export const useCreatePost = () => { avatar: user?.profile_pic || null, title: inputs.title, content: inputs.description || "", - photo: "", // Will be updated after server response + photo: tempPhotoUrl, likes: 0, comments: 0, exports: 0, @@ -45,13 +48,26 @@ export const useCreatePost = () => { prependOptimisticPost(optimisticPost) ); - return { previousData }; + return { previousData, tempPhotoUrl }; + }, + + onSuccess: (_data, _inputs, context: any) => { + // queryClient.invalidateQueries({ queryKey: ["community-posts"] }); + + if (context?.tempPhotoUrl) { + setTimeout(() => { + URL.revokeObjectURL(context.tempPhotoUrl); + }, 500); + } }, onError: (_err, _inputs, context: any) => { if(context?.previousData){ queryClient.setQueryData(["community-posts"], context.previousData); } + if (context?.tempPhotoUrl) { + URL.revokeObjectURL(context.tempPhotoUrl); + } showToast("Failed to create post", ToastMessage.ERROR); }, }); diff --git a/client/src/Pages/profile/components/FollowModal.tsx b/client/src/Pages/profile/components/FollowModal.tsx index c9f4e5b..f97c251 100644 --- a/client/src/Pages/profile/components/FollowModal.tsx +++ b/client/src/Pages/profile/components/FollowModal.tsx @@ -48,7 +48,7 @@ const FollowModal: React.FC = ({ title, users, onClose, onUser scoredUsers.map((u) => (
    onUserClick(u)}>
    -
    {u.photo_url ? {u.full_name} : {u.full_name[0]}}
    +
    {u.photo_url ? {u.full_name} : {u.full_name[0]}}
    {u.full_name}
    diff --git a/client/src/styles/Landing.css b/client/src/styles/Landing.css index 2f0fbd9..d5bd669 100644 --- a/client/src/styles/Landing.css +++ b/client/src/styles/Landing.css @@ -255,10 +255,6 @@ body { animation: pulse 4s ease-in-out infinite; } -@keyframes pulse { - 0%, 100% { box-shadow: 0 0 40px #ff9b0060; } - 50% { box-shadow: 0 0 90px #ff9b00cc; } -} /* Nodes */ .node { diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 57fd925..87fdea2 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -19,8 +19,6 @@ services: APP_ENV: production APP_DEBUG: "false" restart: always - volumes: - - ./server:/var/www backend_nginx: image: nginx:alpine diff --git a/microservice/custom-node-generator/.gitignore b/microservice/custom-node-generator/.gitignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/microservice/custom-node-generator/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/readme/README-Diagrams/Generator-flow.png b/readme/README-Diagrams/Generator-flow.png new file mode 100644 index 0000000..c44e3e9 Binary files /dev/null and b/readme/README-Diagrams/Generator-flow.png differ diff --git a/readme/README-Diagrams/GeneratorFlow.png b/readme/README-Diagrams/GeneratorFlow.png deleted file mode 100644 index 1c743e9..0000000 Binary files a/readme/README-Diagrams/GeneratorFlow.png and /dev/null differ diff --git a/readme/README-Diagrams/High-LevelWorkflow.png b/readme/README-Diagrams/High-LevelWorkflow.png index a0e51fe..0bbb78f 100644 Binary files a/readme/README-Diagrams/High-LevelWorkflow.png and b/readme/README-Diagrams/High-LevelWorkflow.png differ diff --git a/readme/README-Diagrams/NSD1.png b/readme/README-Diagrams/NSD1.png deleted file mode 100644 index 4951e08..0000000 Binary files a/readme/README-Diagrams/NSD1.png and /dev/null differ diff --git a/readme/ci-cd.png b/readme/ci-cd.png new file mode 100644 index 0000000..865e882 Binary files /dev/null and b/readme/ci-cd.png differ diff --git a/readme/demo/Community.png b/readme/demo/Community.png new file mode 100644 index 0000000..c196159 Binary files /dev/null and b/readme/demo/Community.png differ diff --git a/readme/demo/Demo-Community.png b/readme/demo/Demo-Community.png deleted file mode 100644 index 400ba1c..0000000 Binary files a/readme/demo/Demo-Community.png and /dev/null differ diff --git a/readme/demo/Landing.png b/readme/demo/Landing.png new file mode 100644 index 0000000..cd6403a Binary files /dev/null and b/readme/demo/Landing.png differ diff --git a/readme/demo/Login.png b/readme/demo/Login.png new file mode 100644 index 0000000..a5b5413 Binary files /dev/null and b/readme/demo/Login.png differ diff --git a/readme/demo/Profile.png b/readme/demo/Profile.png new file mode 100644 index 0000000..43f458b Binary files /dev/null and b/readme/demo/Profile.png differ diff --git a/readme/demo/Settings-1.png b/readme/demo/Settings-1.png new file mode 100644 index 0000000..5e0eba1 Binary files /dev/null and b/readme/demo/Settings-1.png differ diff --git a/readme/demo/Settings-2.png b/readme/demo/Settings-2.png new file mode 100644 index 0000000..9d2f70b Binary files /dev/null and b/readme/demo/Settings-2.png differ diff --git a/readme/demo/Settings-3.png b/readme/demo/Settings-3.png new file mode 100644 index 0000000..f244117 Binary files /dev/null and b/readme/demo/Settings-3.png differ diff --git a/readme/demo/Settings-4.png b/readme/demo/Settings-4.png new file mode 100644 index 0000000..2918259 Binary files /dev/null and b/readme/demo/Settings-4.png differ diff --git a/readme/demo/Signup.png b/readme/demo/Signup.png new file mode 100644 index 0000000..efbe21a Binary files /dev/null and b/readme/demo/Signup.png differ diff --git a/readme/demo/demo-Landing.gif b/readme/demo/demo-Landing.gif new file mode 100644 index 0000000..45882ef Binary files /dev/null and b/readme/demo/demo-Landing.gif differ diff --git a/readme/demo/demo-community.gif b/readme/demo/demo-community.gif new file mode 100644 index 0000000..f9758cd Binary files /dev/null and b/readme/demo/demo-community.gif differ diff --git a/readme/demo/demo-login-1.gif b/readme/demo/demo-login-1.gif new file mode 100644 index 0000000..f7cce07 Binary files /dev/null and b/readme/demo/demo-login-1.gif differ diff --git a/readme/demo/demo-login-2.gif b/readme/demo/demo-login-2.gif new file mode 100644 index 0000000..011b6a6 Binary files /dev/null and b/readme/demo/demo-login-2.gif differ diff --git a/readme/demo/demo-profile.gif b/readme/demo/demo-profile.gif new file mode 100644 index 0000000..15604e6 Binary files /dev/null and b/readme/demo/demo-profile.gif differ diff --git a/readme/demo/demo-signup-1.gif b/readme/demo/demo-signup-1.gif new file mode 100644 index 0000000..09a2476 Binary files /dev/null and b/readme/demo/demo-signup-1.gif differ diff --git a/readme/demo/demo-signup-2.gif b/readme/demo/demo-signup-2.gif new file mode 100644 index 0000000..76c107a Binary files /dev/null and b/readme/demo/demo-signup-2.gif differ diff --git a/readme/deployment/db-build.png b/readme/deployment/db-build.png new file mode 100644 index 0000000..504e555 Binary files /dev/null and b/readme/deployment/db-build.png differ diff --git a/readme/deployment/docker-be.png b/readme/deployment/docker-be.png new file mode 100644 index 0000000..5e0ea82 Binary files /dev/null and b/readme/deployment/docker-be.png differ diff --git a/readme/deployment/docker-fe.png b/readme/deployment/docker-fe.png new file mode 100644 index 0000000..5891a55 Binary files /dev/null and b/readme/deployment/docker-fe.png differ diff --git a/readme/deployment/images.png b/readme/deployment/images.png new file mode 100644 index 0000000..cb77b60 Binary files /dev/null and b/readme/deployment/images.png differ diff --git a/readme/deployment/root-docker-be.png b/readme/deployment/root-docker-be.png new file mode 100644 index 0000000..1f18890 Binary files /dev/null and b/readme/deployment/root-docker-be.png differ diff --git a/readme/deployment/root-docker-fe.png b/readme/deployment/root-docker-fe.png new file mode 100644 index 0000000..aecd333 Binary files /dev/null and b/readme/deployment/root-docker-fe.png differ diff --git a/readme/development/Controller.png b/readme/development/Controller.png new file mode 100644 index 0000000..8a9ad81 Binary files /dev/null and b/readme/development/Controller.png differ diff --git a/readme/development/api-interceptor.png b/readme/development/api-interceptor.png new file mode 100644 index 0000000..5ed937a Binary files /dev/null and b/readme/development/api-interceptor.png differ diff --git a/readme/development/centralized-error-handler-be.png b/readme/development/centralized-error-handler-be.png new file mode 100644 index 0000000..7070382 Binary files /dev/null and b/readme/development/centralized-error-handler-be.png differ diff --git a/readme/development/centralized-error-handler-fe.png b/readme/development/centralized-error-handler-fe.png new file mode 100644 index 0000000..cfd0335 Binary files /dev/null and b/readme/development/centralized-error-handler-fe.png differ diff --git a/readme/development/fe-folder-structure.png b/readme/development/fe-folder-structure.png new file mode 100644 index 0000000..334d711 Binary files /dev/null and b/readme/development/fe-folder-structure.png differ diff --git a/readme/development/microservices.png b/readme/development/microservices.png new file mode 100644 index 0000000..74e7834 Binary files /dev/null and b/readme/development/microservices.png differ diff --git a/readme/development/service.png b/readme/development/service.png new file mode 100644 index 0000000..b6a368d Binary files /dev/null and b/readme/development/service.png differ diff --git a/readme/project_highlets.jpg b/readme/project_highlets.jpg new file mode 100644 index 0000000..6392178 Binary files /dev/null and b/readme/project_highlets.jpg differ diff --git a/server/app/Service/ProfileService.php b/server/app/Service/ProfileService.php index e604993..76a06d2 100644 --- a/server/app/Service/ProfileService.php +++ b/server/app/Service/ProfileService.php @@ -113,26 +113,27 @@ public static function isFollowingUser(int $userId, int $viewerId): array{ public static function uploadFile(Model $user , UploadedFile $file){ try { $folder = 'avatar_photos'; + $disk = Storage::disk('public'); - if (!Storage::exists($folder)) { - Storage::makeDirectory($folder); + if (!$disk->exists($folder)) { + $disk->makeDirectory($folder); } if ($user->photo_url) { $oldPath = $folder . '/' . $user->id . '-' . basename($user->photo_url); - if (Storage::exists($oldPath)) { - Storage::delete($oldPath); + if ($disk->exists($oldPath)) { + $disk->delete($oldPath); } } $extension = $file->getClientOriginalExtension(); $filename = $user->id . '-' . Str::uuid() . '.' . $extension; - $path = Storage::disk('public')->putFileAs($folder, $file, $filename); + + $path = $disk->putFileAs($folder, $file, $filename); $user->photo_url = '/storage' . "/" . $path; - $user->save(); - Log::debug("Success" , ["context" => $path]); + $user->save(); } catch (Exception $e) { throw new Exception($e->getMessage()); } diff --git a/server/app/Service/UserCopilotHistoryService.php b/server/app/Service/UserCopilotHistoryService.php index 33d37b3..c34330a 100644 --- a/server/app/Service/UserCopilotHistoryService.php +++ b/server/app/Service/UserCopilotHistoryService.php @@ -41,9 +41,7 @@ public static function deleteHistory(int $userId, Model $userCopilotHistory){ } public static function getDownloadableContent(int $userId , Model $history){ - if($history->user_id !== $userId){ - abort(403); - } + $lastMessage = $history->messages() ->latest('created_at') diff --git a/server/storage/harvest_creds_cache.json b/server/storage/harvest_creds_cache.json deleted file mode 100644 index e69de29..0000000