
Research
Supply Chain Attack on Axios Pulls Malicious Dependency from npm
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.
A modern React meta-framework powered by Vite, designed for building fast and scalable web applications.
npm install fohl react react-dom
# or
pnpm add fohl react react-dom
# or
yarn add fohl react react-dom
my-app/
├── app/
│ ├── pages/
│ │ └── index.tsx
│ └── app.tsx (optional)
├── public/
└── fohl.config.ts (optional)
Create app/pages/index.tsx:
export default function Home() {
return (
<div>
<h1>Welcome to Fohl!</h1>
</div>
)
}
{
"scripts": {
"dev": "fohl dev",
"build": "fohl build",
"preview": "fohl preview"
}
}
npm run dev
The server will start with Hot Module Replacement (HMR) enabled. You can add, remove, or modify pages and the routes will automatically regenerate without restarting the server! 🎉
Fohl automatically generates routes based on your file structure in app/pages/. Routes are automatically regenerated when you add, remove, or modify files - no server restart needed!
app/pages/
├── index.tsx → /
├── about.tsx → /about
├── blog/
│ ├── index.tsx → /blog
│ ├── [slug].tsx → /blog/:slug
│ └── layout.tsx → Layout for /blog/* routes
└── layout.tsx → Root layout
Use square brackets [] for dynamic segments:
// app/pages/blog/[slug].tsx
export default function BlogPost() {
const { slug } = useParams()
return <div>Post: {slug}</div>
}
Fohl supports Nuxt 3-style layouts where pages can declaratively specify which layout to use!
app/layouts/// app/layouts/default.tsx
import { Outlet } from 'react-router'
export default function DefaultLayout() {
return (
<div>
<header>Header</header>
<main>
<Outlet /> {/* Child routes render here */}
</main>
<footer>Footer</footer>
</div>
)
}
// app/layouts/admin.tsx
import { Outlet } from 'react-router'
export default function AdminLayout() {
return (
<div className="admin-layout">
<aside>Admin Navigation</aside>
<main>
<Outlet />
</main>
</div>
)
}
// app/pages/index.tsx
export const layout = 'default' // Uses default layout
export default function HomePage() {
return <h1>Home Page</h1>
}
// app/pages/admin/dashboard.tsx
export const layout = 'admin' // Uses admin layout
export default function AdminDashboard() {
return <h1>Admin Dashboard</h1>
}
If no layout is specified, default is used automatically!
Benefits:
You can also use directory-based layouts for backwards compatibility:
// app/pages/layout.tsx
export default function Layout() {
return (
<div>
<nav>Navigation</nav>
<Outlet />
</div>
)
}
Create a fohl.config.ts file in your project root:
import { defineConfig } from "fohl"
export default defineConfig({
// Development server options
devServer: {
port: 3000,
host: "localhost",
open: false,
},
// Directory configuration
dir: {
app: "app",
public: "public",
build: "dist",
buildAssets: "_fohl/",
},
// App configuration
app: {
baseURL: "/",
rootAttrs: {
id: "__fohl",
},
},
// Build options
build: {
sourcemap: false,
minify: true,
},
// Preview server options
previewServer: {
port: 4321,
host: "localhost",
open: false,
},
// Path aliases
alias: {
"@components": "./app/components",
"@utils": "./app/utils",
},
// TypeScript config overrides
tsconfig: {
compilerOptions: {
strict: true,
},
},
})
Start the development server with Hot Module Replacement:
fohl dev [--port 3000] [--host localhost]
Features in development mode:
Build your application for production:
fohl build
Preview your production build:
fohl preview [--port 4321] [--host localhost]
The following are automatically imported in your components:
// No need to import these
useState, useEffect, useCallback, useMemo, useRef,
useContext, useReducer, etc.
// No need to import these
useParams, Outlet
// No need to import
defineConfig
// Available for use
useHead, useSeoMeta, useServerHead, etc.
Fohl supports a layer system for modular functionality:
layers/
├── auth/
│ └── pages/
│ └── login.tsx
└── admin/
└── pages/
└── dashboard.tsx
Layers are automatically merged with your main application.
Fohl is built with TypeScript and provides full type safety out of the box. Auto-generated type definitions are created in the .fohl directory.
The production build includes:
Export a loader function to load data before rendering:
export async function loader({ params }) {
const data = await fetchData(params.id)
return data
}
export default function Page({ loaderData }) {
return <div>{loaderData.title}</div>
}
Export a middleware function for route protection:
export async function middleware({ params, request }) {
const isAuthenticated = await checkAuth(request)
if (!isAuthenticated) {
return redirect("/login")
}
}
export default function ProtectedPage() {
return <div>Protected Content</div>
}
MIT
Contributions are welcome! Please feel free to submit a Pull Request.
FAQs
A React meta-framework powered by Vite
We found that fohl demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.

Security News
TeamPCP is partnering with ransomware group Vect to turn open source supply chain attacks on tools like Trivy and LiteLLM into large-scale ransomware operations.