diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9960145 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,47 @@ +name: CI + +on: + push: + branches: + - master + pull_request: + +permissions: + actions: read + contents: read + +jobs: + main: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + filter: tree:0 + fetch-depth: 0 + + - uses: pnpm/action-setup@v4 + name: Install pnpm + with: + version: 9.8.0 + run_install: false + + # This enables task distribution via Nx Cloud + # Run this command as early as possible, before dependencies are installed + # Learn more at https://nx.dev/ci/reference/nx-cloud-cli#npx-nxcloud-startcirun + # Uncomment this line to enable task distribution + # - run: pnpm dlx nx start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="build" + + # Cache node_modules + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'pnpm' + + - run: pnpm install --frozen-lockfile + + # Prepend any command with "nx-cloud record --" to record its logs to Nx Cloud + # - run: pnpm exec nx-cloud record -- echo Hello World + - run: pnpm exec nx run-many -t lint test build + # Nx Cloud recommends fixes for failures to help you get CI green faster. Learn more: https://nx.dev/ci/features/self-healing-ci + - run: pnpm exec nx fix-ci + if: always() diff --git a/.gitignore b/.gitignore index 5ef6a52..abf19da 100644 --- a/.gitignore +++ b/.gitignore @@ -1,41 +1,53 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. +# See https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files for more about ignoring files. -# dependencies -/node_modules -/.pnp -.pnp.* -.yarn/* -!.yarn/patches -!.yarn/plugins -!.yarn/releases -!.yarn/versions - -# testing -/coverage - -# next.js -/.next/ -/out/ +# compiled output +dist +tmp +out-tsc -# production -/build +# dependencies +node_modules + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json # misc +/.sass-cache +/connect.lock +/coverage +/libpeerconnection.log +npm-debug.log +yarn-error.log +testem.log +/typings + +# System Files .DS_Store -*.pem +Thumbs.db -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* -.pnpm-debug.log* +.nx/cache +.nx/workspace-data +.cursor/rules/nx-rules.mdc +.github/instructions/nx.instructions.md -# env files (can opt-in for committing if needed) -.env* +vite.config.*.timestamp* +vitest.config.*.timestamp* -# vercel -.vercel +# Next.js +.next +out -# typescript -*.tsbuildinfo -next-env.d.ts +test-output diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..19be10e --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +strict-peer-dependencies=false +auto-install-peers=true diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..e26f0b3 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,5 @@ +# Add files here to ignore them from prettier formatting +/dist +/coverage +/.nx/cache +/.nx/workspace-data \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..1ca87ab --- /dev/null +++ b/.prettierrc @@ -0,0 +1,3 @@ +{ + "singleQuote": false +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..8e21401 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "nxConsole.generateAiAgentRules": true +} diff --git a/README.md b/README.md index e340364..e1f3644 100644 --- a/README.md +++ b/README.md @@ -1 +1,90 @@ -## BrowserPlugins +# Browserplugins + + + +✨ Your new, shiny [Nx workspace](https://nx.dev) is almost ready ✨. + +[Learn more about this workspace setup and its capabilities](https://nx.dev/nx-api/js?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or run `npx nx graph` to visually explore what was created. Now, let's get you up to speed! + +## Finish your CI setup + +[Click here to finish setting up your workspace!](https://cloud.nx.app/connect/1dtRgv7sbF) + + +## Generate a library + +```sh +npx nx g @nx/js:lib packages/pkg1 --publishable --importPath=@my-org/pkg1 +``` + +## Run tasks + +To build the library use: + +```sh +npx nx build pkg1 +``` + +To run any task with Nx use: + +```sh +npx nx +``` + +These targets are either [inferred automatically](https://nx.dev/concepts/inferred-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or defined in the `project.json` or `package.json` files. + +[More about running tasks in the docs »](https://nx.dev/features/run-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) + +## Versioning and releasing + +To version and release the library use + +``` +npx nx release +``` + +Pass `--dry-run` to see what would happen without actually releasing the library. + +[Learn more about Nx release »](https://nx.dev/features/manage-releases?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) + +## Keep TypeScript project references up to date + +Nx automatically updates TypeScript [project references](https://www.typescriptlang.org/docs/handbook/project-references.html) in `tsconfig.json` files to ensure they remain accurate based on your project dependencies (`import` or `require` statements). This sync is automatically done when running tasks such as `build` or `typecheck`, which require updated references to function correctly. + +To manually trigger the process to sync the project graph dependencies information to the TypeScript project references, run the following command: + +```sh +npx nx sync +``` + +You can enforce that the TypeScript project references are always in the correct state when running in CI by adding a step to your CI job configuration that runs the following command: + +```sh +npx nx sync:check +``` + +[Learn more about nx sync](https://nx.dev/reference/nx-commands#sync) + + +[Learn more about Nx on CI](https://nx.dev/ci/intro/ci-with-nx#ready-get-started-with-your-provider?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) + +## Install Nx Console + +Nx Console is an editor extension that enriches your developer experience. It lets you run tasks, generate code, and improves code autocompletion in your IDE. It is available for VSCode and IntelliJ. + +[Install Nx Console »](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) + +## Useful links + +Learn more: + +- [Learn more about this workspace setup](https://nx.dev/nx-api/js?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) +- [Learn about Nx on CI](https://nx.dev/ci/intro/ci-with-nx?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) +- [Releasing Packages with Nx release](https://nx.dev/features/manage-releases?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) +- [What are Nx plugins?](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) + +And join the Nx community: +- [Discord](https://go.nx.dev/community) +- [Follow us on X](https://twitter.com/nxdevtools) or [LinkedIn](https://www.linkedin.com/company/nrwl) +- [Our Youtube channel](https://www.youtube.com/@nxdevtools) +- [Our blog](https://nx.dev/blog?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) diff --git a/apps/client/.env.example b/apps/client/.env.example new file mode 100644 index 0000000..a7844fd --- /dev/null +++ b/apps/client/.env.example @@ -0,0 +1 @@ +SERVER_URL="" \ No newline at end of file diff --git a/apps/client/.gitignore b/apps/client/.gitignore new file mode 100644 index 0000000..e72b4d6 --- /dev/null +++ b/apps/client/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/apps/client/README.md b/apps/client/README.md new file mode 100644 index 0000000..e340364 --- /dev/null +++ b/apps/client/README.md @@ -0,0 +1 @@ +## BrowserPlugins diff --git a/components.json b/apps/client/components.json similarity index 100% rename from components.json rename to apps/client/components.json diff --git a/apps/client/eslint.config.mjs b/apps/client/eslint.config.mjs new file mode 100644 index 0000000..c85fb67 --- /dev/null +++ b/apps/client/eslint.config.mjs @@ -0,0 +1,16 @@ +import { dirname } from "path"; +import { fileURLToPath } from "url"; +import { FlatCompat } from "@eslint/eslintrc"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const compat = new FlatCompat({ + baseDirectory: __dirname, +}); + +const eslintConfig = [ + ...compat.extends("next/core-web-vitals", "next/typescript"), +]; + +export default eslintConfig; diff --git a/next.config.ts b/apps/client/next.config.ts similarity index 100% rename from next.config.ts rename to apps/client/next.config.ts diff --git a/notes.md b/apps/client/notes.md similarity index 100% rename from notes.md rename to apps/client/notes.md diff --git a/apps/client/package.json b/apps/client/package.json new file mode 100644 index 0000000..3d23b84 --- /dev/null +++ b/apps/client/package.json @@ -0,0 +1,55 @@ +{ + "name": "@browserplugins/client", + "version": "1.1.2", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "@browserplugins/schema": "workspace:*", + "@radix-ui/react-avatar": "^1.1.10", + "@radix-ui/react-checkbox": "^1.3.2", + "@radix-ui/react-dialog": "^1.1.14", + "@radix-ui/react-dropdown-menu": "^2.1.15", + "@radix-ui/react-hover-card": "^1.1.14", + "@radix-ui/react-label": "^2.1.7", + "@radix-ui/react-progress": "^1.1.7", + "@radix-ui/react-select": "^2.2.5", + "@radix-ui/react-separator": "^1.1.7", + "@radix-ui/react-slider": "^1.3.5", + "@radix-ui/react-slot": "^1.2.3", + "@radix-ui/react-switch": "^1.2.5", + "@radix-ui/react-tabs": "^1.1.12", + "@radix-ui/react-tooltip": "^1.2.7", + "axios": "^1.11.0", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "lucide-react": "^0.525.0", + "moment": "^2.30.1", + "next": "15.3.5", + "next-themes": "^0.4.6", + "postcss": "^8.5.6", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "sonner": "^2.0.6", + "tailwind-merge": "^3.3.1", + "tailwindcss-animate": "^1.0.7", + "zod": "^4.0.14", + "zustand": "^5.0.7" + }, + "devDependencies": { + "@eslint/eslintrc": "^3", + "@tailwindcss/postcss": "^4", + "@types/node": "^20", + "@types/react": "^19.1.10", + "@types/react-dom": "^19.1.7", + "eslint": "^9", + "eslint-config-next": "15.3.5", + "tailwindcss": "^4", + "tw-animate-css": "^1.3.5", + "typescript": "^5" + } +} diff --git a/postcss.config.mjs b/apps/client/postcss.config.mjs similarity index 100% rename from postcss.config.mjs rename to apps/client/postcss.config.mjs diff --git a/public/placeholder-logo.png b/apps/client/public/placeholder-logo.png similarity index 100% rename from public/placeholder-logo.png rename to apps/client/public/placeholder-logo.png diff --git a/public/placeholder-logo.svg b/apps/client/public/placeholder-logo.svg similarity index 100% rename from public/placeholder-logo.svg rename to apps/client/public/placeholder-logo.svg diff --git a/public/placeholder-thumb.jpg b/apps/client/public/placeholder-thumb.jpg similarity index 100% rename from public/placeholder-thumb.jpg rename to apps/client/public/placeholder-thumb.jpg diff --git a/public/placeholder-user.jpg b/apps/client/public/placeholder-user.jpg similarity index 100% rename from public/placeholder-user.jpg rename to apps/client/public/placeholder-user.jpg diff --git a/public/placeholder.jpg b/apps/client/public/placeholder.jpg similarity index 100% rename from public/placeholder.jpg rename to apps/client/public/placeholder.jpg diff --git a/public/placeholder.svg b/apps/client/public/placeholder.svg similarity index 100% rename from public/placeholder.svg rename to apps/client/public/placeholder.svg diff --git a/src/@types/extension/browser.ts b/apps/client/src/@types/extension/browser.ts similarity index 95% rename from src/@types/extension/browser.ts rename to apps/client/src/@types/extension/browser.ts index d1e09a8..64241b5 100644 --- a/src/@types/extension/browser.ts +++ b/apps/client/src/@types/extension/browser.ts @@ -1,7 +1,7 @@ -export const browsers = [ - "chrome", - "firefox", - "microsoft edge", - "safari", -] as const; -export type Browser = (typeof browsers)[number]; +export const browsers = [ + "chrome", + "firefox", + "microsoft edge", + "safari", +] as const; +export type Browser = (typeof browsers)[number]; diff --git a/src/@types/extension/category.ts b/apps/client/src/@types/extension/category.ts similarity index 94% rename from src/@types/extension/category.ts rename to apps/client/src/@types/extension/category.ts index d2b4a3d..a96f748 100644 --- a/src/@types/extension/category.ts +++ b/apps/client/src/@types/extension/category.ts @@ -1,10 +1,10 @@ -export const category = [ - "productivity", - "security", - "developer", - "social", - "entertainment", - "utility", - "all", -] as const; -export type Category = (typeof category)[number]; +export const category = [ + "productivity", + "security", + "developer", + "social", + "entertainment", + "utility", + "all", +] as const; +export type Category = (typeof category)[number]; diff --git a/src/@types/extension/developer.ts b/apps/client/src/@types/extension/developer.ts similarity index 94% rename from src/@types/extension/developer.ts rename to apps/client/src/@types/extension/developer.ts index e880861..cbae9b9 100644 --- a/src/@types/extension/developer.ts +++ b/apps/client/src/@types/extension/developer.ts @@ -1,5 +1,5 @@ -export type Developer = { - name: string; - avatar: string; - verified: boolean; -}; +export type Developer = { + name: string; + avatar: string; + verified: boolean; +}; diff --git a/src/@types/extension/filter.ts b/apps/client/src/@types/extension/filter.ts similarity index 97% rename from src/@types/extension/filter.ts rename to apps/client/src/@types/extension/filter.ts index 9e96257..4589948 100644 --- a/src/@types/extension/filter.ts +++ b/apps/client/src/@types/extension/filter.ts @@ -1,2 +1,2 @@ -import { sortsBy } from "@/constants"; -export type SortBy = (typeof sortsBy)[number]; +import { sortsBy } from "@/constants"; +export type SortBy = (typeof sortsBy)[number]; diff --git a/src/@types/extension/media.ts b/apps/client/src/@types/extension/media.ts similarity index 94% rename from src/@types/extension/media.ts rename to apps/client/src/@types/extension/media.ts index 358c13f..ee5e39e 100644 --- a/src/@types/extension/media.ts +++ b/apps/client/src/@types/extension/media.ts @@ -1,5 +1,5 @@ -export type Media = { - type: "video" | "image"; - url: string; - thumbnail?: string; -}; +export type Media = { + type: "video" | "image"; + url: string; + thumbnail?: string; +}; diff --git a/src/@types/extension/stats.ts b/apps/client/src/@types/extension/stats.ts similarity index 94% rename from src/@types/extension/stats.ts rename to apps/client/src/@types/extension/stats.ts index db05d01..c130864 100644 --- a/src/@types/extension/stats.ts +++ b/apps/client/src/@types/extension/stats.ts @@ -1,5 +1,5 @@ -export type Stats = { - downloads: number; - likes: number; - views: number; -}; +export type Stats = { + downloads: number; + likes: number; + views: number; +}; diff --git a/src/@types/index.ts b/apps/client/src/@types/index.ts similarity index 97% rename from src/@types/index.ts rename to apps/client/src/@types/index.ts index b35b4e3..d1cafbe 100644 --- a/src/@types/index.ts +++ b/apps/client/src/@types/index.ts @@ -1,8 +1,8 @@ -export type LooseAutocomplete = T | Omit; -export * from "./extension/browser"; -export * from "./extension/category"; -export * from "./extension/developer"; -export * from "./extension/extension"; -export * from "./extension/filter"; -export * from "./extension/media"; -export * from "./extension/stats"; +export type LooseAutocomplete = T | Omit; +export * from "./extension/browser"; +export * from "./extension/category"; +export * from "./extension/developer"; +export * from "./extension/extension"; +export * from "./extension/filter"; +export * from "./extension/media"; +export * from "./extension/stats"; diff --git a/apps/client/src/app/(admin)/_components/admin-sidebar.tsx b/apps/client/src/app/(admin)/_components/admin-sidebar.tsx new file mode 100644 index 0000000..49c8fea --- /dev/null +++ b/apps/client/src/app/(admin)/_components/admin-sidebar.tsx @@ -0,0 +1,63 @@ +import { + Sidebar, + SidebarContent, + SidebarFooter, + SidebarGroup, + SidebarGroupContent, + SidebarGroupLabel, + SidebarHeader, + SidebarMenu, + SidebarMenuButton, + SidebarMenuItem, + SidebarProvider, + SidebarRail, + SidebarTrigger, +} from "@/components/ui/sidebar"; +import { Package } from "lucide-react"; +import { adminNavItems } from "../_constants"; +import Link from "next/link"; +import { ThemeToggle } from "@/components/theme-toggle"; + +export default function AdminSidebar() { + return ( + + +
+
+ +
+
+ BrowserPlugins + Admin Panel +
+
+
+ + + Administration + + + {adminNavItems.map((item) => ( + + + + + {item.title} + + + + ))} + + + + + +
+ Admin Mode + +
+
+ +
+ ); +} diff --git a/apps/client/src/app/(admin)/_components/shared/page-header.tsx b/apps/client/src/app/(admin)/_components/shared/page-header.tsx new file mode 100644 index 0000000..ab7251c --- /dev/null +++ b/apps/client/src/app/(admin)/_components/shared/page-header.tsx @@ -0,0 +1,12 @@ +type Props = { + title: string; + description?: string; +}; +export default function PageHeader({ title, description }: Props) { + return ( +
+

{title}

+

{description}

+
+ ); +} diff --git a/apps/client/src/app/(admin)/_components/upload-form/basic-information.tsx b/apps/client/src/app/(admin)/_components/upload-form/basic-information.tsx new file mode 100644 index 0000000..ef97763 --- /dev/null +++ b/apps/client/src/app/(admin)/_components/upload-form/basic-information.tsx @@ -0,0 +1,122 @@ +"use client"; +import { + Card, + CardHeader, + CardTitle, + CardDescription, + CardContent, +} from "@/components/ui/card"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { Textarea } from "@/components/ui/textarea"; +import { categories } from "@/constants"; +import { useExtensionStore } from "../../_providers/template-store-provider"; +import type { ExtensionSchema } from "@browserplugins/schema"; + +export default function BasicInformation() { + const { formData, setFormData } = useExtensionStore((state) => state); + + + }; + return ( + + + Basic Information + + Provide basic details about your extension + + + +
+
+ + setFormData} + placeholder="Enter extension name" + required + /> +
+
+ + handleInputChange("version", e.target.value)} + placeholder="1.0.0" + required + /> +
+
+ +
+ + + // handleInputChange("shortDescription", e.target.value) + // } + placeholder="Brief description (max 100 characters)" + maxLength={100} + required + /> +
+ +
+ +