• Townie
    AI
  • Blog
  • Docs
  • Pricing
  • We’re hiring!
Log inSign up
zcpbx

zcpbx

MolstarViewer

Public
Like
MolstarViewer
Home
Code
13
frontend
10
routes
6
shared
2
utils
.vtignore
AGENTS.md
CHANGELOG.md
MIGRATION.md
QUICKSTART.md
README.md
deno.json
index.html
index.tsx
Branches
1
Pull requests
Remixes
History
Environment variables
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Sign up now
Code
/
MIGRATION.md
Code
/
MIGRATION.md
Search
…
Viewing readonly version of main branch: v569
View latest version
MIGRATION.md

Migration to Val Town Blog Structure

This document describes the migration from a backend/ folder structure to a top-level routes structure, following the Val Town blog pattern.

What Changed

Before (Backend Folder Pattern)

MolstarViewer/
β”œβ”€β”€ index.tsx                    # Simple re-export
β”‚   └── import app from "./backend/index.tsx"
β”œβ”€β”€ backend/
β”‚   β”œβ”€β”€ index.tsx               # Main Hono app with all routes
β”‚   └── routes/                 # Empty directory
β”œβ”€β”€ frontend/
β”‚   └── apps/                   # App components
└── shared/

After (Val Town Blog Pattern)

MolstarViewer/
β”œβ”€β”€ index.tsx                    # Main Hono app (entry point)
β”œβ”€β”€ routes/                      # Individual route modules
β”‚   β”œβ”€β”€ home.tsx
β”‚   β”œβ”€β”€ viewer.tsx
β”‚   β”œβ”€β”€ docking-viewer.tsx
β”‚   β”œβ”€β”€ mesoscale-explorer.tsx
β”‚   └── mvs-stories.tsx
β”œβ”€β”€ frontend/
β”‚   └── apps/                   # App components (unchanged)
β”œβ”€β”€ shared/                      # Shared code (unchanged)
└── utils/                       # Utility functions (new)

Benefits of New Structure

  1. Simpler Entry Point: index.tsx is now the main app, not a re-export
  2. Modular Routes: Each route is its own Hono app in a separate file
  3. Better Organization: Routes are at top level, making them easy to find
  4. Follows Val Town Conventions: Matches the pattern used by Val Town's own blog
  5. Easier to Extend: Adding new routes is as simple as creating a new file

Code Changes

Old index.tsx

/** @jsxImportSource https://esm.sh/react@18.2.0 */ import app from "./backend/index.tsx"; export default app;

New index.tsx

/** @jsxImportSource https://esm.sh/react@18.2.0 */ import { Hono } from "jsr:@hono/hono@4"; import homeRoutes from "./routes/home.tsx"; import viewerRoute from "./routes/viewer.tsx"; import dockingViewerRoute from "./routes/docking-viewer.tsx"; import mesoscaleExplorerRoute from "./routes/mesoscale-explorer.tsx"; import mvsStoriesRoute from "./routes/mvs-stories.tsx"; const app = new Hono(); app.onError((err, c) => { throw err; }); app.route("/", homeRoutes); app.route("/", viewerRoute); app.route("/", dockingViewerRoute); app.route("/", mesoscaleExplorerRoute); app.route("/", mvsStoriesRoute); export default app.fetch;

Old backend/index.tsx (All Routes)

const app = new Hono(); app.get("/", (c) => { return c.html(`<html>...</html>`); }); app.get("/viewer", async (c) => { const html = renderToString(<ViewerApp />); return c.html(html); }); app.get("/docking-viewer", (c) => { const html = renderToString(<DockingViewerApp />); return c.html(html); }); // ... all routes in one file

New Route Pattern (routes/viewer.tsx)

/** @jsxImportSource https://esm.sh/react@18.2.0 */ import { Hono } from "jsr:@hono/hono@4"; import { renderToString } from "https://esm.sh/react-dom@18.2.0/server?deps=react@18.2.0,react-dom@18.2.0"; import { readFile } from "https://esm.town/v/std/utils@85-main/index.ts"; import ViewerApp from "../frontend/apps/viewer.tsx"; const app = new Hono(); app.get("/viewer", async (c) => { const molstarCss = await readFile( "/frontend/styles/molstar.css", import.meta.url, ); const html = renderToString(<ViewerApp molstarCss={molstarCss} />); return c.html(html); }); export default app;

Route Responsibilities

Each route file:

  1. Creates its own Hono app instance
  2. Defines one or more related routes
  3. Imports necessary frontend components
  4. Handles server-side rendering
  5. Exports the app as default

The main index.tsx:

  1. Creates the top-level Hono app
  2. Imports all route modules
  3. Mounts routes using app.route()
  4. Sets up global error handling
  5. Exports app.fetch for Val Town

Migration Checklist

  • Create routes/ directory
  • Move home route to routes/home.tsx
  • Create routes/viewer.tsx
  • Create routes/docking-viewer.tsx
  • Create routes/mesoscale-explorer.tsx
  • Create routes/mvs-stories.tsx
  • Update index.tsx to be main app
  • Import and mount all routes in index.tsx
  • Create utils/ directory for future utilities
  • Update README.md with new structure
  • Remove backend/ directory (kept for reference)

Files That Can Be Removed

Once you're confident the migration is complete:

  • backend/index.tsx - Logic moved to routes
  • backend/routes/ - Empty directory
  • backend/README.md - Outdated documentation

Testing Checklist

  • Test home page at /
  • Test viewer at /viewer
  • Test docking-viewer at /docking-viewer
  • Test mesoscale-explorer at /mesoscale-explorer
  • Test mvs-stories at /mvs-stories
  • Verify Molstar initialization works
  • Check that CSS loads properly
  • Verify error handling shows full stack traces

Next Steps

  1. Test in Val Town: Deploy and verify all routes work
  2. Add More Features: Now easier to extend with new routes
  3. Create Utilities: Add shared functions to utils/ as needed
  4. Clean Up: Remove old backend/ folder once confirmed working
  5. Document Patterns: Add examples to AGENTS.md if needed

References

  • Val Town Blog Structure - Inspiration
  • Hono Routing Documentation
  • Val Town Utils - readFile, serveFile, etc.
FeaturesVersion controlCode intelligenceCLI
Use cases
TeamsAI agentsSlackGTM
DocsShowcaseTemplatesNewestTrendingAPI examplesNPM packages
PricingNewsletterBlogAboutCareers
We’re hiring!
Brandhi@val.townStatus
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Open Source Pledge
Terms of usePrivacy policyAbuse contact
Β© 2025 Val Town, Inc.