@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.
- package/README.md +212 -0
- package/dist/index.js +386 -0
- package/package.json +63 -0
- package/templates/angular/angular.json +36 -0
- package/templates/angular/package.json +29 -0
- package/templates/angular/src/app/app.component.ts +27 -0
- package/templates/angular/src/index.html +11 -0
- package/templates/angular/src/main.ts +4 -0
- package/templates/angular/src/styles.css +24 -0
- package/templates/angular/tsconfig.json +27 -0
- package/templates/base/README.md +16 -0
- package/templates/base/_gitignore +11 -0
- package/templates/extras/eslint/config/eslint.config.js +18 -0
- package/templates/extras/eslint/deps.json +7 -0
- package/templates/extras/prettier/config/.prettierignore +6 -0
- package/templates/extras/prettier/config/.prettierrc +7 -0
- package/templates/extras/prettier/deps.json +5 -0
- package/templates/nextjs/next.config.ts +5 -0
- package/templates/nextjs/package.json +16 -0
- package/templates/nextjs/src/app/globals.css +36 -0
- package/templates/nextjs/src/app/layout.tsx +19 -0
- package/templates/nextjs/src/app/page.tsx +8 -0
- package/templates/nextjs/tsconfig.json +21 -0
- package/templates/nuxt/app.vue +3 -0
- package/templates/nuxt/assets/css/main.css +24 -0
- package/templates/nuxt/nuxt.config.ts +5 -0
- package/templates/nuxt/package.json +17 -0
- package/templates/nuxt/pages/index.vue +20 -0
- package/templates/nuxt/tsconfig.json +3 -0
- package/templates/overlays/blog/react/src/App.css +41 -0
- package/templates/overlays/blog/react/src/App.tsx +39 -0
- package/templates/overlays/blog/react/src/components/BlogFooter.tsx +7 -0
- package/templates/overlays/blog/react/src/components/BlogHeader.tsx +15 -0
- package/templates/overlays/blog/react/src/components/BlogSidebar.tsx +26 -0
- package/templates/overlays/blog/react/src/components/PostList.tsx +27 -0
- package/templates/overlays/crm/react/src/App.css +48 -0
- package/templates/overlays/crm/react/src/App.tsx +49 -0
- package/templates/overlays/crm/react/src/components/ContactsTable.tsx +40 -0
- package/templates/overlays/crm/react/src/components/Filters.tsx +22 -0
- package/templates/overlays/crm/react/src/components/Sidebar.tsx +25 -0
- package/templates/overlays/crm/react/src/components/StatsCards.tsx +26 -0
- package/templates/overlays/dashboard/react/src/App.css +64 -0
- package/templates/overlays/dashboard/react/src/App.tsx +30 -0
- package/templates/overlays/dashboard/react/src/components/ChartPlaceholder.tsx +18 -0
- package/templates/overlays/dashboard/react/src/components/DataTable.tsx +44 -0
- package/templates/overlays/dashboard/react/src/components/KPICards.tsx +22 -0
- package/templates/overlays/dashboard/react/src/components/Sidebar.tsx +24 -0
- package/templates/overlays/ecommerce/react/src/App.css +82 -0
- package/templates/overlays/ecommerce/react/src/App.tsx +68 -0
- package/templates/overlays/ecommerce/react/src/components/Cart.tsx +47 -0
- package/templates/overlays/ecommerce/react/src/components/Footer.tsx +29 -0
- package/templates/overlays/ecommerce/react/src/components/Header.tsx +26 -0
- package/templates/overlays/ecommerce/react/src/components/ProductGrid.tsx +32 -0
- package/templates/overlays/ecommerce/vue/src/App.vue +44 -0
- package/templates/overlays/ecommerce/vue/src/components/CartPanel.vue +46 -0
- package/templates/overlays/ecommerce/vue/src/components/ProductGrid.vue +40 -0
- package/templates/overlays/ecommerce/vue/src/components/StoreFooter.vue +17 -0
- package/templates/overlays/ecommerce/vue/src/components/StoreHeader.vue +33 -0
- package/templates/overlays/landing/angular/src/app/app.component.ts +21 -0
- package/templates/overlays/landing/angular/src/app/components/cta.component.ts +24 -0
- package/templates/overlays/landing/angular/src/app/components/features.component.ts +42 -0
- package/templates/overlays/landing/angular/src/app/components/footer.component.ts +45 -0
- package/templates/overlays/landing/angular/src/app/components/hero.component.ts +41 -0
- package/templates/overlays/landing/nextjs/src/app/components/CTA.tsx +12 -0
- package/templates/overlays/landing/nextjs/src/app/components/Features.tsx +26 -0
- package/templates/overlays/landing/nextjs/src/app/components/Footer.tsx +27 -0
- package/templates/overlays/landing/nextjs/src/app/components/Hero.tsx +22 -0
- package/templates/overlays/landing/nextjs/src/app/globals.css +49 -0
- package/templates/overlays/landing/nextjs/src/app/page.tsx +15 -0
- package/templates/overlays/landing/nuxt/components/LandingCta.vue +18 -0
- package/templates/overlays/landing/nuxt/components/LandingFeatures.vue +36 -0
- package/templates/overlays/landing/nuxt/components/LandingFooter.vue +29 -0
- package/templates/overlays/landing/nuxt/components/LandingHero.vue +35 -0
- package/templates/overlays/landing/nuxt/pages/index.vue +15 -0
- package/templates/overlays/landing/react/src/App.css +70 -0
- package/templates/overlays/landing/react/src/App.tsx +18 -0
- package/templates/overlays/landing/react/src/components/CTA.tsx +14 -0
- package/templates/overlays/landing/react/src/components/Features.tsx +50 -0
- package/templates/overlays/landing/react/src/components/Footer.tsx +34 -0
- package/templates/overlays/landing/react/src/components/Hero.tsx +22 -0
- package/templates/overlays/landing/vanilla/src/main.ts +68 -0
- package/templates/overlays/landing/vanilla/src/style.css +43 -0
- package/templates/overlays/landing/vue/src/App.vue +19 -0
- package/templates/overlays/landing/vue/src/components/AppFooter.vue +44 -0
- package/templates/overlays/landing/vue/src/components/CTA.vue +21 -0
- package/templates/overlays/landing/vue/src/components/Features.vue +36 -0
- package/templates/overlays/landing/vue/src/components/Hero.vue +35 -0
- package/templates/overlays/portfolio/react/src/App.css +81 -0
- package/templates/overlays/portfolio/react/src/App.tsx +20 -0
- package/templates/overlays/portfolio/react/src/components/ContactForm.tsx +29 -0
- package/templates/overlays/portfolio/react/src/components/HeroSection.tsx +24 -0
- package/templates/overlays/portfolio/react/src/components/PortfolioFooter.tsx +14 -0
- package/templates/overlays/portfolio/react/src/components/Projects.tsx +33 -0
- package/templates/overlays/portfolio/react/src/components/Skills.tsx +27 -0
- package/templates/react/index.html +13 -0
- package/templates/react/package.json +19 -0
- package/templates/react/public/vite.svg +1 -0
- package/templates/react/src/App.css +11 -0
- package/templates/react/src/App.tsx +12 -0
- package/templates/react/src/index.css +42 -0
- package/templates/react/src/main.tsx +10 -0
- package/templates/react/vite.config.ts +6 -0
- package/templates/state/mobx/deps.json +6 -0
- package/templates/state/mobx/react/src/store/AppStore.ts +15 -0
- package/templates/state/ngrx/angular/src/app/store/app.state.ts +22 -0
- package/templates/state/ngrx/deps.json +7 -0
- package/templates/state/pinia/deps.json +5 -0
- package/templates/state/pinia/vue/src/store/useAppStore.ts +15 -0
- package/templates/state/redux/deps.json +6 -0
- package/templates/state/redux/react/src/store/counterSlice.ts +20 -0
- package/templates/state/redux/react/src/store/index.ts +11 -0
- package/templates/state/rxjs/angular/src/app/services/app-state.service.ts +18 -0
- package/templates/state/rxjs/deps.json +3 -0
- package/templates/state/zustand/deps.json +5 -0
- package/templates/state/zustand/react/src/store/useStore.ts +15 -0
- package/templates/styling/angular-material/deps.json +6 -0
- package/templates/styling/ant-design/deps.json +5 -0
- package/templates/styling/chakra-ui/deps.json +5 -0
- package/templates/styling/css-modules/deps.json +3 -0
- package/templates/styling/material-ui/deps.json +7 -0
- package/templates/styling/scss/deps.json +5 -0
- package/templates/styling/styled-components/deps.json +5 -0
- package/templates/styling/tailwind/config/postcss.config.js +5 -0
- package/templates/styling/tailwind/config/tailwind.config.js +11 -0
- package/templates/styling/tailwind/deps.json +6 -0
- package/templates/vanilla/index.html +13 -0
- package/templates/vanilla/package.json +14 -0
- package/templates/vanilla/src/main.ts +9 -0
- package/templates/vanilla/src/style.css +36 -0
- package/templates/vanilla/vite.config.ts +3 -0
- package/templates/vue/index.html +13 -0
- package/templates/vue/package.json +18 -0
- package/templates/vue/src/App.vue +23 -0
- package/templates/vue/src/main.ts +5 -0
- package/templates/vue/src/style.css +39 -0
- 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,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,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,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,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,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,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,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,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
|
+
}
|