1# iClickWolf - Val Town Edition
2
3This app is a port of the iClickWolf Next.js application to Val Town, using SQLite for database storage.
4
5## Project Structure
6
7- **Backend**: `/backend/index.ts` - The main HTTP server that serves the frontend and API endpoints
8 - `/backend/database/` - Contains SQLite database setup and queries
9 - `/backend/routes/` - API routes for checkout, webhook, and items
10
18- Stripe integration for payments
19- Email notifications for order confirmations
20- SQLite database for storing items and preorders
21
22## Environment Variables
34
35- If Stripe is not configured (missing API keys), appropriate error messages are shown
36- If the database fails to load items, default values are used as a fallback
37- All API errors are properly logged and user-friendly messages are displayed
38- Form validation prevents submission of invalid data
39
40## Database
41
42The application uses Val Town's SQLite database with the following tables:
43
44- `iclickwolf_items_v1` - Stores product information
1import { Hono } from "npm:hono";
2import { getFirstItem } from "../database/queries.ts";
3
4const app = new Hono();
9 const item = await getFirstItem();
10 if (!item) {
11 // Create a default item if none exists in the database
12 const defaultItem = {
13 id: 1,
33 image: "https://placehold.co/200x200?text=iClicker",
34 buyUrl: "",
35 error: "Database error: " + error.message
36 }, 200); // Return 200 with error in the payload so frontend can still display something
37 }
41 email,
42 pickupLocation,
43 productID: 1 // We'll get the actual ID from the database on the server
44 }),
45 });
1import { Hono } from "npm:hono";
2import { getFirstItem, getPreorderBySessionId, updatePreorderStatus } from "../database/queries.ts";
3
4const app = new Hono();
1import { Hono } from "npm:hono";
2import { createPreorder, getFirstItem } from "../database/queries.ts";
3
4const app = new Hono();
36 }
37
38 // Get the product from the database
39 const item = await getFirstItem();
40 if (!item) {
63 });
64
65 // Create a new preorder in the database
66 const preorderId = await createPreorder({
67 customerName,
5import webhookRoutes from "./routes/webhook.ts";
6import itemsRoutes from "./routes/items.ts";
7import { runMigrations } from "./database/migrations.ts";
8
9// Initialize the app
16try {
17 await runMigrations();
18 console.log("Database migrations completed successfully");
19} catch (error) {
20 console.error("Database migration error:", error);
21}
22
1# Database
2
3This directory contains the SQLite database setup for the iClickWolf application.
4
5## Files
6
7- `migrations.ts` - Contains the database schema and table creation logic
8- `queries.ts` - Contains typed functions for interacting with the database
9
10## Tables
2import { ITEMS_TABLE, PREORDERS_TABLE } from "./migrations.ts";
3
4// Types matching our database schema
5export interface Item {
6 id: number;
1// Script to set up the telegram_chats table in SQLite
2// Run this script manually to create the database table
3
4export default async function setupTelegramChatDb() {
25 `);
26
27 return "Telegram chat database table created successfully.";
28 } catch (error) {
29 console.error("Error setting up telegram_chats table:", error);
13## Technical Architecture
14
15**⚠️ important caveat: the admin dashboard doesn't have auth! currently it just relies on security by obscurity of people not knowing the url to a private val. this is not very secure. if you fork this project and put sensitive data in a database you should think carefully about how to secure it.**
16
17Stevens has been designed with the utmost simplicity and extensibility, much like a well-organized household. At the heart of his operation lies a single "memories" table - a digital equivalent of a butler's meticulous records. This table serves as the foundation for all of Stevens' operations.
45- `dashboard`: the admin view for showing the memories notebook + visualizing imports
46- `dailyBriefing`: stuff related to sending a daily update via telegram
47- `dbUtils`: little one-off scripts for database stuff
48
49## Hiring your own Stevens
57- For the Google Calendar integration you'll need `GOOGLE_CALENDAR_ACCOUNT_ID` and `GOOGLE_CALENDAR_CALENDAR_ID`. See [these instuctions](https://www.val.town/v/stevekrouse/pipedream) for details.
58
59**important caveat: the admin dashboard doesn't have auth! currently it just relies on security by obscurity of people not knowing the url to a private val. this is not very secure, if you put sensitive data in a database you should think carefully about how to secure it.**
60
61Overall it's a simple enough project that I encourage you to just copy the ideas and run in your own direction rather than try to use it as-is.