Shipped
HomeContacts
  • Get started
  • 📚Tutorials
    • Make a waiting list
    • Launch a pre-sale
    • Build a SaaS
    • Create your store on Lemon Squeezy
  • 🟩Features
    • AI Services
    • Affiliate Program
    • Analytics
    • Authentication
      • MailChimp
      • Loops
      • AWS SES
      • SendGrid
      • Supabase Auth
        • Supabase Authentication Flow
        • Supabase Magic Link
        • Supabase Email & Password
        • Supabase Login with Google
    • API endpoints
      • 🛡️Authenticated API
    • Blog
    • Customer support
    • Chrome Extension
    • Dark mode
    • Database
      • Update your database
      • MongoDB
    • Emails
    • Error pages
    • Icons
    • Onboarding
    • Payments
      • Lemon Squeezy
        • Subscriptions
        • One-time purchase
        • Test mode
      • Stripe
    • Private pages
    • SEO
    • shadcn/ui
    • Supabase
    • Workspace / Organizations
  • 📦Components
    • AccountMenu
    • CtaBox
    • DarkModeSwitch
    • Explainer video
    • FAQ
    • Features
    • Footer
    • Header
    • Hero
    • Lifetime
    • Pricing
    • Sales Notification
    • Secondary Sidebar Pages
    • Sidebar
    • Tabs
    • Testimonials
    • Waitlist
    • WebAppPage
  • 🚀Deployment
  • ✅Other
    • Configuration
    • Changelog widget
    • Favicon
    • Google Fonts
    • Sitemap
    • Theme
  • Updates
  • GitHub Repository
  • Support
Powered by GitBook
On this page
  • Authenticated pages
  • Authenticated API endpoints
  • How to add a new private page

Was this helpful?

  1. Features

Private pages

If you need to authenticate your users, you probably need to give them access to a private section of the website.

Shipped provides patterns to handle private pages.

Authenticated pages

These are pages accessible only if a user is logged in.

Use the NextAuth hook useSession you retrieve the current user session, and if they are logged in or not.

src/app/dashboard/page.tsx
"use client";

import { Button, Center, Spinner, Stack, Text } from "@chakra-ui/react";
import { useSession } from "next-auth/react";

const Dashboard = () => {
  const { data: session, status } = useSession();

  return (
    <Center minH="100vh">
      {status === "loading" && <Spinner color="brand.500" />}
      {status === "authenticated" && (
        <p>You are logged in as {session?.user?.email}</p>
      )}
      {status === "unauthenticated" && (
        <Stack>
          <Text>Sign in to access</Text>
          <Button as="a" href="/login" colorScheme="brand">
            Sign in
          </Button>
        </Stack>
      )}
    </Center>
  );
};

export default Dashboard;

Authenticated API endpoints

These are API endpoints that are protected and only logged in users can call them and get a correct response.

src/app/api/user/route.ts
import { NextRequest, NextResponse } from "next/server";
import { getServerSession } from "next-auth/next";
import { authOptions } from "../auth/[...nextauth]/route";
import { HttpStatusCode } from "axios";
import { prismaClient } from "@/prisma/db";

export async function POST(req: NextRequest) {
  const session = await getServerSession(authOptions);

  if (!session || !session?.user?.email) {
    return NextResponse.json(
      { error: "Unauthorized" },
      { status: HttpStatusCode.Unauthorized } // 401
    );
  }

  if (session && session?.user?.email) {
    const user = await prismaClient.user.findFirst({
      where: {
        email: session?.user?.email,
      },
    });

    if (!user) {
      return NextResponse.json(
        { error: "Unauthorized" },
        { status: HttpStatusCode.Unauthorized } // 401
      );
    }

    if (user) {
      return NextResponse.json({ user }, { status: HttpStatusCode.Ok }); // 200
    }
  }
}

How to add a new private page

As an example, let's say we want to add a new section to our SaaS, at /todo to show a simple todo app.

Add the new route to the file src/data/routes.ts

src/data/routes.ts
export enum Routes {
  /* ... */
  todo = "/todo",
}

Create a new folder in src/app and call it todo.

Create a new file, called page.tsx inside the todo folder.

In the page.tsx, add a code similar to this

src/app/todo/page.tsx
import { WebAppPage } from "@/components/templates/WebAppPage/WebAppPage";
import { Routes } from "@/data/routes";

const TodoPage = () => {
  return <WebAppPage currentPage={Routes.todo} />;
};

export default TodoPage;

Open the component <WebAppPage /> at src/components/templates/WebAppPage/WebAppPage.tsx and scroll down.

Render your new page, when the current page is Routes.todo

<Flex>
  {currentPage === Routes.dashboard && (
    <Center w="100%" flexDir="column">
      <Dashboard />
    </Center>
  )}
  
  {currentPage === Routes.todo && (
    <Center w="100%" flexDir="column">
      <Todo />
    </Center>
  )}
  
  {/* Add the route components here */}
</Flex>

To add the new menu item to the sidebar, open src/components/organisms/Sidebar/SidebarMenuItems.tsx scroll to the MenuItem, and add a new element:

src/components/organisms/Sidebar/SidebarMenuItems.tsx
<MenuItem
    route={Routes.todo}
    currentPage={currentPage}
    onClick={onMenuItemClick}
    loadingRoute={loadingRoute}
    >
    <TbChecklist size="16px" /> &nbsp;<MenuLabel>Todo</MenuLabel>
</MenuItem>

Your menu item will now appear in the sidebar:

PreviousStripeNextSEO

Last updated 7 months ago

Was this helpful?

🟩
How to add a new page
Todo page in the sidebar