blog2025-04-23-upgrading.md9 matches
8Today, weβre unifying our two primitives β *vals* and *projects* β into a single primitive: the **val**, with the best features of both.
910Historically, vals have been simple and lightweight, but limited to a single file. This upgrade will preserve the elegant spirit of our platform while supporting more complex code and collaborative workflows. This upgrade will help you create bigger things on Val Town β APIs, internal tools, fullstack apps, blogs ([like this one](https://www.val.town/x/valdottown/blog)), and much more β without sacrificing the simplicity you've always loved about vals.
1112*Legacy vals* will temporarily become *projects* during this migration. Post-migration, the concept of *projects* will disappear entirely β leaving only upgraded *vals*. In short: *legacy vals* β *projects* β *vals*.
16For most users, no upgrade action is required. Weβll auto-migrate your vals next week. All existing HTTP endpoints, crons, email handlers, and custom domains will be preserved.
1718For those with mission-critical vals or who use our API to edit or create vals, you can start upgrading your legacy vals today and integrating with our updated API.
1920- **April 23, 2025** β Announcement of changes & API deprecations.
21- **April 30, 2025** β All remaining *legacy vals* auto-upgraded. Deprecated API routes become read-only.
22- **May 1, 2025** β The term *projects* will no longer exist β everything will simply be a *val*.
2335[See more details in our docs.](https://docs.val.town/upgrading/legacy-vals)
3637## API Changes
3839Today, we're introducing the following API routes:
4041```bash
73```
7475View our [updated API reference here](https://docs.val.town/openapi).
7677All `v1/vals` API routes become read-only on **April 30, 2025**. If you rely on *writing* to those routes, please upgrade to our new `v2/vals` API. All deprecated API routes will continue serving historical legacy val data.
7879### SDK changes
85861. Upgrade your mission-critical vals early.
872. Update your Val Town API & SDK usage to `/v2` routes.
883. All remaining legacy vals migrate on **April 30, 2025**.
894. Migration completes on **May 1, 2025**.
TownieuseProject.tsx2 matches
2import { useAuth } from "./useAuth.tsx";
34const PROJECT_ENDPOINT = "/api/project";
5const FILES_ENDPOINT = "/api/project-files";
67export function useProject (projectId: string, branchId?: string) {
TownieuseProjects.tsx1 match
2import { useAuth } from "./useAuth.tsx";
34const ENDPOINT = "/api/projects-loader";
56export function useProjects () {
TownieuseCreateProject.tsx1 match
3import { useAuth } from "./useAuth.tsx";
45const ENDPOINT = "/api/create-project";
67export function useCreateProject () {
TownieuseCreateBranch.tsx1 match
2import { useAuth } from "./useAuth.tsx";
34const ENDPOINT = "/api/create-branch";
56export function useCreateBranch (projectId: string) {
TownieuseChatLogic.ts4 matches
6project: any;
7branchId: string | undefined;
8anthropicApiKey: string;
9bearerToken: string;
10selectedFiles: string[];
16project,
17branchId,
18anthropicApiKey,
19bearerToken,
20selectedFiles,
37status,
38} = useChat({
39api: "/api/send-message",
40body: {
41project,
42branchId,
43anthropicApiKey,
44selectedFiles,
45images: images
TownieuseBranches.tsx1 match
2import { useAuth } from "./useAuth.tsx";
34const ENDPOINT = "/api/project-branches";
56export function useBranches (projectId: string) {
TownieuseAuth.tsx11 matches
34const TOKEN_KEY = "bearer";
5const ANTHROPIC_KEY = "anthropic_api_key";
67export function useAuth() {
8const [token, setToken, removeToken] = useLocalStorage(TOKEN_KEY, "");
9const [anthropicApiKey, setAnthropicApiKey, removeAnthropicApiKey] = useLocalStorage(ANTHROPIC_KEY, "");
10const [error, setError] = useState(null);
1112const isAuthenticated = !!token;
1314const authenticate = async (valTownAPIKey: string, anthropicKey: string) => {
15// replace all this with oauth when it's ready
16try {
17const res = await fetch("/api/user", {
18headers: {
19"Authorization": "Bearer " + valTownAPIKey,
20},
21});
25setError(data.error);
26removeToken();
27removeAnthropicApiKey();
28return;
29}
30setError(null);
31setToken(valTownAPIKey);
32setAnthropicApiKey(anthropicKey);
33} catch (e) {
34console.error(e);
35setError(e.error);
36removeToken();
37removeAnthropicApiKey();
38}
39};
41const logOut = () => {
42removeToken();
43removeAnthropicApiKey();
44};
4550logOut,
51token,
52anthropicApiKey,
53};
54}
Townieusage-dashboard.ts3 matches
76SUM(num_images) as total_images
77FROM ${USAGE_TABLE}
78WHERE our_api_token = 1
79GROUP BY user_id, username
80ORDER BY total_price DESC
256<th>Finish</th>
257<th>Images</th>
258<th>Our API</th>
259</tr>
260</thead>
276<td>${row.finish_reason}</td>
277<td>${formatNumber(row.num_images)}</td>
278<td>${formatBoolean(row.our_api_token)}</td>
279</tr>
280`).join("")
Towniesystem_prompt.txt10 matches
13- Generate code in TypeScript or TSX
14- Add appropriate TypeScript types and interfaces for all data structures
15- Prefer official SDKs or libraries than writing API calls directly
16- Ask the user to supply API or library documentation if you are at all unsure about it
17- **Never bake in secrets into the code** - always use environment variables
18- Include comments explaining complex logic (avoid commenting obvious operations)
23### 1. HTTP Trigger
2425- Create web APIs and endpoints
26- Handle HTTP requests and responses
27- Example structure:
167However, it's *extremely importing* to note that `parseProject` and other Standard Library utilities ONLY RUN ON THE SERVER.
168If you need access to this data on the client, run it in the server and pass it to the client by splicing it into the HTML page
169or by making an API request for it.
170171## Val Town Platform Specifics
175- **AI Image:** To inline generate an AI image use: `<img src="https://maxm-imggenurl.web.val.run/the-description-of-your-image" />`
176- **Storage:** DO NOT use the Deno KV module for storage
177- **Browser APIs:** DO NOT use the `alert()`, `prompt()`, or `confirm()` methods
178- **Weather Data:** Use open-meteo for weather data (doesn't require API keys) unless otherwise specified
179- **View Source:** Add a view source link by importing & using `import.meta.url.replace("ems.sh", "val.town)"` (or passing this data to the client) and include `target="_top"` attribute
180- **Error Debugging:** Add `<script src="https://esm.town/v/std/catch"></script>` to HTML to capture client-side errors
181- **Error Handling:** Only use try...catch when there's a clear local resolution; Avoid catches that merely log or return 500s. Let errors bubble up with full context
182- **Environment Variables:** Use `Deno.env.get('keyname')` when you need to, but generally prefer APIs that don't require keys
183- **Imports:** Use `https://esm.sh` for npm and Deno dependencies to ensure compatibility on server and browser
184- **Storage Strategy:** Only use backend storage if explicitly required; prefer simple static client-side sites
218### Backend (Hono) Best Practices
219220- Hono is the recommended API framework
221- Main entry point should be `backend/index.ts`
222- **Static asset serving:** Use the utility functions to read and serve project files:
242});
243```
244- Create RESTful API routes for CRUD operations
245- Always include this snippet at the top-level Hono app to re-throwing errors to see full stack traces:
246```ts
279- For files in the project, use `readFile` helpers
2802815. **API Design:**
282- `fetch` handler is the entry point for HTTP vals
283- Run the Hono app with `export default app.fetch // This is the entry point for HTTP vals`