Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
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
4 changes: 4 additions & 0 deletions .github/workflows/run-ci-cd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ jobs:
echo "NEXT_PUBLIC_IDX_URL=${{ secrets.VITE_IDX_URL }}" >> frontend/.env
echo "NEXT_PUBLIC_RELEASE_VERSION=${{ github.event.release.tag_name }}" >> frontend/.env
echo "NEXT_PUBLIC_SENTRY_DSN=${{ secrets.VITE_SENTRY_DSN }}" >> frontend/.env
echo "NEXT_SERVER_CSRF_URL=${{ secrets.NEXT_SERVER_CSRF_URL }}" >> frontend/.env
echo "NEXT_SERVER_GRAPHQL_URL=${{ secrets.NEXT_SERVER_GRAPHQL_URL }}" >> frontend/.env

- name: Build frontend image
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1
Expand Down Expand Up @@ -431,6 +433,8 @@ jobs:
echo "NEXT_PUBLIC_IDX_URL=${{ secrets.VITE_IDX_URL }}" >> frontend/.env
echo "NEXT_PUBLIC_RELEASE_VERSION=${{ github.event.release.tag_name }}" >> frontend/.env
echo "NEXT_PUBLIC_SENTRY_DSN=${{ secrets.VITE_SENTRY_DSN }}" >> frontend/.env
echo "NEXT_SERVER_CSRF_URL=${{ secrets.NEXT_SERVER_CSRF_URL }}" >> frontend/.env
echo "NEXT_SERVER_GRAPHQL_URL=${{ secrets.NEXT_SERVER_GRAPHQL_URL }}" >> frontend/.env

- name: Build frontend image
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1
Expand Down
3 changes: 3 additions & 0 deletions frontend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ NEXT_PUBLIC_GTM_PREVIEW=
NEXT_PUBLIC_IDX_URL=http://localhost:8000/idx/
NEXT_PUBLIC_RELEASE_VERSION=
NEXT_PUBLIC_SENTRY_DSN=
NEXT_SERVER_CSRF_URL=http://backend:8000/csrf/
NEXT_SERVER_DISABLE_SSR=false
NEXT_SERVER_GRAPHQL_URL=http://backend:8000/graphql/
2 changes: 1 addition & 1 deletion frontend/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const config: Config = {
'src/**/*.{js,jsx,ts,tsx}',
'!src/**/*.d.ts',
'!src/api/**',
'!src/app/layout.tsx',
'!src/app/**/layout.tsx',
'!src/components/**',
'!src/hooks/**',
'!src/instrumentation.ts',
Expand Down
2 changes: 1 addition & 1 deletion frontend/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default defineConfig({
trace: 'off',
},
webServer: {
command: 'pnpm run build:turbo && pnpm run start',
command: 'pnpm run build:turbo && NEXT_SERVER_DISABLE_SSR=true pnpm run start',
timeout: 120_000,
url: 'http://localhost:3000',
},
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/app/about/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Metadata } from 'next'
import React from 'react'
import { getStaticMetadata } from 'utils/metaconfig'

export const metadata: Metadata = getStaticMetadata('about', '/about')

export default function AboutLayout({ children }: { children: React.ReactNode }) {
return children
}
35 changes: 35 additions & 0 deletions frontend/src/app/chapters/[chapterKey]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Metadata } from 'next'
import React from 'react'
import { apolloClient } from 'server/apolloClient'
import { GET_CHAPTER_METADATA } from 'server/queries/chapterQueries'
import { generateSeoMetadata } from 'utils/metaconfig'

export async function generateMetadata({
params,
}: {
params: Promise<{ chapterKey: string }>
}): Promise<Metadata> {
const { chapterKey } = await params
const { data } = await apolloClient.query({
query: GET_CHAPTER_METADATA,
variables: {
key: chapterKey,
},
})
const chapter = data?.chapter

return chapter
? generateSeoMetadata({
canonicalPath: `/chapters/${chapterKey}`,
description: chapter.summary ?? `${chapter.name} chapter details`,
keywords: ['owasp', 'security', 'chapter', chapterKey, chapter.name],
title: chapter.name,
})
: null
}

export default function ChapterDetailsLayout({
children,
}: Readonly<{ children: React.ReactNode }>) {
return children
}
9 changes: 9 additions & 0 deletions frontend/src/app/chapters/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Metadata } from 'next'
import React from 'react'
import { getStaticMetadata } from 'utils/metaconfig'

export const metadata: Metadata = getStaticMetadata('chapters', '/chapters')

export default function ChaptersLayout({ children }: { children: React.ReactNode }) {
return children
}
37 changes: 37 additions & 0 deletions frontend/src/app/committees/[committeeKey]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Metadata } from 'next'
import React from 'react'
import { apolloClient } from 'server/apolloClient'
import { GET_COMMITTEE_METADATA } from 'server/queries/committeeQueries'
import { generateSeoMetadata } from 'utils/metaconfig'

export async function generateMetadata({
params,
}: {
params: Promise<{ committeeKey: string }>
}): Promise<Metadata> {
const { committeeKey } = await params
const { data } = await apolloClient.query({
query: GET_COMMITTEE_METADATA,
variables: {
key: committeeKey,
},
})
const committee = data?.committee

return committee
? generateSeoMetadata({
canonicalPath: `/committees/${committeeKey}`,
description: committee.summary ?? `${committee.name} details`,
keywords: ['owasp', 'security', 'committee', committeeKey, committee.name],
title: committee.name,
})
: null
}

export default function CommitteeDetailsLayout({
children,
}: Readonly<{
children: React.ReactNode
}>) {
return children
}
9 changes: 9 additions & 0 deletions frontend/src/app/committees/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Metadata } from 'next'
import React from 'react'
import { getStaticMetadata } from 'utils/metaconfig'

export const metadata: Metadata = getStaticMetadata('committees', '/committees')

export default function CommitteesLayout({ children }: { children: React.ReactNode }) {
return children
}
8 changes: 8 additions & 0 deletions frontend/src/app/contribute/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import React from 'react'
import { getStaticMetadata } from 'utils/metaconfig'

export const metadata = getStaticMetadata('contribute', '/contribute')

export default function ContributeLayout({ children }: { children: React.ReactNode }) {
return children
}
26 changes: 25 additions & 1 deletion frontend/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,31 @@ const geistMono = Geist_Mono({

export const metadata: Metadata = {
title: 'OWASP Nest',
description: 'OWASP Nest',
description: 'Your gateway to OWASP. Discover, engage, and help shape the future!',
openGraph: {
title: 'OWASP Nest',
description: 'Your gateway to OWASP. Discover, engage, and help shape the future!',
url: 'https://nest.owasp.org/',
siteName: 'OWASP Nest',
images: [
{
url: 'https://nest.owasp.org/img/owasp_icon_white_background.png',
width: 1200,
height: 630,
alt: 'OWASP logo',
},
],
locale: 'en_US',
type: 'website',
},
twitter: {
card: 'summary_large_image',
title: 'Home – OWASP Nest',
description: 'Your gateway to OWASP. Discover, engage, and help shape the future!',
images: ['https://nest.owasp.org/img/owasp_icon_white_background.png'],
creator: '@owasp',
site: '@owasp',
},
icons: {
icon: 'https://owasp.org/www--site-theme/favicon.ico',
shortcut: 'https://owasp.org/www--site-theme/favicon.ico',
Expand Down
34 changes: 34 additions & 0 deletions frontend/src/app/members/[memberKey]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Metadata } from 'next'
import React from 'react'
import { apolloClient } from 'server/apolloClient'
import { GET_USER_METADATA } from 'server/queries/userQueries'
import { generateSeoMetadata } from 'utils/metaconfig'

export async function generateMetadata({
params,
}: {
params: Promise<{ memberKey: string }>
}): Promise<Metadata> {
const { memberKey } = await params
const { data } = await apolloClient.query({
query: GET_USER_METADATA,
variables: {
key: memberKey,
},
})
const user = data?.user
const title = user?.name ?? user?.login

return user
? generateSeoMetadata({
canonicalPath: `/members/${memberKey}`,
description: user.bio ?? `${title} OWASP community member details.`,
keywords: [user.login, user.name, 'owasp', 'owasp community member'],
title: title,
})
: null
}

export default function UserDetailsLayout({ children }: { children: React.ReactNode }) {
return children
}
9 changes: 9 additions & 0 deletions frontend/src/app/members/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Metadata } from 'next'
import React from 'react'
import { getStaticMetadata } from 'utils/metaconfig'

export const metadata: Metadata = getStaticMetadata('members', '/members')

export default function UsersLayout({ children }: { children: React.ReactNode }) {
return children
}
33 changes: 33 additions & 0 deletions frontend/src/app/organizations/[organizationKey]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Metadata } from 'next'
import React from 'react'
import { apolloClient } from 'server/apolloClient'
import { GET_ORGANIZATION_METADATA } from 'server/queries/organizationQueries'
import { generateSeoMetadata } from 'utils/metaconfig'

export async function generateMetadata({
params,
}: {
params: Promise<{ organizationKey: string }>
}): Promise<Metadata> {
const { organizationKey } = await params
const { data } = await apolloClient.query({
query: GET_ORGANIZATION_METADATA,
variables: {
login: organizationKey,
},
})
const organization = data?.organization
const title = organization?.name ?? organization?.login

return organization
? generateSeoMetadata({
canonicalPath: `/organizations/${organizationKey}`,
description: organization?.description ?? `${title} organization details`,
title: title,
})
: null
}

export default function OrganizationDetailsLayout({ children }: { children: React.ReactNode }) {
return children
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Metadata } from 'next'
import React from 'react'
import { apolloClient } from 'server/apolloClient'
import { GET_REPOSITORY_METADATA } from 'server/queries/repositoryQueries'
import { generateSeoMetadata } from 'utils/metaconfig'

export async function generateMetadata({
params,
}: {
params: Promise<{
repositoryKey: string
organizationKey: string
}>
}): Promise<Metadata> {
const { repositoryKey, organizationKey } = await params
const { data } = await apolloClient.query({
query: GET_REPOSITORY_METADATA,
variables: { organizationKey: organizationKey, repositoryKey: repositoryKey },
})
const repository = data?.repository

return repository
? generateSeoMetadata({
canonicalPath: `/organizations/${organizationKey}/repositories/${repositoryKey}`,
description: repository.description ?? `${repository.name} repository details`,
keywords: ['owasp', 'repository', repositoryKey, repository.name],
title: repository.name,
})
: null
}

export default function RepositoryDetailsLayout({ children }: { children: React.ReactNode }) {
return children
}
9 changes: 9 additions & 0 deletions frontend/src/app/organizations/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Metadata } from 'next'
import React from 'react'
import { getStaticMetadata } from 'utils/metaconfig'

export const metadata: Metadata = getStaticMetadata('organizations', '/organizations')

export default function OrganizationsLayout({ children }: { children: React.ReactNode }) {
return children
}
35 changes: 35 additions & 0 deletions frontend/src/app/projects/[projectKey]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Metadata } from 'next'
import React from 'react'
import { apolloClient } from 'server/apolloClient'
import { GET_PROJECT_METADATA } from 'server/queries/projectQueries'
import { generateSeoMetadata } from 'utils/metaconfig'

export async function generateMetadata({
params,
}: {
params: Promise<{
projectKey: string
}>
}): Promise<Metadata> {
const { projectKey } = await params
const { data } = await apolloClient.query({
query: GET_PROJECT_METADATA,
variables: {
key: projectKey,
},
})
const project = data?.project

return project
? generateSeoMetadata({
canonicalPath: `/projects/${projectKey}`,
description: project.summary ?? `${project.name} project details`,
keywords: ['owasp', 'project', projectKey, project.name],
title: project.name,
})
: null
}

export default function ProjectDetailsLayout({ children }: { children: React.ReactNode }) {
return children
}
9 changes: 9 additions & 0 deletions frontend/src/app/projects/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Metadata } from 'next'
import React from 'react'
import { getStaticMetadata } from 'utils/metaconfig'

export const metadata: Metadata = getStaticMetadata('projects', '/projects')

export default function ProjectsLayout({ children }: { children: React.ReactNode }) {
return children
}
30 changes: 30 additions & 0 deletions frontend/src/app/snapshots/[id]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Metadata } from 'next'
import React from 'react'
import { apolloClient } from 'server/apolloClient'
import { GET_SNAPSHOT_DETAILS_METADATA } from 'server/queries/snapshotQueries'
import { generateSeoMetadata } from 'utils/metaconfig'

export async function generateMetadata({
params,
}: {
params: Promise<{ id: string }>
}): Promise<Metadata> {
const { id: snapshotKey } = await params
const { data } = await apolloClient.query({
query: GET_SNAPSHOT_DETAILS_METADATA,
variables: { key: snapshotKey },
})
const snapshot = data?.snapshot

return snapshot
? generateSeoMetadata({
canonicalPath: `/snapshots/${snapshotKey}`,
description: `${snapshot?.title} details.`,
keywords: ['owasp', 'snapshot', snapshotKey, snapshot?.title],
title: snapshot?.title,
})
: null
}
export default function SnapshotDetailsLayout({ children }: { children: React.ReactNode }) {
return children
}
8 changes: 8 additions & 0 deletions frontend/src/app/snapshots/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import React from 'react'
import { getStaticMetadata } from 'utils/metaconfig'

export const metadata = getStaticMetadata('snapshots', '/snapshots')

export default function SnapshotsLayout({ children }: { children: React.ReactNode }) {
return children
}
Loading