2import { readFile, serveFile } from "https://esm.town/v/std/utils@85-main/index.ts";
3import { runMigrations } from "./database/migrations.ts";
4import api from "./routes/api.ts";
5
6const app = new Hono();
14await runMigrations();
15
16// API routes
17app.route("/api", api);
18
19// Serve static files
8} from "../database/queries.ts";
9
10const api = new Hono();
11
12// Search companies
13api.get("/companies/search", async (c) => {
14 const query = c.req.query("q");
15
28
29// Get all companies with stats (for homepage)
30api.get("/companies", async (c) => {
31 try {
32 const companies = await getAllCompaniesWithStats();
39
40// Get company details with reviews
41api.get("/companies/:id", async (c) => {
42 const id = parseInt(c.req.param("id"));
43
61
62// Submit a new review
63api.post("/reviews", async (c) => {
64 try {
65 const body = await c.req.json() as ReviewSubmission;
90});
91
92export default api;
18โ โ โโโ queries.ts # Database query functions
19โ โโโ routes/
20โ โโโ api.ts # API endpoints
21โ โโโ index.ts # Main Hono server
22โโโ frontend/
33```
34
35## API Endpoints
36
37- `GET /api/companies/search?q={query}` - Search companies
38- `GET /api/companies/{id}/reviews` - Get reviews for a company
39- `POST /api/reviews` - Submit a new review
40- `GET /api/companies/{id}` - Get company details
41
42## Database Schema
32});
33
34// API Routes
35
36// Get list of cryptocurrencies
37app.get("/api/coins", async c => {
38 try {
39 const limit = Math.min(parseInt(c.req.query("limit") || "50"), 250);
47
48// Get chart data for a specific coin
49app.get("/api/coins/:id/chart", async c => {
50 try {
51 const coinId = c.req.param("id");
64async function fetchCoins(limit: number = 50): Promise<CryptoCoin[]> {
65 const response = await fetch(
66 `https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=${limit}&page=1&sparkline=false&price_change_percentage=24h,7d,30d`
67 );
68
69 if (!response.ok) {
70 throw new Error(`CoinGecko API error: ${response.status}`);
71 }
72
85
86 const response = await fetch(
87 `https://api.coingecko.com/api/v3/coins/${coinId}/market_chart?vs_currency=usd&days=${days}${interval}`
88 );
89
90 if (!response.ok) {
91 const errorText = await response.text();
92 console.error(`CoinGecko API error: ${response.status} - ${errorText}`);
93 throw new Error(`CoinGecko API error: ${response.status}`);
94 }
95
50 setError(null);
51
52 const response = await fetch(`/api/coins/${coin.id}/chart?days=${timeRange}`);
53 if (!response.ok) {
54 throw new Error('Failed to fetch chart data');
35 setLoading(true);
36 setError(null);
37 const response = await fetch('/api/coins?limit=50');
38 if (!response.ok) {
39 throw new Error('Failed to fetch cryptocurrency data');
118 <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
119 <div className="text-center text-gray-500 text-sm">
120 <p>Data provided by CoinGecko API</p>
121 <p className="mt-1">Built with React, Hono, and Chart.js</p>
122 </div>
7- **Crypto Asset Listing**: Browse popular cryptocurrencies with real-time prices
8- **Interactive Charts**: View price history for multiple time periods (1D, 1W, 1M, 3M, 6M, 1Y, 5Y)
9- **Real-time Data**: Powered by CoinGecko API for accurate market data
10- **Responsive Design**: Works seamlessly on desktop and mobile devices
11
14```
15โโโ backend/
16โ โโโ index.ts # Main Hono server with API routes
17โ โโโ README.md # Backend documentation
18โโโ frontend/
30```
31
32## API Endpoints
33
34- `GET /` - Serves the main application
35- `GET /api/coins` - Fetches list of cryptocurrencies
36- `GET /api/coins/:id/chart` - Fetches chart data for a specific coin
37- `GET /frontend/*` - Serves frontend assets
38- `GET /shared/*` - Serves shared utilities
44- **Charts**: Chart.js with React wrapper
45- **Styling**: TailwindCSS
46- **Data Source**: CoinGecko API (no API key required)
47
48## Usage
15await runMigrations();
16
17// API routes
18app.route("/api/jobs", jobsRouter);
19app.route("/api/chat", chatRouter);
20
21// Serve static files
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import { useState, useEffect, useRef } from "https://esm.sh/react@18.2.0";
3import type { ChatMessage, CreateMessageRequest, ApiResponse } from "../../shared/types.ts";
4
5export default function ChatRoom() {
19 try {
20 setLoading(true);
21 const response = await fetch('/api/chat/messages');
22 const result: ApiResponse<ChatMessage[]> = await response.json();
23
24 if (result.success && result.data) {
51 };
52
53 const response = await fetch('/api/chat/messages', {
54 method: 'POST',
55 headers: {
59 });
60
61 const result: ApiResponse<ChatMessage> = await response.json();
62
63 if (result.success && result.data) {
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import { useState } from "https://esm.sh/react@18.2.0";
3import type { Job, CreateJobRequest, ApiResponse } from "../../shared/types.ts";
4
5interface JobFormProps {
25
26 try {
27 const response = await fetch('/api/jobs', {
28 method: 'POST',
29 headers: {
33 });
34
35 const result: ApiResponse<Job> = await response.json();
36
37 if (result.success && result.data) {