### Seed the Database with npm Source: https://dirstarter.com/docs/first-steps Run this command to populate your directory with default seed data. This is the quickest way to get started and see Dirstarter in action. ```bash npm run db:seed ``` -------------------------------- ### Start Development Server with npm Source: https://dirstarter.com/docs/first-steps Execute this command to start the development server. Navigate to http://localhost:3000/admin to access the admin panel. ```bash npm run dev ``` -------------------------------- ### Install Project Dependencies Source: https://dirstarter.com/docs/getting-started Install all necessary project dependencies using npm. Ensure you have Node.js and npm installed. ```bash npm install ``` -------------------------------- ### Install Stripe CLI Source: https://dirstarter.com/docs/integrations/payments Install the Stripe Command Line Interface using Homebrew. ```bash brew install stripe/stripe-cli/stripe ``` -------------------------------- ### Copy Environment Example File Source: https://dirstarter.com/docs/getting-started Copy the `.env.example` file to `.env` to create your project's environment configuration file. ```bash cp .env.example .env ``` -------------------------------- ### Local Postgres Installation Connection String Source: https://dirstarter.com/docs/database/hosting Connection string for a locally installed Postgres database. Replace 'yourpassword' with your actual password and 'dirstarter' if you created a different database name. ```plaintext DATABASE_URL="postgres://postgres:yourpassword@localhost:5432/dirstarter" ``` -------------------------------- ### Product Configuration Example: Free Listing Source: https://dirstarter.com/docs/integrations/payments Configuration for a free listing product in Stripe. This is a one-time product with no charge. ```json { name: "Free Listing", description: "Free listing with wait time", amount: 0, currency: "usd", type: "one_time", features: [ "• {queue} processing time", // will be replaced with the actual wait time "✗ No content updates", "✗ No-follow link to your website", "✗ No featured spot", "✗ No prominent placement", ] } ``` -------------------------------- ### Run Stripe Product Setup Script Source: https://dirstarter.com/docs/integrations/payments Use this command to run the provided script for setting up Stripe products and prices. Ensure your Stripe secret key is set in the environment variables. ```bash bun run scripts/setup-stripe-products.ts ``` -------------------------------- ### Example Translation File Structure Source: https://dirstarter.com/docs/i18n Translation files are organized in `messages/{locale}/` directories, with each JSON file representing a namespace. This example shows translations for the 'pages' namespace. ```json { "about": { "title": "About Us", "description": "{siteName} is a community driven list of tools." }, "advertise": { "title": "Advertise", "description": "Promote your business on {siteName}." } } ``` -------------------------------- ### Fetch and Upload Media Source: https://dirstarter.com/docs/integrations/media Usage example for fetching a screenshot and uploading it to S3. The actual implementation of `fetchAndUploadMedia` is in `lib/media.ts`. ```typescript import { fetchAndUploadMedia } from "~/lib/media" const screenshotUrl = await fetchAndUploadMedia( "https://example.com", "tools/my-tool/screenshot", "screenshot", ) ``` -------------------------------- ### Query Data with Prisma Client Source: https://dirstarter.com/docs/database/prisma Example of fetching 'Published' tools with their associated categories and tags using the Prisma Client. ```typescript import { db } from "~/services/db" // Example query const tools = await db.tool.findMany({ where: { status: "Published" }, include: { categories: true, tags: true }, }) ``` -------------------------------- ### Seed Database from CSV Source: https://dirstarter.com/docs/database/prisma Example of reading data from a CSV file and seeding the database using Prisma Client. ```typescript import { parse } from "csv-parse/sync" import { readFileSync } from "fs" async function main() { const csvContent = readFileSync("./data/tools.csv", "utf-8") const records = parse(csvContent, { columns: true, skip_empty_lines: true, }) for (const record of records) { await prisma.tool.create({ data: { name: record.name, slug: record.slug, // ... map other fields from your CSV }, }) } } ``` -------------------------------- ### Product Configuration Example: Standard Listing Source: https://dirstarter.com/docs/integrations/payments Configuration for a standard one-time payment listing product in Stripe. Includes faster processing and content updates. ```json { name: "Standard Listing", description: "Do-follow link with faster processing", amount: 97, // set your own price currency: "usd", type: "one_time", features: [ "✓ 24h processing time", "✓ Unlimited content updates", "✓ Do-follow link to your website", "✗ No featured spot", "✗ No prominent placement", ] } ``` -------------------------------- ### Fetch and Rebase Dirstarter Updates with Git Source: https://dirstarter.com/docs/codebase/updates This rebase approach provides a cleaner, linear history but requires more Git experience to resolve conflicts. Ensure your Git repository is clean before starting. ```bash git remote add upstream https://github.com/dirstarter/dirstarter.git git pull upstream main --rebase ``` -------------------------------- ### Preview Email Templates Locally Source: https://dirstarter.com/docs/integrations/email Run this command to preview your email templates locally. Ensure you have the necessary package manager installed. ```bash npm run email ``` -------------------------------- ### Fetch and Merge Dirstarter Updates with Git Source: https://dirstarter.com/docs/codebase/updates Use this merge approach for a safer update process with clear merge points. Ensure your Git repository is clean before starting. ```bash git remote add upstream https://github.com/dirstarter/dirstarter.git git fetch upstream git checkout -b update-dirstarter git merge upstream/main ``` -------------------------------- ### Product Configuration Example: Premium Listing Source: https://dirstarter.com/docs/integrations/payments Configuration for a premium recurring subscription listing product in Stripe. Offers featured placement and faster processing. ```json { name: "Premium Listing", description: "Featured placement with do-follow link", amount: 197, // set your own price currency: "usd", type: "recurring", interval: "month", features: [ "✓ 12h processing time", "✓ Unlimited content updates", "✓ Do-follow link to your website", "✓ Featured spot on homepage", "✓ Prominent placement" ] } ``` -------------------------------- ### Update Project Dependencies with Bun Source: https://dirstarter.com/docs/codebase/updates Use these commands to manage project dependencies. 'bun update' updates all, 'bun update ' updates a specific one, and 'bun install @' installs a specific version. ```bash bun update ``` ```bash bun update next ``` ```bash bun install next@15.2.0 ``` -------------------------------- ### Fetch and Upload Favicon Source: https://dirstarter.com/docs/integrations/media Usage example for fetching a favicon and uploading it to S3. The `fetchAndUploadMedia` function handles the download and upload process. ```typescript import { fetchAndUploadMedia } from "~/lib/media" const faviconUrl = await fetchAndUploadMedia( "https://example.com", "tools/my-tool/favicon", "favicon", ) ``` -------------------------------- ### Define Prisma Model Source: https://dirstarter.com/docs/database/prisma Example of adding a new 'Post' model to your prisma/schema.prisma file, including fields and relationships. ```prisma model Post { id String @id @default(cuid()) title String content String author User @relation(fields: [authorId], references: [id]) authorId String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } ``` -------------------------------- ### Generate Prisma Client Source: https://dirstarter.com/docs/database/prisma Regenerate the Prisma client after pushing schema changes. This often happens automatically when starting the dev server. ```bash npm run db:generate ``` -------------------------------- ### Protect Server Action with Middleware Source: https://dirstarter.com/docs/authentication Chain middleware like withAuthRateLimit with input validation and a handler to create a protected server action. This example shows how to define input schema and handle the submission. ```typescript import { withAuthRateLimit } from "~/lib/orpc" const submit = withAuthRateLimit("submission") .input( z.object({ name: z.string().min(1), websiteUrl: z.url().min(1), submitterNote: z.string().max(256), newsletterOptIn: z.boolean().optional().default(true), }), ) .handler(async ({ input, context: { user, db } }) => { // Creates a new tool submission in the database // ... }) ``` -------------------------------- ### Check and Apply Major Dependency Updates with Bun Source: https://dirstarter.com/docs/codebase/updates Before applying major dependency updates, check for compatibility using 'bunx npm-check-updates'. Use '-u' with caution to apply updates, followed by 'bun install'. ```bash bunx npm-check-updates ``` ```bash bunx npm-check-updates -u bun install ``` -------------------------------- ### Custom Button with Tailwind Classes Source: https://dirstarter.com/docs/theming Example of creating a custom button component that extends base button variants with additional custom styles and accepts a `className` prop for further customization. ```javascript const CustomButton = ({ className, ...props }) => ( ) } ``` -------------------------------- ### Define Rate Limit Actions Source: https://dirstarter.com/docs/integrations/rate-limiting Centralize rate limit configurations in `config/rate-limit.ts`. Define actions with points and duration for different use cases. ```typescript export const rateLimitConfig = { actions: { // 3 submissions per 24 hours submission: { points: 3, duration: 24 * 60 * 60 }, // 3 newsletter signups per 24 hours newsletter: { points: 3, duration: 24 * 60 * 60 }, // 3 reports per hour report: { points: 3, duration: 60 * 60 }, // 5 claim attempts per hour claim: { points: 5, duration: 60 * 60 }, // 20 media uploads per hour media: { points: 20, duration: 60 * 60 }, }, } ``` -------------------------------- ### Replace Git Remote Origin Source: https://dirstarter.com/docs/getting-started After cloning, replace the default remote origin with your own GitHub repository URL to push your changes. ```bash git remote set-url origin https://github.com/your-username/your-repo.git ``` -------------------------------- ### Prisma Schema for Blog Posts Source: https://dirstarter.com/docs/blog Defines the database schema for blog posts, including fields like title, slug, content, status, and author relationships. It also includes an enum for post status. ```prisma model Post { id String @id @default(cuid(2)) title String @db.Citext slug String @unique description String? content String plainText String @default("") imageUrl String? status PostStatus @default(Draft) publishedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt author User @relation(fields: [authorId], references: [id]) authorId String } enum PostStatus { Draft Scheduled Published } ``` -------------------------------- ### Base Metadata Configuration (TypeScript) Source: https://dirstarter.com/docs/seo Defines the base metadata for the entire website, including OpenGraph and Twitter card settings. This file is located at config/metadata.ts. ```typescript import type { Metadata } from "next" import { linksConfig } from "~/config/links" import { siteConfig } from "~/config/site" import { getOpenGraphImageUrl } from "~/lib/opengraph" export const metadataConfig: Metadata = { openGraph: { url: "/", siteName: siteConfig.name, locale: "en_US", type: "website", images: { url: getOpenGraphImageUrl({}), width: 1200, height: 630, }, }, twitter: { site: "@dirstarter", creator: "@piotrkulpinski", card: "summary_large_image", }, alternates: { canonical: "/", types: { "application/rss+xml": linksConfig.feeds }, }, } ``` -------------------------------- ### Client-Side Session Management Source: https://dirstarter.com/docs/authentication Use the useSession hook from auth-client to manage user authentication state on the client. This allows for conditional rendering of sign-in/sign-out buttons. ```typescript "use client" import { useSession, signIn, signOut } from "~/lib/auth-client" export function AuthButton() { const { data: session, isPending } = useSession() if (isPending) { return
Loading...
} if (session) { return } return ``` -------------------------------- ### Format Dates and Times with next-intl Source: https://dirstarter.com/docs/i18n Use the `useFormatter` hook from `next-intl` in client components for localized date and time formatting. It provides methods like `dateTime` and `relativeTime`. ```typescript import { useFormatter } from "next-intl" export function DateDisplay({ date }: { date: Date }) { const format = useFormatter() return (

{format.dateTime(date, { dateStyle: "long" })}

{format.relativeTime(date)}

) } ``` -------------------------------- ### Add New Translation File (Namespace) Source: https://dirstarter.com/docs/i18n To add a new namespace, create a new JSON file in `messages/{locale}/`. Remember to add a static import for this file in `lib/i18n.ts` and include it in the `messages` object. ```json { "greeting": "Hello", "farewell": "Goodbye" } ``` -------------------------------- ### Load Geist Font with CSS Variable Source: https://dirstarter.com/docs/theming Load the Geist font and assign it to the `--font-sans` CSS variable. This configuration is typically done in a font utility file and applied automatically by Next.js. ```typescript export const fontSans = Geist({ variable: "--font-sans", display: "swap", subsets: ["latin"], weight: "variable", }) ```