1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/**
* This val creates a tech stack inventory chooser using React and Tailwind CSS for styling.
* It allows users to select technologies for different categories and displays the chosen stack.
*/
/** @jsxImportSource https://esm.sh/react */
import React, { useState } from "https://esm.sh/react";
import { createRoot } from "https://esm.sh/react-dom/client";
const techCategories = {
frontend: ["React", "Vue", "Angular", "Svelte"],
backend: ["Node.js", "Python", "Ruby", "Java"],
database: ["PostgreSQL", "MongoDB", "MySQL", "SQLite"],
hosting: ["AWS", "Google Cloud", "Heroku", "DigitalOcean"],
};
function App() {
const [selectedTech, setSelectedTech] = useState({});
const handleTechSelect = (category, tech) => {
setSelectedTech(prev => ({
...prev,
[category]: tech
}));
};
return (
<div className="max-w-2xl mx-auto p-4">
<h1 className="text-3xl font-bold mb-6 text-gray-800">Tech Stack Chooser</h1>
{Object.entries(techCategories).map(([category, technologies]) => (
<div key={category} className="mb-6">
<h2 className="text-xl font-semibold mb-2 text-gray-700 capitalize">{category}</h2>
<div className="flex flex-wrap gap-2">
{technologies.map(tech => (
<button
key={tech}
onClick={() => handleTechSelect(category, tech)}
className={`px-3 py-1 rounded-full text-sm ${
selectedTech[category] === tech
? "bg-blue-500 text-white"
: "bg-gray-200 text-gray-700 hover:bg-gray-300"
}`}
>
{tech}
</button>
))}
</div>
</div>
))}
<div className="mt-8 p-4 bg-white shadow-md rounded-lg">
<h2 className="text-xl font-semibold mb-2 text-gray-800">Your Chosen Stack:</h2>
<ul className="list-disc list-inside">
{Object.entries(selectedTech).map(([category, tech]) => (
<li key={category} className="text-gray-700">
<span className="font-medium capitalize">{category}:</span> {tech}
</li>
))}
</ul>
</div>
<p className="mt-4 text-sm text-gray-500">
View source on <a href={import.meta.url.replace("esm.town", "val.town")} className="text-blue-500 hover:underline">Val Town</a>
</p>
</div>
);
}
function client() {
createRoot(document.getElementById("root")).render(<App />);
}
if (typeof document !== "undefined") { client(); }
async function server(request: Request): Promise<Response> {
return new Response(`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tech Stack Chooser</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-100 text-gray-900">
<div id="root"></div>
<script type="module" src="${import.meta.url}"></script>
</body>
</html>
`, {
headers: { "Content-Type": "text/html" },
});
}
export default server;