Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions strapi-nextjs-navigation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Strapi Plugin Navigation example with NextJS

This example is set up to show how to create a project with our navigation plugin installed as well as integrate it with a sample frontend.

## 🔧 Getting Started

To run this project, you need to prepare two shell windows. One window will be used to set up and run strapi server and the second one will be used to run development server for nextjs frontend.

### Strapi Server

Install all packages

```sh
cd ./strapi-app
yarn install
```

Run the server

> Before running the strapi server be sure to create your own `.env` file. Example of this file can be found in strapi app folder.
```sh
yarn build
yarn develop
# or
yarn develop --watch-admin
```

After that open strapi admin panel and create admin user. The strapi project should be ready to use at this point.

### NextJS development server

Install all packages
```sh
cd ./next-app
yarn install
```

Run the server
```sh
yarn dev
```

After that the nextJs frontend should be ready to use. You can direct to `localhost:3000` to see it.
15 changes: 15 additions & 0 deletions strapi-nextjs-navigation/next-app/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"presets": [
"next/babel"
],
"plugins": [
[
"styled-components",
{
"ssr": true,
"displayName": true,
"preprocess": false
}
]
]
}
3 changes: 3 additions & 0 deletions strapi-nextjs-navigation/next-app/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}
35 changes: 35 additions & 0 deletions strapi-nextjs-navigation/next-app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
13 changes: 13 additions & 0 deletions strapi-nextjs-navigation/next-app/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { NavigationItemFlat, NavigationItemTree } from "../types/navigation";

export const fetchMainNavigation = async (idOrSlug: string | number) => {
const res = await fetch(`http://localhost:1337/api/navigation/render/${idOrSlug}?type=TREE`)
const data: NavigationItemTree[] = await res.json();
return data;
}

export const fetchFooterNavigation = async () => {
const res = await fetch("http://localhost:1337/api/navigation/render/2?type=FLAT");
const data: NavigationItemFlat[] = await res.json();
return data;
}
35 changes: 35 additions & 0 deletions strapi-nextjs-navigation/next-app/components/Footer/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { useEffect, useState } from "react";
import { NavigationItemFlat } from "../../types/navigation";
import Link from "next/link";
import { fetchFooterNavigation } from "../../api";

const MainFooter = () => {
const [footerItems, setFooterItems] = useState<NavigationItemFlat[]>([]);
useEffect(() => {
fetchFooterNavigation()
.then(setFooterItems)
.catch(e => console.error(e));
}, []);

return (
<footer className="footer mt-auto py-3 bg-light">
<div className="container d-flex flex-wrap justify-content-between align-items-center">
<p className="col-md-4 mb-0 text-muted">Created by VirtusLab</p>
<ul className="nav col-md-auto justify-content-end">
{footerItems.map((navItem) => {
const isExternal = navItem.type === "EXTERNAL";
return (
<Link key={navItem.id} href={isExternal ? navItem.externalPath : navItem.path}>
<li className="nav-item nav-link px-3 text-muted">
{navItem.title}
</li>
</Link>
);
})}
</ul>
</div>
</footer>
);
}

export default MainFooter;
17 changes: 17 additions & 0 deletions strapi-nextjs-navigation/next-app/components/MainLayout/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Container } from "react-bootstrap";
import Footer from "../Footer";
import Navbar from "../Navbar";

const MainLayout: React.FC<any> = ({ children }) => {
return (
<div className="d-flex flex-column" style={{ height: "100vh" }}>
<Navbar />
<Container className="my-5">
{children}
</Container>
<Footer />
</div>
);
}

export default MainLayout;
39 changes: 39 additions & 0 deletions strapi-nextjs-navigation/next-app/components/Navbar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { useEffect, useState } from "react";
import { NavigationItemTree } from "../../types/navigation";
import { Container, Nav, Navbar } from 'react-bootstrap';
import Link from "next/link";
import List from "./list";
import { fetchMainNavigation } from "../../api";

interface IProps {
idOrSlug?: number | string;
}

const MainNavbar: React.FC<IProps> = ({ idOrSlug = 1 }) => {
const [navigationItems, setNavigationItems] = useState<NavigationItemTree[]>([]);
useEffect(() => {
fetchMainNavigation(idOrSlug)
.then(setNavigationItems)
.catch(e => console.error(e));
}, [idOrSlug]);

return (
<Navbar bg="light" expand="lg">
<Container>
<Link href="/">
<Navbar.Brand className="cursor-pointer">
Strapi Plugin Navigation Example
</Navbar.Brand>
</Link>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav" className="justify-content-end">
<Nav>
<List items={navigationItems} level={0} />
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
);
}

export default MainNavbar;
22 changes: 22 additions & 0 deletions strapi-nextjs-navigation/next-app/components/Navbar/item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import Link from "next/link";
import { Nav } from "react-bootstrap";
import { NavigationItemTree } from "../../types/navigation";
import List from "./list";

interface IProps {
item: NavigationItemTree;
level: number;
}

const Item: React.FC<IProps> = ({ item, level }) => {
return (
<Nav.Link href={item.path}>
<Link href={item.path} passHref={item.type === "EXTERNAL"}>
{item.title}
</Link>
{item.items && item.items.length ? <List items={item.items} level={level + 1} /> : null}
</Nav.Link>
);
}

export default Item;
16 changes: 16 additions & 0 deletions strapi-nextjs-navigation/next-app/components/Navbar/list.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { NavigationItemTree } from "../../types/navigation";
import Item from "./item";

interface IProps {
items: NavigationItemTree[];
level: number;
}

const List: React.FC<IProps> = ({ items, level }) => {
const preparedItems = items.map(item => <Item item={item} level={level} key={item.id} />);
return level > 0
? <div className="dropdown-menu">{preparedItems}</div>
: <>{preparedItems}</>;
}

export default List;
5 changes: 5 additions & 0 deletions strapi-nextjs-navigation/next-app/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
6 changes: 6 additions & 0 deletions strapi-nextjs-navigation/next-app/next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
}

module.exports = nextConfig
Loading