Convert v0.dev React to Rails ViewComponents
One of the delights of building solo projects with Ruby on Rails is the framework’s thoughtfully chosen defaults. These carefully selected conventions allow developers to focus more on modeling business logic and core value propositions rather than evaluating endless package options. While exploring development across both Rails and JavaScript ecosystems, it’s become apparent how much time in JavaScript development can be consumed by dependency selection and configuration—a process that often feels at odds with the creative joy that drew many of us to programming in the first place.
For prototyping interfaces quickly, v0.dev has emerged as a remarkable tool. It generates polished UI mockups that closely align with mental visions—often requiring only minor adjustments to achieve the desired result. However, a persistent challenge arises: these beautifully crafted components are produced as NextJS/React UI code, creating a barrier for Rails developers wanting to incorporate them into their projects.
This disconnect between modern design tooling and Rails development inspired a modest attempt to bridge the gap: a conversion utility that transforms React/JSX + Tailwind code components from v0.dev into Rails ViewComponent classes with ERB templates.
This v0-rails npm package aims to provide a simple pathway between these different worlds. The utility transforms v0.dev React components into Rails ViewComponents while detecting and preserving dynamic content areas through intelligent slot handling. It maps React icon components to appropriate Rails equivalents, generates sensible routes for navigation components, and maintains the integrity of Tailwind CSS classes and styling. The underlying goal isn’t to create something revolutionary but simply to reduce the friction between these powerful tools, allowing Rails developers to benefit from v0.dev’s design capabilities without the tedium of manually rewriting each component.
Example usage remains straightforward:
# Install globally
npm install -g v0-rails
# Convert a component
v0-rails convert my-v0-component.jsx --output app/components
The conversion process addresses several common translation points that would otherwise require manual intervention. It converts JSX syntax to ERB, transforms React props into ViewComponent parameters, preserves component relationships, and maintains all the carefully crafted Tailwind styling from the original design.
Getting Started (Simple Example)
The workflow follows a natural progression:
sequenceDiagram
participant User as You
participant V0 as Vercel v0
participant CLI as v0-rails CLI
participant Rails as Rails App
User->>V0: Create design
V0->>User: Generate React code
User->>User: Save code to Button.jsx
User->>CLI: Run v0-rails Button.jsx -d app/components
CLI->>Rails: Generate ViewComponent files
User->>Rails: Use component in views
Rails->>User: Render component
Note over User,Rails: Complete conversion workflow
Step 1: Generate a design with v0.dev
Visit v0.dev to create your interface element (such as a button, card, or form). The service will generate React code similar to:
// Button.jsx
export function Button({ children, variant = "primary", size = "medium" }) {
return (
<button className="rounded-md font-normal bg-blue-500 text-white px-4 py-2">
{children}
</button>
)
}
Step 2: Save the generated code
Store the React component in a file like Button.jsx on your computer.
Step 3: Run the conversion
Execute the v0-rails converter to transform the React component:
v0-rails Button.jsx -d app/components
Step 4: Integrate with your Rails application
The resulting ViewComponent can be used naturally in any Rails view:
<%# In any Rails view %>
<%= render(ButtonComponent.new) do %>
Click me!
<% end %>
The component is now seamlessly integrated within your Rails application.
Understanding What Happens
The conversion process generates several interconnected files that work together to recreate the original component’s functionality. First, it creates a Ruby class (app/components/button_component.rb) that handles the component’s logic and parameters. Next, it builds an ERB template (app/components/button_component.html.erb) containing the converted markup and styling. For interactive elements, it might also generate a Stimulus controller to manage client-side behavior. Throughout this process, the original design intent is preserved while adapting to Rails conventions.
flowchart TD
A[React Component<br/>Button.jsx] --> B[Conversion Process]
B --> C[Ruby Class<br/>button_component.rb]
B --> D[ERB Template<br/>button_component.html.erb]
B --> E{Interactive?}
E -->|Yes| F[Stimulus Controller<br/>button_controller.js]
E -->|No| G[No JS needed]
style A fill:#f9d5e5,stroke:#333,stroke-width:2px
style B fill:#eeeeee,stroke:#333,stroke-width:2px
style C fill:#d3f8e2,stroke:#333,stroke-width:2px
style D fill:#d3f8e2,stroke:#333,stroke-width:2px
style F fill:#e3f2fd,stroke:#333,stroke-width:2px
A key benefit is that no React knowledge is required to use these converted components—they function like any other Rails components within your application. This allows Rails developers to take advantage of v0.dev’s design capabilities without needing to learn React or maintain two parallel component systems.
Subscribe to get future posts via email (or grab the RSS feed). 2-3 ideas every month across design and tech
Read more
- Breadboarding, shaping, slicing, and steelthreading solutions with AI agentsproduct-management
- How I started building softwares with AI agents being non technicalagentic-engineering
- Legible and illegible tasks in organisationsproduct
- L2 Fat marker sketchesdesign
- Writing as moats for humanswriting
- Beauty of second degree probesdecision-making
- Read raw transcriptsknowledge
- Boundary objects as the new prototypesprototyping
- One way door decisionsproduct
- Finished softwares should existproduct
- Essay Quality Rankerobsidian
- Export LLM conversations as snippetsbrowser-extension
- Flipping questions on its headinterviewing
- Vibe writing maximswriting
- How I blog with Obsidian, Cloudflare, AstroJS, Githubwriting
- How I build greenfield apps with AI-assisted codingai-coding
- We have been scammed by the Gaussian distribution clubmathematics
- Classify incentive problems into stag hunts, and prisoners dilemmasgame-theory
- I was wrong about optimal stoppingmathematics
- Thinking like a ship
- Hyperpersonalised N=1 learningeducation
- New mediums for humans to complement superintelligenceai-coding
- Maxims for AI assisted codingai-coding
- Personal Website Starter Kitai-coding
- Virtual bookshelvesaesthetics
- It's computational and AI everythingai-coding
- Public gardens, secret routesdigital-garden
- Git way of learning to codeai-coding
- Kaomoji generatorsoftware
- Copy, Paste and Citecuriosities
- Style Transfer in AI writingai-coding
- Understanding codebases without using codeai-coding
- Vibe coding with Cursorai-coding
- Virtuoso Guide for Personal Memory Systemsmemory
- Writing in Future Pastwriting
- Publish Originally, Syndicate Elsewhereblogging
- Poetic License of Designdesign
- Idea in the shower, testing before breakfastsoftware
- Technology and regulation have a dance of ice and firetechnology
- How I ship "stuff"software
- Weekly TODO List on CLIcli
- Writing is thinkingwriting
- Song of Shapes, Words and Pathscreativity
- How do we absorb ideas better?knowledge
- Read writers who operatewriting
- Brew your ideas lazilyideas
- Vibescreativity
- Trees, Branches, Twigs and Leaves — Mental Models for Writingwriting
- Compound Interest of Private Notesknowledge
- Conceptual Compression for LLMsai-coding
- Meta-analysis for contradictory research findingsdigital-health
- Beauty of Zettelswriting
- Proof of workproduct
- Gauging previous work of new joinees to the teamleadership
- Task management for product managersproduct
- Stitching React and Rails togetherai-coding
- Exploring "smart connections" for note takingknowledge
- Deploying Home Cooked Apps with Railssoftware
- Self Marketing
- Repetitive Copypromptingwriting
- Questions to ask every decadejournalling
- Balancing work, time and focusproductivity
- Hyperlinks are like cashew nutswriting
- Brand treatments, Design Systems, Vibesdesign
- How to spot human writing on the internet?writing
- Can a thought be an algorithm?product
- Opportunity Harvestingcareers
- How does AI affect UI?design
- Everything is a prioritisation problemproduct-management
- Nowlifestyle
- How I do product roastsproduct
- The Modern Startup Stacksoftware
- In-person vision transmissionproduct
- How might we help children invent for social good?social-design
- The meeting before the meetingmeetings
- Design that's so bad it's actually gooddesign
- Breaking the fourth wall of an interviewinterviewing
- Obsessing over personal websitessoftware
- Convert v0.dev React to Rails ViewComponentsrails
- English is the hot new programming languagesoftware
- Better way to think about conflictsconflict-management
- The role of taste in building productsdesign
- World's most ancient public health problemsoftware
- Dear enterprises, we're tired of your subscriptionssoftware
- Products need not be user centereddesign
- Pluginisation of Modern Softwaredesign
- Let's make every work 'strategic'consulting
- Making Nielsen's heuristics more digestibledesign
- Startups are a fertile ground for risk takingentrepreneurship
- Insights are not just a salad of factsdesign
- Minimum Lovable Productproduct
- Methods are lifejackets not straight jacketsmethodology
- How to arrive at on-brand colours?design
- Minto principle for writing memoswriting
- Importance of Whytask-management
- Quality Ideas Trump Executionsoftware
- How to hire a personal doctor
- Why I prefer indie softwareslifestyle
- Use code only if no code failscode
- Personal Observation Techniquesdesign
- Design is a confusing worddesign
- A Primer to Service Design Blueprintsdesign
- Rapid Journey Prototypingdesign
- Directory Structure Visualizercli
- AI git commitscli
- Do's and Don'ts of User Researchdesign
- Design Manifestodesign
- Complex project management for productproducts
- How might we enable patients and caregivers to overcome preventable health conditions?digital-health
- Pedagogy of the Uncharted — What for, and Where to?education
- Future of Ageing with Mehdi Yacoubiinterviewing
- Future of Equity with Ludovick Petersinterviewing
- Future of Mental Health with Kavya Raointerviewing
- Future of Tacit knowledge with Celeste Volpiinterviewing
- Future of Rural Innovation with Thabiso Blak Mashabainterviewing
- Future of unschooling with Che Vanniinterviewing
- Future of work with Laetitia Vitaudinterviewing
- How might we prevent acquired infections in hospitals?digital-health
- The soul searching yearsentrepreneurship
- Design education amidst social tribulationsdesign
- How might we assist deafblind runners to navigate?social-design