Skip to main content

3. Create base for your app

Let's start build React app using Vite and pnpm.


Firstly, open your terminal and create app using template (vitejs guide).

pnpm create vite my-react-app --template react-swc-ts

Next, install deps:

cd my-react-app
pnpm install

And start developing app

pnpm run dev


Project structure

What we have in project:

├── public "Place for global assets like favicon, fonts"
│ └── vite.svg
├── src "Place for your code"
│ ├── App.css
│ ├── App.tsx "4. First component that we render"
│ ├── assets
│ │ └── react.svg
│ ├── index.css
│ ├── main.tsx "3. Main tsx file with Creation of react app in root div"
│ └── vite-env.d.ts
├── index.html "2. Main html file with root div and main script attached"
├── package.json
├── pnpm-lock.yaml
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts "1. Conf for frontend tool"

Of course the structure of folders can be different like this:

└── src
├── components
├── hooks
├── store
├── styles
├── tests
├── types
└── utils

It always depends what you will use in your project.


This the file that we define how frontend tool should work, by default only react plugin is enable:

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

export default defineConfig({
plugins: [react()],

but we can adjust in this file much more:

import { defineConfig, PluginOption } from "vite";
import react from "@vitejs/plugin-react";

const plugins: PluginOption[] = [react()];

export default defineConfig(({ command }) => {
if (command === "build") {
return {
build: {
// Generate source map for production build is grate for debugging,
// but also expose all code for everyone
sourcemap: true,

// We can define different behavior depends of envs
if (process.env.VITE_FAKE_API) {
return {

return {
// And we can connect app with real server
server: {
proxy: {
[`/my_service`]: {
target: `http//`,
secure: false,
auth: "test:test",
"/sap/bc/apc": {
target: `ws://`,
ws: true,
secure: false,


<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
<!-- Place that react app will be rendered -->
<div id="root"></div>
<!-- Script that is responsible to render react app -->
<script type="module" src="/src/main.tsx"></script>


import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css' // importing global styles

// Render react in root div tag
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<App />


import { useState } from 'react'
import reactLogo from './assets/react.svg' // Way how you can import assets
import viteLogo from '/vite.svg'
import './App.css'

function App() {
const [count, setCount] = useState(0) // Hook for keeping state of 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" />
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
Edit <code>src/App.tsx</code> and save to test HMR
<p className="read-the-docs">
Click on the Vite and React logos to learn more

export default App