Juniper is a web framework for building React applications with Deno. It combines Hono for server-side routing with React Router for client-side navigation, providing a seamless full-stack development experience.
- File-Based Routing - Create routes by adding files to your
routesdirectory. The file structure directly maps to your URL structure. - Server-Side Rendering - React components render on the server for fast initial page loads and SEO benefits.
- Data Loading and Actions - Fetch data with loaders and handle form submissions with actions, on either server or client.
- Hot Reload - See changes instantly during development.
- TypeScript First - Full TypeScript support with type-safe route parameters, loader data, and action data.
- React 19 Support - Built for React 19, including native document metadata support.
- Hono Middleware - Use Hono's extensive middleware ecosystem for authentication, logging, CORS, and more.
- Error Boundaries - Graceful error handling with route-level and root error boundaries.
- Code Splitting - Automatic code splitting for routes, loading only the code needed for each page.
Use degit to clone a template and get started:
# Minimal template
deno run -A npm:degit udibo/juniper/templates/minimal my-app
cd my-app
deno install
deno task devOr with TailwindCSS:
deno run -A npm:degit udibo/juniper/templates/tailwindcss my-app
cd my-app
deno install
deno task devOpen your browser to http://localhost:8000 to see your application.
// routes/index.tsx
export default function Home() {
return (
<>
<title>Home</title>
<h1>Welcome to Juniper</h1>
</>
);
}// routes/blog/[id].ts
import { HttpError } from "@udibo/juniper";
import type { RouteLoaderArgs } from "@udibo/juniper";
export async function loader({ params }: RouteLoaderArgs<{ id: string }>) {
const post = await getPost(params.id);
if (!post) {
throw new HttpError(404, "Post not found");
}
return { post };
}// routes/blog/[id]/index.tsx
import type { RouteProps } from "@udibo/juniper";
export default function BlogPost({ loaderData }: RouteProps) {
return (
<>
<title>{loaderData.post.title}</title>
<article>
<h1>{loaderData.post.title}</h1>
<p>{loaderData.post.content}</p>
</article>
</>
);
}Comprehensive guides for using the framework:
- Introduction - Overview and key concepts
- Getting Started - Set up your first project
- Configuration - Project and build configuration
- Development Tools - Hot reload and debugging
- Routing - File-based routing and data loading
- Middleware - Server and client middleware
- Forms - Form handling with client and server actions
- State Management - Sharing data across your app
- Error Handling - Error boundaries and HttpError
- Styling - CSS and TailwindCSS integration
- Static Files - Serving static assets
- Metadata - Page titles and meta tags
- Database - Deno KV and other databases
- Testing - Testing utilities and patterns
- Logging - Logging and OpenTelemetry
- CI/CD - GitHub Actions workflows
- Deployment - Deploy to Deno Deploy, Docker, and more
- Tutorials - Step-by-step guides for building applications
The API documentation is available on JSR: @udibo/juniper
Contributions are welcome! Please read the contributing guide before submitting a pull request.
MIT License - see LICENSE for details.
