@beknurakhmed/webforge-cli 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 (136) hide show
  1. package/README.md +212 -0
  2. package/dist/index.js +386 -0
  3. package/package.json +63 -0
  4. package/templates/angular/angular.json +36 -0
  5. package/templates/angular/package.json +29 -0
  6. package/templates/angular/src/app/app.component.ts +27 -0
  7. package/templates/angular/src/index.html +11 -0
  8. package/templates/angular/src/main.ts +4 -0
  9. package/templates/angular/src/styles.css +24 -0
  10. package/templates/angular/tsconfig.json +27 -0
  11. package/templates/base/README.md +16 -0
  12. package/templates/base/_gitignore +11 -0
  13. package/templates/extras/eslint/config/eslint.config.js +18 -0
  14. package/templates/extras/eslint/deps.json +7 -0
  15. package/templates/extras/prettier/config/.prettierignore +6 -0
  16. package/templates/extras/prettier/config/.prettierrc +7 -0
  17. package/templates/extras/prettier/deps.json +5 -0
  18. package/templates/nextjs/next.config.ts +5 -0
  19. package/templates/nextjs/package.json +16 -0
  20. package/templates/nextjs/src/app/globals.css +36 -0
  21. package/templates/nextjs/src/app/layout.tsx +19 -0
  22. package/templates/nextjs/src/app/page.tsx +8 -0
  23. package/templates/nextjs/tsconfig.json +21 -0
  24. package/templates/nuxt/app.vue +3 -0
  25. package/templates/nuxt/assets/css/main.css +24 -0
  26. package/templates/nuxt/nuxt.config.ts +5 -0
  27. package/templates/nuxt/package.json +17 -0
  28. package/templates/nuxt/pages/index.vue +20 -0
  29. package/templates/nuxt/tsconfig.json +3 -0
  30. package/templates/overlays/blog/react/src/App.css +41 -0
  31. package/templates/overlays/blog/react/src/App.tsx +39 -0
  32. package/templates/overlays/blog/react/src/components/BlogFooter.tsx +7 -0
  33. package/templates/overlays/blog/react/src/components/BlogHeader.tsx +15 -0
  34. package/templates/overlays/blog/react/src/components/BlogSidebar.tsx +26 -0
  35. package/templates/overlays/blog/react/src/components/PostList.tsx +27 -0
  36. package/templates/overlays/crm/react/src/App.css +48 -0
  37. package/templates/overlays/crm/react/src/App.tsx +49 -0
  38. package/templates/overlays/crm/react/src/components/ContactsTable.tsx +40 -0
  39. package/templates/overlays/crm/react/src/components/Filters.tsx +22 -0
  40. package/templates/overlays/crm/react/src/components/Sidebar.tsx +25 -0
  41. package/templates/overlays/crm/react/src/components/StatsCards.tsx +26 -0
  42. package/templates/overlays/dashboard/react/src/App.css +64 -0
  43. package/templates/overlays/dashboard/react/src/App.tsx +30 -0
  44. package/templates/overlays/dashboard/react/src/components/ChartPlaceholder.tsx +18 -0
  45. package/templates/overlays/dashboard/react/src/components/DataTable.tsx +44 -0
  46. package/templates/overlays/dashboard/react/src/components/KPICards.tsx +22 -0
  47. package/templates/overlays/dashboard/react/src/components/Sidebar.tsx +24 -0
  48. package/templates/overlays/ecommerce/react/src/App.css +82 -0
  49. package/templates/overlays/ecommerce/react/src/App.tsx +68 -0
  50. package/templates/overlays/ecommerce/react/src/components/Cart.tsx +47 -0
  51. package/templates/overlays/ecommerce/react/src/components/Footer.tsx +29 -0
  52. package/templates/overlays/ecommerce/react/src/components/Header.tsx +26 -0
  53. package/templates/overlays/ecommerce/react/src/components/ProductGrid.tsx +32 -0
  54. package/templates/overlays/ecommerce/vue/src/App.vue +44 -0
  55. package/templates/overlays/ecommerce/vue/src/components/CartPanel.vue +46 -0
  56. package/templates/overlays/ecommerce/vue/src/components/ProductGrid.vue +40 -0
  57. package/templates/overlays/ecommerce/vue/src/components/StoreFooter.vue +17 -0
  58. package/templates/overlays/ecommerce/vue/src/components/StoreHeader.vue +33 -0
  59. package/templates/overlays/landing/angular/src/app/app.component.ts +21 -0
  60. package/templates/overlays/landing/angular/src/app/components/cta.component.ts +24 -0
  61. package/templates/overlays/landing/angular/src/app/components/features.component.ts +42 -0
  62. package/templates/overlays/landing/angular/src/app/components/footer.component.ts +45 -0
  63. package/templates/overlays/landing/angular/src/app/components/hero.component.ts +41 -0
  64. package/templates/overlays/landing/nextjs/src/app/components/CTA.tsx +12 -0
  65. package/templates/overlays/landing/nextjs/src/app/components/Features.tsx +26 -0
  66. package/templates/overlays/landing/nextjs/src/app/components/Footer.tsx +27 -0
  67. package/templates/overlays/landing/nextjs/src/app/components/Hero.tsx +22 -0
  68. package/templates/overlays/landing/nextjs/src/app/globals.css +49 -0
  69. package/templates/overlays/landing/nextjs/src/app/page.tsx +15 -0
  70. package/templates/overlays/landing/nuxt/components/LandingCta.vue +18 -0
  71. package/templates/overlays/landing/nuxt/components/LandingFeatures.vue +36 -0
  72. package/templates/overlays/landing/nuxt/components/LandingFooter.vue +29 -0
  73. package/templates/overlays/landing/nuxt/components/LandingHero.vue +35 -0
  74. package/templates/overlays/landing/nuxt/pages/index.vue +15 -0
  75. package/templates/overlays/landing/react/src/App.css +70 -0
  76. package/templates/overlays/landing/react/src/App.tsx +18 -0
  77. package/templates/overlays/landing/react/src/components/CTA.tsx +14 -0
  78. package/templates/overlays/landing/react/src/components/Features.tsx +50 -0
  79. package/templates/overlays/landing/react/src/components/Footer.tsx +34 -0
  80. package/templates/overlays/landing/react/src/components/Hero.tsx +22 -0
  81. package/templates/overlays/landing/vanilla/src/main.ts +68 -0
  82. package/templates/overlays/landing/vanilla/src/style.css +43 -0
  83. package/templates/overlays/landing/vue/src/App.vue +19 -0
  84. package/templates/overlays/landing/vue/src/components/AppFooter.vue +44 -0
  85. package/templates/overlays/landing/vue/src/components/CTA.vue +21 -0
  86. package/templates/overlays/landing/vue/src/components/Features.vue +36 -0
  87. package/templates/overlays/landing/vue/src/components/Hero.vue +35 -0
  88. package/templates/overlays/portfolio/react/src/App.css +81 -0
  89. package/templates/overlays/portfolio/react/src/App.tsx +20 -0
  90. package/templates/overlays/portfolio/react/src/components/ContactForm.tsx +29 -0
  91. package/templates/overlays/portfolio/react/src/components/HeroSection.tsx +24 -0
  92. package/templates/overlays/portfolio/react/src/components/PortfolioFooter.tsx +14 -0
  93. package/templates/overlays/portfolio/react/src/components/Projects.tsx +33 -0
  94. package/templates/overlays/portfolio/react/src/components/Skills.tsx +27 -0
  95. package/templates/react/index.html +13 -0
  96. package/templates/react/package.json +19 -0
  97. package/templates/react/public/vite.svg +1 -0
  98. package/templates/react/src/App.css +11 -0
  99. package/templates/react/src/App.tsx +12 -0
  100. package/templates/react/src/index.css +42 -0
  101. package/templates/react/src/main.tsx +10 -0
  102. package/templates/react/vite.config.ts +6 -0
  103. package/templates/state/mobx/deps.json +6 -0
  104. package/templates/state/mobx/react/src/store/AppStore.ts +15 -0
  105. package/templates/state/ngrx/angular/src/app/store/app.state.ts +22 -0
  106. package/templates/state/ngrx/deps.json +7 -0
  107. package/templates/state/pinia/deps.json +5 -0
  108. package/templates/state/pinia/vue/src/store/useAppStore.ts +15 -0
  109. package/templates/state/redux/deps.json +6 -0
  110. package/templates/state/redux/react/src/store/counterSlice.ts +20 -0
  111. package/templates/state/redux/react/src/store/index.ts +11 -0
  112. package/templates/state/rxjs/angular/src/app/services/app-state.service.ts +18 -0
  113. package/templates/state/rxjs/deps.json +3 -0
  114. package/templates/state/zustand/deps.json +5 -0
  115. package/templates/state/zustand/react/src/store/useStore.ts +15 -0
  116. package/templates/styling/angular-material/deps.json +6 -0
  117. package/templates/styling/ant-design/deps.json +5 -0
  118. package/templates/styling/chakra-ui/deps.json +5 -0
  119. package/templates/styling/css-modules/deps.json +3 -0
  120. package/templates/styling/material-ui/deps.json +7 -0
  121. package/templates/styling/scss/deps.json +5 -0
  122. package/templates/styling/styled-components/deps.json +5 -0
  123. package/templates/styling/tailwind/config/postcss.config.js +5 -0
  124. package/templates/styling/tailwind/config/tailwind.config.js +11 -0
  125. package/templates/styling/tailwind/deps.json +6 -0
  126. package/templates/vanilla/index.html +13 -0
  127. package/templates/vanilla/package.json +14 -0
  128. package/templates/vanilla/src/main.ts +9 -0
  129. package/templates/vanilla/src/style.css +36 -0
  130. package/templates/vanilla/vite.config.ts +3 -0
  131. package/templates/vue/index.html +13 -0
  132. package/templates/vue/package.json +18 -0
  133. package/templates/vue/src/App.vue +23 -0
  134. package/templates/vue/src/main.ts +5 -0
  135. package/templates/vue/src/style.css +39 -0
  136. package/templates/vue/vite.config.ts +6 -0
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "{{projectName}}",
3
+ "private": true,
4
+ "version": "0.1.0",
5
+ "scripts": {
6
+ "dev": "ng serve",
7
+ "build": "ng build",
8
+ "test": "ng test"
9
+ },
10
+ "dependencies": {
11
+ "@angular/animations": "^19.0.0",
12
+ "@angular/common": "^19.0.0",
13
+ "@angular/compiler": "^19.0.0",
14
+ "@angular/core": "^19.0.0",
15
+ "@angular/forms": "^19.0.0",
16
+ "@angular/platform-browser": "^19.0.0",
17
+ "@angular/platform-browser-dynamic": "^19.0.0",
18
+ "@angular/router": "^19.0.0",
19
+ "rxjs": "~7.8.0",
20
+ "tslib": "^2.6.0",
21
+ "zone.js": "~0.15.0"
22
+ },
23
+ "devDependencies": {
24
+ "@angular/cli": "^19.0.0",
25
+ "@angular/compiler-cli": "^19.0.0",
26
+ "@angular-devkit/build-angular": "^19.0.0",
27
+ "typescript": "~5.6.0"
28
+ }
29
+ }
@@ -0,0 +1,27 @@
1
+ import { Component } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'app-root',
5
+ standalone: true,
6
+ template: `
7
+ <div class="app">
8
+ <h1>{{projectName}}</h1>
9
+ <p>Welcome to your new project!</p>
10
+ </div>
11
+ `,
12
+ styles: [`
13
+ .app {
14
+ max-width: 1280px;
15
+ margin: 0 auto;
16
+ padding: 2rem;
17
+ text-align: center;
18
+ }
19
+ h1 {
20
+ font-size: 3.2em;
21
+ line-height: 1.1;
22
+ }
23
+ `]
24
+ })
25
+ export class AppComponent {
26
+ title = '{{projectName}}';
27
+ }
@@ -0,0 +1,11 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>{{projectName}}</title>
7
+ </head>
8
+ <body>
9
+ <app-root></app-root>
10
+ </body>
11
+ </html>
@@ -0,0 +1,4 @@
1
+ import { bootstrapApplication } from '@angular/platform-browser';
2
+ import { AppComponent } from './app/app.component';
3
+
4
+ bootstrapApplication(AppComponent).catch((err) => console.error(err));
@@ -0,0 +1,24 @@
1
+ :root {
2
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3
+ line-height: 1.5;
4
+ font-weight: 400;
5
+ color: #213547;
6
+ background-color: #ffffff;
7
+ }
8
+
9
+ *, *::before, *::after {
10
+ box-sizing: border-box;
11
+ margin: 0;
12
+ padding: 0;
13
+ }
14
+
15
+ body {
16
+ min-height: 100vh;
17
+ }
18
+
19
+ @media (prefers-color-scheme: dark) {
20
+ :root {
21
+ color: rgba(255, 255, 255, 0.87);
22
+ background-color: #242424;
23
+ }
24
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "compileOnSave": false,
3
+ "compilerOptions": {
4
+ "outDir": "./dist/out-tsc",
5
+ "strict": true,
6
+ "noImplicitOverride": true,
7
+ "noPropertyAccessFromIndexSignature": true,
8
+ "noImplicitReturns": true,
9
+ "noFallthroughCasesInSwitch": true,
10
+ "sourceMap": true,
11
+ "declaration": false,
12
+ "downlevelIteration": true,
13
+ "experimentalDecorators": true,
14
+ "moduleResolution": "node",
15
+ "importHelpers": true,
16
+ "target": "ES2022",
17
+ "module": "ES2022",
18
+ "lib": ["ES2022", "dom"],
19
+ "skipLibCheck": true
20
+ },
21
+ "angularCompilerOptions": {
22
+ "enableI18nLegacyMessageIdFormat": false,
23
+ "strictInjectionParameters": true,
24
+ "strictInputAccessModifiers": true,
25
+ "strictTemplates": true
26
+ }
27
+ }
@@ -0,0 +1,16 @@
1
+ # {{projectName}}
2
+
3
+ Generated with [webforge-cli](https://www.npmjs.com/package/webforge-cli).
4
+
5
+ ## Getting Started
6
+
7
+ ```bash
8
+ npm install
9
+ npm run dev
10
+ ```
11
+
12
+ ## Scripts
13
+
14
+ - `npm run dev` — Start development server
15
+ - `npm run build` — Build for production
16
+ - `npm run preview` — Preview production build
@@ -0,0 +1,11 @@
1
+ node_modules/
2
+ dist/
3
+ .output/
4
+ .nuxt/
5
+ .next/
6
+ .angular/
7
+ *.local
8
+ .env
9
+ .env.*
10
+ !.env.example
11
+ .DS_Store
@@ -0,0 +1,18 @@
1
+ import js from '@eslint/js';
2
+ import globals from 'globals';
3
+
4
+ export default [
5
+ js.configs.recommended,
6
+ {
7
+ languageOptions: {
8
+ globals: {
9
+ ...globals.browser,
10
+ ...globals.node,
11
+ },
12
+ },
13
+ rules: {
14
+ 'no-unused-vars': 'warn',
15
+ 'no-console': 'warn',
16
+ },
17
+ },
18
+ ];
@@ -0,0 +1,7 @@
1
+ {
2
+ "devDependencies": {
3
+ "eslint": "^9.0.0",
4
+ "@eslint/js": "^9.0.0",
5
+ "globals": "^15.0.0"
6
+ }
7
+ }
@@ -0,0 +1,6 @@
1
+ node_modules
2
+ dist
3
+ .output
4
+ .nuxt
5
+ .next
6
+ .angular
@@ -0,0 +1,7 @@
1
+ {
2
+ "semi": true,
3
+ "singleQuote": true,
4
+ "tabWidth": 2,
5
+ "trailingComma": "es5",
6
+ "printWidth": 100
7
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "devDependencies": {
3
+ "prettier": "^3.4.0"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ import type { NextConfig } from 'next';
2
+
3
+ const nextConfig: NextConfig = {};
4
+
5
+ export default nextConfig;
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "{{projectName}}",
3
+ "private": true,
4
+ "version": "0.1.0",
5
+ "scripts": {
6
+ "dev": "next dev",
7
+ "build": "next build",
8
+ "start": "next start",
9
+ "lint": "next lint"
10
+ },
11
+ "dependencies": {
12
+ "next": "^15.0.0",
13
+ "react": "^19.0.0",
14
+ "react-dom": "^19.0.0"
15
+ }
16
+ }
@@ -0,0 +1,36 @@
1
+ :root {
2
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3
+ line-height: 1.5;
4
+ font-weight: 400;
5
+ color: #213547;
6
+ background-color: #ffffff;
7
+ }
8
+
9
+ *, *::before, *::after {
10
+ box-sizing: border-box;
11
+ margin: 0;
12
+ padding: 0;
13
+ }
14
+
15
+ body {
16
+ min-height: 100vh;
17
+ }
18
+
19
+ .app {
20
+ max-width: 1280px;
21
+ margin: 0 auto;
22
+ padding: 2rem;
23
+ text-align: center;
24
+ }
25
+
26
+ h1 {
27
+ font-size: 3.2em;
28
+ line-height: 1.1;
29
+ }
30
+
31
+ @media (prefers-color-scheme: dark) {
32
+ :root {
33
+ color: rgba(255, 255, 255, 0.87);
34
+ background-color: #242424;
35
+ }
36
+ }
@@ -0,0 +1,19 @@
1
+ import type { Metadata } from 'next';
2
+ import './globals.css';
3
+
4
+ export const metadata: Metadata = {
5
+ title: '{{projectName}}',
6
+ description: 'Generated with webforge-cli',
7
+ };
8
+
9
+ export default function RootLayout({
10
+ children,
11
+ }: {
12
+ children: React.ReactNode;
13
+ }) {
14
+ return (
15
+ <html lang="en">
16
+ <body>{children}</body>
17
+ </html>
18
+ );
19
+ }
@@ -0,0 +1,8 @@
1
+ export default function Home() {
2
+ return (
3
+ <div className="app">
4
+ <h1>{{projectName}}</h1>
5
+ <p>Welcome to your new project!</p>
6
+ </div>
7
+ );
8
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2017",
4
+ "lib": ["dom", "dom.iterable", "esnext"],
5
+ "allowJs": true,
6
+ "skipLibCheck": true,
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "esModuleInterop": true,
10
+ "module": "esnext",
11
+ "moduleResolution": "bundler",
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "jsx": "preserve",
15
+ "incremental": true,
16
+ "plugins": [{ "name": "next" }],
17
+ "paths": { "@/*": ["./src/*"] }
18
+ },
19
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
20
+ "exclude": ["node_modules"]
21
+ }
@@ -0,0 +1,3 @@
1
+ <template>
2
+ <NuxtPage />
3
+ </template>
@@ -0,0 +1,24 @@
1
+ :root {
2
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3
+ line-height: 1.5;
4
+ font-weight: 400;
5
+ color: #213547;
6
+ background-color: #ffffff;
7
+ }
8
+
9
+ *, *::before, *::after {
10
+ box-sizing: border-box;
11
+ margin: 0;
12
+ padding: 0;
13
+ }
14
+
15
+ body {
16
+ min-height: 100vh;
17
+ }
18
+
19
+ @media (prefers-color-scheme: dark) {
20
+ :root {
21
+ color: rgba(255, 255, 255, 0.87);
22
+ background-color: #242424;
23
+ }
24
+ }
@@ -0,0 +1,5 @@
1
+ export default defineNuxtConfig({
2
+ compatibilityDate: '2025-01-01',
3
+ devtools: { enabled: true },
4
+ css: ['~/assets/css/main.css'],
5
+ });
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "{{projectName}}",
3
+ "private": true,
4
+ "version": "0.1.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "nuxt dev",
8
+ "build": "nuxt build",
9
+ "generate": "nuxt generate",
10
+ "preview": "nuxt preview"
11
+ },
12
+ "dependencies": {
13
+ "nuxt": "^3.14.0",
14
+ "vue": "^3.5.0",
15
+ "vue-router": "^4.4.0"
16
+ }
17
+ }
@@ -0,0 +1,20 @@
1
+ <template>
2
+ <div class="app">
3
+ <h1>{{projectName}}</h1>
4
+ <p>Welcome to your new project!</p>
5
+ </div>
6
+ </template>
7
+
8
+ <style scoped>
9
+ .app {
10
+ max-width: 1280px;
11
+ margin: 0 auto;
12
+ padding: 2rem;
13
+ text-align: center;
14
+ }
15
+
16
+ h1 {
17
+ font-size: 3.2em;
18
+ line-height: 1.1;
19
+ }
20
+ </style>
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "./.nuxt/tsconfig.json"
3
+ }
@@ -0,0 +1,41 @@
1
+ .blog { min-height: 100vh; display: flex; flex-direction: column; }
2
+
3
+ .blog-header { border-bottom: 1px solid #e5e7eb; }
4
+ .blog-header .header-content { max-width: 1100px; margin: 0 auto; padding: 1.25rem 2rem; display: flex; justify-content: space-between; align-items: center; }
5
+ .blog-title { font-size: 1.5rem; color: #111827; margin: 0; }
6
+ .blog-nav { display: flex; gap: 1.5rem; }
7
+ .blog-nav a { text-decoration: none; color: #6b7280; font-weight: 500; }
8
+ .blog-nav a:hover, .blog-nav a.active { color: #4f46e5; }
9
+
10
+ .blog-layout { max-width: 1100px; margin: 0 auto; padding: 2rem; display: grid; grid-template-columns: 1fr 300px; gap: 3rem; flex: 1; }
11
+
12
+ .post-card { display: flex; gap: 1.5rem; padding: 1.5rem 0; border-bottom: 1px solid #f3f4f6; }
13
+ .post-image { font-size: 3rem; width: 80px; text-align: center; flex-shrink: 0; }
14
+ .post-category { font-size: 0.75rem; color: #4f46e5; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; }
15
+ .post-title { font-size: 1.25rem; font-weight: 700; color: #111827; margin: 0.25rem 0 0.5rem; }
16
+ .post-excerpt { color: #6b7280; line-height: 1.6; margin-bottom: 0.75rem; }
17
+ .post-meta { display: flex; gap: 1rem; font-size: 0.8rem; color: #9ca3af; }
18
+
19
+ .blog-sidebar { display: flex; flex-direction: column; gap: 2rem; }
20
+ .sidebar-section { background: #f9fafb; padding: 1.5rem; border-radius: 12px; }
21
+ .sidebar-section h3 { font-size: 1rem; font-weight: 600; margin-bottom: 0.75rem; color: #111827; }
22
+ .sidebar-section p { color: #6b7280; font-size: 0.9rem; line-height: 1.5; margin-bottom: 0.75rem; }
23
+ .category-list { display: flex; flex-wrap: wrap; gap: 0.5rem; }
24
+ .category-tag { background: white; border: 1px solid #e5e7eb; padding: 0.25rem 0.75rem; border-radius: 20px; font-size: 0.8rem; color: #374151; text-decoration: none; }
25
+ .category-tag:hover { border-color: #4f46e5; color: #4f46e5; }
26
+ .newsletter-input { width: 100%; padding: 0.5rem 0.75rem; border: 1px solid #d1d5db; border-radius: 6px; font-size: 0.9rem; margin-bottom: 0.5rem; }
27
+ .newsletter-btn { width: 100%; background: #4f46e5; color: white; border: none; padding: 0.5rem; border-radius: 6px; cursor: pointer; font-weight: 600; }
28
+
29
+ .blog-footer { border-top: 1px solid #e5e7eb; padding: 2rem; text-align: center; color: #9ca3af; font-size: 0.875rem; }
30
+
31
+ @media (max-width: 768px) { .blog-layout { grid-template-columns: 1fr; } .post-card { flex-direction: column; } }
32
+
33
+ @media (prefers-color-scheme: dark) {
34
+ .blog-header { border-color: #374151; }
35
+ .blog-title, .post-title, .sidebar-section h3 { color: white; }
36
+ .post-card { border-color: #374151; }
37
+ .sidebar-section { background: #1f2937; }
38
+ .category-tag { background: #1f2937; border-color: #374151; color: #d1d5db; }
39
+ .newsletter-input { background: #1f2937; border-color: #374151; color: white; }
40
+ .blog-footer { border-color: #374151; }
41
+ }
@@ -0,0 +1,39 @@
1
+ import { BlogHeader } from './components/BlogHeader';
2
+ import { PostList } from './components/PostList';
3
+ import { BlogSidebar } from './components/BlogSidebar';
4
+ import { BlogFooter } from './components/BlogFooter';
5
+ import './App.css';
6
+
7
+ export interface Post {
8
+ id: number;
9
+ title: string;
10
+ excerpt: string;
11
+ author: string;
12
+ date: string;
13
+ category: string;
14
+ readTime: string;
15
+ image: string;
16
+ }
17
+
18
+ const posts: Post[] = [
19
+ { id: 1, title: 'Getting Started with Modern Web Development', excerpt: 'Learn the fundamentals of modern web development including frameworks, build tools, and best practices.', author: 'Beknur', date: 'Feb 20, 2025', category: 'Tutorial', readTime: '5 min', image: '📘' },
20
+ { id: 2, title: 'Understanding TypeScript Generics', excerpt: 'A deep dive into TypeScript generics and how they can make your code more reusable and type-safe.', author: 'Beknur', date: 'Feb 18, 2025', category: 'TypeScript', readTime: '8 min', image: '📗' },
21
+ { id: 3, title: 'CSS Grid vs Flexbox: When to Use Which', excerpt: 'A practical comparison of CSS Grid and Flexbox with real-world examples and use cases.', author: 'Beknur', date: 'Feb 15, 2025', category: 'CSS', readTime: '6 min', image: '📙' },
22
+ { id: 4, title: 'Building Accessible Web Applications', excerpt: 'Best practices for building web applications that are accessible to everyone.', author: 'Beknur', date: 'Feb 12, 2025', category: 'Accessibility', readTime: '7 min', image: '📕' },
23
+ { id: 5, title: 'State Management in 2025', excerpt: 'An overview of state management solutions and when to use them in modern applications.', author: 'Beknur', date: 'Feb 10, 2025', category: 'Architecture', readTime: '10 min', image: '📓' },
24
+ ];
25
+
26
+ function App() {
27
+ return (
28
+ <div className="blog">
29
+ <BlogHeader />
30
+ <div className="blog-layout">
31
+ <PostList posts={posts} />
32
+ <BlogSidebar />
33
+ </div>
34
+ <BlogFooter />
35
+ </div>
36
+ );
37
+ }
38
+
39
+ export default App;
@@ -0,0 +1,7 @@
1
+ export function BlogFooter() {
2
+ return (
3
+ <footer className="blog-footer">
4
+ <p>&copy; 2025 {{projectName}}. Built with passion for the web.</p>
5
+ </footer>
6
+ );
7
+ }
@@ -0,0 +1,15 @@
1
+ export function BlogHeader() {
2
+ return (
3
+ <header className="blog-header">
4
+ <div className="header-content">
5
+ <h1 className="blog-title">{{projectName}}</h1>
6
+ <nav className="blog-nav">
7
+ <a href="#" className="active">Home</a>
8
+ <a href="#">Articles</a>
9
+ <a href="#">Categories</a>
10
+ <a href="#">About</a>
11
+ </nav>
12
+ </div>
13
+ </header>
14
+ );
15
+ }
@@ -0,0 +1,26 @@
1
+ const categories = ['Tutorial', 'TypeScript', 'CSS', 'Accessibility', 'Architecture', 'JavaScript', 'React'];
2
+
3
+ export function BlogSidebar() {
4
+ return (
5
+ <aside className="blog-sidebar">
6
+ <div className="sidebar-section">
7
+ <h3>About</h3>
8
+ <p>A blog about modern web development, best practices, and software engineering.</p>
9
+ </div>
10
+ <div className="sidebar-section">
11
+ <h3>Categories</h3>
12
+ <div className="category-list">
13
+ {categories.map((cat, i) => (
14
+ <a key={i} href="#" className="category-tag">{cat}</a>
15
+ ))}
16
+ </div>
17
+ </div>
18
+ <div className="sidebar-section">
19
+ <h3>Newsletter</h3>
20
+ <p>Subscribe to get the latest posts delivered to your inbox.</p>
21
+ <input type="email" placeholder="your@email.com" className="newsletter-input" />
22
+ <button className="newsletter-btn">Subscribe</button>
23
+ </div>
24
+ </aside>
25
+ );
26
+ }
@@ -0,0 +1,27 @@
1
+ import type { Post } from '../App';
2
+
3
+ interface PostListProps {
4
+ posts: Post[];
5
+ }
6
+
7
+ export function PostList({ posts }: PostListProps) {
8
+ return (
9
+ <main className="post-list">
10
+ {posts.map((post) => (
11
+ <article key={post.id} className="post-card">
12
+ <div className="post-image">{post.image}</div>
13
+ <div className="post-content">
14
+ <span className="post-category">{post.category}</span>
15
+ <h2 className="post-title">{post.title}</h2>
16
+ <p className="post-excerpt">{post.excerpt}</p>
17
+ <div className="post-meta">
18
+ <span className="post-author">By {post.author}</span>
19
+ <span className="post-date">{post.date}</span>
20
+ <span className="post-read-time">{post.readTime} read</span>
21
+ </div>
22
+ </div>
23
+ </article>
24
+ ))}
25
+ </main>
26
+ );
27
+ }
@@ -0,0 +1,48 @@
1
+ .crm { display: flex; min-height: 100vh; }
2
+ .sidebar { width: 240px; background: #111827; color: white; padding: 1.5rem; flex-shrink: 0; }
3
+ .sidebar-logo { font-size: 1.25rem; font-weight: 700; padding: 0.5rem 0.75rem; margin-bottom: 2rem; color: #4f46e5; }
4
+ .sidebar-nav { display: flex; flex-direction: column; gap: 0.25rem; }
5
+ .sidebar-item { display: flex; align-items: center; gap: 0.75rem; padding: 0.7rem; border-radius: 8px; color: #9ca3af; text-decoration: none; transition: all 0.15s; }
6
+ .sidebar-item:hover { background: #1f2937; color: white; }
7
+ .sidebar-item.active { background: #4f46e5; color: white; }
8
+
9
+ .crm-main { flex: 1; background: #f9fafb; padding: 2rem; overflow-y: auto; }
10
+ .crm-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 2rem; }
11
+ .crm-header h1 { font-size: 1.75rem; font-weight: 700; color: #111827; margin: 0; }
12
+ .btn-primary { background: #4f46e5; color: white; border: none; padding: 0.6rem 1.25rem; border-radius: 8px; cursor: pointer; font-weight: 600; font-size: 0.9rem; }
13
+
14
+ .stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1rem; margin-bottom: 1.5rem; }
15
+ .stat-card { background: white; border-radius: 12px; padding: 1.25rem; border: 1px solid #e5e7eb; position: relative; overflow: hidden; }
16
+ .stat-indicator { position: absolute; top: 0; left: 0; width: 4px; height: 100%; }
17
+ .stat-label { font-size: 0.8rem; color: #6b7280; }
18
+ .stat-value { font-size: 1.75rem; font-weight: 700; color: #111827; }
19
+
20
+ .filters { display: flex; gap: 0.5rem; margin-bottom: 1.5rem; }
21
+ .filter-btn { background: white; border: 1px solid #d1d5db; padding: 0.4rem 1rem; border-radius: 20px; cursor: pointer; font-size: 0.85rem; color: #6b7280; transition: all 0.15s; }
22
+ .filter-btn:hover { border-color: #4f46e5; color: #4f46e5; }
23
+ .filter-btn.active { background: #4f46e5; color: white; border-color: #4f46e5; }
24
+
25
+ .table-card { background: white; border-radius: 12px; border: 1px solid #e5e7eb; overflow: hidden; }
26
+ .data-table { width: 100%; border-collapse: collapse; }
27
+ .data-table th { text-align: left; padding: 0.75rem 1.25rem; font-size: 0.8rem; color: #6b7280; text-transform: uppercase; letter-spacing: 0.05em; background: #f9fafb; border-bottom: 1px solid #e5e7eb; }
28
+ .data-table td { padding: 0.75rem 1.25rem; border-bottom: 1px solid #f3f4f6; font-size: 0.9rem; }
29
+ .contact-name { font-weight: 600; color: #111827; }
30
+ .contact-email { color: #6b7280; }
31
+ .contact-value { font-weight: 600; color: #111827; }
32
+ .contact-time { color: #9ca3af; font-size: 0.85rem; }
33
+ .status-badge { padding: 0.2rem 0.6rem; border-radius: 9999px; font-size: 0.75rem; font-weight: 500; }
34
+ .status-lead { background: #fef3c7; color: #92400e; }
35
+ .status-prospect { background: #dbeafe; color: #1e40af; }
36
+ .status-customer { background: #d1fae5; color: #065f46; }
37
+ .status-churned { background: #fee2e2; color: #991b1b; }
38
+
39
+ @media (max-width: 768px) { .crm { flex-direction: column; } .sidebar { width: 100%; } }
40
+
41
+ @media (prefers-color-scheme: dark) {
42
+ .crm-main { background: #0f172a; }
43
+ .crm-header h1, .stat-value, .contact-name, .contact-value { color: white; }
44
+ .stat-card, .table-card { background: #1e293b; border-color: #334155; }
45
+ .data-table th { background: #1e293b; border-color: #334155; color: #94a3b8; }
46
+ .data-table td { border-color: #334155; color: #cbd5e1; }
47
+ .filter-btn { background: #1e293b; border-color: #334155; color: #94a3b8; }
48
+ }