Tina4

Chapter 31: Vibe Coding with AI#

Why Tina4 is Built for AI-Assisted Development#

Tell your AI assistant: "Add a product catalog with search, pagination, and category filtering." In most frameworks, the AI needs to know which packages to install, which config files to create, which naming conventions to follow, how to wire everything together. It hallucinated half of it.

With Tina4, the AI reads one file -- CLAUDE.md -- and knows everything. Every method signature. Every import path. Every convention. It generates correct, runnable code on the first attempt because there is one way to do things in Tina4.

This is not accidental. Tina4 was designed from the ground up for AI-assisted development. Here is why.


The Zero-Dependency Advantage#

When an AI writes Rails code, it might suggest ActiveRecord::Base or ApplicationRecord. Both exist. Both behave differently. It might suggest render json: or respond_to do |format|. The AI guesses.

Tina4 gives it nothing to guess about. One ORM. One queue. One template engine. One cache. No ambiguity. No alternatives. No "it depends on which gem you installed." The AI knows.

ruby
# There is only one way to cache in Tina4cached = Tina4.cache_get("products") || Tina4.cache_set("products", db.fetch("SELECT * FROM products"), 300)โ€‹# There is only one way to queue in Tina4Tina4::Queue.produce("emails", { to: "user@test.com", subject: "Welcome" })โ€‹# There is only one way to send email in Tina4mail = Tina4::Messenger.newmail.to = "user@test.com"mail.subject = "Welcome"mail.send

Zero dependencies means zero confusion for AI.


CLAUDE.md -- The AI's Instruction Manual#

Every Tina4 project includes a CLAUDE.md file that tells AI assistants exactly how the framework works. It contains:

  • Every method signature with parameters and return types
  • The project structure convention (src/routes/, src/orm/, src/templates/)
  • The .env variable reference
  • Code style rules (routes use response.json, ORM uses to_h)
  • Database connection string formats
  • Common gotchas and how to avoid them

When you open a Tina4 project in Claude Code, Cursor, or GitHub Copilot -- the AI reads this file first and immediately understands how to write correct Tina4 code.


Skills -- Deep Framework Knowledge#

Beyond CLAUDE.md, Tina4 ships with three AI skill files:

tina4-maintainer#

For framework maintenance -- porting features between languages, reviewing PRs, running benchmarks, checking parity.

tina4-developer#

For application development -- creating routes, defining models, writing templates, setting up auth, configuring queues.

tina4-js#

For frontend development -- tina4-js signals, Tina4Element components, reactive templates, WebSocket client.


Supported AI Tools#

Tina4 auto-detects and installs context for eight tools. The exact list lives in the framework's Tina4::AI module:

ToolDetection (context file)Context installed
Claude CodeCLAUDE.mdCLAUDE.md + .claude/ skills
Cursor.cursorules.cursorules (+ .cursor/)
GitHub Copilot.github/copilot-instructions.md.github/copilot-instructions.md
Windsurf.windsurfrules.windsurfrules
AiderCONVENTIONS.mdCONVENTIONS.md
Cline.clinerules.clinerules
OpenAI CodexAGENTS.mdAGENTS.md
Google Antigravity.antigravity/context.md.antigravity/context.md

Run tina4 ai to see which tools are detected and install context files via the menu.


The AI Chat in Dev Dashboard#

The dev dashboard at /__dev includes an AI chat tab. By default it talks to a local qwen2.5-coder model served via Ollama, grounded by Tina4's built-in RAG index of the framework source. Nothing leaves your machine.

Configure it in .env:

bash
TINA4_AI_URL=http://localhost:11434      # Ollama HTTP endpointTINA4_AI_MODEL=qwen2.5-coder             # Default coding modelTINA4_RAG_URL=http://localhost:11434     # RAG embedding endpoint (defaults to TINA4_AI_URL)

If you prefer a remote provider, point TINA4_AI_URL at any OpenAI-compatible endpoint and set TINA4_AI_MODEL accordingly.


The Convention Advantage#

AI thrives on convention. When every Tina4 project follows the same structure, the AI never has to ask "where should I put this?"

src/  routes/hello.rb     -> AI knows: this is a route file  orm/product.rb      -> AI knows: this is an ORM model  templates/page.html -> AI knows: this is a Frond template  migrations/         -> AI knows: SQL migration files go here

The AI generates code that drops into the right directory with the right naming convention, every time.


Prompt Engineering for Tina4#

Here are effective prompts for AI-assisted Tina4 Ruby development:

Creating a New Feature#

Add a product catalog to my Tina4 Ruby project:1. Create a Product model with fields: name, category, price, in_stock2. Create a migration for the products table3. Create CRUD routes at /api/products4. Create a product listing template with category filters5. Add response caching for the product list (5 minutes)

The AI generates all five files with correct Tina4 syntax because it read CLAUDE.md.

Adding Authentication#

Add JWT authentication to my Tina4 Ruby project:1. Create a users table migration with name, email, password_hash, role2. Create register and login routes at /api/auth/register and /api/auth/login3. Create auth middleware that validates Bearer tokens4. Protect the /api/tasks group with auth middleware5. Use Tina4::Auth.get_token and Tina4::Auth.valid_token

Building a Dashboard#

Create an admin dashboard for my Tina4 Ruby project:1. Create a GET /admin route that renders a dashboard template2. The dashboard shows: total users, total products, recent orders3. Use tina4css for styling (cards, tables, grid)4. Use frond.js for AJAX data loading5. Cache the dashboard stats for 60 seconds

Adding WebSocket#

Add a real-time notification system to my Tina4 Ruby project:1. Create a WebSocket endpoint at /ws/notifications/{user_id}2. When a task is assigned, push a notification via WebSocket3. Include a JavaScript snippet that connects and shows browser notifications4. Auto-reconnect on disconnect

The Ruby Advantage for AI#

Ruby's expressiveness makes AI-generated code particularly clean:

Block Syntax#

ruby
Tina4::Router.get("/api/products") do |request, response|  products = Tina4.cache_get("products:all")  if products.nil?    db = Tina4.database    products = db.fetch("SELECT * FROM products ORDER BY name")    Tina4.cache_set("products:all", products, 300)  endโ€‹  response.json({ products: products, count: products.length })end

The block syntax is unambiguous. The AI knows exactly where the route handler starts and ends. No curly brace confusion, no indentation ambiguity.

Hash Syntax#

ruby
response.json({  user: { id: user.id, name: user.name, email: user.email },  tasks: tasks.map(&:to_h),  stats: { total: total, completed: completed }})

Ruby's symbol-key hash syntax (name: instead of "name" =>) is concise and consistent. The AI generates clean, idiomatic Ruby.

Enumerable Methods#

ruby
# Filter productselectronics = products.select { |p| p[:category] == "Electronics" }โ€‹# Transform datanames = products.map { |p| p[:name] }โ€‹# Aggregatetotal = items.sum { |item| item[:price] * item[:quantity] }โ€‹# Count with conditionfeatured_count = products.count { |p| p[:featured] }

These are the Ruby idioms the AI knows and uses. No external libraries, no complex method chains -- just Ruby.


Vibe Coding Workflow#

The "vibe coding" workflow with AI and Tina4 looks like this:

1. Describe What You Want#

Tell the AI what you need in plain English. Be specific about the data model, the endpoints, and the behavior.

2. Review the Generated Code#

The AI generates the routes, models, migrations, and templates. Review them for correctness and completeness.

3. Run and Test#

bash
tina4 migratetina4 serve

Test the endpoints with curl or the Swagger UI. If something is wrong, tell the AI what needs to change.

4. Iterate#

"The product list should be paginated. Add page and per_page query parameters." The AI updates the code.

5. Deploy#

bash
docker compose builddocker compose up -d

From idea to production in minutes, not days.


Real-World Example: Building an API in 5 Minutes#

Here is a real conversation with an AI assistant:

You: "Add a blog to my Tina4 Ruby app. Posts with title, body, published flag, and user_id. CRUD API at /api/posts. Only published posts should be visible to anonymous users. Authors can see their own drafts."

AI generates:

  1. migrations/20260322_create_posts_table.sql -- the migration
  2. src/orm/post.rb -- the model with fields and relationships
  3. src/routes/posts.rb -- CRUD routes with authentication and filtering
  4. tests/posts_spec.rb -- RSpec tests for all scenarios

All using correct Tina4 conventions:

ruby
Tina4::Router.get("/api/posts") do |request, response|  db = Tina4.databaseโ€‹  # Check if user is authenticated (optional)  user_id = nil  auth_header = request.headers["Authorization"] || ""  if auth_header.start_with?("Bearer ")    token = auth_header.sub("Bearer ", "")    if Tina4::Auth.valid_token(token)      payload = Tina4::Auth.get_payload(token)      user_id = payload["user_id"]    end  endโ€‹  if user_id    # Authenticated: show published + own drafts    posts = db.fetch(      "SELECT * FROM posts WHERE published = 1 OR user_id = :user_id ORDER BY created_at DESC",      { user_id: user_id }    )  else    # Anonymous: show published only    posts = db.fetch("SELECT * FROM posts WHERE published = 1 ORDER BY created_at DESC")  endโ€‹  response.json({ posts: posts, count: posts.length })end

The AI knows:

  • Tina4::Router.get for routes
  • request.headers["Authorization"] for the token
  • Tina4::Auth.valid_token and Tina4::Auth.get_payload for JWT
  • db.fetch with named parameters for queries
  • response.json for JSON responses

It did not hallucinate. It did not guess. It read CLAUDE.md and wrote correct code.


Why This Matters#

Traditional development: write every line, look up every API, debug every typo. A simple CRUD feature takes an hour.

Vibe coding with Tina4: describe what you want. The AI generates correct code. You review and deploy. The same feature takes 5 minutes.

The insight: AI can only be as good as the framework it targets. A framework with 200 gems, 15 configuration files, and 3 ways to do everything gives the AI too many choices. A framework with zero dependencies, one way to do everything, and a complete reference in CLAUDE.md gives the AI exactly what it needs.

Every Tina4 design decision -- zero deps, convention over configuration, identical API across 4 languages, CLAUDE.md -- exists to make AI-assisted development work.

You bring the ideas. The AI brings the implementation. Tina4 is the bridge.


Exercise: Vibe-Code a Feature#

Open your Tina4 Ruby project with an AI assistant (Claude Code, Cursor, or Copilot) and try this prompt:

Add a comment system to my blog:1. Create a comments table with post_id, author_name, body, created_at2. Create a Comment model with belongs_to :post relationship3. Add POST /api/posts/{id}/comments to add a comment4. Add GET /api/posts/{id}/comments to list comments5. Modify GET /api/posts/{id} to include comments6. Add RSpec tests for the comment endpoints

Verify the AI generates:

  • A migration file in migrations/
  • A model file in src/orm/
  • Route handlers in src/routes/
  • Test file in tests/

Run tina4 migrate && tina4 test to verify everything works.


Gotchas#

1. AI Generates Rails Syntax Instead of Tina4#

Problem: The AI writes render json: instead of response.json.

Cause: The AI defaulted to Rails conventions.

Fix: Make sure CLAUDE.md is in your project root. Mention "Tina4 Ruby" explicitly in your prompt.

2. AI Invents Non-Existent Methods#

Problem: The AI calls Tina4::Router.resource which does not exist.

Cause: The AI hallucinated a method from another framework.

Fix: Review generated code against the CLAUDE.md reference. Ask the AI to only use methods documented in CLAUDE.md.

3. AI Generates Tests That Do Not Match the Implementation#

Problem: Tests reference endpoints or response formats that differ from the actual routes.

Fix: Generate routes first, then ask the AI to generate tests that match the existing routes.

4. AI Forgets to Run Migrations#

Problem: The app crashes because the table does not exist.

Fix: Always run tina4 migrate after generating migrations. Include it in your prompts: "...and tell me the commands to run."

5. AI Uses require Instead of Auto-Loading#

Problem: The AI adds require_relative "../orm/product" at the top of route files.

Cause: Ruby convention is to require files explicitly, but Tina4 auto-loads everything in src/routes/ and src/orm/.

Fix: Remove the require statements. Tina4 handles loading automatically.

6. AI Generates Over-Engineered Solutions#

Problem: The AI creates service objects, repository patterns, and dependency injection for a simple CRUD feature.

Fix: Tell the AI: "Keep it simple. Use Tina4's built-in features only. No extra abstractions." Tina4's philosophy is simplicity -- the AI should follow it.

7. AI Does Not Know About to_h#

Problem: The AI serializes model objects with to_json instead of to_h.

Fix: Tina4 ORM objects use to_h (Ruby idiom for hash conversion) followed by response.json. The CLAUDE.md file documents this pattern.