The website is built with Next.js and integrated with Contentful CMS (headless) for content management. It leverages Next.js App Router and Server-Side Rendering (SSR). Styled with Tailwind CSS, interactive animations powered by Framer Motion.
- Server components (default): Most UI is rendered on the server. By rendering most components on the server, the site ships less JavaScript to the browser, improving performance and reducing hydration overhead. Components requiring interactivity opt into the browser using the
'use client'directive. - Data fetching: Content is fetched from GraphQL Contentful API.
The website content is managed through Contentful, a headless CMS service. Login credentials are available in Bitwarden. A quick guide of Contentful and the setup can be found in Google Drive.
Content structure:
- Pages: Each route corresponds to a page in Contentful, fetched by their unique ID
- Sections: Pages are composed of different section types that can be mixed and matched
- Publishing: Content changes are either in draft or published state
- Published changes reflect immediately on the live site (may take up to 60 seconds)
- No local CMS hosting required - fully managed service
Workflow:
- Log into Contentful
- Edit or create content
- Publish when ready - changes go live instantly
The website supports English (default in Contentful) and Swedish as options.
The project auto-detects the browser language through a middleware that runs on the server and set a cookie in the browser and redirects if necessary. User can toggle language from the navigation menu.
- English (default):
/en/careers,/en/about,/en/services - Swedish:
/karriar,/om-oss,/tjanster
Swedish routes have no prefix, while English routes are prefixed with /en/.
Contentful setup:
- All content is localized in Contentful with Swedish and English locales
- Navigation links are stored as a separate content type (
navigationLink) with:title: Display name in each languageslug: URL path (e.g.,/karriarin Swedish,/en/careersin English)isExternal: Boolean flag for external links
- Both language versions of a navigation link share the same
sys.id, enabling automatic route mapping
Implementation:
- Navigation links are fetched from Contentful based on the current locale
- A route map is dynamically built by matching Swedish and English links via their
sys.id - The language switcher uses this route map to navigate between corresponding pages
- Page content is fetched with the appropriate locale parameter
Adding new translated pages:
- Create the page content in Contentful for both locales
- Add navigation links for both Swedish and English versions with matching
sys.id - Ensure the English slug includes the
/en/prefix - Create route folders matching the slugs:
app/
├── (routes)/
│ ├── karriar/ # Swedish route
│ └── en/
│ └── careers/ # English route
- Both route components fetch the same content ID but with different locale parameters
The project automatically detects the current locale from the URL path. Swedish content is fetched when no locale is specified, and English content is fetched when the URL starts with /en.
Metadata is generated for every page in both languages and can be customized in metadata.ts. The sitemap is automatically created from sitemap.ts.
- Node.js 20 or higher
- npm, yarn
- Clone the repository
- Install dependencies:
npm install- Set up environment variables. You can find the required values in the relevant Contentful/Google Analytics item notes in Bitwarden.
npm run dev # Start development server with Turbopack
npm run build # Create production build with Turbopack
npm run start # Start production servernpm run lint # Run ESLint
npm run format # Format code with PrettierThe application is deployed on Netlify, as with all of Etimos products.
Changes pushed to the main branch are automatically deployed.