GuidesPage Types

Static Page

ShipFast comes with many components to help you build SEO-optimized pages (like a landing page) in no time.

  • The /components folder contains all you need (hero, pricing, FAQ sections). Checkout each component docs.
  • The /libs/seo.tsx file helps you set SEO tags to better rank on Google. Make sure to customize SEO tags.

A simple landing page can done like this in the pages.tsx file:

/app/page.tsx

1import { getSEOTags } from "@/libs/seo";
2
3export const metadata = getSEOTags({ canonicalUrlRelative: "/" });
4
5export default function Landing() {
6  return (
7    <>
8      <main className="min-h-screen p-12 pb-24 text-center" data-theme="dark">
9        <section className="max-w-xl mx-auto space-y-8">
10          <h1 className="text-3xl md:text-4xl font-extrabold">
11            Food recipes you&apos;ll love 🥦
12          </h1>
13
14          <p className="text-lg leading-relaxed text-base-content/80">
15            Our AI will generate recipes based on your preferences. New recipes
16            will be added every week!
17          </p>
18
19          <img
20            src="https://images.unsplash.com/photo-1518843875459-f738682238a6?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=3484&q=80"
21            alt="Vegetables"
22            width={500}
23            height={250}
24            className="rounded-lg mx-auto"
25          />
26
27          <button className="btn btn-primary btn-wide">Get started</button>
28        </section>
29      </main>
30    </>
31  );
32}

Private Page

Once user is authenticated, you can build private routes like a user dashboard, account, etc.

If you want to make protected API calls, follow this tutorial.

The layout.tsx in /dashboard ensures any pages & subpages are private. If the user is not authenticated, he'll be redirected to the login page (see auth in config.ts).

NextAuth & Mongo

Here's an example of a simple user dashboard showing private user data in a server component:

/app/dashboard/page.tsx

1import { getServerSession } from "next-auth";
2import { authOptions } from "@/libs/next-auth";
3import connectMongo from "@/libs/mongoose";
4import User from "@/models/User";
5
6export default async function Dashboard() {
7  await connectMongo();
8  const session = await getServerSession(authOptions);
9  const user = await User.findById(session.user.id);
10
11  return (
12    <>
13      <main className="min-h-screen p-8 pb-24">
14        <section className="max-w-xl mx-auto space-y-8">
15          <h1 className="text-3xl md:text-4xl font-extrabold">
16            User Dashboard
17          </h1>
18          <p>Welcome {user.name} 👋</p>
19          <p>Your email is {user.email}</p>
20        </section>
21      </main>
22    </>
23  );
24}

Supabase

Here's an example of a simple user dashboard showing private user data in a server component:

/app/dashboard/page.tsx

1import { cookies } from "next/headers";
2import { createServerComponentClient } from "@supabase/auth-helpers-nextjs";
3
4export const dynamic = "force-dynamic";
5
6// This is a private page: It's protected by the layout.tsx component which ensures the user is authenticated.
7// It's a server compoment which means you can fetch data (like the user profile) before the page is rendered.
8export default async function Dashboard() {
9  const supabase = createServerComponentClient({ cookies });
10  const { data } = await supabase.from("todos").select();
11
12  return (
13    <main className="min-h-screen p-8 pb-24">
14      <section className="max-w-xl mx-auto space-y-8">
15        <h1 className="text-3xl md:text-4xl font-extrabold">Private Page</h1>
16
17        {/* You will only see something if you create an SQL table called todos with at least 1 row */}
18        <pre>{JSON.stringify(data, null, 2)}</pre>
19      </section>
20    </main>
21  );
22}