19await runMigrations();
20
21// API routes
22app.route("/api/crypto", crypto);
23app.route("/api/predictions", predictions);
24app.route("/api/chat", chat);
25app.route("/api/exchange", exchange);
26
27// Serve static files
8 try {
9 const response = await fetch(
10 "https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=20&page=1&sparkline=false"
11 );
12
13 if (!response.ok) {
14 throw new Error(`CoinGecko API error: ${response.status}`);
15 }
16
16## Tech Stack
17
18- **Backend**: Hono.js API with SQLite database
19- **Frontend**: React with TailwindCSS
20- **Data**: CoinGecko API for cryptocurrency prices
21- **Storage**: Val Town SQLite for predictions and chat messages
22
46```
47
48## API Endpoints
49
50- `GET /api/crypto` - Get current crypto prices
51- `GET /api/predictions` - Get all predictions
52- `POST /api/predictions` - Create new prediction
53- `GET /api/chat` - Get chat messages
54- `POST /api/chat` - Send chat message
55
56## Database Schema
13## Authentication
14
15Login to your SQLite Explorer with [password authentication](https://www.val.town/v/pomdtr/password_auth) with your [Val Town API Token](https://www.val.town/settings/api) as the password.
16
17## Todos / Plans
27 <head>
28 <title>SQLite Explorer</title>
29 <link rel="preconnect" href="https://fonts.googleapis.com" />
30
31 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
32 <link
33 href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@300..700&family=Source+Sans+3:ital,wght@0,200..900;1,200..900&display=swap"
34 rel="stylesheet"
35 />
16await runMigrations();
17
18// API routes
19app.route("/api/artists", artistsRouter);
20app.route("/api/portfolio", portfolioRouter);
21app.route("/api/contact", contactRouter);
22
23// Serve static files
30
31 try {
32 const response = await fetch('/api/artists', {
33 method: 'POST',
34 headers: {
31 };
32
33 const response = await fetch('/api/contact', {
34 method: 'POST',
35 headers: {
104 <div>
105 <h1 className="text-2xl font-bold text-gray-900">Contact {artist.name}</h1>
106 <p className="text-purple-600 capitalize">{artist.type} • {artist.location}</p>
107 </div>
108 </div>
20 const loadPortfolio = async () => {
21 try {
22 const response = await fetch(`/api/portfolio/artist/${artist.id}`);
23 const data = await response.json();
24 setPortfolio(data);
81 <div>
82 <h1 className="text-3xl font-bold text-gray-900">{artist.name}</h1>
83 <p className="text-purple-600 capitalize text-lg">{artist.type}</p>
84 <div className="flex items-center text-gray-500 mt-1">
85 <svg className="w-4 h-4 mr-1" fill="currentColor" viewBox="0 0 20 20">
21 <div>
22 <h3 className="text-xl font-semibold text-gray-900">{artist.name}</h3>
23 <p className="text-purple-600 capitalize">{artist.type}</p>
24 </div>
25 </div>