1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React, { useState, useEffect } from "https://esm.sh/react@18.2.0?deps=react@18.2.0";
3import { createRoot } from "https://esm.sh/react-dom@18.2.0/client?deps=react@18.2.0,react-dom@18.2.0";
4import { LoginWithGoogleButton } from "https://esm.town/v/stevekrouse/LoginWithGoogleButton";
5
111 };
112
113 const handleKeyPress = (e: React.KeyboardEvent) => {
114 if (e.key === 'Enter' && !e.shiftKey) {
115 e.preventDefault();
1# ChatGPT Clone with LastLogin Authentication
2
3A fullstack React + Hono app that lets you chat with ChatGPT, with user authentication and thread history.
4
5## Features
18โโโ frontend/
19โ โโโ index.html # Main HTML template
20โ โโโ index.tsx # React frontend app
21โโโ README.md
22```
28- โ
SQLite schema for threads and messages
29- โ
Basic API endpoints for threads CRUD
30- โ
Static file serving for React frontend
31
32**Frontend Foundation:**
33- โ
React app with authentication UI
34- โ
Basic layout with sidebar for threads
35- โ
Login/logout flow with LoginWithGoogleButton
47## API Endpoints
48
49- `GET /` - Main React app
50- `GET /api/threads` - List user's threads
51- `POST /api/threads` - Create new thread
44app.get("/shared/*", c => serveFile(c.req.path, import.meta.url));
45
46// Main route - serve React app with initial data
47app.get("/", async (c) => {
48 const email = c.req.header('X-LastLogin-Email');
34
35If you want more interactivity, check out this
36[React starter](https://www.val.town/x/std/reactHonoStarter).
37
38### โ favicon.svg
1/** @jsxImportSource https://esm.sh/react */
2import React, { useEffect, useState } from "https://esm.sh/react";
3import { createRoot } from "https://esm.sh/react-dom/client";
4
5import {
13 TbSend as Send,
14 TbUsers as Users,
15} from "https://esm.sh/react-icons/tb";
16
17
307 <div className="flex justify-center mb-6">
308 <div className="w-16 h-16 sm:w-20 sm:h-20 bg-gradient-to-br from-orange-100 to-yellow-100 rounded-full flex items-center justify-center text-orange-500 group-hover:scale-110 transition-transform duration-300 shadow-md">
309 {React.cloneElement(area.icon, {
310 className: "w-8 h-8 sm:w-10 sm:h-10",
311 })}
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React, { useState, useEffect } from "https://esm.sh/react@18.2.0";
3import { createRoot } from "https://esm.sh/react-dom@18.2.0/client";
4
5function App() {
20 }
21
22 async function handleSubmit(e: React.FormEvent) {
23 e.preventDefault();
24 setResult(null);
392
393 <script type="text/jsx">
394 import React, { useState, useEffect } from 'https://esm.sh/react@18.3.1';
395 import ReactDOM from 'https://esm.sh/react-dom@18.3.1';
396
397 const sourceUrl = "${sourceUrl}";
540 }
541
542 ReactDOM.render(<App />, document.querySelector('main .container'));
543 </script>
544</body>
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2
3export function ValTownLogo () {
1import { useState, useEffect } from "react";
2
3const USER_ENDPOINT = "/api/user";
1import { useEffect } from "react";
2
3export function useUsageStats(messages: any[], usages: any[]) {