DEV Community

Cover image for Umbraco 11 + .NET 7 + React + Vite + Hooks Part 2
Mohammed Zaki
Mohammed Zaki

Posted on • Updated on

Umbraco 11 + .NET 7 + React + Vite + Hooks Part 2

Last article we discussed how to create empty umbraco site with strongly typed model, if you didnt read it, please read here it because will continue from we left it off

Create React App No Longer the Standard

React developer team recently removed create-react-app from the official documentation. This means it is no longer the default method of setting up a new project in React. According to this pull request on Github, create-react-app is finally gone.

first lets create react app using vite
within project folder
open the terminal and type this command
npm create vite@latest ClientApp --template react
update package.json to be like this

  "name": "clientapp",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "start-dev": "tsc && vite build --emptyOutDir --mode development --watch",
    "preview": "vite preview"
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.10.0"
  "devDependencies": {
    "@types/node": "^18.15.11",
    "@types/react": "^18.0.28",
    "@types/react-dom": "^18.0.11",
    "@vitejs/plugin-react": "^3.1.0",
    "typescript": "^4.9.3",
    "vite": "^4.2.0"

Enter fullscreen mode Exit fullscreen mode
  • run npm install to install packages

then update vite.config.ts

/// <reference types="node" />

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path';

const root = path.join(__dirname, './');
const main = path.resolve(__dirname, 'src', 'main.tsx');

export default defineConfig(({ command, mode }) => ({
  plugins: [react()],
  publicDir: command === 'build' ? false : 'src/assets',
   root: root,
  resolve: {
    extensions: ['.js', '.jsx', '.tsx', '.ts'],
  server: {
    port: 3000

  build: {
    outDir: './dist/umbraco-app',
    minify: mode === 'development' ? false : 'terser',
    brotliSize: false,
    manifest: false,
    sourcemap: command === 'serve' ? 'inline' : false,
    rollupOptions: {
      input: {
        main: main
      output: {
        assetFileNames: 'assets/[name][extname]',
        chunkFileNames: 'chunks/[name].[hash].js',
        entryFileNames: 'js/[name].js',


Enter fullscreen mode Exit fullscreen mode
  • create pages folder and within this folder add 4 pages
  • Home.tsx
  • About.tsx.
  • Contact.tsx
  • NotFound.tsx ## Home Component Syntax
export const Home = () => {
  return (
      <h4>Home Works</h4>

Enter fullscreen mode Exit fullscreen mode
  • update content of App.tsx

import reactLogo from "./assets/react.svg";
import viteLogo from "./assets/vite.png";
import { HashRouter as Router, Routes, Route, Link } from "react-router-dom";
// we're using Hash Router to override umbraco routing when  page is refreshed 
import { Home } from "./pages/Home";
import { About } from "./pages/About";
import { ContactUs } from "./pages/Contact";
import { NotFound } from "./pages/NotFound";
import "./App.css"; 
export const App = () => {
    return (
      <div className="App">
          <a href="" target="_blank">
            <img src={viteLogo} className="logo" alt="Vite logo" />
          <a href="" target="_blank">
            <img src={reactLogo} className="logo react" alt="React logo" />
          <a href="" target="_blank">
              className="umbraco logo"
              alt="umbraco logo"
        <h1>Vite + React + Umbraco</h1>
                <Link to="/">Home</Link>
                <Link to="/about">About </Link>
                <Link to="/contact">Contact </Link>
            <Route path="/" element={<Home />} />
            <Route path="/about" element={<About />} />
            <Route path="/contact" element={<ContactUs />} />
            <Route path="*" element={<NotFound />} />
        <div className="card"></div>

export default App;

Enter fullscreen mode Exit fullscreen mode

run the app npm run start-dev

so far we only created SPA in vite, to integrate with umbraco please follow thse steps

open VScode and install this nuget package

dotnet add package Microsoft.AspNetCore.SpaServices.Extensions
edit startup class ConfigureServices function

   public void ConfigureServices(IServiceCollection services)
            services.AddUmbraco(_env, _config)
            services.AddSpaStaticFiles(configuration =>
                configuration.RootPath = "ClientApp/dist/umbraco-app";

Enter fullscreen mode Exit fullscreen mode

update configure function

 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            if (env.IsDevelopment())

                .WithMiddleware(u =>
                .WithEndpoints(u =>
            app.UseStaticFiles(new StaticFileOptions

                FileProvider = new Microsoft.Extensions.FileProviders.PhysicalFileProvider(
                               Path.Combine(env.ContentRootPath, "ClientApp/dist/umbraco-app")),
                RequestPath = "",
                OnPrepareResponse = ctx =>
                    // Set cache control header to allow caching of static files
                    ctx.Context.Response.Headers.Append("Cache-Control", "public,max-age=31536000,immutable");
            app.UseEndpoints(endpoints =>

               name: "Default",
               pattern: "",
               defaults: new { controller = "Home", action = "Index" });
 endpoints.MapFallbackToController("Index", "Home");

            app.UseSpa(spa =>

                spa.Options.SourcePath = "ClientApp";
                if (env.IsDevelopment())

                    spa.UseReactDevelopmentServer(npmScript: "start-dev");


Enter fullscreen mode Exit fullscreen mode

Now we need to tell VS Code how to run your project.
Open the command palette, you can use the shortcut Ctrl+Shift+P, and type in Tasks: Configure and select the Tasks: Configure Task option:

Image description

Select "Create task.json from template"

Image description

Now select ".NET Core" as your template.

Image description

After this VS Code will have created a folder called .vscode that contains a file called tasks.json, it's this file that tells VS Code how to build your project.
Now that we've told VS Code how to build your project, we need to tell it how to launch it. VS Code can do this for you. First, select the little play button in the left side menu, and then select the "create a launch.json file" link.

Image description

  • This will prompt a menu to appear, select: .Net Core

Image description

and that's it, you should find this output

Image description

next article i'll cover how consume content from umbraco through API's and render it home page using custom fetch hook in typescript

stay tuned

Top comments (2)

ajdinzutic profile image
Ajdin Zutic

hi thank you for the article :) but what would be the benefit to use React? Also we use webpack 5. would there be any different setup?

mozaky profile image
Mohammed Zaki

In react it’s faster to render content, u can use nice frontend libraries like ant design, prime react and others, plus u can write ur own components with styled components, more feature like u can use lazy loading to load components, u can do code splitting also,
For webpack the setup is totally different, because I used vite CLI and out of the box it generated empty react project and I had to update vite-config.ts build so I can inject it to homepage.cshtml