Repository: zinedkaloc/aipage.dev
Branch: master
Commit: 508cff651c7c
Files: 105
Total size: 179.8 KB
Directory structure:
gitextract_yf13pds3/
├── .github/
│ └── ISSUE_TEMPLATE/
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── app/
│ ├── (aipage)/
│ │ ├── layout.tsx
│ │ ├── loading.tsx
│ │ ├── not-found.tsx
│ │ ├── page.tsx
│ │ └── profile/
│ │ ├── invoices/
│ │ │ ├── loading.tsx
│ │ │ └── page.tsx
│ │ ├── layout.tsx
│ │ ├── projects/
│ │ │ ├── [id]/
│ │ │ │ ├── domains/
│ │ │ │ │ ├── layout.tsx
│ │ │ │ │ └── page.tsx
│ │ │ │ ├── integrations/
│ │ │ │ │ └── page.tsx
│ │ │ │ ├── layout.tsx
│ │ │ │ ├── loading.tsx
│ │ │ │ ├── page.tsx
│ │ │ │ └── settings/
│ │ │ │ └── page.tsx
│ │ │ ├── loading.tsx
│ │ │ └── page.tsx
│ │ └── settings/
│ │ ├── loading.tsx
│ │ └── page.tsx
│ ├── (preview)/
│ │ ├── not-found.tsx
│ │ └── profile/
│ │ └── projects/
│ │ └── [id]/
│ │ └── preview/
│ │ ├── loading.tsx
│ │ └── page.tsx
│ ├── api/
│ │ ├── chat/
│ │ │ └── route.ts
│ │ ├── create-checkout-session/
│ │ │ └── route.ts
│ │ ├── domain/
│ │ │ ├── check-domain/
│ │ │ │ └── route.ts
│ │ │ ├── remove-domain/
│ │ │ │ └── route.ts
│ │ │ └── verify-domain/
│ │ │ └── route.ts
│ │ ├── logout/
│ │ │ └── route.ts
│ │ ├── message/
│ │ │ └── route.ts
│ │ ├── og/
│ │ │ └── route.tsx
│ │ ├── project/
│ │ │ ├── [id]/
│ │ │ │ ├── domain/
│ │ │ │ │ └── route.ts
│ │ │ │ └── route.ts
│ │ │ └── route.ts
│ │ └── user/
│ │ └── route.ts
│ ├── auth-redirect/
│ │ └── route.ts
│ ├── layout.tsx
│ └── not-found.tsx
├── components/
│ ├── AddDomainModal.tsx
│ ├── AlertCircleFill.tsx
│ ├── AlertDialog.tsx
│ ├── AuthModal.tsx
│ ├── Badge.tsx
│ ├── BrowserWindow.tsx
│ ├── Button.tsx
│ ├── Chart.tsx
│ ├── CheckCircleFill.tsx
│ ├── ConfiguredSection.tsx
│ ├── ConfirmDialog.tsx
│ ├── DeleteAccountConfirmDialog.tsx
│ ├── DeleteProjectConfirmDialog.tsx
│ ├── Divider.tsx
│ ├── DomainCard.tsx
│ ├── DomainConfiguration.tsx
│ ├── Drawer.tsx
│ ├── HTMLPreview.tsx
│ ├── Header.tsx
│ ├── IconMenu.tsx
│ ├── ListProjects.tsx
│ ├── LoadingIcon.tsx
│ ├── Logo.tsx
│ ├── LogoutIcon.tsx
│ ├── Modal.tsx
│ ├── NavLink.tsx
│ ├── Popover.tsx
│ ├── PricesModal.tsx
│ ├── Product.tsx
│ ├── Products.tsx
│ ├── ProfileLayout.tsx
│ ├── ProfileMenu.tsx
│ ├── ProjectDesign.tsx
│ ├── ProjectIcon.tsx
│ ├── ProjectSelect.tsx
│ ├── RateModal.tsx
│ ├── ShowRate.tsx
│ ├── Switch.tsx
│ ├── UserDropdown.tsx
│ ├── XCircleFill.tsx
│ ├── customDropdown.tsx
│ ├── loadingSpinner.module.css
│ ├── loadingSpinner.tsx
│ └── tweetButton.tsx
├── context/
│ └── AuthContext.tsx
├── custom.css
├── hooks/
│ ├── useProject.tsx
│ ├── useProjectList.tsx
│ └── useSearchParams.ts
├── next.config.js
├── package.json
├── postcss.config.js
├── public/
│ └── site.webmanifest
├── styles/
│ ├── custom.css
│ └── globals.css
├── tailwind.config.js
├── tsconfig.json
├── types/
│ └── index.ts
└── utils/
├── altogic.ts
├── auth.ts
├── helpers.ts
└── redis.ts
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a bug report for AI landing page generator
title: "[BUG]"
labels: ''
assignees: ''
---
# Bug Report
**Description**
⚠️ Please provide a clear and concise description of the bug.
**Steps to Reproduce**
⚠️ Please provide step-by-step instructions to reproduce the bug.
**Expected Behavior**
⚠️ Please describe what you expected to happen.
**Actual Behavior**
⚠️ Please describe what actually happened.
**Additional Information**
⚠️ Add any additional information or context about the bug here.
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
# Feature Request
**Description**
Please provide a clear and concise description of the feature request.
**Proposed Solution**
Please describe the proposed solution or new feature in detail.
**Alternatives Considered**
Please describe any alternative solutions or features you've considered.
**Additional Information**
Add any additional information or context about the feature request here.
================================================
FILE: .gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
.env
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
/.idea
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Code of Conduct
As contributors and maintainers of the AI Landing Page Generator project, we pledge to make participation in our project a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
- Being respectful and considerate of others' opinions and ideas.
- Using inclusive language and being mindful of our words and their impact.
- Being open to constructive feedback and providing feedback in a respectful manner.
- Showing empathy and kindness towards others.
- Focusing on collaboration and fostering a supportive community.
Examples of unacceptable behavior include:
- Harassment, discrimination, or derogatory comments and personal attacks.
- Any form of offensive or inappropriate language or imagery.
- Trolling, flaming, or insulting/derogatory comments.
- Intimidating or bullying behavior.
- Any other conduct that could be considered inappropriate in a professional setting.
## Scope
This Code of Conduct applies to all project contributors, both online and offline, as well as in all project-related spaces.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [zinedkaloc](https://twitter.com/zinedkaloc). The project team is committed to reviewing and addressing all reported incidents promptly and fairly.
## Consequences
Any contributor who engages in behavior violating this Code of Conduct may be temporarily or permanently excluded from project participation at the discretion of the project team.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.0, available at [https://www.contributor-covenant.org/version/2/0/code_of_conduct.html](https://www.contributor-covenant.org/version/2/0/code_of_conduct.html).
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to AI Landing Page Generator
We welcome and appreciate contributions from the community! By contributing to the AI Landing Page Generator project, you can help us make it even better.
## Ways to Contribute
There are several ways you can contribute to this project:
- Report bugs: If you come across any issues or bugs, please [open a new issue](https://github.com/zinedkaloc/ai-page/issues) and provide as much detail as possible.
- Suggest new features: Have an idea for a new feature or improvement? We'd love to hear it! [Open a new issue](https://github.com/zinedkaloc/ai-page/issues) and let us know.
- Submit pull requests: If you have code changes or enhancements you'd like to contribute, you can do so by opening a pull request. Make sure to follow the guidelines below when submitting your pull request.
## Guidelines for Pull Requests
To ensure smooth collaboration and maintain code quality, please follow these guidelines when submitting a pull request:
1. Fork the repository and create a new branch for your changes.
2. Before making changes, make sure your branch is up to date with the master repository.
3. Follow the coding style and conventions used in the project.
4. Include clear and concise commit messages that describe the purpose of your changes.
5. Provide a detailed description of the changes you've made in the pull request.
6. Test your changes thoroughly to ensure they work as intended.
7. Make sure your code is properly documented.
8. Ensure that your changes do not introduce any breaking changes to the existing functionality.
9. Be responsive to any feedback or questions regarding your pull request.
10. Once your changes are approved, they will be merged into the master repository.
## Code of Conduct
Please note that by participating in this project, you are expected to adhere to the [Code of Conduct](CODE_OF_CONDUCT.md). We kindly ask you to respect the guidelines and treat others with respect and kindness.
## Questions or Concerns
If you have any questions or concerns regarding the project or the contribution process, please feel free to [zinedkaloc](https://twitter.com/zinedkaloc).
Thank you for your interest in contributing to the AI Landing Page Generator project!
================================================
FILE: LICENSE
================================================
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
# AI Landing Page Generator
[](LICENSE)
## Description

The AI Landing Page Generator is a powerful tool that allows you to quickly create stunning landing pages using artificial intelligence. With this generator, you can save time and effort by automating the process of designing and coding landing pages. It is now experimental and only supports the creation of landing pages with HTML and Tailwind CSS.
## Installation
1. Clone the repository: `git clone https://github.com/zinedkaloc/aipage.dev.git`
2. Install the required dependencies: `pnpm install`
3. Navigate to the project directory `cd aipage.dev`
4. Copy the `.env.example` file to `.env` and fill in the required information.
> Note: If you are not comfortable with creating OPENAI_API_KEY, please reach out to me at [zinedkaloc](https://twitter.com/zinedkaloc) and I will be happy to help you.
## Usage
1. Run the generator: `pnpm dev`
2. Open the browser and go to `http://localhost:3000`
3. Describe your website and click on the "Enter".
4. Wait for the genie to generate the landing page.
### Test prompts
> A landing page for a design studio located in New york. They make websites and custom logos. All the work is very stylish and minimalist. The page should include a contact form a some call to actions as well as a link to the portfolio.
> A landing page for an interior architecture company based in Istanbul. They specialize in creating exceptional spatial designs and innovative interior solutions. Their work showcases a unique blend of style, minimalism, and functionality. The landing page should feature a captivating design with using gradients, including a contact form, compelling call-to-action elements, and a prominent link to their portfolio.
> A landing page for a cutting-edge technology company based in Istanbul. They specialize in developing innovative software solutions and advanced technological products. Their work is known for its sleek design, seamless user experience, and transformative capabilities. The landing page should feature a modern design, including a contact form, compelling call-to-action elements, and a prominent link to their product offerings.
## Roadmap
- [x] Create a basic landing page generator.
- [x] Display the generated landing page in the main page with an iframe.
- [ ] Update text input to textarea and add submit button.
- [ ] Add support to download the generated landing page as a zip file.
- [ ] Add support to deploy the generated landing page to Vercel or Netlify with a single click.
- [ ] Add support for dark mode.
- [ ] Add support for multiple pages.
- [ ] Add support for multiple languages.
This project is still in its early stages of development. If you have any suggestions or ideas, please feel free to open an issue or submit a pull request.
## Contributing
Thank you for considering contributing to this project! To contribute, follow these steps:
1. Fork the repository.
2. Create a new branch for your feature/fix: `git checkout -b feature/your-feature-name`.
3. Add your changes with: `git add .`.
4. Make your changes and commit them: `git commit -m "Add your feature description"`.
5. Push to the branch: `git push origin feature/your-feature-name`.
6. Open a pull request to the `master` branch of the original repository. Provide a clear and descriptive title and description for your pull request. Include any relevant information or context that would help with the review process.
7. Wait for the maintainers to review your pull request. Make any necessary changes or address any feedback provided.
8. Once your pull request is approved, it will be merged into the `master` branch.
Congratulations on your contribution!
## License
This project is licensed under the [MIT License](LICENSE).
## Contact
For any inquiries or feedback, please reach out to us at [zinedkaloc](https://twitter.com/zinedkaloc).
================================================
FILE: app/(aipage)/layout.tsx
================================================
import "@smastrom/react-rating/style.css";
import { ReactNode } from "react";
import Header from "@/components/Header";
export default async function AipageLayout({
children,
}: {
children: ReactNode;
}) {
return (
<>
{children}
>
);
}
================================================
FILE: app/(aipage)/loading.tsx
================================================
import LoadingSpinner from "@/components/loadingSpinner";
export default function RootLoading() {
return (
);
}
================================================
FILE: app/(aipage)/not-found.tsx
================================================
import Link from "next/link";
import Button from "@/components/Button";
export default async function NotFound() {
return (
404 NOT FOUND
We can’t find that page
Sorry, the page you are looking for doesn't exist or has been moved.
);
}
================================================
FILE: app/(aipage)/page.tsx
================================================
"use client";
import { useChat } from "ai/react";
import { useEffect, useRef, useState } from "react";
import Frame from "react-frame-component";
import Image from "next/image";
import html2canvas from "html2canvas";
import TweetButton from "@/components/tweetButton";
import { useAuth } from "@/context/AuthContext";
import useSearchParams from "@/hooks/useSearchParams";
import RateModal from "@/components/RateModal";
import { cn, updateProject } from "@/utils/helpers";
import Link from "next/link";
enum DeviceSize {
Mobile = "w-1/2",
Tablet = "w-3/4",
Desktop = "w-full",
}
export default function Chat() {
const { user, setUser } = useAuth();
const [lastMessageId, setLastMessageId] = useState(null);
const [hasNoCreditsError, setHasNoCreditsError] = useState(false);
const { set } = useSearchParams();
const { messages, input, handleInputChange, handleSubmit, isLoading, stop } =
useChat({
onResponse: (message) => {
setHasNoCreditsError(false);
setLastMessageId(null);
decreaseCredit();
},
onFinish: async (message) => {
try {
const res = JSON.parse(message.content) as { credits: number };
setCredits(res.credits);
setHasNoCreditsError(res.credits === 0);
} catch {
await saveResult(message.content);
}
},
});
function decreaseCredit(by: number = 1) {
if (user) {
setUser({ ...user, credits: user.credits - by });
}
}
function setCredits(credits: number) {
if (user) {
setUser({ ...user, credits });
}
}
async function saveResult(result: string) {
const { _id } = await updateProject({
result,
});
setLastMessageId(_id);
set("rateModal", "true");
}
const [iframeContent, setIframeContent] = useState("");
const [imageSrc, setImageSrc] = useState("");
const [deviceSize, setDeviceSize] = useState(DeviceSize.Desktop);
const iframeRef = useRef(null);
const [fileName, setFileName] = useState("");
const [selectedElement, setSelectedElement] = useState(null);
const [editedContent, setEditedContent] = useState("");
const [editingMode, setEditingMode] = useState(false);
const [codeViewActive, setCodeViewActive] = useState(false);
const [isStopped, setIsStopped] = useState(false);
const appendToIframe = (content: any) => {
if (iframeRef.current) {
const iframeDocument = (iframeRef.current as HTMLIFrameElement)
.contentDocument;
if (iframeDocument) {
const newNode = iframeDocument.createElement("div");
newNode.innerHTML = content;
newNode.querySelectorAll("*").forEach((element) => {
element.addEventListener("mouseover", () => {
element.classList.add("outline-blue"); // Blue border
});
element.addEventListener("mouseout", () => {
element.style.outline = "none";
});
element.addEventListener("click", () => {
setSelectedElement(element);
setEditedContent(element.innerHTML);
});
});
requestAnimationFrame(() => {
iframeDocument.body.appendChild(newNode);
});
}
}
};
const captureIframeContent = async () => {
if (iframeRef.current) {
const iframeDocument = (iframeRef.current as HTMLIFrameElement)
.contentDocument;
if (iframeDocument) {
const canvas = await html2canvas(iframeDocument.body);
const imgURL = canvas.toDataURL();
// You can use imgURL as the src for an image tag to display the image representation of the iframe content
// For simplicity, let's just set it to a state variable
setImageSrc(imgURL);
}
}
};
useEffect(() => {
const stream = new EventSource("/api/chat");
stream.onmessage = (event) => {
appendToIframe(event.data);
};
return () => stream.close();
}, []);
useEffect(() => {
const lastMessage = messages[messages.length - 1];
if (lastMessage && lastMessage.role !== "user") {
setIframeContent(lastMessage.content);
}
}, [messages]);
const handleSave = () => {
const element = document.createElement("a");
const file = new Blob([iframeContent], { type: "text/html" });
element.href = URL.createObjectURL(file);
element.download = fileName || "index.html";
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
const completionInput = iframeContent;
};
const listenersMap = useRef<
Map void; mouseout: () => void }>
>(new Map());
// Create a map to store the listeners for each element
const handleEdit = () => {
if (editingMode) {
// Save the updated iframe content
if (iframeRef.current) {
const iframeDocument = (iframeRef.current as HTMLIFrameElement)
.contentDocument;
if (iframeDocument) {
setIframeContent(iframeDocument.documentElement.innerHTML);
}
}
// Disable editing mode by setting the contentEditable property of all elements to false and remove the event listeners
if (iframeRef.current) {
const iframeDocument = (iframeRef.current as HTMLIFrameElement)
.contentDocument;
if (iframeDocument) {
iframeDocument
.querySelectorAll("*")
.forEach((element) => {
element.contentEditable = "false";
// Get the listeners for the element from the map
const listeners = listenersMap.current.get(element);
if (listeners) {
// Remove the listeners
element.removeEventListener("mouseover", listeners.mouseover);
element.removeEventListener("mouseout", listeners.mouseout);
// Remove the element from the map
listenersMap.current.delete(element);
}
});
}
}
} else {
// Enable editing mode by setting the contentEditable property of all elements to true and add event listeners
if (iframeRef.current) {
const iframeDocument = (iframeRef.current as HTMLIFrameElement)
.contentDocument;
if (iframeDocument) {
iframeDocument
.querySelectorAll("*")
.forEach((element) => {
element.contentEditable = "true";
// Create the event listeners
const mouseoverListener = () => {
element.classList.add("outline-blue");
console.log("Mouseover event fired");
};
const mouseoutListener = () => {
console.log("Mouseout event fired");
element.classList.remove("outline-blue");
};
// Add the listeners to the element
element.addEventListener("mouseover", mouseoverListener);
element.addEventListener("mouseout", mouseoutListener);
// Store the listeners in the map
listenersMap.current.set(element, {
mouseover: mouseoverListener,
mouseout: mouseoutListener,
});
});
}
}
}
setEditingMode(!editingMode);
};
const handleUpdate = () => {
if (selectedElement) {
selectedElement.innerHTML = editedContent;
setSelectedElement(null);
setEditedContent("");
if (iframeRef.current) {
const iframeDocument = (iframeRef.current as HTMLIFrameElement)
.contentDocument;
if (iframeDocument) {
setIframeContent(iframeDocument.documentElement.innerHTML);
}
}
}
};
function onFocusHandler() {
if (!user) {
set("authModal", "true");
}
}
const handleStop = async () => {
stop();
setIsStopped(true);
await saveResult(iframeContent);
};
return (
<>
Help spread the word! 📢 Post a tweet of your creation on Twitter
and tag @aipagedev for early access to our exclusive beta—packed
with stunning features. 🚀
);
}
interface PanelProps {
open: boolean;
onOpenChange?: (open: boolean) => void;
selected?: HTMLElement | null;
onSave: (values: [string, string][]) => void;
}
function Panel(props: PanelProps) {
const { open, onOpenChange, selected, onSave } = props;
const includedKeys = [
"padding",
"color",
"width",
"height",
"margin",
"fontSize",
"display",
"position",
"top",
"left",
"right",
"bottom",
"border",
"background",
"transform",
];
function onSubmit(e: FormEvent) {
e.preventDefault();
if (!selected) return;
const formData = new FormData(e.target as HTMLFormElement);
onSave?.(Array.from(formData.entries()) as [string, string][]);
}
return (
);
}
================================================
FILE: app/(aipage)/profile/projects/[id]/settings/page.tsx
================================================
"use client";
import useProject from "@/hooks/useProject";
import { FormEvent, useEffect, useState } from "react";
import { cn, updateProject } from "@/utils/helpers";
import NavLink from "@/components/NavLink";
import Button from "@/components/Button";
import DeleteProjectConfirmDialog from "@/components/DeleteProjectConfirmDialog";
import LoadingSpinner from "@/components/loadingSpinner";
import { useRouter } from "next/navigation";
export default function ProjectSettingsPage() {
const { setProject, project } = useProject();
const [name, setName] = useState(project?.name);
const [loading, setLoading] = useState(false);
const { refresh } = useRouter();
async function onNameFormSubmit(event: FormEvent) {
event.preventDefault();
if (!name || name === project?.name) return;
setLoading(true);
const { message: projectFromAPI } = await updateProject(
{
name,
},
project?._id as string,
);
setLoading(false);
setProject(projectFromAPI);
refresh();
}
return (
General
Delete Project
Permanently delete your AIPage.dev project
);
}
================================================
FILE: app/(aipage)/profile/projects/loading.tsx
================================================
import LoadingSpinner from "@/components/loadingSpinner";
export default function ProjectsLoading() {
return (
);
}
================================================
FILE: app/(aipage)/profile/projects/page.tsx
================================================
import { cn } from "@/utils/helpers";
import Link from "next/link";
import Button from "@/components/Button";
import ListProjects from "@/components/ListProjects";
import { fetchProjects } from "@/utils/auth";
export const revalidate = 0;
export default async function ProfileProjects() {
const projects = await fetchProjects();
const hasProjects = !!projects && projects.length > 0;
return (
{!hasProjects ? (
You don't have any projects yet!
) : (
)}
);
}
================================================
FILE: app/(aipage)/profile/settings/loading.tsx
================================================
import LoadingSpinner from "@/components/loadingSpinner";
export default function SettingsLoading() {
return (
);
}
================================================
FILE: app/(aipage)/profile/settings/page.tsx
================================================
"use client";
import { useAuth } from "@/context/AuthContext";
import { useState, FormEvent } from "react";
import LoadingSpinner from "@/components/loadingSpinner";
import Button from "@/components/Button";
import { cn } from "@/utils/helpers";
import DeleteAccountConfirmDialog from "@/components/DeleteAccountConfirmDialog";
import NavLink from "@/components/NavLink";
export default function ProfileSettings() {
const { user, setUser } = useAuth();
const [name, setName] = useState(user?.name);
const [loading, setLoading] = useState(false);
async function onNameFormSubmit(event: FormEvent) {
event.preventDefault();
if (!name || name === user?.name) return;
setLoading(true);
const res = await fetch("/api/user", {
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ name }),
});
const { user: userFromAPI, errors } = await res.json();
setLoading(false);
if (!errors) {
setUser(userFromAPI);
}
}
return (
General
Delete Account
Permanently delete your AIPage.dev account and all of your data.
This action cannot be undone - please proceed with caution.
);
}
================================================
FILE: app/(preview)/not-found.tsx
================================================
import Link from "next/link";
import Button from "@/components/Button";
export default async function NotFound() {
return (
404 NOT FOUND
We can’t find that page
Sorry, the page you are looking for doesn't exist or has been moved.
);
}
================================================
FILE: app/(preview)/profile/projects/[id]/preview/loading.tsx
================================================
import LoadingSpinner from "@/components/loadingSpinner";
export default function PreviewLoading() {
return (
);
}
================================================
FILE: app/(preview)/profile/projects/[id]/preview/page.tsx
================================================
import { fetchProjectById } from "@/utils/auth";
import { notFound } from "next/navigation";
import HTMLPreview from "@/components/HTMLPreview";
export default async function projectPreview({
params,
}: {
params: { id: string };
}) {
const project = await fetchProjectById(params.id);
if (!project || !project.result) return notFound();
return ;
}
================================================
FILE: app/api/chat/route.ts
================================================
import { Configuration, OpenAIApi } from "openai-edge";
import { Ratelimit } from "@upstash/ratelimit";
import redis from "../../../utils/redis";
import { OpenAIStream, StreamingTextResponse } from "ai";
import { headers, cookies } from "next/headers";
import { NextResponse } from "next/server";
/* // REMOVE THIS IF YOU DON'T WANT RATE LIMITING
// START
const ratelimit = redis
? new Ratelimit({
redis: redis,
limiter: Ratelimit.fixedWindow(5, "1440 m"),
analytics: true,
})
: undefined;
// END
*/
const config = new Configuration({
apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(config);
export const runtime = "edge";
export async function POST(req: Request) {
const cookieStore = cookies();
/* // REMOVE THIS IF YOU DON'T WANT RATE LIMITING
// START
if (ratelimit) {
const headersList = headers();
const ipIdentifier = headersList.get("x-real-ip");
const result = await ratelimit.limit(ipIdentifier ?? "");
if (!result.success) {
const fakeStream =
"Too many requests in 1 day. Please try again in a 24 hours. Thank you. 🙏";
return new Response(fakeStream, {
status: 429,
headers: {
"X-RateLimit-Limit": result.limit,
"X-RateLimit-Remaining": result.remaining,
} as any,
});
}
}
// END */
const { messages } = await req.json();
// Implemented for to test the API
const sessionToken = cookieStore.get("sessionToken")?.value as string;
const storeMessage = await fetch(
"https://c3-na.altogic.com/e:64d52ccfc66bd54b97bdd78a/test",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Session: sessionToken,
},
body: JSON.stringify({ content: messages[0].content }),
},
);
const { credits } = await storeMessage.json();
if (credits === 0) {
return NextResponse.json({ code: "no-credits", credits });
}
const systemPrompt = `You are a talented UI designer who needs help creating a clear and concise HTML UI using Tailwind CSS. The UI should be visually appealing and responsive. Please design a UI component that includes the following elements:
1. A header Section: Include a logo and a navigation menu.
2. A hero Section: Create a captivating headline and a call-to-action button. Use a random image related to the prompt for the background image, generating it with the URL "https://source.unsplash.com/featured/1280x720/?{description}" (replace {description} with a relevant keyword).
3. A feature Section: Showcase three standout feature cards with eye-catching featured icons from the Fontawesome CDN icon library. Apply subtle CSS animations, such as fade-in or slide-in effects using Animate.css, to enhance visual appeal.
4. An individual Feature Sections: Create a separate section for each feature card. Each section should include a captivating title, description, and a call-to-action button. Use a random image related to the prompt for the background image, generating it with the URL "https://source.unsplash.com/featured/1280x720/?{description}" (replace {description} with a relevant keyword). You can float the image to the left or right of the text.
5. A testimonial Section: Display two testimonials with names, roles, and feedback. Apply a CSS animation, like fade-in or slide-in animation using Animate.css, to reveal testimonials when scrolled into view.
6. A blog Section: Include a section that displays recent blog posts with a title, short description, and a "Read More" link.
7. An FAQ Section: Add a section for frequently asked questions and answers.
8. A Team Section: Showcase the team with photos, names, roles, and social media links.
9. A Newsletter Subscription: Add a section for users to subscribe to a newsletter.
10. A Contact Form: Create fields for name, email, and message. Apply appropriate CSS animations or transitions using jQuery for smooth interactivity.
11. A map Section: Include a Google Maps section with a marker showing the location of the business (you may need a Google Maps API key).
12. A footer Section: Add links to social media profiles, utilizing the Fontawesome CDN icon library for social media icons.
Please ensure the HTML code is valid and properly structured, incorporating the necessary CDN links for Tailwind CSS, Fontawesome icons, jQuery, Animate.css, Google Maps API, and any additional CSS or JS files.
Remember to keep the design minimalistic, intuitive, and visually appealing. Your attention to detail is highly appreciated. Once you complete the design, provide the HTML code for the UI component. The code should be valid HTML, formatted for readability, and include the necessary CDN links for Tailwind CSS, icons, and any additional libraries used for data visualization.
Given the prompt, generate the only HTML code for the UI component. The code should be valid HTML and include the necessary CDN links for Tailwind CSS, Fontawesome icons, and any additional CSS and JavaScript files.
Start with and end with