DEV Community

Alex Spinov
Alex Spinov

Posted on

Remix Has a Free API — Here's How to Build Full-Stack Web Apps with Nested Routes

Remix is a full-stack web framework focused on web standards. It uses nested routes, server-side rendering, and progressive enhancement to build fast, resilient web applications.

Getting Started

npx create-remix@latest my-app
cd my-app
npm run dev
Enter fullscreen mode Exit fullscreen mode

Route-Based Data Loading

// app/routes/posts._index.tsx
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";

export async function loader() {
  const posts = await db.post.findMany({ orderBy: { createdAt: "desc" } });
  return json({ posts });
}

export default function Posts() {
  const { posts } = useLoaderData<typeof loader>();
  return (
    <ul>
      {posts.map(post => (
        <li key={post.id}>
          <a href={`/posts/${post.slug}`}>{post.title}</a>
        </li>
      ))}
    </ul>
  );
}
Enter fullscreen mode Exit fullscreen mode

Actions — Handle Form Submissions

// app/routes/posts.new.tsx
import { redirect } from "@remix-run/node";
import { Form } from "@remix-run/react";

export async function action({ request }) {
  const formData = await request.formData();
  const title = formData.get("title");
  const content = formData.get("content");

  const post = await db.post.create({ data: { title, content } });
  return redirect(`/posts/${post.slug}`);
}

export default function NewPost() {
  return (
    <Form method="post">
      <input name="title" placeholder="Title" required />
      <textarea name="content" placeholder="Content" required />
      <button type="submit">Create Post</button>
    </Form>
  );
}
Enter fullscreen mode Exit fullscreen mode

Nested Routes with Layout

app/routes/
  posts._index.tsx    → /posts
  posts.$slug.tsx     → /posts/:slug
  posts.new.tsx       → /posts/new
  posts.tsx           → Layout for all /posts/* routes
Enter fullscreen mode Exit fullscreen mode
// app/routes/posts.tsx (layout)
import { Outlet } from "@remix-run/react";

export default function PostsLayout() {
  return (
    <div className="posts-layout">
      <nav>Posts Navigation</nav>
      <main><Outlet /></main>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Error Boundaries

export function ErrorBoundary() {
  const error = useRouteError();
  if (isRouteErrorResponse(error)) {
    return <div>{error.status}: {error.statusText}</div>;
  }
  return <div>Something went wrong</div>;
}
Enter fullscreen mode Exit fullscreen mode

Need to extract or automate web content at scale? Check out my web scraping tools on Apify — no coding required. Or email me at spinov001@gmail.com for custom solutions.

Top comments (0)