create-credbuild-app 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 +52 -0
- package/bin/index.mjs +147 -0
- package/package.json +20 -0
- package/template/credbuild.config.tsx +7 -0
- package/template/eslint.config.mjs +18 -0
- package/template/next-env.d.ts +6 -0
- package/template/next.config.ts +28 -0
- package/template/package.json +29 -0
- package/template/postcss.config.mjs +7 -0
- package/template/public/file.svg +1 -0
- package/template/public/globe.svg +1 -0
- package/template/public/next.svg +1 -0
- package/template/public/uploads/1779603188480-puzzle_10262348.png +0 -0
- package/template/public/vercel.svg +1 -0
- package/template/public/window.svg +1 -0
- package/template/src/app/api/credbuild/route.ts +17 -0
- package/template/src/app/api/media/proxy/route.ts +23 -0
- package/template/src/app/api/media/route.ts +52 -0
- package/template/src/app/credbuild/[[...path]]/EditorClient.tsx +33 -0
- package/template/src/app/credbuild/[[...path]]/page.tsx +22 -0
- package/template/src/app/favicon.ico +0 -0
- package/template/src/app/globals.css +31 -0
- package/template/src/app/layout.tsx +34 -0
- package/template/src/app/page.tsx +355 -0
- package/template/src/proxy.ts +16 -0
- package/template/tsconfig.json +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# create-credbuild-app
|
|
2
|
+
|
|
3
|
+
Create a new [CredBuild](https://crediblemark.com) project with a single command.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx create-credbuild-app my-website
|
|
9
|
+
cd my-website
|
|
10
|
+
npm run dev
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Then open [http://localhost:3000/edit](http://localhost:3000/edit) to access the visual editor.
|
|
14
|
+
|
|
15
|
+
## What's included
|
|
16
|
+
|
|
17
|
+
- ⚡ **Next.js 16** — Latest framework with App Router
|
|
18
|
+
- 🎨 **40+ Premium Blocks** — Hero sections, pricing, testimonials, galleries, and more
|
|
19
|
+
- 🖼️ **Visual Drag & Drop Editor** — Build pages without code
|
|
20
|
+
- 📱 **Responsive** — Every block works on all screen sizes
|
|
21
|
+
- 🎯 **SEO Optimized** — Semantic HTML and meta tags built-in
|
|
22
|
+
- 🔧 **Fully Customizable** — Fine-tune colors, spacing, and typography
|
|
23
|
+
|
|
24
|
+
## Project Structure
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
my-website/
|
|
28
|
+
├── src/
|
|
29
|
+
│ ├── app/
|
|
30
|
+
│ │ ├── page.tsx # Landing page
|
|
31
|
+
│ │ ├── layout.tsx # Root layout
|
|
32
|
+
│ │ ├── globals.css # Global styles
|
|
33
|
+
│ │ ├── credbuild/ # Editor route
|
|
34
|
+
│ │ └── api/ # API routes
|
|
35
|
+
│ └── proxy.ts # Media proxy
|
|
36
|
+
├── credbuild.config.tsx # Block configuration
|
|
37
|
+
├── next.config.ts # Next.js config
|
|
38
|
+
└── package.json
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Commands
|
|
42
|
+
|
|
43
|
+
| Command | Description |
|
|
44
|
+
|---------|-------------|
|
|
45
|
+
| `npm run dev` | Start development server |
|
|
46
|
+
| `npm run build` | Build for production |
|
|
47
|
+
| `npm start` | Start production server |
|
|
48
|
+
|
|
49
|
+
## Learn More
|
|
50
|
+
|
|
51
|
+
- [CredBuild Documentation](https://crediblemark.com/docs)
|
|
52
|
+
- [Next.js Documentation](https://nextjs.org/docs)
|
package/bin/index.mjs
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { execSync } from "node:child_process";
|
|
4
|
+
import { cpSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { basename, join, resolve, dirname } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
|
|
8
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
|
|
10
|
+
// ── Colors (no dependencies) ────────────────────────────────────────
|
|
11
|
+
const bold = (t) => `\x1b[1m${t}\x1b[22m`;
|
|
12
|
+
const cyan = (t) => `\x1b[36m${t}\x1b[39m`;
|
|
13
|
+
const green = (t) => `\x1b[32m${t}\x1b[39m`;
|
|
14
|
+
const yellow = (t) => `\x1b[33m${t}\x1b[39m`;
|
|
15
|
+
const dim = (t) => `\x1b[2m${t}\x1b[22m`;
|
|
16
|
+
const red = (t) => `\x1b[31m${t}\x1b[39m`;
|
|
17
|
+
|
|
18
|
+
// ── Banner ──────────────────────────────────────────────────────────
|
|
19
|
+
function banner() {
|
|
20
|
+
console.log();
|
|
21
|
+
console.log(bold(cyan(" ╔═══════════════════════════════════════╗")));
|
|
22
|
+
console.log(bold(cyan(" ║ ║")));
|
|
23
|
+
console.log(bold(cyan(" ║") + " ⚡ " + yellow("create-credbuild-app") + " " + cyan("║")));
|
|
24
|
+
console.log(bold(cyan(" ║") + " Visual Website Builder Scaffold " + cyan("║")));
|
|
25
|
+
console.log(bold(cyan(" ║ ║")));
|
|
26
|
+
console.log(bold(cyan(" ╚═══════════════════════════════════════╝")));
|
|
27
|
+
console.log();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// ── Detect package manager ──────────────────────────────────────────
|
|
31
|
+
function detectPM() {
|
|
32
|
+
const ua = process.env.npm_config_user_agent || "";
|
|
33
|
+
if (ua.startsWith("bun")) return "bun";
|
|
34
|
+
if (ua.startsWith("pnpm")) return "pnpm";
|
|
35
|
+
if (ua.startsWith("yarn")) return "yarn";
|
|
36
|
+
return "npm";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// ── Main ────────────────────────────────────────────────────────────
|
|
40
|
+
function main() {
|
|
41
|
+
banner();
|
|
42
|
+
|
|
43
|
+
const args = process.argv.slice(2);
|
|
44
|
+
const projectName = args[0];
|
|
45
|
+
|
|
46
|
+
if (!projectName || projectName.startsWith("-")) {
|
|
47
|
+
console.log(` ${red("Error:")} Please specify the project name:`);
|
|
48
|
+
console.log();
|
|
49
|
+
console.log(` ${cyan("npx create-credbuild-app")} ${green("<project-name>")}`);
|
|
50
|
+
console.log();
|
|
51
|
+
console.log(" Example:");
|
|
52
|
+
console.log(` ${cyan("npx create-credbuild-app")} ${green("my-website")}`);
|
|
53
|
+
console.log();
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const targetDir = resolve(process.cwd(), projectName);
|
|
58
|
+
|
|
59
|
+
// Check if directory already exists
|
|
60
|
+
if (existsSync(targetDir)) {
|
|
61
|
+
console.log(` ${red("Error:")} Directory ${bold(projectName)} already exists.`);
|
|
62
|
+
console.log(` Please choose a different name or remove the existing directory.`);
|
|
63
|
+
console.log();
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const templateDir = join(__dirname, "..", "template");
|
|
68
|
+
|
|
69
|
+
// 1. Copy template
|
|
70
|
+
console.log(` ${cyan("●")} Creating project in ${bold(projectName)}...`);
|
|
71
|
+
mkdirSync(targetDir, { recursive: true });
|
|
72
|
+
cpSync(templateDir, targetDir, { recursive: true });
|
|
73
|
+
|
|
74
|
+
// 2. Update package.json with project name
|
|
75
|
+
const pkgPath = join(targetDir, "package.json");
|
|
76
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
77
|
+
pkg.name = basename(projectName);
|
|
78
|
+
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
79
|
+
console.log(` ${green("✓")} Template copied`);
|
|
80
|
+
|
|
81
|
+
// 3. Create .gitignore (can't be included in npm package as "template/.gitignore")
|
|
82
|
+
const gitignoreContent = `# dependencies
|
|
83
|
+
node_modules/
|
|
84
|
+
.pnp
|
|
85
|
+
.pnp.js
|
|
86
|
+
|
|
87
|
+
# testing
|
|
88
|
+
coverage/
|
|
89
|
+
|
|
90
|
+
# next.js
|
|
91
|
+
.next/
|
|
92
|
+
out/
|
|
93
|
+
|
|
94
|
+
# production
|
|
95
|
+
build/
|
|
96
|
+
dist/
|
|
97
|
+
|
|
98
|
+
# misc
|
|
99
|
+
.DS_Store
|
|
100
|
+
*.pem
|
|
101
|
+
|
|
102
|
+
# debug
|
|
103
|
+
npm-debug.log*
|
|
104
|
+
yarn-debug.log*
|
|
105
|
+
yarn-error.log*
|
|
106
|
+
.pnpm-debug.log*
|
|
107
|
+
|
|
108
|
+
# env
|
|
109
|
+
.env*.local
|
|
110
|
+
|
|
111
|
+
# typescript
|
|
112
|
+
*.tsbuildinfo
|
|
113
|
+
next-env.d.ts
|
|
114
|
+
`;
|
|
115
|
+
writeFileSync(join(targetDir, ".gitignore"), gitignoreContent);
|
|
116
|
+
|
|
117
|
+
// 4. Install dependencies
|
|
118
|
+
const pm = detectPM();
|
|
119
|
+
console.log(` ${cyan("●")} Installing dependencies with ${bold(pm)}...`);
|
|
120
|
+
console.log();
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
execSync(`${pm} install`, {
|
|
124
|
+
cwd: targetDir,
|
|
125
|
+
stdio: "inherit",
|
|
126
|
+
});
|
|
127
|
+
} catch {
|
|
128
|
+
console.log();
|
|
129
|
+
console.log(` ${yellow("⚠")} Install failed. You can install manually:`);
|
|
130
|
+
console.log(` cd ${projectName} && ${pm} install`);
|
|
131
|
+
console.log();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// 5. Done!
|
|
135
|
+
console.log();
|
|
136
|
+
console.log(` ${green("✓")} ${bold("Project created successfully!")}`);
|
|
137
|
+
console.log();
|
|
138
|
+
console.log(" Get started:");
|
|
139
|
+
console.log();
|
|
140
|
+
console.log(` ${cyan("cd")} ${projectName}`);
|
|
141
|
+
console.log(` ${cyan(`${pm === "npm" ? "npm run" : pm} dev`)}`);
|
|
142
|
+
console.log();
|
|
143
|
+
console.log(` Then open ${bold(cyan("http://localhost:3000/edit"))} in your browser.`);
|
|
144
|
+
console.log();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-credbuild-app",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Create a new CredBuild project with a single command",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-credbuild-app": "./bin/index.mjs"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"template"
|
|
12
|
+
],
|
|
13
|
+
"keywords": [
|
|
14
|
+
"credbuild",
|
|
15
|
+
"website-builder",
|
|
16
|
+
"nextjs",
|
|
17
|
+
"drag-and-drop",
|
|
18
|
+
"visual-editor"
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineConfig, globalIgnores } from "eslint/config";
|
|
2
|
+
import nextVitals from "eslint-config-next/core-web-vitals";
|
|
3
|
+
import nextTs from "eslint-config-next/typescript";
|
|
4
|
+
|
|
5
|
+
const eslintConfig = defineConfig([
|
|
6
|
+
...nextVitals,
|
|
7
|
+
...nextTs,
|
|
8
|
+
// Override default ignores of eslint-config-next.
|
|
9
|
+
globalIgnores([
|
|
10
|
+
// Default ignores of eslint-config-next:
|
|
11
|
+
".next/**",
|
|
12
|
+
"out/**",
|
|
13
|
+
"build/**",
|
|
14
|
+
"next-env.d.ts",
|
|
15
|
+
]),
|
|
16
|
+
]);
|
|
17
|
+
|
|
18
|
+
export default eslintConfig;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// @ts-ignore
|
|
2
|
+
import type { NextConfig } from "next";
|
|
3
|
+
|
|
4
|
+
const nextConfig: NextConfig = {
|
|
5
|
+
transpilePackages: ['@crediblemark/build', '@crediblemark/build-ui'],
|
|
6
|
+
serverExternalPackages: ['isomorphic-dompurify', 'jsdom', 'parse5'],
|
|
7
|
+
images: {
|
|
8
|
+
unoptimized: true,
|
|
9
|
+
},
|
|
10
|
+
webpack: (config: any, { isServer, webpack }: { isServer: boolean; webpack: any }) => {
|
|
11
|
+
if (!isServer) {
|
|
12
|
+
config.plugins.push(
|
|
13
|
+
new webpack.NormalModuleReplacementPlugin(
|
|
14
|
+
/^isomorphic-dompurify$/,
|
|
15
|
+
'dompurify'
|
|
16
|
+
)
|
|
17
|
+
);
|
|
18
|
+
config.resolve.fallback = {
|
|
19
|
+
...config.resolve.fallback,
|
|
20
|
+
"parse5": false,
|
|
21
|
+
"jsdom": false,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return config;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default nextConfig;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "my-credbuild-app",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "next dev --webpack",
|
|
7
|
+
"build": "next build --webpack",
|
|
8
|
+
"start": "next start",
|
|
9
|
+
"lint": "eslint"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@crediblemark/build": "^0.25.5",
|
|
13
|
+
"@crediblemark/build-ui": "^0.25.7",
|
|
14
|
+
"@tiptap/starter-kit": "^3.23.4",
|
|
15
|
+
"next": "^16.2.6",
|
|
16
|
+
"react": "^19.2.4",
|
|
17
|
+
"react-dom": "^19.2.4"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@tailwindcss/postcss": "^4",
|
|
21
|
+
"@types/node": "^20",
|
|
22
|
+
"@types/react": "^19",
|
|
23
|
+
"@types/react-dom": "^19",
|
|
24
|
+
"eslint": "^9",
|
|
25
|
+
"eslint-config-next": "^16.2.6",
|
|
26
|
+
"tailwindcss": "^4",
|
|
27
|
+
"typescript": "^5"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { writeFile } from 'fs/promises';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
|
|
5
|
+
export async function POST(req: Request) {
|
|
6
|
+
try {
|
|
7
|
+
const data = await req.json();
|
|
8
|
+
const DB_PATH = join(process.cwd(), 'database.json');
|
|
9
|
+
|
|
10
|
+
// Save the published data to a local JSON file to simulate a database
|
|
11
|
+
await writeFile(DB_PATH, JSON.stringify(data, null, 2));
|
|
12
|
+
|
|
13
|
+
return NextResponse.json({ success: true });
|
|
14
|
+
} catch (error) {
|
|
15
|
+
return NextResponse.json({ error: "Failed to save" }, { status: 500 });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
|
|
3
|
+
export async function GET(request: Request) {
|
|
4
|
+
const { searchParams } = new URL(request.url);
|
|
5
|
+
const url = searchParams.get('url');
|
|
6
|
+
|
|
7
|
+
if (!url) {
|
|
8
|
+
return new NextResponse('Missing url parameter', { status: 400 });
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
try {
|
|
12
|
+
const response = await fetch(url);
|
|
13
|
+
const buffer = await response.arrayBuffer();
|
|
14
|
+
return new NextResponse(buffer, {
|
|
15
|
+
headers: {
|
|
16
|
+
'Content-Type': response.headers.get('content-type') || 'image/jpeg',
|
|
17
|
+
'Cache-Control': 'public, max-age=31536000, immutable',
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
} catch (error) {
|
|
21
|
+
return new NextResponse('Error fetching image', { status: 500 });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { writeFile, mkdir } from 'fs/promises';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
|
|
5
|
+
// In-memory store for development simulation
|
|
6
|
+
// In production, you would fetch this from a database
|
|
7
|
+
let mediaStore: any[] = [];
|
|
8
|
+
|
|
9
|
+
export async function GET() {
|
|
10
|
+
return NextResponse.json({ data: mediaStore });
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export async function POST(request: Request) {
|
|
14
|
+
try {
|
|
15
|
+
const formData = await request.formData();
|
|
16
|
+
const file = formData.get('file') as File;
|
|
17
|
+
|
|
18
|
+
if (!file) {
|
|
19
|
+
return NextResponse.json({ error: "No file uploaded" }, { status: 400 });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const bytes = await file.arrayBuffer();
|
|
23
|
+
const buffer = Buffer.from(bytes);
|
|
24
|
+
|
|
25
|
+
// Save locally to simulate S3/Cloudflare R2 bucket behavior
|
|
26
|
+
const uploadDir = join(process.cwd(), 'public', 'uploads');
|
|
27
|
+
await mkdir(uploadDir, { recursive: true });
|
|
28
|
+
|
|
29
|
+
const filename = `${Date.now()}-${file.name.replace(/[^a-zA-Z0-9.-]/g, '_')}`;
|
|
30
|
+
const path = join(uploadDir, filename);
|
|
31
|
+
await writeFile(path, buffer);
|
|
32
|
+
|
|
33
|
+
// Generate the public URL that acts like a cloud storage URL
|
|
34
|
+
const url = `/uploads/${filename}`;
|
|
35
|
+
|
|
36
|
+
const mediaItem = {
|
|
37
|
+
id: Date.now().toString(),
|
|
38
|
+
filename: file.name,
|
|
39
|
+
url,
|
|
40
|
+
mimeType: file.type,
|
|
41
|
+
size: file.size,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// Save to our dummy database
|
|
45
|
+
mediaStore = [mediaItem, ...mediaStore];
|
|
46
|
+
|
|
47
|
+
return NextResponse.json(mediaItem);
|
|
48
|
+
} catch (e) {
|
|
49
|
+
console.error("Upload error:", e);
|
|
50
|
+
return NextResponse.json({ error: "Upload failed" }, { status: 500 });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { CredBuild } from "@crediblemark/build";
|
|
4
|
+
import config from "../../../../credbuild.config";
|
|
5
|
+
|
|
6
|
+
export function EditorClient({ path, data }: { path: string[], data: any }) {
|
|
7
|
+
return (
|
|
8
|
+
<CredBuild
|
|
9
|
+
config={config as any}
|
|
10
|
+
data={data}
|
|
11
|
+
headerPath={path.length > 0 ? path.join("/") : "/"}
|
|
12
|
+
iframe={{ enabled: false }}
|
|
13
|
+
onPublish={async (newData: any) => {
|
|
14
|
+
try {
|
|
15
|
+
const res = await fetch('/api/credbuild', {
|
|
16
|
+
method: 'POST',
|
|
17
|
+
body: JSON.stringify(newData),
|
|
18
|
+
});
|
|
19
|
+
if (res.ok) {
|
|
20
|
+
alert("Berhasil disimpan!");
|
|
21
|
+
} else {
|
|
22
|
+
alert("Gagal menyimpan!");
|
|
23
|
+
}
|
|
24
|
+
} catch (e) {
|
|
25
|
+
alert("Terjadi kesalahan jaringan!");
|
|
26
|
+
}
|
|
27
|
+
}}
|
|
28
|
+
onChange={(newData: any) => {
|
|
29
|
+
console.log("Editor Data Changed:", newData);
|
|
30
|
+
}}
|
|
31
|
+
/>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { EditorClient } from "./EditorClient";
|
|
2
|
+
import { readFile } from "fs/promises";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
|
|
5
|
+
export default async function EditorPage({ params }: { params: Promise<{ path?: string[] }> }) {
|
|
6
|
+
const { path } = await params;
|
|
7
|
+
|
|
8
|
+
let data = {};
|
|
9
|
+
try {
|
|
10
|
+
const DB_PATH = join(process.cwd(), "database.json");
|
|
11
|
+
const file = await readFile(DB_PATH, "utf-8");
|
|
12
|
+
data = JSON.parse(file);
|
|
13
|
+
} catch (e) {
|
|
14
|
+
// ignore, start fresh
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<div style={{ height: "100vh", display: "flex", flexDirection: "column" }}>
|
|
19
|
+
<EditorClient path={path || []} data={data} />
|
|
20
|
+
</div>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* Layer 2: Theming (colors, variables, font) */
|
|
2
|
+
@import "@crediblemark/build/dist/index.css";
|
|
3
|
+
/* Layer 3: Compact sizing (padding, height, font-size) */
|
|
4
|
+
@import "@crediblemark/build-ui/sidebar-neat.css";
|
|
5
|
+
/* Tailwind */
|
|
6
|
+
@import "tailwindcss";
|
|
7
|
+
|
|
8
|
+
:root {
|
|
9
|
+
--background: #ffffff;
|
|
10
|
+
--foreground: #171717;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@theme inline {
|
|
14
|
+
--color-background: var(--background);
|
|
15
|
+
--color-foreground: var(--foreground);
|
|
16
|
+
--font-sans: var(--font-geist-sans);
|
|
17
|
+
--font-mono: var(--font-geist-mono);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@media (prefers-color-scheme: dark) {
|
|
21
|
+
:root {
|
|
22
|
+
--background: #0a0a0a;
|
|
23
|
+
--foreground: #ededed;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
body {
|
|
28
|
+
background: var(--background);
|
|
29
|
+
color: var(--foreground);
|
|
30
|
+
font-family: Arial, Helvetica, sans-serif;
|
|
31
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Metadata } from "next";
|
|
2
|
+
import { Geist, Geist_Mono } from "next/font/google";
|
|
3
|
+
import "./globals.css";
|
|
4
|
+
|
|
5
|
+
const geistSans = Geist({
|
|
6
|
+
variable: "--font-geist-sans",
|
|
7
|
+
subsets: ["latin"],
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const geistMono = Geist_Mono({
|
|
11
|
+
variable: "--font-geist-mono",
|
|
12
|
+
subsets: ["latin"],
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export const metadata: Metadata = {
|
|
16
|
+
title: "CredBuild — Visual Website Builder",
|
|
17
|
+
description:
|
|
18
|
+
"Build stunning websites visually with drag-and-drop blocks. No coding required.",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default function RootLayout({
|
|
22
|
+
children,
|
|
23
|
+
}: Readonly<{
|
|
24
|
+
children: React.ReactNode;
|
|
25
|
+
}>) {
|
|
26
|
+
return (
|
|
27
|
+
<html
|
|
28
|
+
lang="en"
|
|
29
|
+
className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
|
|
30
|
+
>
|
|
31
|
+
<body className="min-h-full flex flex-col">{children}</body>
|
|
32
|
+
</html>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import Link from "next/link";
|
|
2
|
+
|
|
3
|
+
export default function Home() {
|
|
4
|
+
return (
|
|
5
|
+
<div className="flex flex-col min-h-screen bg-[#0a0a0a] text-white overflow-hidden">
|
|
6
|
+
{/* Ambient glow effects */}
|
|
7
|
+
<div
|
|
8
|
+
className="pointer-events-none fixed inset-0"
|
|
9
|
+
aria-hidden="true"
|
|
10
|
+
>
|
|
11
|
+
<div className="absolute top-[-20%] left-[10%] w-[500px] h-[500px] rounded-full bg-amber-500/[0.07] blur-[120px]" />
|
|
12
|
+
<div className="absolute bottom-[-10%] right-[15%] w-[400px] h-[400px] rounded-full bg-violet-500/[0.05] blur-[100px]" />
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
{/* Header */}
|
|
16
|
+
<header className="relative z-10 flex items-center justify-between px-6 py-5 md:px-12">
|
|
17
|
+
<div className="flex items-center gap-2">
|
|
18
|
+
<div className="w-8 h-8 rounded-lg bg-gradient-to-br from-amber-400 to-orange-500 flex items-center justify-center font-bold text-sm text-black">
|
|
19
|
+
CB
|
|
20
|
+
</div>
|
|
21
|
+
<span className="text-lg font-semibold tracking-tight">
|
|
22
|
+
CredBuild
|
|
23
|
+
</span>
|
|
24
|
+
</div>
|
|
25
|
+
<nav className="hidden md:flex items-center gap-8 text-sm text-zinc-400">
|
|
26
|
+
<a href="#features" className="hover:text-white transition-colors">
|
|
27
|
+
Features
|
|
28
|
+
</a>
|
|
29
|
+
<a href="#blocks" className="hover:text-white transition-colors">
|
|
30
|
+
Blocks
|
|
31
|
+
</a>
|
|
32
|
+
<a href="#pricing" className="hover:text-white transition-colors">
|
|
33
|
+
Pricing
|
|
34
|
+
</a>
|
|
35
|
+
</nav>
|
|
36
|
+
<Link
|
|
37
|
+
href="/edit"
|
|
38
|
+
className="px-5 py-2 text-sm font-medium rounded-lg bg-white/10 border border-white/10 hover:bg-white/15 transition-all backdrop-blur-sm"
|
|
39
|
+
>
|
|
40
|
+
Open Editor
|
|
41
|
+
</Link>
|
|
42
|
+
</header>
|
|
43
|
+
|
|
44
|
+
{/* Hero */}
|
|
45
|
+
<main className="relative z-10 flex-1 flex flex-col items-center justify-center text-center px-6 py-20 md:py-32">
|
|
46
|
+
<div className="inline-flex items-center gap-2 px-4 py-1.5 mb-8 rounded-full border border-amber-500/20 bg-amber-500/5 text-amber-400 text-xs font-medium tracking-wide uppercase">
|
|
47
|
+
<span className="w-1.5 h-1.5 rounded-full bg-amber-400 animate-pulse" />
|
|
48
|
+
Visual Website Builder
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<h1 className="max-w-3xl text-4xl md:text-6xl lg:text-7xl font-bold tracking-tight leading-[1.1]">
|
|
52
|
+
Build websites{" "}
|
|
53
|
+
<span className="bg-gradient-to-r from-amber-300 via-orange-400 to-amber-500 bg-clip-text text-transparent">
|
|
54
|
+
visually
|
|
55
|
+
</span>
|
|
56
|
+
<br />
|
|
57
|
+
with drag & drop
|
|
58
|
+
</h1>
|
|
59
|
+
|
|
60
|
+
<p className="mt-6 max-w-xl text-lg text-zinc-400 leading-relaxed">
|
|
61
|
+
Powerful block-based editor with 40+ premium components.
|
|
62
|
+
Design stunning pages without writing a single line of code.
|
|
63
|
+
</p>
|
|
64
|
+
|
|
65
|
+
<div className="flex flex-col sm:flex-row items-center gap-4 mt-10">
|
|
66
|
+
<Link
|
|
67
|
+
href="/edit"
|
|
68
|
+
className="group relative px-8 py-3.5 rounded-xl bg-gradient-to-r from-amber-500 to-orange-500 text-black font-semibold text-sm tracking-wide hover:shadow-[0_0_30px_rgba(245,158,11,0.3)] transition-all duration-300"
|
|
69
|
+
>
|
|
70
|
+
Start Building
|
|
71
|
+
<span className="ml-2 inline-block group-hover:translate-x-1 transition-transform">
|
|
72
|
+
→
|
|
73
|
+
</span>
|
|
74
|
+
</Link>
|
|
75
|
+
<a
|
|
76
|
+
href="#features"
|
|
77
|
+
className="px-8 py-3.5 rounded-xl border border-white/10 text-sm font-medium text-zinc-300 hover:text-white hover:border-white/20 transition-all"
|
|
78
|
+
>
|
|
79
|
+
Learn More
|
|
80
|
+
</a>
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
{/* Editor preview mockup */}
|
|
84
|
+
<div className="relative mt-20 w-full max-w-4xl">
|
|
85
|
+
<div className="absolute inset-0 bg-gradient-to-t from-[#0a0a0a] via-transparent to-transparent z-10 pointer-events-none" />
|
|
86
|
+
<div className="rounded-xl border border-white/10 bg-white/[0.03] backdrop-blur-sm overflow-hidden shadow-2xl shadow-black/50">
|
|
87
|
+
{/* Mockup toolbar */}
|
|
88
|
+
<div className="flex items-center gap-2 px-4 py-3 border-b border-white/10 bg-white/[0.02]">
|
|
89
|
+
<div className="flex gap-1.5">
|
|
90
|
+
<div className="w-3 h-3 rounded-full bg-red-500/60" />
|
|
91
|
+
<div className="w-3 h-3 rounded-full bg-yellow-500/60" />
|
|
92
|
+
<div className="w-3 h-3 rounded-full bg-green-500/60" />
|
|
93
|
+
</div>
|
|
94
|
+
<div className="flex-1 flex justify-center">
|
|
95
|
+
<div className="px-4 py-1 rounded-md bg-white/5 text-xs text-zinc-500 font-mono">
|
|
96
|
+
localhost:3000/edit
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
{/* Mockup content */}
|
|
101
|
+
<div className="flex h-64 md:h-80">
|
|
102
|
+
{/* Left sidebar */}
|
|
103
|
+
<div className="w-48 border-r border-white/10 bg-white/[0.02] p-3 hidden sm:block">
|
|
104
|
+
<div className="text-[10px] font-semibold text-zinc-500 uppercase tracking-wider mb-3">
|
|
105
|
+
Blocks
|
|
106
|
+
</div>
|
|
107
|
+
{[
|
|
108
|
+
"Hero Section",
|
|
109
|
+
"Feature Grid",
|
|
110
|
+
"Testimonials",
|
|
111
|
+
"Pricing Table",
|
|
112
|
+
"Contact Form",
|
|
113
|
+
"FAQ Accordion",
|
|
114
|
+
].map((block) => (
|
|
115
|
+
<div
|
|
116
|
+
key={block}
|
|
117
|
+
className="px-2.5 py-1.5 mb-1 rounded text-xs text-zinc-400 bg-white/[0.03] border border-white/5 hover:border-amber-500/20 transition-colors"
|
|
118
|
+
>
|
|
119
|
+
{block}
|
|
120
|
+
</div>
|
|
121
|
+
))}
|
|
122
|
+
</div>
|
|
123
|
+
{/* Canvas */}
|
|
124
|
+
<div className="flex-1 p-6 flex items-center justify-center">
|
|
125
|
+
<div className="text-center">
|
|
126
|
+
<div className="w-16 h-16 mx-auto mb-4 rounded-xl bg-gradient-to-br from-amber-500/20 to-orange-500/20 border border-amber-500/10 flex items-center justify-center">
|
|
127
|
+
<svg
|
|
128
|
+
width="24"
|
|
129
|
+
height="24"
|
|
130
|
+
viewBox="0 0 24 24"
|
|
131
|
+
fill="none"
|
|
132
|
+
stroke="currentColor"
|
|
133
|
+
strokeWidth="1.5"
|
|
134
|
+
className="text-amber-400"
|
|
135
|
+
>
|
|
136
|
+
<rect x="3" y="3" width="7" height="7" rx="1" />
|
|
137
|
+
<rect x="14" y="3" width="7" height="7" rx="1" />
|
|
138
|
+
<rect x="3" y="14" width="7" height="7" rx="1" />
|
|
139
|
+
<rect x="14" y="14" width="7" height="7" rx="1" />
|
|
140
|
+
</svg>
|
|
141
|
+
</div>
|
|
142
|
+
<p className="text-sm text-zinc-500">
|
|
143
|
+
Drag blocks here to start building
|
|
144
|
+
</p>
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
{/* Right sidebar */}
|
|
148
|
+
<div className="w-48 border-l border-white/10 bg-white/[0.02] p-3 hidden md:block">
|
|
149
|
+
<div className="text-[10px] font-semibold text-zinc-500 uppercase tracking-wider mb-3">
|
|
150
|
+
Properties
|
|
151
|
+
</div>
|
|
152
|
+
{["Title", "Subtitle", "Background", "Padding"].map(
|
|
153
|
+
(prop) => (
|
|
154
|
+
<div key={prop} className="mb-2">
|
|
155
|
+
<div className="text-[9px] text-zinc-600 mb-1">
|
|
156
|
+
{prop}
|
|
157
|
+
</div>
|
|
158
|
+
<div className="h-6 rounded bg-white/[0.04] border border-white/5" />
|
|
159
|
+
</div>
|
|
160
|
+
)
|
|
161
|
+
)}
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
</div>
|
|
166
|
+
</main>
|
|
167
|
+
|
|
168
|
+
{/* Features */}
|
|
169
|
+
<section id="features" className="relative z-10 px-6 py-24 md:px-12">
|
|
170
|
+
<div className="max-w-5xl mx-auto">
|
|
171
|
+
<h2 className="text-3xl md:text-4xl font-bold text-center mb-4">
|
|
172
|
+
Everything you need
|
|
173
|
+
</h2>
|
|
174
|
+
<p className="text-zinc-400 text-center mb-16 max-w-lg mx-auto">
|
|
175
|
+
A complete toolkit for building professional websites at speed.
|
|
176
|
+
</p>
|
|
177
|
+
|
|
178
|
+
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
|
179
|
+
{[
|
|
180
|
+
{
|
|
181
|
+
icon: "⚡",
|
|
182
|
+
title: "40+ Premium Blocks",
|
|
183
|
+
desc: "Hero sections, pricing tables, testimonials, galleries, and more — all customizable.",
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
icon: "🎨",
|
|
187
|
+
title: "Visual Editor",
|
|
188
|
+
desc: "Intuitive drag-and-drop interface. See changes in real-time as you build.",
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
icon: "📱",
|
|
192
|
+
title: "Responsive Design",
|
|
193
|
+
desc: "Every block looks great on desktop, tablet, and mobile out of the box.",
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
icon: "🔧",
|
|
197
|
+
title: "Full Customization",
|
|
198
|
+
desc: "Fine-tune every property — colors, spacing, typography, and animations.",
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
icon: "🚀",
|
|
202
|
+
title: "Production Ready",
|
|
203
|
+
desc: "Export clean, optimized code. Built on Next.js for blazing fast performance.",
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
icon: "🎯",
|
|
207
|
+
title: "SEO Optimized",
|
|
208
|
+
desc: "Semantic HTML, meta tags, and structured data built into every component.",
|
|
209
|
+
},
|
|
210
|
+
].map((feature) => (
|
|
211
|
+
<div
|
|
212
|
+
key={feature.title}
|
|
213
|
+
className="group p-6 rounded-xl border border-white/5 bg-white/[0.02] hover:border-amber-500/20 hover:bg-amber-500/[0.02] transition-all duration-300"
|
|
214
|
+
>
|
|
215
|
+
<div className="text-2xl mb-4">{feature.icon}</div>
|
|
216
|
+
<h3 className="font-semibold mb-2">{feature.title}</h3>
|
|
217
|
+
<p className="text-sm text-zinc-500 leading-relaxed">
|
|
218
|
+
{feature.desc}
|
|
219
|
+
</p>
|
|
220
|
+
</div>
|
|
221
|
+
))}
|
|
222
|
+
</div>
|
|
223
|
+
</div>
|
|
224
|
+
</section>
|
|
225
|
+
|
|
226
|
+
{/* Get Started / Installation */}
|
|
227
|
+
<section className="relative z-10 px-6 py-24 md:px-12">
|
|
228
|
+
<div className="max-w-3xl mx-auto">
|
|
229
|
+
<h2 className="text-3xl md:text-4xl font-bold text-center mb-4">
|
|
230
|
+
Get started in seconds
|
|
231
|
+
</h2>
|
|
232
|
+
<p className="text-zinc-400 text-center mb-12 max-w-lg mx-auto">
|
|
233
|
+
Install the packages and start building right away.
|
|
234
|
+
</p>
|
|
235
|
+
|
|
236
|
+
<div className="space-y-4">
|
|
237
|
+
{/* Step 1 */}
|
|
238
|
+
<div className="rounded-xl border border-white/10 bg-white/[0.02] overflow-hidden">
|
|
239
|
+
<div className="flex items-center gap-3 px-5 py-3 border-b border-white/5">
|
|
240
|
+
<div className="w-6 h-6 rounded-full bg-amber-500/10 border border-amber-500/20 flex items-center justify-center text-xs font-bold text-amber-400">
|
|
241
|
+
1
|
|
242
|
+
</div>
|
|
243
|
+
<span className="text-sm font-medium text-zinc-300">
|
|
244
|
+
Install packages
|
|
245
|
+
</span>
|
|
246
|
+
</div>
|
|
247
|
+
<div className="p-5 space-y-3">
|
|
248
|
+
<div className="group relative rounded-lg bg-black/60 border border-white/5 px-4 py-3 font-mono text-sm text-zinc-300">
|
|
249
|
+
<span className="text-amber-400">$</span>{" "}
|
|
250
|
+
npm i @crediblemark/build
|
|
251
|
+
</div>
|
|
252
|
+
<div className="group relative rounded-lg bg-black/60 border border-white/5 px-4 py-3 font-mono text-sm text-zinc-300">
|
|
253
|
+
<span className="text-amber-400">$</span>{" "}
|
|
254
|
+
npm i @crediblemark/build-ui
|
|
255
|
+
</div>
|
|
256
|
+
</div>
|
|
257
|
+
</div>
|
|
258
|
+
|
|
259
|
+
{/* Step 2 */}
|
|
260
|
+
<div className="rounded-xl border border-white/10 bg-white/[0.02] overflow-hidden">
|
|
261
|
+
<div className="flex items-center gap-3 px-5 py-3 border-b border-white/5">
|
|
262
|
+
<div className="w-6 h-6 rounded-full bg-amber-500/10 border border-amber-500/20 flex items-center justify-center text-xs font-bold text-amber-400">
|
|
263
|
+
2
|
|
264
|
+
</div>
|
|
265
|
+
<span className="text-sm font-medium text-zinc-300">
|
|
266
|
+
Import and configure
|
|
267
|
+
</span>
|
|
268
|
+
</div>
|
|
269
|
+
<div className="p-5">
|
|
270
|
+
<div className="rounded-lg bg-black/60 border border-white/5 px-4 py-3 font-mono text-sm text-zinc-300 whitespace-pre leading-relaxed">
|
|
271
|
+
<span className="text-violet-400">import</span>
|
|
272
|
+
{" { "}
|
|
273
|
+
<span className="text-amber-300">buildUiPreset</span>
|
|
274
|
+
{" } "}
|
|
275
|
+
<span className="text-violet-400">from</span>{" "}
|
|
276
|
+
<span className="text-green-400">
|
|
277
|
+
"@crediblemark/build-ui"
|
|
278
|
+
</span>
|
|
279
|
+
;{"\n"}
|
|
280
|
+
<span className="text-violet-400">import</span>{" "}
|
|
281
|
+
<span className="text-green-400">
|
|
282
|
+
"@crediblemark/build/dist/index.css"
|
|
283
|
+
</span>
|
|
284
|
+
;{"\n"}
|
|
285
|
+
<span className="text-violet-400">import</span>{" "}
|
|
286
|
+
<span className="text-green-400">
|
|
287
|
+
"@crediblemark/build-ui/sidebar-neat.css"
|
|
288
|
+
</span>
|
|
289
|
+
;
|
|
290
|
+
</div>
|
|
291
|
+
</div>
|
|
292
|
+
</div>
|
|
293
|
+
|
|
294
|
+
{/* Step 3 */}
|
|
295
|
+
<div className="rounded-xl border border-white/10 bg-white/[0.02] overflow-hidden">
|
|
296
|
+
<div className="flex items-center gap-3 px-5 py-3 border-b border-white/5">
|
|
297
|
+
<div className="w-6 h-6 rounded-full bg-amber-500/10 border border-amber-500/20 flex items-center justify-center text-xs font-bold text-amber-400">
|
|
298
|
+
3
|
|
299
|
+
</div>
|
|
300
|
+
<span className="text-sm font-medium text-zinc-300">
|
|
301
|
+
Start building
|
|
302
|
+
</span>
|
|
303
|
+
</div>
|
|
304
|
+
<div className="p-5">
|
|
305
|
+
<div className="rounded-lg bg-black/60 border border-white/5 px-4 py-3 font-mono text-sm text-zinc-300">
|
|
306
|
+
<span className="text-amber-400">$</span> npm run dev
|
|
307
|
+
</div>
|
|
308
|
+
<p className="mt-3 text-xs text-zinc-500">
|
|
309
|
+
Open{" "}
|
|
310
|
+
<code className="px-1.5 py-0.5 rounded bg-white/5 text-amber-400 font-mono">
|
|
311
|
+
localhost:3000/edit
|
|
312
|
+
</code>{" "}
|
|
313
|
+
to access the visual editor.
|
|
314
|
+
</p>
|
|
315
|
+
</div>
|
|
316
|
+
</div>
|
|
317
|
+
</div>
|
|
318
|
+
</div>
|
|
319
|
+
</section>
|
|
320
|
+
|
|
321
|
+
{/* CTA */}
|
|
322
|
+
<section className="relative z-10 px-6 py-24 md:px-12">
|
|
323
|
+
<div className="max-w-2xl mx-auto text-center">
|
|
324
|
+
<h2 className="text-3xl md:text-4xl font-bold mb-4">
|
|
325
|
+
Ready to build?
|
|
326
|
+
</h2>
|
|
327
|
+
<p className="text-zinc-400 mb-8">
|
|
328
|
+
Jump straight into the editor and start creating your website.
|
|
329
|
+
</p>
|
|
330
|
+
<Link
|
|
331
|
+
href="/edit"
|
|
332
|
+
className="inline-flex items-center gap-2 px-8 py-4 rounded-xl bg-gradient-to-r from-amber-500 to-orange-500 text-black font-semibold tracking-wide hover:shadow-[0_0_40px_rgba(245,158,11,0.3)] transition-all duration-300"
|
|
333
|
+
>
|
|
334
|
+
Open Editor →
|
|
335
|
+
</Link>
|
|
336
|
+
</div>
|
|
337
|
+
</section>
|
|
338
|
+
|
|
339
|
+
{/* Footer */}
|
|
340
|
+
<footer className="relative z-10 border-t border-white/5 px-6 py-8 md:px-12">
|
|
341
|
+
<div className="max-w-5xl mx-auto flex flex-col md:flex-row items-center justify-between gap-4">
|
|
342
|
+
<div className="flex items-center gap-2 text-sm text-zinc-500">
|
|
343
|
+
<div className="w-5 h-5 rounded bg-gradient-to-br from-amber-400 to-orange-500 flex items-center justify-center font-bold text-[8px] text-black">
|
|
344
|
+
CB
|
|
345
|
+
</div>
|
|
346
|
+
CredBuild © {new Date().getFullYear()}
|
|
347
|
+
</div>
|
|
348
|
+
<p className="text-xs text-zinc-600">
|
|
349
|
+
Built with Next.js • Powered by CredBuild Engine
|
|
350
|
+
</p>
|
|
351
|
+
</div>
|
|
352
|
+
</footer>
|
|
353
|
+
</div>
|
|
354
|
+
);
|
|
355
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import type { NextRequest } from "next/server";
|
|
3
|
+
|
|
4
|
+
export function proxy(request: NextRequest) {
|
|
5
|
+
const url = request.nextUrl.clone();
|
|
6
|
+
|
|
7
|
+
if (url.pathname.endsWith("/edit")) {
|
|
8
|
+
const pathWithoutEdit = url.pathname.replace(/\/edit$/, "");
|
|
9
|
+
url.pathname = `/credbuild${pathWithoutEdit || "/"}`;
|
|
10
|
+
return NextResponse.rewrite(url);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const config = {
|
|
15
|
+
matcher: '/:path*',
|
|
16
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
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": "react-jsx",
|
|
15
|
+
"incremental": true,
|
|
16
|
+
"plugins": [
|
|
17
|
+
{
|
|
18
|
+
"name": "next"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"paths": {
|
|
22
|
+
"@/*": ["./src/*"]
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"include": [
|
|
26
|
+
"next-env.d.ts",
|
|
27
|
+
"**/*.ts",
|
|
28
|
+
"**/*.tsx",
|
|
29
|
+
".next/types/**/*.ts",
|
|
30
|
+
".next/dev/types/**/*.ts",
|
|
31
|
+
"**/*.mts"
|
|
32
|
+
],
|
|
33
|
+
"exclude": ["node_modules"]
|
|
34
|
+
}
|