@prmvx/frontend-forge 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +224 -0
  3. package/dist/cli.js +662 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/templates/architectures/next/enterprise/src/components/common/Button.tsx +17 -0
  6. package/dist/templates/architectures/next/enterprise/src/components/home/HomeView.tsx +41 -0
  7. package/dist/templates/architectures/next/enterprise/src/components/layout/Footer.tsx +9 -0
  8. package/dist/templates/architectures/next/enterprise/src/components/layout/Header.tsx +19 -0
  9. package/dist/templates/architectures/next/enterprise/src/config/env.ts +3 -0
  10. package/dist/templates/architectures/next/enterprise/src/constants/routes.ts +4 -0
  11. package/dist/templates/architectures/next/enterprise/src/features/dashboard/components/DashboardSummary.tsx +22 -0
  12. package/dist/templates/architectures/next/enterprise/src/features/dashboard/hooks/useDashboard.ts +18 -0
  13. package/dist/templates/architectures/next/enterprise/src/features/dashboard/services/dashboard-api.ts +22 -0
  14. package/dist/templates/architectures/next/enterprise/src/features/dashboard/types/index.ts +4 -0
  15. package/dist/templates/architectures/next/enterprise/src/hooks/useDebounce.ts +14 -0
  16. package/dist/templates/architectures/next/enterprise/src/hooks/useToggle.ts +15 -0
  17. package/dist/templates/architectures/next/enterprise/src/providers/index.tsx +17 -0
  18. package/dist/templates/architectures/next/enterprise/src/providers/theme-provider.tsx +11 -0
  19. package/dist/templates/architectures/next/enterprise/src/services/api.ts +22 -0
  20. package/dist/templates/architectures/next/enterprise/src/store/app-store.tsx +33 -0
  21. package/dist/templates/architectures/next/enterprise/src/types/user.ts +5 -0
  22. package/dist/templates/architectures/next/enterprise/src/utils/cn.ts +3 -0
  23. package/dist/templates/architectures/next/enterprise/src/utils/formatDate.ts +7 -0
  24. package/dist/templates/architectures/next/feature/src/config/env.ts +3 -0
  25. package/dist/templates/architectures/next/feature/src/features/home/components/HomeHero.tsx +38 -0
  26. package/dist/templates/architectures/next/feature/src/features/home/components/HomePage.tsx +19 -0
  27. package/dist/templates/architectures/next/feature/src/features/home/constants/routes.ts +4 -0
  28. package/dist/templates/architectures/next/feature/src/features/home/hooks/useHome.ts +18 -0
  29. package/dist/templates/architectures/next/feature/src/features/home/services/home-api.ts +22 -0
  30. package/dist/templates/architectures/next/feature/src/features/home/types/index.ts +4 -0
  31. package/dist/templates/architectures/next/feature/src/features/profile/components/ProfileCard.tsx +19 -0
  32. package/dist/templates/architectures/next/feature/src/features/profile/hooks/useProfile.ts +18 -0
  33. package/dist/templates/architectures/next/feature/src/features/profile/services/profile-api.ts +22 -0
  34. package/dist/templates/architectures/next/feature/src/features/profile/types/index.ts +5 -0
  35. package/dist/templates/architectures/next/feature/src/shared/components/common/Button.tsx +17 -0
  36. package/dist/templates/architectures/next/feature/src/shared/components/layout/Footer.tsx +9 -0
  37. package/dist/templates/architectures/next/feature/src/shared/components/layout/Header.tsx +19 -0
  38. package/dist/templates/architectures/next/feature/src/shared/hooks/useDebounce.ts +14 -0
  39. package/dist/templates/architectures/next/feature/src/shared/hooks/useToggle.ts +15 -0
  40. package/dist/templates/architectures/next/feature/src/shared/providers/index.tsx +8 -0
  41. package/dist/templates/architectures/next/feature/src/shared/providers/theme-provider.tsx +7 -0
  42. package/dist/templates/architectures/next/feature/src/shared/utils/cn.ts +3 -0
  43. package/dist/templates/architectures/next/feature/src/shared/utils/formatDate.ts +7 -0
  44. package/dist/templates/architectures/next/standard/src/components/common/Button.tsx +17 -0
  45. package/dist/templates/architectures/next/standard/src/components/home/HomeView.tsx +53 -0
  46. package/dist/templates/architectures/next/standard/src/components/layout/Footer.tsx +9 -0
  47. package/dist/templates/architectures/next/standard/src/components/layout/Header.tsx +19 -0
  48. package/dist/templates/architectures/next/standard/src/config/env.ts +3 -0
  49. package/dist/templates/architectures/next/standard/src/constants/routes.ts +4 -0
  50. package/dist/templates/architectures/next/standard/src/hooks/useDebounce.ts +14 -0
  51. package/dist/templates/architectures/next/standard/src/hooks/useToggle.ts +15 -0
  52. package/dist/templates/architectures/next/standard/src/providers/index.tsx +12 -0
  53. package/dist/templates/architectures/next/standard/src/providers/theme-provider.tsx +11 -0
  54. package/dist/templates/architectures/next/standard/src/services/api.ts +22 -0
  55. package/dist/templates/architectures/next/standard/src/types/user.ts +5 -0
  56. package/dist/templates/architectures/next/standard/src/utils/cn.ts +3 -0
  57. package/dist/templates/architectures/next/standard/src/utils/formatDate.ts +7 -0
  58. package/dist/templates/modules/axios/module.ts +7 -0
  59. package/dist/templates/modules/core/module.ts +5 -0
  60. package/dist/templates/modules/core/src/components/common/Button.tsx +12 -0
  61. package/dist/templates/modules/core/src/components/layout/Header.tsx +7 -0
  62. package/dist/templates/modules/core/src/config/env.ts +3 -0
  63. package/dist/templates/modules/core/src/constants/index.ts +1 -0
  64. package/dist/templates/modules/core/src/constants/routes.ts +3 -0
  65. package/dist/templates/modules/core/src/hooks/index.ts +1 -0
  66. package/dist/templates/modules/core/src/hooks/useToggle.ts +13 -0
  67. package/dist/templates/modules/core/src/providers/index.tsx +9 -0
  68. package/dist/templates/modules/core/src/services/api.ts +5 -0
  69. package/dist/templates/modules/core/src/utils/cn.ts +3 -0
  70. package/dist/templates/modules/core/src/utils/index.ts +1 -0
  71. package/dist/templates/modules/zustand/module.ts +7 -0
  72. package/package.json +70 -0
@@ -0,0 +1,19 @@
1
+ import Link from "next/link";
2
+ import { Button } from "@/shared/components/common/Button";
3
+ import { HOME_ROUTES } from "@/features/home/constants/routes";
4
+
5
+ export function Header() {
6
+ return (
7
+ <header className="flex items-center justify-between border-b px-6 py-4">
8
+ <Link href={HOME_ROUTES.HOME} className="text-lg font-semibold">
9
+ Feature App
10
+ </Link>
11
+ <nav className="flex items-center gap-3">
12
+ <Link href={HOME_ROUTES.PROFILE} className="text-sm text-zinc-600">
13
+ Profile
14
+ </Link>
15
+ <Button>Explore</Button>
16
+ </nav>
17
+ </header>
18
+ );
19
+ }
@@ -0,0 +1,14 @@
1
+ "use client";
2
+
3
+ import { useEffect, useState } from "react";
4
+
5
+ export function useDebounce<T>(value: T, delay = 300) {
6
+ const [debouncedValue, setDebouncedValue] = useState(value);
7
+
8
+ useEffect(() => {
9
+ const timer = setTimeout(() => setDebouncedValue(value), delay);
10
+ return () => clearTimeout(timer);
11
+ }, [value, delay]);
12
+
13
+ return debouncedValue;
14
+ }
@@ -0,0 +1,15 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+
5
+ export function useToggle(defaultValue = false) {
6
+ const [value, setValue] = useState(defaultValue);
7
+
8
+ const toggle = () => setValue((prev) => !prev);
9
+
10
+ return {
11
+ value,
12
+ toggle,
13
+ setValue,
14
+ };
15
+ }
@@ -0,0 +1,8 @@
1
+ "use client";
2
+
3
+ import { ReactNode } from "react";
4
+ import { ThemeProvider } from "./theme-provider";
5
+
6
+ export function Providers({ children }: { children: ReactNode }) {
7
+ return <ThemeProvider>{children}</ThemeProvider>;
8
+ }
@@ -0,0 +1,7 @@
1
+ "use client";
2
+
3
+ import { ReactNode } from "react";
4
+
5
+ export function ThemeProvider({ children }: { children: ReactNode }) {
6
+ return <div className="min-h-screen bg-white text-zinc-900">{children}</div>;
7
+ }
@@ -0,0 +1,3 @@
1
+ export function cn(...classes: (string | undefined | false | null)[]) {
2
+ return classes.filter(Boolean).join(" ");
3
+ }
@@ -0,0 +1,7 @@
1
+ export function formatDate(date: Date) {
2
+ return date.toLocaleDateString("en-US", {
3
+ year: "numeric",
4
+ month: "long",
5
+ day: "numeric",
6
+ });
7
+ }
@@ -0,0 +1,17 @@
1
+ import { cn } from "@/utils/cn";
2
+
3
+ type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement>;
4
+
5
+ export function Button({ children, className, ...props }: ButtonProps) {
6
+ return (
7
+ <button
8
+ {...props}
9
+ className={cn(
10
+ "rounded-md bg-zinc-900 px-4 py-2 text-sm font-medium text-white transition hover:bg-zinc-700",
11
+ className
12
+ )}
13
+ >
14
+ {children}
15
+ </button>
16
+ );
17
+ }
@@ -0,0 +1,53 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+ import { Header } from "@/components/layout/Header";
5
+ import { Footer } from "@/components/layout/Footer";
6
+ import { Button } from "@/components/common/Button";
7
+ import { useToggle } from "@/hooks/useToggle";
8
+ import { useDebounce } from "@/hooks/useDebounce";
9
+ import { formatDate } from "@/utils/formatDate";
10
+
11
+ export function HomeView() {
12
+ const { value, toggle } = useToggle();
13
+ const [query, setQuery] = useState("architecture");
14
+ const debouncedQuery = useDebounce(query);
15
+
16
+ return (
17
+ <div className="flex min-h-screen flex-col">
18
+ <Header />
19
+ <main className="mx-auto flex w-full max-w-3xl flex-1 flex-col gap-6 px-6 py-10">
20
+ <section className="space-y-2">
21
+ <p className="text-sm uppercase tracking-wide text-zinc-500">
22
+ Standard Architecture
23
+ </p>
24
+ <h1 className="text-3xl font-bold">A simple, connected starter</h1>
25
+ <p className="text-zinc-600">
26
+ Components, hooks, services, and utilities work together from day
27
+ one. Today is {formatDate(new Date())}.
28
+ </p>
29
+ </section>
30
+
31
+ <section className="rounded-lg border p-4">
32
+ <h2 className="mb-2 font-medium">Hook demo</h2>
33
+ <p className="mb-3 text-sm text-zinc-600">
34
+ Toggle state: {value ? "On" : "Off"}
35
+ </p>
36
+ <Button onClick={toggle}>Toggle with useToggle</Button>
37
+ </section>
38
+
39
+ <section className="rounded-lg border p-4">
40
+ <h2 className="mb-2 font-medium">Debounce demo</h2>
41
+ <input
42
+ className="mb-2 w-full rounded-md border px-3 py-2"
43
+ value={query}
44
+ onChange={(event) => setQuery(event.target.value)}
45
+ placeholder="Type to debounce"
46
+ />
47
+ <p className="text-sm text-zinc-600">Debounced: {debouncedQuery}</p>
48
+ </section>
49
+ </main>
50
+ <Footer />
51
+ </div>
52
+ );
53
+ }
@@ -0,0 +1,9 @@
1
+ import { formatDate } from "@/utils/formatDate";
2
+
3
+ export function Footer() {
4
+ return (
5
+ <footer className="border-t px-6 py-4 text-sm text-zinc-500">
6
+ Built with Frontend Init · {formatDate(new Date())}
7
+ </footer>
8
+ );
9
+ }
@@ -0,0 +1,19 @@
1
+ import Link from "next/link";
2
+ import { Button } from "@/components/common/Button";
3
+ import { ROUTES } from "@/constants/routes";
4
+
5
+ export function Header() {
6
+ return (
7
+ <header className="flex items-center justify-between border-b px-6 py-4">
8
+ <Link href={ROUTES.HOME} className="text-lg font-semibold">
9
+ Frontend Init
10
+ </Link>
11
+ <nav className="flex items-center gap-3">
12
+ <Link href={ROUTES.ABOUT} className="text-sm text-zinc-600">
13
+ About
14
+ </Link>
15
+ <Button>Get Started</Button>
16
+ </nav>
17
+ </header>
18
+ );
19
+ }
@@ -0,0 +1,3 @@
1
+ export const env = {
2
+ apiUrl: process.env.NEXT_PUBLIC_API_URL ?? "https://api.example.com",
3
+ };
@@ -0,0 +1,4 @@
1
+ export const ROUTES = {
2
+ HOME: "/",
3
+ ABOUT: "/about",
4
+ } as const;
@@ -0,0 +1,14 @@
1
+ "use client";
2
+
3
+ import { useEffect, useState } from "react";
4
+
5
+ export function useDebounce<T>(value: T, delay = 300) {
6
+ const [debouncedValue, setDebouncedValue] = useState(value);
7
+
8
+ useEffect(() => {
9
+ const timer = setTimeout(() => setDebouncedValue(value), delay);
10
+ return () => clearTimeout(timer);
11
+ }, [value, delay]);
12
+
13
+ return debouncedValue;
14
+ }
@@ -0,0 +1,15 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+
5
+ export function useToggle(defaultValue = false) {
6
+ const [value, setValue] = useState(defaultValue);
7
+
8
+ const toggle = () => setValue((prev) => !prev);
9
+
10
+ return {
11
+ value,
12
+ toggle,
13
+ setValue,
14
+ };
15
+ }
@@ -0,0 +1,12 @@
1
+ "use client";
2
+
3
+ import { ReactNode } from "react";
4
+ import { ThemeProvider } from "./theme-provider";
5
+
6
+ type ProvidersProps = {
7
+ children: ReactNode;
8
+ };
9
+
10
+ export function Providers({ children }: ProvidersProps) {
11
+ return <ThemeProvider>{children}</ThemeProvider>;
12
+ }
@@ -0,0 +1,11 @@
1
+ "use client";
2
+
3
+ import { ReactNode } from "react";
4
+
5
+ type ThemeProviderProps = {
6
+ children: ReactNode;
7
+ };
8
+
9
+ export function ThemeProvider({ children }: ThemeProviderProps) {
10
+ return <div className="min-h-screen bg-white text-zinc-900">{children}</div>;
11
+ }
@@ -0,0 +1,22 @@
1
+ import { env } from "@/config/env";
2
+ import type { User } from "@/types/user";
3
+
4
+ export async function fetchHealth() {
5
+ const response = await fetch(`${env.apiUrl}/health`);
6
+
7
+ if (!response.ok) {
8
+ throw new Error("Health check failed");
9
+ }
10
+
11
+ return response.json();
12
+ }
13
+
14
+ export async function fetchCurrentUser(): Promise<User> {
15
+ const response = await fetch(`${env.apiUrl}/users/me`);
16
+
17
+ if (!response.ok) {
18
+ throw new Error("Failed to fetch user");
19
+ }
20
+
21
+ return response.json();
22
+ }
@@ -0,0 +1,5 @@
1
+ export type User = {
2
+ id: string;
3
+ name: string;
4
+ email: string;
5
+ };
@@ -0,0 +1,3 @@
1
+ export function cn(...classes: (string | undefined | false | null)[]) {
2
+ return classes.filter(Boolean).join(" ");
3
+ }
@@ -0,0 +1,7 @@
1
+ export function formatDate(date: Date) {
2
+ return date.toLocaleDateString("en-US", {
3
+ year: "numeric",
4
+ month: "long",
5
+ day: "numeric",
6
+ });
7
+ }
@@ -0,0 +1,7 @@
1
+ export default {
2
+ name: "axios",
3
+ dependencies: [
4
+ "axios",
5
+ ],
6
+ devDependencies: [],
7
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ name: "core",
3
+ dependencies: [],
4
+ devDependencies: [],
5
+ };
@@ -0,0 +1,12 @@
1
+ type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement>;
2
+
3
+ export function Button({ children, ...props }: ButtonProps) {
4
+ return (
5
+ <button
6
+ {...props}
7
+ className="rounded-md bg-black px-4 py-2 text-white"
8
+ >
9
+ {children}
10
+ </button>
11
+ );
12
+ }
@@ -0,0 +1,7 @@
1
+ export function Header() {
2
+ return (
3
+ <header className="border-b p-4">
4
+ <h1>Frontend Init</h1>
5
+ </header>
6
+ );
7
+ }
@@ -0,0 +1,3 @@
1
+ export const env = {
2
+ apiUrl: process.env.NEXT_PUBLIC_API_URL ?? "",
3
+ };
@@ -0,0 +1 @@
1
+ export * from "./routes";
@@ -0,0 +1,3 @@
1
+ export const ROUTES = {
2
+ HOME: "/",
3
+ };
@@ -0,0 +1 @@
1
+ export * from "./useToggle";
@@ -0,0 +1,13 @@
1
+ import { useState } from "react";
2
+
3
+ export function useToggle(defaultValue = false) {
4
+ const [value, setValue] = useState(defaultValue);
5
+
6
+ const toggle = () => setValue((prev) => !prev);
7
+
8
+ return {
9
+ value,
10
+ toggle,
11
+ setValue,
12
+ };
13
+ }
@@ -0,0 +1,9 @@
1
+ import { ReactNode } from "react";
2
+
3
+ type Props = {
4
+ children: ReactNode;
5
+ };
6
+
7
+ export function Providers({ children }: Props) {
8
+ return <>{children}</>;
9
+ }
@@ -0,0 +1,5 @@
1
+ export const api = {
2
+ get: async () => {
3
+ throw new Error("Not implemented");
4
+ },
5
+ };
@@ -0,0 +1,3 @@
1
+ export function cn(...classes: (string | undefined | false | null)[]) {
2
+ return classes.filter(Boolean).join(" ");
3
+ }
@@ -0,0 +1 @@
1
+ export * from "./cn";
@@ -0,0 +1,7 @@
1
+ export default {
2
+ name: "zustand",
3
+ dependencies: [
4
+ "zustand",
5
+ ],
6
+ devDependencies: [],
7
+ };
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "@prmvx/frontend-forge",
3
+ "version": "0.1.0",
4
+ "description": "A modern CLI to scaffold production-ready frontend architectures and starter modules for existing Next.js projects.",
5
+ "keywords": [
6
+ "cli",
7
+ "nextjs",
8
+ "react",
9
+ "frontend",
10
+ "starter",
11
+ "boilerplate",
12
+ "scaffold",
13
+ "architecture",
14
+ "template",
15
+ "generator",
16
+ "typescript",
17
+ "developer-tools",
18
+ "productivity",
19
+ "app-router"
20
+ ],
21
+ "homepage": "https://github.com/Parimal2607/frontend-forge#readme",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/Parimal2607/frontend-forge.git"
25
+ },
26
+ "bugs": {
27
+ "url": "https://github.com/Parimal2607/frontend-forge/issues"
28
+ },
29
+ "author": {
30
+ "name": "Parimal Sharma",
31
+ "url": "https://github.com/Parimal2607"
32
+ },
33
+ "license": "MIT",
34
+ "type": "module",
35
+ "bin": {
36
+ "frontend-forge": "./dist/cli.js"
37
+ },
38
+ "files": [
39
+ "dist",
40
+ "README.md",
41
+ "LICENSE"
42
+ ],
43
+ "engines": {
44
+ "node": ">=20"
45
+ },
46
+ "scripts": {
47
+ "clean": "rimraf dist",
48
+ "build": "npm run clean && tsup && npm run copy-templates",
49
+ "copy-templates": "cpy \"templates/**/*\" dist/templates",
50
+ "dev": "tsup --watch",
51
+ "prepare": "npm run build"
52
+ },
53
+ "dependencies": {
54
+ "@clack/prompts": "^1.7.0",
55
+ "commander": "^12.0.0",
56
+ "execa": "^9.6.1",
57
+ "fs-extra": "^11.2.0",
58
+ "picocolors": "^1.1.1"
59
+ },
60
+ "devDependencies": {
61
+ "@types/node": "^22.0.0",
62
+ "cpy-cli": "^7.0.0",
63
+ "rimraf": "^6.0.1",
64
+ "tsup": "^8.0.0",
65
+ "typescript": "^5.8.0"
66
+ },
67
+ "publishConfig": {
68
+ "access": "public"
69
+ }
70
+ }