Creating a Todo Application using Next.js

Next.js is a framework for building server-rendered React applications. It provides a powerful set of features for web development such as automatic code splitting, server-side rendering, and static site generation. In this blog post, we will be creating a simple Todo application using Next.js.

Setting up the project

To get started, you will need to have Node.js and npm (or yarn) installed on your machine. Once you have these dependencies set up, you can create a new Next.js project using the following command:

npx create-next-app my-todo-app

This will create a new directory called “my-todo-app” with the basic file structure and dependencies for a Next.js app.

Creating the Todo List component

In this step, we will create a TodoList component that will display a list of todo items. Create a new file called TodoList.js in the components folder and add the following code:

import React from 'react';

const TodoList = ({ todos }) => {
  return (
    <ul>
      {todos.map((todo) => (
        <li key={todo.id}>
          <span>{todo.text}</span>
          <button>Delete</button>
        </li>
      ))}
    </ul>
  );
};

export default TodoList;

In this code, we are rendering an unordered list and mapping over the todos prop to create a list item for each todo item. We also added a button to delete the todo item.

Adding the Todo Form

Now that we have the TodoList component, we need to create a form to add new todo items. Create a new file called TodoForm.js in the components folder and add the following code:


import React, { useState } from 'react';

const TodoForm = ({ addTodo }) => {
  const [text, setText] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    if (!text) return;
    addTodo(text);
    setText('');
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="Add Todo..."
      />
    </form>
  );
};

export default TodoForm;


In this code, we are creating a form with an input that allows the user to enter a new todo item. When the form is submitted, it calls the addTodo function with the text of the input as an argument. We are also reset the text state after adding the todo item.

Creating the TodoPage

Create a new file called TodoPage.js in the pages folder and add the following code:


import React, { useState } from 'react';
import TodoList from '../components/TodoList';
import TodoForm from '../components/TodoForm';

const TodoPage = () => {
const [todos, setTodos] = useState([]);

const addTodo = (text) => {
setTodos([...todos, { id: todos.length + 1, text }]);
};

const deleteTodo = (id) => {
setTodos(todos.filter((todo) => todo.id !== id));
};

return (
<div>
<TodoForm addTodo={addTodo} />
<TodoList todos={todos} deleteTodo={deleteTodo} />
</div>
);
};

export default TodoPage;


In this file, we are creating a TodoPage component that contains the TodoForm and TodoList components. We are also using React’s useState hook to manage the state of the todo items. The addTodo function is passed down to the TodoForm component as a prop and is called when a new todo item is added. The deleteTodo function is passed down to the TodoList component as a prop and is called when a todo item is deleted.

Adding Routing

Add the following code in your pages/index.js file to redirect users to the TodoPage by default

import TodoPage from './TodoPage';

export default function Home() {
  return <TodoPage />;
}

Now the user will be able to access the TodoPage by visiting the root of your application.

That’s it! You now have a working Todo application built with Next.js. You can customize the application further by adding styles, saving the todo items to a database, or adding more features.

Adding Styles

You can add styles to your Todo application using a CSS preprocessor like SASS or using CSS-in-JS libraries like styled-components.

If you decide to use a CSS preprocessor, you will need to install the necessary dependencies and configure Next.js to use it. You can add the CSS files to the styles directory in the root of your project.

If you prefer to use styled-components, you can install it using npm or yarn by running the following command:

npm install styled-components

And then you can import it in your TodoForm.js and TodoList.js and add styles to your components.

import styled from 'styled-components';

const TodoForm = ({ addTodo }) => {
  // ...
  return (
    <Form onSubmit={handleSubmit}>
      <Input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="Add Todo..."
      />
    </Form>
  );
};

const Form = styled.form`
  display: flex;
  margin-bottom: 16px;
`;

const Input = styled.input`
  flex: 1;
  padding: 8px;
  border-radius: 4px;
  border: 1px solid #ccc;
`;


Saving Todo items to a database

To save the todo items to a database, you will need to create a backend service that the Next.js app can communicate with. You can use a variety of technologies to build the backend, such as Node.js with Express, Python with Flask or Ruby on Rails.

In your backend service, you will need to create a REST API that the frontend can send requests to for creating, reading, updating, and deleting todo items.

Then you need to call the API in the TodoPage component’s functions like addTodo, deleteTodo to perform the CRUD operations on todo items.

Additionally, you can also use a library like axios or fetch to communicate with the backend service.

In summary, creating a Todo application using Next.js is a straightforward process, but you can also add further functionality like styles, routing, and saving the data to a database. It’s a great way to learn more about building web applications with React and Next.js and you can use the concepts you learn to build more advanced applications in the future.

Installing and Using Swagger in C# 11 with Code Samples

Swagger is a tool that allows developers to document and test their API endpoints. It is a popular choice for building APIs in a variety of programming languages, including C#. In this blog post, we will walk through the process of installing and using Swagger in a C# 11 project.

Step 1: Install the necessary packages

To get started, you will need to install the following packages to your C# project:

  • Swashbuckle.AspNetCore: This package is the main package that integrates Swagger with your ASP.NET Core project.
  • Microsoft.AspNetCore.Swagger: This package provides the necessary tools for generating and displaying the Swagger documentation.

To install these packages, you can use the following command in the Package Manager Console:

PM> Install-Package Swashbuckle.AspNetCore -Version 5.7.1
PM> Install-Package Microsoft.AspNetCore.Swagger -Version 5.0.0

Step 2: Configure Swagger in Startup.cs

Once you have the necessary packages installed, you can configure Swagger in your project’s Startup.cs file. In the ConfigureServices method, add the following code to add Swagger services to your project:

services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});

Then, in the Configure method, add the following code to enable Swagger UI:

app.UseSwagger();
app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});

Step 3: Add documentation to your API

You can now add documentation to your API by adding XML comments to your code. For example:

/// <summary>/// Get the value of x
/// </summary>/// <param name="x">The x value</param>/// <returns>The x value</returns>
[HttpGet("{x}")]
public int Get(int x)
{
    return x;
}

Step 4: Run and Test the API

You can now run your API and test it using Swagger UI by visiting the following URL:

<http://localhost>:<port>/swagger

Note that the “port” should be replaced with the actual port that your API is running on.

Please note the above steps are for general guidance and implementation may vary depending on the use case, for example the specific version of package, or different framework etc.

Step 5: Customizing the Swagger UI

The default Swagger UI that is generated when you add Swagger to your project can be customized to fit your needs. Some of the ways that you can customize the UI include:

  • Changing the layout and styling: You can use CSS to change the appearance of the Swagger UI. You can also use the Swagger UI custom layout feature to change the layout of the UI.
  • Adding custom pages: You can add custom pages to the Swagger UI to provide additional information about your API, such as examples and tutorials.
  • Customizing the authentication process: You can customize the authentication process so that users are prompted to enter their credentials when accessing your API.

Step 6: Additional Swagger Features

Swagger also has other features that can help you work with your API, including:

  • Validation: You can use the Swagger validator to validate the requests and responses of your API.
  • Code generation: You can use the Swagger code generator to generate client code for your API in a variety of programming languages, including C#.
  • Middleware: You can use the Swagger middleware to add additional functionality to your API, such as logging and security.

In this post, we have covered the basics of installing and using Swagger in a C# 11 project. By following the steps outlined in this post, you can quickly and easily add Swagger to your project and start documenting and testing your API. With the rich functionality that it offers, you can further customize the UI and find other useful functionalities to improve the developer experience and make the API more understandable.

Step 7: Advanced Usage

Once you have set up Swagger in your project, you can start exploring the advanced usage of it.

  • Advanced configuration options: You can configure the Swagger settings to suit your needs, such as disabling the authorization dialog, hiding the API version or enabling JWT.
services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Description = "JWT Authorization header using the Bearer scheme. Example: \\"Authorization: Bearer {token}\\"",
        Name = "Authorization",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.ApiKey,
        Scheme = "Bearer"
    });
    c.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }
            },
            new string[] {}
        }
    });
});

  • Grouping endpoints by tags: You can group your endpoints by using tags in the XML comments. This way you can make it easier for users to navigate through your API.
/// <summary>/// Get the value of x
/// </summary>/// <param name="x">The x value</param>/// <returns>The x value</returns>/// <tag>Values</tag>
[HttpGet("{x}")]
public int Get(int x)
{
    return x;
}

  • Custom operations: You can create custom operations by using the IOperationFilter and ISchemaFilter interfaces. These interfaces allow you to add custom functionality to the Swagger UI, such as adding extra fields or changing the behavior of the UI.

Step 8: Use Swagger for ASP.Net Core 3.1

If you are using ASP.NET Core 3.1, you will need to install the appropriate packages and configure them slightly differently.

  • First, you need to install the following NuGet package:
Microsoft.OpenApi

  • Then, in the Startup.cs file, you need to configure the services and the app in the ConfigureServices and Configure methods:
// ConfigureServices method
services.AddControllers();
services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});

// Configure method
app.UseSwagger();
app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});
app.UseRouting();
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
});

  • Finally, you need to add the XML comments to your controllers and actions, and you can run the application and access the Swagger UI at the /swagger endpoint.

Step 9: Use the advanced features

Swagger provides a wide range of advanced features that can help you work with your API, some of them are:

  • Versioning: You can version your API by specifying different versions of the Swagger documentation, this will enable users to access different versions of the API.
services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
    c.SwaggerDoc("v2", new OpenApiInfo { Title = "My API", Version = "v2" });
});

  • Deprecation: You can deprecate an endpoint by adding [Obsolete] attribute, which will notify the users that this endpoint is no longer available in the latest version.
[Obsolete]
[HttpGet("{x}")]
public int Get(int x)
{
    return x;
}

  • OperationId: You can provide a unique operationId for each endpoint, this will provide a specific identifier for the endpoint.
[HttpGet("{x}")]
[Operation(OperationId = "GetX")]
public int Get(int x)
{
    return x;
}

  • Examples: You can provide examples of the expected request and response for each endpoint, this will help the users understand how to use the endpoint correctly.
[HttpGet("{x}")]
[ProducesResponseType(typeof(int), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(void), 500)]
[SwaggerResponseExample(200, typeof(int), "{x:10}")]
[SwaggerRequestExample(typeof(int), "{x:10}")]
public int Get(int x)
{
    return x;
}

These are just a few examples of the advanced features that Swagger provides, there are many more features available that you can use to enhance the developer experience and make your API more understandable.

Step 10: Implementing security

Securing your API is an important aspect to ensure the confidentiality and integrity of the data. Swagger provides a feature that enables you to define and implement security for your API.

  • Security Definitions: You can define the type of security that your API supports, for example, OAuth2 or Basic Authentication.
services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Description = "JWT Authorization header using the Bearer scheme. Example: \\"Authorization: Bearer {token}\\"",
        Name = "Authorization",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.ApiKey,
        Scheme = "Bearer"
    });
});

  • Security Requirements: You can specify the security requirements for your API, for example, which endpoints require authentication and which do not.
services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
    c.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }
            },
            new string[] {}
        }
    });
});

It’s important to note that, the above example uses JWT Bearer authentication, but you can use other types of authentication schemes such as OAuth2, Basic or others. Additionally, security is a complex topic that requires a thorough understanding of the different types of threats and best practices for securing your application. You should consult the appropriate security documentation and guidelines for your specific use case.

In this step, you have learned how to define and implement security for your API using Swagger. By defining security definitions and requirements, you can ensure the confidentiality and integrity of your API and enhance the developer experience by clearly communicating the security requirements of your API.

In conclusion, Swagger is a powerful tool for documenting and testing APIs in C#. With the ability to customize the UI, add custom pages, and advanced configuration options, Swagger provides a great developer experience. It is worth taking the time to learn how to use the different features that Swagger offers so that you can take full advantage of it in your projects.