I built a todo app using 9 different languages
Tags: webdev, beginners, tutorial, codenewbie
Published: 2023-06-09 00:48:37

> Hi, I'm John, Multi Startup Builder.
> I enjoy both coding and marketing.
> See all my 20 products here
> → [johnrush.me](https://johnrush.me/)
> → [my BIO ](https://twitter.com/johnrushx/bio)
> → [Say Hi to me On Twitter](https://twitter.com/johnrushx)
> → [Try my website builder](https://unicornplatform.com/)
--

Greetings, fellow web developers! 
Today we're going on an epic journey through not one, not two... but _nine_ different web frameworks! 🤯

![mindblown](https://media.giphy.com/media/xT0xeJpnrWC4XWblEk/giphy.gif)

But first... Why did I do this? Well as a founder and CEO of MarsX - lowcode platform (since age 6 🤯), who lived in many countries and has lofty dreams to transform the software development world; it was just another day at work!

That's right - I painstakingly built a simple todo list app in each of these languages and documented my experience for your reading pleasure. 

Without further ado, let's meet our contenders:

1. Next.js
2. Ruby on Rails
3. Python Django
4. PHP Laravel
5. Java Spring
6. C# .NET
7. Go Gin 
8. Swift Vapor 
9. Kotlin Ktor
10. MarsX (bonus)

For each language/framework combo, we'll discuss setup time⏱️ ,routing🚦 ,database integration💾 ,as well as overall architecture. And ofc, you'll see the code...my spagetti code :D


## 1. Next.js

```javascript
import { useState } from 'react'

export default function TodoList() {
  const [todos, setTodos] = useState([])
  const [inputValue, setInputValue] = useState('')

  const addTodo = () => {
    if (inputValue) {
      setTodos([...todos, inputValue])
      setInputValue('')
    }
  }

  return (
    <div>
      <h1>Todo List</h1>

      <ul>
        {todos.map((todo) => (
          <li key={todo}>{todo}</li>
        ))}
      </ul>

      <form onSubmit={(e) => e.preventDefault()}>
        <input
          type="text"
          value={inputValue}
          onChange={(e) => setInputValue(e.target.value)}
        />

        <button onClick={() => addTodo()}>Add</button>
      </form>
    </div>
  )
}
```

Next.js brings React to life with its easy setup process and great developer experience out-of-the-box!

_Setup_: Easy peasy lemon squeezy 🍋
_Routing_: Built-in dynamic routing.
_Database integration_: Use any database you like, as long as it's supported by Node.js.


## 2. Ruby on Rails

```ruby
# todo.rb

class Todo < ApplicationRecord
  validates :title, presence: true
end

# todos_controller.rb

class TodosController < ApplicationController
  before_action :set_todo, only: [:show, :edit, :update, :destroy]

  def index
    @todos = Todo.all.order(created_at: :desc)
  end
  
  def create
    @todo = Todo.new(todo_params)

    if @todo.save
      redirect_to todos_path, notice: 'Todo was successfully created.'
    else 
      render 'new'
    end 
  end 

private 

def set_todo 
   @todo = Todo.find(params[:id])
end 

def todo_params 
   params.require(:todo).permit(:title) # add additional parameters as needed.  
end 
  
end

# index.html.erb

<h1>Todos</h1>

<ul>
<% @todos.each do |t| %>
<li><%= t.title %></li>
<% end %>
</ul>

<%= form_for(@todo) do |f| %>  
 <%= f.text_field :title %>   
 <%= f.submit "Add" %>              
<% end %>
```

Ah, the classic Ruby on Rails. This framework has been around for ages and remains one of my favorites!

_Setup_: `rails new` and off we go! 🚀
_Database integration_: ActiveRecord has your back, making it easy to work with databases.
_Routing_: RESTful routing is built-in and simple to use.


## 3. Python Django

```django
# models.py
from django.db import models

class TodoItem(models.Model):
    title = models.CharField(max_length=200)
    completed = models.BooleanField(default=False)

    def __str__(self):
        return self.title


# views.py
from django.shortcuts import render
from .models import TodoItem

def todo_list(request):
    todo_items = TodoItem.objects.all()
    context = {
        'todo_items': todo_items,
    }
    return render(request, 'todo/todo_list.html', context)


# urls.py (inside app folder)
from django.urls import path
from .views import todo_list

app_name = 'todo'
urlpatterns = [
  path('', todo_list, name='list'),
]


# templates/todo/todo_list.html
{% extends "base.html" %}

{% block content %}
  <h1>Todo List</h1>
  <ul>
  {% for item in todo_items %}
      <li>{{ item.title }} - {{ item.completed }}</li>
  {% endfor %}
  </ul>
{% endblock %}
```

Django - the web framework "for perfectionists with deadlines" - doesn't disappoint. Plus, who doesn't love Python?

_Setup_: `django-admin startproject` gets you up and running quickly.
_Routing_: URL configuration can be a bit more complex than other frameworks but is still manageable.
_Database integration_: ORM makes database interactions smooth sailing⛵️ .


## 4. PHP Laravel

```php
// routes/web.php
Route::get('/', 'TodoController@index');
Route::post('/todos', 'TodoController@store');

// Todo model
class Todo extends Model {
  protected $fillable = ['title'];
}

// Todo controller
class TodoController extends Controller {
  public function index() {
    $todos = Todo::all();
    return view('todo.index', compact('todos'));
  }

  public function store(Request $request) {
    $this->validate($request, [
      'title' => 'required'
    ]);

    Todo::create(['title' => request('title')]);
    
    return redirect('/');
  }
}

// resources/views/todo/index.blade.php
<form method="POST" action="/todos">
	{{ csrf_field() }}
	
	<label>Title:</label>
	<input type="text" name="title">
	
	<button type="submit">Add</button>
</form>

<ul>
@foreach ($todos as $todo)
<li>{{ $todo->title }}</li>
@endforeach
</ul>
```

Laravel brings elegance to PHP development by providing clean syntax and an enjoyable developer experience.

_Setup_: A breeze with Composer (`composer create-project --prefer-dist laravel/laravel my_todo_app`)
_Routing_: Simple web.php file for defining routes 🗺️ .
_Database integration_: Eloquent ORM keeps everything neat and tidy.


## 5. Java Spring

```java
@RestController
@RequestMapping("/todos")
public class TodoController {

    private final TodoRepository todoRepository;

    public TodoController(TodoRepository todoRepository) {
        this.todoRepository = todoRepository;
    }

    @GetMapping("/")
    public List<Todo> getAllTodos() {
        return this.todoRepository.findAll();
    }

    @PostMapping("/")
    public ResponseEntity<Object> createTodo(@RequestBody Todo newTodo) {
        try {
            this.todoRepository.save(newTodo);
            return ResponseEntity.ok().build();
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
     }
}

@Entity
@Table(name = "todos")
public class Todo {

  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  private Long id;
  
  private String title;
  
  private boolean completed;

}
```

Java Spring brings the power of Java to web development with a robust framework and plenty of configuration options.

_Setup_: A bit more involved, but manageable.
_Routing_: Annotated controllers make routing a breeze.
_Database integration_: JPA provides solid database support.


## 6. C# .NET

```csharp
using System;
using System.Collections.Generic;

class Program {
    static void Main(string[] args) {
        List<string> todos = new List<string>();

        Console.WriteLine("Todo list");

        while (true) {
            Console.Write("> ");
            string input = Console.ReadLine();

            if (input == "quit") {
                break;
            }

            if (input.StartsWith("+")) {
                string todo = input.Substring(1).Trim();
                todos.Add(todo);
                Console.WriteLine($"Added: {todo}");
            } else if (input.StartsWith("-")) {
                int indexToRemove = int.Parse(input.Substring(1).Trim()) - 1;

                if (indexToRemove >= 0 && indexToRemove < todos.Count) {                    
                    string removedTodo = todos[indexToRemove];
                    todos.RemoveAt(indexToRemove);
                    Console.WriteLine($"Removed: {removedTodo}");
                }
            } else if (input == "") {
                Console.WriteLine("Todos:");
                
                 for(int i=0; i<todos.Count; i++){
                     Console.WriteLine($"{i+1}: {todos[i]}");
                 }
             }else{
                 //invalid command entered
             }
         }
     }
}
```

C# .NET offers top-notch performance and comes packed with features for building full-stack web apps.

_Setup_: Use Visual Studio or CLI tools - either way, it's smooth sailing⛵️ .
_Routing_: Attribute-based routing lets you define routes directly on your controller methods 🎯 .
_Database integration_: Entity Framework Core is powerful and well-integrated into the ecosystem.


## 7. Go Gin

```go
package main

import (
    "github.com/gin-gonic/gin"
)

type Todo struct {
    ID        int    `json:"id"`
    Title     string `json:"title"`
    Completed bool   `json:"completed"`
}

var todoList []Todo

func main() {
	r := gin.Default()

	// GET all todos
	r.GET("/todos", func(c *gin.Context) {
		c.JSON(200, todoList)
	})

	// POST a new todo
	r.POST("/todos", func(c *gin.Context) {
	    var newTodo Todo
	    c.BindJSON(&newTodo)
	    
	    // Generate unique ID for the new todo item
        if len(todoList) == 0 {
            newTodo.ID = 1 
        } else { 
            lastID := todoList[len(todoList)-1].ID 
            newTodo.ID = lastID + 1 
        }
        
        // Append the newly created item to the list of todos.
        todoList = append(todoList, newTodo)
		
	    c.JSON(201, gin.H{
	        "message": "New ToDo added successfully",
	        "todo": &newToDo,
	     })
	})
	
	r.Run(":8080")
}
```

Gin is an excellent choice for those who prefer the simplicity and speed of Go. It's lightweight yet fully featured!

_Setup_: Easy setup using `go mod init`🚀 .
_Routing:_ Simple route definition in just a few lines of code!
_Database integration:_ GORM makes working with databases enjoyable 💾.


## 8. Swift Vapor

```swift
import Vapor

final class Todo: Content {
    var id: Int?
    var title: String
    
    init(title: String) {
        self.title = title
    }
}

func routes(_ app: Application) throws {

    // create a new todo item
    app.post("todo") { req -> EventLoopFuture<Todo> in
        let todo = try req.content.decode(Todo.self)
        return todo.save(on: req.db).map { todo }
    }

    // get all todos from the database
    app.get("todos") { req -> EventLoopFuture<[Todo]> in
        return Todo.query(on: req.db).all()
    }

}
```

Vapor brings the power of Swift to server-side development, and it's almost as delightful as a freshly-baked 🍏 pie!

_Setup_: A bit more involved due to Xcode setup time.
_Routing_: Route definition is straightforward and readable.
_Database integration_: Fluent ORM is powerful and expressive.


## 9. Kotlin Ktor

```kotlin
data class Todo(val id: Int, val task: String)

val todos = mutableListOf<Todo>()

fun main() {
    embeddedServer(Netty, port = 8080) {
        install(ContentNegotiation) {
            json()
        }

        routing {
            get("/todos") {
                call.respond(todos)
            }
            
            post("/todos") {
                val todo = call.receive<Todo>()
                todos.add(todo)
                call.respond(HttpStatusCode.Created)
            }
            
            delete("/todos/{id}") {
                val id = call.parameters["id"]?.toIntOrNull()
                
                if (id == null || !todos.removeIf { it.id == id }) 
                    call.respond(HttpStatusCode.NotFound)
                 else 
                    call.respond(HttpStatusCode.OK)    
           }
       }  
   }.start(wait = true)
}
```

Ktor helps you build web apps with Kotlin, combining simplicity with the power of JetBrains' language innovations💡 .

_Setup:_ Requires some initial configuration but manageable.
_Routing:_ Uses DSL for defining routes - clean and elegant🎩 .
_Database integration:_ Exposed library makes working with databases simple yet powerful⚙️ .


## 10. MarsX (Bonus) 🚀

Hold on to your hats, folks! We've got a brand new framework/language that's so ridiculously easy, even my grandma managed to build the todo list in just _7 minutes_!

But here's the catch - it's still in private beta, and you'll have to battle through a waitlist like Black Friday shoppers trying to snag that sweet deal. Want in? Join the frenzy [here](https://www.marsx.dev/).

![Funny gif of people fighting for deals](https://media.giphy.com/media/3orif9DJNKDfXqXbBS/giphy.gif)

```jsx
<schema>
  <array name="todo">
    <object>
      <string name="title" />
    </object>
  </array>
</schema>
```



## And there you have it! 

Nine different frameworks used to build the same app - may your startup grow into a deca unicorn🦄 , no matter which one you choose. Just remember to choose wisely; after all, your framework will dictate your life for the next nine years😉 .

![choosewisely](https://media.giphy.com/media/26BRzozg4TCBXv6QU/giphy.gif)

Happy coding!

--
> Hi, I'm John, Multi Startup Builder.
> I enjoy both coding and marketing.
> See all my 20 products here
> → [johnrush.me](https://johnrush.me/)
> → [my BIO ](https://twitter.com/johnrushx/bio)
> → [Say Hi to me On Twitter](https://twitter.com/johnrushx)
> → [Try my website builder](https://unicornplatform.com/)