{"id":16862,"library":"naystack","title":"Naystack: Next.js Full-Stack Toolkit","description":"Naystack is a full-stack utility library for Next.js applications, currently at version 1.7.26. It provides pre-built solutions for common web development challenges, including robust email-based authentication (with optional Google/Instagram OAuth), GraphQL API scaffolding, and file upload functionalities. The library is designed to be modular, allowing developers to integrate specific features as needed, and follows a 'bring-your-own database' philosophy, demonstrating integration with ORMs like Drizzle ORM in its examples. Naystack is actively maintained and focuses on providing a cohesive, opinionated yet flexible framework for server-side API routes and client-side React components within the Next.js ecosystem. Its key differentiator is providing integrated, end-to-end solutions for authentication, GraphQL, and file management without dictating the database layer.","status":"active","version":"1.7.26","language":"javascript","source_language":"en","source_url":"https://github.com/abhinaypandey02/naystack","tags":["javascript","typescript","graphql","nextjs","drizzle-orm","nextjs-api","typescript-library","backend","fullstack"],"install":[{"cmd":"npm install naystack","lang":"bash","label":"npm"},{"cmd":"yarn add naystack","lang":"bash","label":"yarn"},{"cmd":"pnpm add naystack","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Required peer dependency for Next.js application development.","package":"next","optional":false},{"reason":"Required peer dependency for client-side React components and hooks.","package":"react","optional":false},{"reason":"Required peer dependency for rendering React components.","package":"react-dom","optional":false}],"imports":[{"note":"Used for defining server-side authentication API routes within Next.js App Router. This module is ESM-only.","wrong":"const { setupEmailAuth } = require('naystack/auth');","symbol":"setupEmailAuth","correct":"import { setupEmailAuth } from 'naystack/auth';"},{"note":"A client-side React component to wrap your application, providing authentication context to hooks. Requires specific subpath import.","wrong":"import { AuthWrapper } from 'naystack/auth';","symbol":"AuthWrapper","correct":"import { AuthWrapper } from 'naystack/auth/client';"},{"note":"A client-side React hook to access the current JWT access token. Must be used within an `AuthWrapper`.","wrong":"import { useToken } from 'naystack/auth';","symbol":"useToken","correct":"import { useToken } from 'naystack/auth/client';"},{"note":"A client-side React hook to trigger the user sign-up process. Must be used within an `AuthWrapper`.","symbol":"useSignUp","correct":"import { useSignUp } from 'naystack/auth/client';"},{"note":"A client-side React component to wrap your application for GraphQL client setup. Requires specific subpath import.","symbol":"ApolloWrapper","correct":"import { ApolloWrapper } from 'naystack/graphql/client';"}],"quickstart":{"code":"import { setupEmailAuth } from 'naystack/auth';\nimport { AuthWrapper, useToken } from 'naystack/auth/client';\nimport { ApolloWrapper } from 'naystack/graphql/client';\nimport React from 'react';\n\n// --- Simulate a Drizzle ORM setup for the server-side --- \n// In a real app, this would be your database connection and schema\nconst db = { \n  select: () => ({ from: () => ({ where: () => ([{ id: 'user-id-123', password: 'hashed-password' }]) }) }),\n  insert: () => ({ values: () => ({ returning: () => ([{ id: 'new-user-id', password: 'new-hashed-password' }]) }) })\n};\nconst UserTable = { id: 'id', email: 'email', password: 'password' };\nconst eq = (a: any, b: any) => ({}); // Dummy eq function\n\n// --- Server-side (app/api/(auth)/email/route.ts) ---\n// Ensure process.env.SIGNING_KEY and process.env.REFRESH_KEY are set\nexport const { GET, POST, PUT, DELETE } = setupEmailAuth({\n  getUser: async ({ email }) => {\n    // Replace with your actual database query\n    const [user] = await db.select({ id: UserTable.id, password: UserTable.password }).from(UserTable).where(eq(UserTable.email, email));\n    return user;\n  },\n  createUser: async (data) => {\n    // Replace with your actual database insertion\n    const [user] = await db.insert(UserTable).values(data).returning({ id: UserTable.id, password: UserTable.password });\n    return user;\n  },\n  onSignUp: async (userId, body) => {\n    console.log(`User ${userId} signed up.`);\n  }\n});\n\n// --- Client-side (app/layout.tsx) ---\nexport default function RootLayout({ children }: { children: React.ReactNode }) {\n  return (\n    <html lang=\"en\">\n      <body>\n        <AuthWrapper>\n          <ApolloWrapper>\n            {children}\n          </ApolloWrapper>\n        </AuthWrapper>\n      </body>\n    </html>\n  );\n}\n\n// --- Client-side (app/page.tsx or any client component) ---\n'use client';\n\nfunction DashboardButton() {\n  const token = useToken();\n\n  return (\n    <div>\n      {token ? (\n        <button>Go to Dashboard (Logged In)</button>\n      ) : (\n        <button>Sign Up / Login (Logged Out)</button>\n      )}\n      <p>Current Token: {token ? 'Present' : 'Not Present'}</p>\n    </div>\n  );\n}\n\n// To make the client component render within the quickstart context\nexport { DashboardButton };","lang":"typescript","description":"This quickstart demonstrates the core Naystack setup for authentication, combining server-side route handlers with client-side context providers and hooks. It simulates a basic Drizzle ORM integration for the server logic and shows how to wrap a Next.js application with `AuthWrapper` and `ApolloWrapper`, then conditionally render UI based on authentication state using `useToken()`."},"warnings":[{"fix":"Ensure `SIGNING_KEY` and `REFRESH_KEY` are securely defined in your `.env.local` file or deployment environment variables. These should be strong, randomly generated strings.","message":"Authentication functionality heavily relies on two critical environment variables: `SIGNING_KEY` and `REFRESH_KEY`. Failure to set these will lead to runtime errors and authentication failures.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Place `<AuthWrapper>` around the children in your main `app/layout.tsx` file to ensure all client components have access to the authentication context.","message":"Client-side authentication hooks like `useToken()`, `useSignUp()`, and `useLogin()` require your application's root component (e.g., `app/layout.tsx`) to be wrapped with `AuthWrapper` to provide the necessary React context. Using these hooks outside of the `AuthWrapper` will result in runtime errors.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Follow the App Router conventions for API routes, creating files like `app/api/(auth)/email/route.ts` for authentication endpoints.","message":"Naystack is built for the Next.js App Router. Its server-side API handlers (`setupEmailAuth`) are designed to be exported directly from `route.ts` files within the `app/api` directory structure. Using it with the Pages Router or an incorrect App Router structure may not work as expected.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Verify your `package.json` for `next`, `react`, and `react-dom` and update them to match the compatible peer dependency ranges using your package manager (e.g., `npm install next@latest react@latest react-dom@latest`).","message":"Naystack lists `next`, `react`, and `react-dom` as peer dependencies. Ensure your project's installed versions of these packages are compatible with Naystack's specified ranges (`next: >=13`, `react: ^18 || ^19`, `react-dom: ^18 || ^19`). Incompatible versions can lead to unexpected behavior or build issues.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Define `SIGNING_KEY` and `REFRESH_KEY` in your `.env.local` file for local development, or in your deployment environment variables for production. Example: `SIGNING_KEY=\"super-secret-signing-key\"`.","cause":"The required environment variables for JWT signing and refreshing are missing or undefined.","error":"Error: SIGNING_KEY and REFRESH_KEY must be set in environment variables."},{"fix":"Ensure that the `AuthWrapper` component is placed high enough in your React component tree, typically in `app/layout.tsx`, to encompass all components that utilize Naystack's authentication hooks.","cause":"A client-side authentication hook (e.g., `useToken`, `useSignUp`) was called outside the React context provided by `AuthWrapper`.","error":"Error: You must wrap your application with AuthWrapper to use auth hooks."},{"fix":"First, ensure `naystack` is installed (`pnpm add naystack`). Then, verify the import paths. Client-side modules typically require `/client` or `/graphql/client` subpaths, e.g., `import { AuthWrapper } from 'naystack/auth/client';`.","cause":"The `naystack` package is not installed, or the import path for a specific module is incorrect (e.g., missing `/client` subpath for client-side components).","error":"Module not found: Can't resolve 'naystack/auth' in '...' OR Module not found: Can't resolve 'naystack/auth/client'"},{"fix":"Verify that your `db` connection and `UserTable` (or equivalent) schema are correctly initialized and imported into your `route.ts` file, and that the `getUser` and `createUser` functions access them properly.","cause":"The `db` object or `UserTable` schema passed to `setupEmailAuth` is not correctly configured or is undefined, likely due to a database setup issue.","error":"TypeError: Cannot read properties of undefined (reading 'select') at setupEmailAuth"}],"ecosystem":"npm","meta_description":null}