Part of the Open Budgets India Project
Budget Basics aims to demystify concepts and processes of Government budgets in India. Built as a documentation platform, it provides the content in easily digestible form. This is the front end of the platform built using nextjs. We welcome all contributions and pull requests!
Visit Budget Basics
- π± Responsive: Use Desktop, Laptop or Mobile devices. It's optimized for all.
- βΏ Accessible: The platform is screen-reader friendly.
- π Performant: It's fast!
- π JAMStack: Next.js with Strapi headless CMS to make development process fast and efficient.
- π MeiliSearch: Super fast search by using Meilisearch as a micro-service.
- π BEM & SASS: The platform utilizes BEM methodology with SASS to make styling efficient and maintainable.
- π Modular: Easy to add or remove components based on usage -
- Highlights to show multiple important content/news on the header
- Custom lightweight carousel to show Youtube videos that are lazy-loaded.
- Sticky sidebar to list all sections and sub-sections available.
- Footer Buttons to navigate to the next or previous chapter.
- and more...
Make sure to have a recent version of Node. You'll need Node 10.13 or later.
To run this project, you will need to create a new .env file on the root directory add the following environment variables.
NEXT_PUBLIC_STRAPI_API_URL
- required to fetch content. Setup the strapi instance
NEXT_PUBLIC_MEILISEARCH_URL
- required to enable search functionality
NEXT_PUBLIC_MEILISEARCH_API
- required to enable search functionality
eg: NEXT_PUBLIC_STRAPI_API_URL = "https://strapi-api-server.com/"
Follow the steps at budget-basic-strapi first to set up the backend instance before booting up the frontend. This should set up Postgresql database, Strapi CMS and Meilisearch Instance.
budget-basics-next/
β£ components/
β£ lib/
β£ pages/
β£ public/
β β£ assets/
β β β£ fonts/
β β β£ icons/
β£ style/
β β£ pages/
β β£ tools/
β£ utils/
This project follows BEM Methodology with Sass Preprocessor to make styling more efficient and future maintainable. Have a look around different files to know more about it. You can learn more about styling directory here
It is a component-based project which makes it easier to add, edit or remove features in the future.
All the components are available at /components
. Each component has its folder with its styling file is included. This makes it easier to use that component on some other
project. Learn more here
To handle styling on scroll for sidebar in desktop and menubar for mobile, GSAP is used. You will find following
function in /pages/[chapter].js
:
handleSidebarAnimation
handleSubheadingAnimation
and the following in /components/menu.js
:
handleMenuAnimation
handleSubheadingAnimation
These functions use GSAP ScrollTrigger to add classes to Menu
and Sidebar
.
All the data is being fetched from a Strapi CMS. You can use any headless CMS.
Fetching Global Settings and data on _app.js
which then can be passed to other components using createContext
import React, { createContext } from 'react'
export const GlobalContext = createContext({})
function MyApp({ Component, pageProps }) {
const { global } = pageProps
return (
<>
<Layout>
<GlobalContext.Provider value={global}>
<Component {...pageProps} />
</GlobalContext.Provider>
</Layout>
</>
)
}
MyApp.getInitialProps = async (ctx) => {
const appProps = await App.getInitialProps(ctx)
const global = await fetchAPI('/global')
return { ...appProps, pageProps: { global } }
}
For example, on /components/search.js
we can use this global data:
import React, { useContext } from 'react'
import { GlobalContext } from 'pages/_app'
const Search = ({ Component, pageProps }) => {
const { articles } = useContext(GlobalContext)
// some cool stuff
}
Homepage data includes a description for header, content for highlights slider, youtube links for carousel, and some metadata.
We can fetch all of that and all of different chapters (categories) easily:
export async function getStaticProps() {
const homepage = await fetchAPI('/homepage')
const chapters = await fetchAPI('/chapters')
return {
props: { homepage, chapters },
revalidate: 1,
}
}
revalidate: 1
- allows us to create or update static pages after building the site. Read
Incremental Static Regeneration
In our project, we have one dynamic route, [chapter].js
. Dynamic routes
requires getStaticPaths
to list paths during build time. Read more.
export async function getStaticPaths() {
const chapters = await fetchAPI('/chapters')
return {
paths: chapters.map((chapter) => ({
params: {
chapter: chapter.slug,
},
})),
fallback: false,
}
}
export async function getStaticProps({ params }) {
const chapter = await fetchAPI(`/chapters?slug=${params.chapter}`)
const chapters = await fetchAPI(`/chapters`)
return {
props: { chapter: chapter[0], chapters },
revalidate: 1,
}
}
Clone the project
git clone https://github.com/cbgaindia/budget-basic-next.git
Go to the project directory
cd budget-basic-next
Install dependencies
npm install
Create .env in the root folder and follows keys
NEXT_PUBLIC_STRAPI_API_URL
NEXT_PUBLIC_MEILISEARCH_URL
NEXT_PUBLIC_MEILISEARCH_API
Start the server in development
npm run dev
or build and start production mode
npm run build && npm run start
For any new feature or bug reports, please request it in issues.
See CONTRIBUTING.md for ways to get started.
Please adhere to Code of Conduct.