I wanted to ask if someone has tried to convert a nextJS application into a remix one?
I have setup specific rules for converting nextJS to remix application put the docs to remix in cursor but it just to complex task to proceed and burns all my premium credits in an instant.
I used sonnet 3.7 with thinking in agent mode trying to convert the project 1 component at a time. Refactored my nextJS application with v0 to use the private folder system which puts everything under routes/feature/_components _lib etc.
But still I wish i could just convert this nextJS project in 1 go fairly easy with cursor the hopes for that are now kinda gone spend hours on it burning 3 free trail account credits untill i had to upgrade to pro. Without pro you seem to be unable to even do slow requests I think some change recently>?
I understand the requests takes money but like this its getting really expensive and no good results.
Any way if anyone has any ideas on how how i Could convert NextJS to remix more properly i would love to hear.
These are my cursor rules:
Below is an enhanced version of your ruleset that incorporates additional examples and guidelines drawn directly from the Remix and Conform documentation. The new sections under “Remix” and “Conform” include code samples and best practices as described in the official docs.
---
## 1. Style and Structure
### 1.0 React Component Conventions
- **CamelCase:** Always use CamelCase for React component names.
_Example:_
```tsx
// Good:
export function UserProfile() { ... }
// Bad:
export function userprofile() { ... }
1.1 Naming Conventions & Directory Structure
- Directories: Use lowercase with dashes (e.g.,
components/auth-wizard
). - Variables: Use descriptive names with auxiliary verbs (e.g.,
isLoading
,hasError
). - Exports: Favor named exports for components and helper functions.
- File Organization: New files should follow this structure:
- Exported component
- Subcomponents
- Helpers
- Static content
- Types
- No Index Files: Do not create index files in the root of folders that re-export components.
Example:
Instead of:
Import directly:// components/auth-wizard/index.ts export { AuthWizard } from './AuthWizard';
import { AuthWizard } from 'components/auth-wizard/AuthWizard';
1.2 TypeScript Usage
- Language: All code must be written in TypeScript.
- Interfaces vs. Types: Prefer interfaces over types for data contracts.
- Enums: Avoid enums; use maps instead.
- Components: Use functional components with TypeScript interfaces.
Example (from Remix style):interface ButtonProps { onClick: () => void; label: string; } export const Button: React.FC<ButtonProps> = ({ onClick, label }) => ( <button onClick={onClick}>{label}</button> );
1.3 UI and Styling
- Styling Framework: Use Tailwind CSS.
- Component Imports:
- Import app-specific components from
<app_package_alias>@/components</app_package_alias>
.
- Import app-specific components from
- Form Library: When using the Conform form library, ensure components strictly adhere to its APIs and patterns.
Example (from Conform docs):import { useForm } from 'conform'; export function LoginForm() { const [formProps, { error }] = useForm({ initialValues: { email: '' }, onSubmit: async (values) => { // handle submission }, }); return ( <form {...formProps}> <input type="email" name="email" placeholder="Email" /> {error && <p className="text-red-500">{error}</p>} <button type="submit" className="btn-primary">Login</button> </form> ); }
1.4 Performance Optimization
- Data Structures: Favor immutable data structures.
- Fetching & Rendering: Optimize data fetching, network requests, and rendering.
- State Management: Use efficient state management strategies.
- General: Optimize new code for performance from the start.
2. Cursor Rules for Component Creation (React & Remix)
2.1 Component Design
- Purpose & Functionality: Clearly define the component’s purpose, design, and required behavior.
- Remix Specifics: For Remix pages/components, include loaders, actions, and error boundaries per Remix best practices.
Example (from Remix docs):import type { LoaderFunction } from '@remix-run/node'; import { json } from '@remix-run/node'; export const loader: LoaderFunction = async ({ params }) => { const user = await getUser(params.userId); return json({ user }); }; export function ErrorBoundary({ error }: { error: Error }) { console.error(error); return <div>Something went wrong!</div>; }
2.2 Component Existence Check
- Search Locations: Verify similar components in:
packages/ui/src/components
apps/spa/src/components
2.3 Prompt Generation for New Components
- Details to Include:
- Component name and purpose.
- Expected props and their types.
- Specific styling or behavior requirements (remember Tailwind CSS and TypeScript usage).
- Remix-specific behaviors (loaders, actions, meta functions) and Conform form commands.
- URL Encoding & Linking:
- URL-encode the detailed prompt.
- Generate a clickable link in this format:
[ComponentName](https://chat.example.com?q={encoded_prompt})
2.4 Project Adaptation
- Import Statements:
- Common components:
<ui_package_alias>@repo/ui/components/ui/</ui_package_alias>
. - App-specific components:
<app_package_alias>@/components</app_package_alias>
.
- Common components:
- Pattern Consistency: Follow existing component patterns.
- Additional Logic: Incorporate any custom logic, state management, or Remix-specific routing/data functions.
Example Prompt Template:
“Create a React component named {ComponentName} using TypeScript and Tailwind CSS. It should {description of functionality}. Props should include {list of props with types}. The component should {any specific styling or behavior notes}. For Remix usage, include proper loader/action functions where needed. For forms, use the Conform form library and its conventions. Please provide the full component code.”
3. Response Constraints
3.1 Code Preservation
- No Unnecessary Removal: Keep existing code unless removal is absolutely required.
- Maintain Comments: Preserve user comments and any commented-out code.
- Import Formatting: Only change import formatting if vital for new functionality.
3.2 Code Style & Structure
- Conciseness: Write concise, technical TypeScript code with accurate examples.
- Functional Patterns: Use functional and declarative programming patterns; avoid classes.
- Modularization: Prefer modular approaches over duplicative code.
- File Structure: Organize files as: exported components, subcomponents, helpers, static content, and types.
3.3 Remix & Conform Specifics
- Remix Pages/Routes: Include loader and action functions per Remix conventions.
- Forms: Integrate the Conform form library with proper validation and submission logic.
3.4 Verification and Consistency
- Verification: Always verify information before presenting.
- File-by-File Edits: Present edits file by file in a single chunk.
- Real File Links: Provide links to real files when referring to specific components.
- No Confirmation: Do not ask for confirmation on provided context details.
4. Additional Guidelines
- Verification: Confirm details before presenting.
- File-by-File Edits: Present changes per file for easier error spotting.
- No Apologies/Meta-Feedback: Avoid meta-feedback on understanding.
- No Formatting-Only Suggestions: Do not suggest changes that involve only whitespace or formatting.
- Single Chunk Edits: Provide all changes in one chunk per file.
- Security & Performance:
- Prioritize performance in every suggestion.
- Consider security implications in all modifications.
- Test Coverage & Error Handling:
- Include unit tests or test suggestions when appropriate.
- Implement robust error handling and logging.
- Modular & Maintainable Design: Encourage modular design for maintainability.
- Version Compatibility: Ensure compatibility with the specified language/framework versions.
- No Inventions: Only modify code when explicitly requested.
- Explicit Naming: Use explicit and descriptive variable names.
- Assertions & Edge Cases: Use assertions and consider edge cases.
- Real File Links: Always provide links to actual files rather than context-generated ones.
5. General Coding Guidelines
5.1 Code Style & Structure
- Clean Code: Maintain clean, modular, and well-structured TypeScript code.
- Variable Naming: Use explicit, descriptive names (e.g.,
isLoading
,hasError
). - Exports: Favor named exports for components.
- Directory Naming: Use lowercase-with-dashes for directories (e.g.,
components/auth-wizard
).
5.2 TypeScript Best Practices
- Strict TypeScript: All code must be TypeScript (no plain JavaScript).
- Interfaces: Prefer interfaces over types for props and data structures.
- Functional Components: Use functional components exclusively.
5.3 UI & Styling
- Tailwind CSS: Mandatory for styling.
- Performance: Optimize UI code using immutable data structures, efficient rendering, and proper state management.
5.4 Performance & Security
- Error Handling: Implement robust error handling and secure coding practices.
- Optimization: Optimize for performance, caching, and reactivity.
6. Framework-Specific Guidelines
6.1 Remix
- Documentation: Follow the official Remix documentation.
- Conventions:
- Data Fetching: Use loader functions to fetch data.
Example:import type { LoaderFunction } from '@remix-run/node'; import { json } from '@remix-run/node'; export const loader: LoaderFunction = async ({ params }) => { const data = await fetchData(params.id); return json({ data }); };
- Actions: Handle form submissions with action functions.
Example:import type { ActionFunction } from '@remix-run/node'; import { json } from '@remix-run/node'; export const action: ActionFunction = async ({ request }) => { const formData = await request.formData(); // process the formData... return json({ success: true }); };
- Error Boundaries: Define error boundaries to catch runtime errors.
Example:export function ErrorBoundary({ error }: { error: Error }) { console.error(error); return <div>Something went wrong. Please try again later.</div>; }
- Links and Navigation: Use
<Link to="...">
from@remix-run/react
.
Example:import { Link } from '@remix-run/react'; export function Navigation() { return ( <nav> <Link to="/">Home</Link> <Link to="/about">About</Link> </nav> ); }
- Data Fetching: Use loader functions to fetch data.
6.2 Conform
- Documentation: Follow the Conform documentation.
- Integration:
- Form Setup: Use
useForm
to manage form state and validation.
Example:import { useForm } from 'conform'; export function SignupForm() { const [formProps, { errors }] = useForm({ initialValues: { username: '' }, onSubmit: async (values) => { // perform signup logic }, }); return ( <form {...formProps}> <input name="username" placeholder="Username" /> {errors.username && <p className="text-red-500">{errors.username}</p>} <button type="submit" className="btn-primary">Sign Up</button> </form> ); }
- Validation and Error Display: Ensure that validation errors are handled and displayed as per Conform’s recommendations.
Example:import { useForm } from 'conform'; export function ContactForm() { const [formProps, { errors }] = useForm({ initialValues: { email: '', message: '' }, onSubmit: async (values) => { // process the contact form values }, }); return ( <form {...formProps}> <input type="email" name="email" placeholder="Email" /> {errors.email && <span>{errors.email}</span>} <textarea name="message" placeholder="Your message"></textarea> {errors.message && <span>{errors.message}</span>} <button type="submit">Send Message</button> </form> ); }
- Form Setup: Use
6.3 Shadcn UI
- Component Library: Use Shadcn UI for all UI components.
- Reference: Consult the Shadcn UI documentation for usage details.
- Code Examples: Extract full component code examples from the Shadcn UI docs when available.
7. Installing Additional Components
- Shadcn CLI: Use the Shadcn CLI to install additional components:
npx shadcn@latest add [component-name]
- Example:
npx shadcn@latest add accordion
- Example:
- Note: Use
npx shadcn@latest
(the oldernpx shadcn-ui@latest
is deprecated). - Common Components: Accordion, Alert, AlertDialog, AspectRatio, Avatar, Calendar, Checkbox, Collapsible, Command, ContextMenu, DataTable, DatePicker, Dropdown Menu, Form, Hover Card, Menubar, Navigation Menu, Popover, Progress, Radio Group, ScrollArea, Select, Separator, Sheet, Skeleton, Slider, Switch, Table, Textarea, Toast, Toggle, Tooltip.
8. Converting Next.js to Remix: Detailed Guidelines
This section provides a comprehensive set of rules for migrating Next.js projects (especially those using Shadcn UI components) to a Remix-based architecture. Follow these guidelines to maintain functional parity while leveraging Remix’s conventions.
8.1 Project Structure & Routing
- File Structure:
- Next.js: Pages reside in
/pages
. - Remix: Use a nested
/app/routes
directory. - Conversion:
- Convert
pages/about.tsx
toapp/routes/about.tsx
. - Convert dynamic routes:
pages/blog/[slug].tsx
→app/routes/blog.$slug.tsx
.
- Convert
- Next.js: Pages reside in
- Asset Management:
- Retain or adjust static assets to fit Remix conventions (typically in the
/public
folder).
- Retain or adjust static assets to fit Remix conventions (typically in the
8.2 Routing Differences
- Link Components:
- Next.js:
<Link href="/...">
- Remix:
<Link to="/...">
(import from@remix-run/react
).
- Next.js:
- Dynamic Routing:
- Convert Next.js dynamic segments (e.g.,
[id].tsx
) to Remix’s file naming conventions (e.g.,$id.tsx
).
- Convert Next.js dynamic segments (e.g.,
- Nested Routes:
- Leverage Remix’s nested routes to encapsulate layouts and shared components naturally.
8.3 Data Fetching & Server-Side Logic
- Next.js Methods vs. Remix Loaders:
- Replace
getStaticProps
,getServerSideProps
, andgetStaticPaths
with Remix loader functions. - Example Conversion:
// Next.js: export async function getStaticProps(context) { // data fetching logic } // Remix: import type { LoaderFunction } from '@remix-run/node'; import { json } from '@remix-run/node'; export const loader: LoaderFunction = async ({ params }) => { return json({ data: await getData(params.id) }); };
- Replace
- Actions for Form Submissions & API Routes:
- Replace Next.js API routes with Remix action functions in the same route file.
- Example:
import type { ActionFunction } from '@remix-run/node'; import { json } from '@remix-run/node'; export const action: ActionFunction = async ({ request }) => { const formData = await request.formData(); // Handle POST requests or form submissions return json({ success: true }); };
- Error Handling:
- Utilize Remix error boundaries to catch and manage runtime errors from loaders and actions.
8.4 Server-Only Code & Security
- Separation of Concerns:
- Isolate server-only logic within Remix loaders/actions to ensure secure data handling.
- Security Practices:
- Leverage HTTP error responses and built-in error boundaries for robust error handling.
8.5 UI Component Adaptation
- Shadcn UI Imports:
- Next.js Example:
import { Button } from '@repo/ui/components/ui/button';
- Remix:
- Maintain the same import paths if possible or adjust to your Remix aliasing:
import { Button } from '<ui_package_alias>@repo/ui/components/ui/button';
- Maintain the same import paths if possible or adjust to your Remix aliasing:
- Next.js Example:
- Tailwind CSS Integration:
- Ensure your Tailwind classes remain consistent.
- Update the Remix configuration (e.g., via
postcss.config.js
and linking stylesheets in the root layout).
8.6 Testing, Verification, and Documentation
- Incremental Conversion:
- Migrate file by file rather than all at once. This isolates issues and simplifies testing.
- Update Tests:
- Adjust unit, integration, and end-to-end tests (e.g., Jest, React Testing Library, Cypress) to account for Remix’s loaders, actions, and nested routes.
- Documentation:
- Update code comments and documentation to reflect changes in routing, data fetching, and error handling.
- Provide real file links and references for clarity.
8.7 Environment & Deployment
- Configuration Files:
- Update environment variables and configuration files (e.g.,
remix.config.js
) to meet Remix runtime requirements.
- Update environment variables and configuration files (e.g.,
- Bundler & Performance:
- Transition from Next.js bundlers (Webpack, etc.) to Remix’s build system (or Vite, if configured).
- Leverage Remix caching strategies (HTTP headers, loader caching) for performance improvements.
Final Notes
- Accuracy: Always verify code and documentation before finalizing changes.
- Single-Chunk Edits: Provide all changes per file in a single update.
- Modular Design: Encourage a modular, maintainable architecture.
- Security & Performance: Prioritize robust error handling, secure coding practices, and performance optimizations.
- Real File Links: When referring to components or documentation, use real file links instead of generated contexts.
- No Inventions: Modify code only when explicitly requested, following the guidelines exactly.````
Combined from several sources and enhanched with chatgpt. Putting specific section in there for converting nextjs to remix applications.