Skip to content

Commit 9060d7c

Browse files
authored
Merge pull request #1378 from datopian/feature/openmetadata-landing-page
Try a new landing page for Open Metadata integration with PortalJS.
2 parents 17678f0 + 3ecbb69 commit 9060d7c

File tree

11 files changed

+552
-17
lines changed

11 files changed

+552
-17
lines changed

site/components/FAQStructuredData.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import React from 'react';
2+
3+
interface FAQItem {
4+
question: string;
5+
answer: string;
6+
}
7+
8+
interface FAQStructuredDataProps {
9+
questions: FAQItem[];
10+
}
11+
12+
export default function FAQStructuredData({ questions }: FAQStructuredDataProps) {
13+
const structuredData = {
14+
"@context": "https://schema.org",
15+
"@type": "FAQPage",
16+
"mainEntity": questions.map(q => ({
17+
"@type": "Question",
18+
"name": q.question,
19+
"acceptedAnswer": {
20+
"@type": "Answer",
21+
"text": q.answer
22+
}
23+
}))
24+
};
25+
26+
return (
27+
<script
28+
type="application/ld+json"
29+
dangerouslySetInnerHTML={{ __html: JSON.stringify(structuredData) }}
30+
/>
31+
);
32+
}

site/components/NavItem.tsx

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,19 @@ export function NavItem({ item, target }) {
3535
{item.name}
3636
</Link>
3737
) : (
38-
<div className="text-slate-400 inline-flex items-center mr-2 px-1 pt-1 text-sm font-medium hover:text-slate-300 fill-slate-500 hover:fill-slate-600 transition duration-300">
38+
<div className="text-slate-400 inline-flex items-center mr-2 px-1 pt-1 text-sm font-medium hover:text-slate-300 fill-slate-500 hover:fill-slate-600 transition duration-300">
3939
{item.name}
40+
{Object.prototype.hasOwnProperty.call(item, "subItems") && (
41+
<svg
42+
xmlns="http://www.w3.org/2000/svg"
43+
className="h-4 w-4 ml-1 text-slate-400"
44+
fill="none"
45+
viewBox="0 0 24 24"
46+
stroke="currentColor"
47+
>
48+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
49+
</svg>
50+
)}
4051
</div>
4152
)}
4253
</Menu.Button>
@@ -53,7 +64,7 @@ export function NavItem({ item, target }) {
5364
leaveTo="transform opacity-0 scale-5"
5465
>
5566
<Menu.Items
56-
className="absolute top-5 flex flex-col dark:bg-slate-900/95 backdrop-blur"
67+
className="absolute top-5 flex flex-col bg-white dark:bg-slate-900/95 backdrop-blur shadow-lg rounded-md py-2 px-3"
5768
ref={dropdownRef}
5869
onMouseEnter={openDropdown}
5970
onMouseLeave={closeDropdown}
@@ -64,13 +75,19 @@ export function NavItem({ item, target }) {
6475
// @ts-ignore
6576
onClick={() => setshowDropdown(false)}
6677
>
67-
<BaseLink
68-
href={subItem.href}
69-
title={subItem.name}
70-
className="text-slate-500 inline-flex items-center mt-2 px-1 pt-1 text-sm font-medium hover:text-slate-600"
71-
>
72-
{subItem.name}
73-
</BaseLink>
78+
{subItem.disabled ? (
79+
<span className={`text-slate-400 cursor-not-allowed inline-flex items-center py-2 px-1 text-sm font-medium ${subItem.style || ''}`}>
80+
{subItem.name}
81+
</span>
82+
) : (
83+
<BaseLink
84+
href={subItem.href}
85+
title={subItem.name}
86+
className="text-slate-700 dark:text-slate-300 inline-flex items-center py-2 px-1 text-sm font-medium hover:text-blue-500 dark:hover:text-blue-400"
87+
>
88+
{subItem.name}
89+
</BaseLink>
90+
)}
7491
</Menu.Item>
7592
))}
7693
</Menu.Items>

site/components/home/Schedule.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import ButtonLink from '../ButtonLink'
22
import { H2, H3 } from '../custom/header'
33

4-
export default function Schedule() {
4+
interface ScheduleProps {
5+
calendar?: string;
6+
}
7+
8+
export default function Schedule({ calendar = "https://calendar.app.google/sn2PU7ZvzjCPo1ok6" }: ScheduleProps) {
59
return (
610
<div className="!max-w-none ring-1 ring-slate-200 dark:ring-slate-800 py-24 bg-zinc-50 dark:bg-slate-800/75 mt-24 relative overflow-hidden ">
711
<div className="relative max-w-8xl mx-auto">
@@ -14,15 +18,15 @@ export default function Schedule() {
1418
</div>
1519
<div className="flex justify-center py-8 max-w-lg mx-auto gap-6">
1620
<ButtonLink
17-
href="https://calendar.app.google/sn2PU7ZvzjCPo1ok6"
21+
href={calendar}
1822
title="Get started with PortalJS Cloud"
1923
className="text-sm"
2024
target="_blank"
2125
>
2226
Schedule a free call
2327
</ButtonLink>
2428
<ButtonLink
25-
href="https://calendar.app.google/sn2PU7ZvzjCPo1ok6"
29+
href={calendar}
2630
title="Book a demo"
2731
style="secondary"
2832
className="text-sm"
@@ -43,9 +47,6 @@ export default function Schedule() {
4347
className="aspect-[1318/752] w-[82.375rem] flex-none bg-gradient-to-r from-[#80caff] to-[#4f46e5] opacity-25 rotate-180"
4448
/>
4549
</div>
46-
<p className="text-center">
47-
No credit card required. 14-day free trial.
48-
</p>
4950
</div>
5051
</div>
5152
)
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { Player } from '@lottiefiles/react-lottie-player'
2+
import { H2, H3 } from '../custom/header'
3+
import { useTheme } from 'next-themes'
4+
5+
export const CommonUseCases = () => {
6+
const { theme } = useTheme()
7+
const features = [
8+
{
9+
title: 'Business-Friendly Data Catalogs',
10+
description:
11+
'Transform OpenMetadata\'s technical interface into intuitive experiences for non-technical users. Create simplified views of complex metadata that business teams can easily navigate and understand.',
12+
icon: `/static/icons/${theme}/data-portal.json`,
13+
style: 'dark:-rotate-[4deg]',
14+
},
15+
{
16+
title: 'Multi-Audience Portals',
17+
description:
18+
'Deploy separate interfaces for different user groups—detailed technical portals for data engineers, simplified asset browsers for analysts, and executive dashboards for leadership—all from a single OpenMetadata instance.',
19+
icon: `/static/icons/${theme}/diagram.json`,
20+
style: 'dark:-rotate-[4deg]',
21+
},
22+
{
23+
title: 'Custom Data Experiences',
24+
description:
25+
'Overcome OpenMetadata\'s UI customization limitations by building completely bespoke interfaces with your branding, terminology, and user flows while leveraging all the powerful metadata management capabilities in the background.',
26+
icon: `/static/icons/${theme}/seminar.json`,
27+
style: 'dark:-rotate-[4deg]',
28+
},
29+
]
30+
31+
return (
32+
<div className="py-24">
33+
<div className="">
34+
<H2 className="text-center mb-4">Common Use Cases</H2>
35+
<H3 className="text-center opacity-75">
36+
Still wondering how PortalJS would fit into your org? These are the most popular ways teams use it.
37+
</H3>
38+
<div className="mt-16 grid grid-cols-1 gap-y-12 sm:gap-x-12 lg:grid-cols-3 lg:gap-x-6">
39+
{features.map((feature) => (
40+
<div
41+
key={feature.title}
42+
className="relative flex flex-col rounded-xl dark:bg-slate-900 dark:hover:bg-slate-800 hover:bg-slate-100 transition-all duration-300 ring-1 ring-slate-200 dark:ring-slate-800 p-7 shadow-lg overflow-hidden"
43+
>
44+
<div className="flex-shrink-0 w-full flex items-start -ml-2">
45+
<Player
46+
autoplay
47+
loop
48+
src={feature.icon}
49+
className={`w-14 h-14 ${feature.style}`}
50+
/>
51+
</div>
52+
<div className="pt-4">
53+
<h3 className="text-lg font-medium ">{feature.title}</h3>
54+
<p className="mt-4 text-base text-gray-400">
55+
{feature.description}
56+
</p>
57+
</div>
58+
</div>
59+
))}
60+
</div>
61+
</div>
62+
</div>
63+
)
64+
}

site/components/openmetadata/FAQ.tsx

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { Disclosure } from '@headlessui/react'
2+
import ReactMarkdown from 'react-markdown'
3+
4+
const questions = [
5+
{
6+
question: 'What is PortalJS?',
7+
answer:
8+
'PortalJS is a modern frontend framework (Next.js-based) for building fast, customizable data portals — compatible with OpenMetadata, CKAN, and other backends.'
9+
},
10+
{
11+
question: 'Does PortalJS replace OpenMetadata?',
12+
answer:
13+
'No. It works with your OpenMetadata backend — just replaces the frontend for better UX.'
14+
},
15+
{
16+
question: 'Can I use PortalJS without modifying OpenMetadata\'s backend?',
17+
answer: 'Yes. PortalJS works as a decoupled frontend — no need to touch your metadata engine.'
18+
},
19+
{
20+
question: 'Is this open source or commercial?',
21+
answer:
22+
'PortalJS is open source. PortalJS Cloud offers a fully managed SaaS version with support and custom features.'
23+
}
24+
]
25+
26+
export function FAQ() {
27+
return (
28+
<div className="py-16 w-full">
29+
<section className="flex flex-col items-center w-full">
30+
<h2 className="text-3xl font-bold tracking-tight text-slate-900 dark:text-white mb-10 text-center">
31+
Quick FAQs
32+
</h2>
33+
<div className="flex flex-col space-y-6 w-full max-w-3xl mx-auto">
34+
{questions.map((question, index) => (
35+
<Disclosure key={question.question} as="div">
36+
{({ open }) => (
37+
<>
38+
<Disclosure.Button className="flex justify-between w-full px-4 py-2 text-lg font-medium text-left dark:text-white focus:outline-none focus-visible:ring focus-visible:ring-primary-500 focus-visible:ring-opacity-75 p-6 group">
39+
<span className="group-hover:text-blue-400 transition">
40+
{question.question}
41+
</span>
42+
<svg
43+
className={`${
44+
open ? 'transform rotate-180' : ''
45+
} w-5 h-5 dark:text-white`}
46+
xmlns="http://www.w3.org/2000/svg"
47+
viewBox="0 0 20 20"
48+
fill="currentColor"
49+
aria-hidden="true"
50+
>
51+
<path
52+
fillRule="evenodd"
53+
d="M10 12a1 1 0 01-.7-.29l-4-4a1 1 0 111.42-1.42L10 10.59l3.29-3.3a1 1 0 111.42 1.42l-4 4a1 1 0 01-.71.29z"
54+
clipRule="evenodd"
55+
/>
56+
</svg>
57+
</Disclosure.Button>
58+
<Disclosure.Panel className="px-4 pt-3 pb-5 text-base dark:text-gray-300 prose dark:prose-dark dark:prose-invert max-w-none">
59+
<ReactMarkdown>{question.answer}</ReactMarkdown>
60+
</Disclosure.Panel>
61+
{index < questions.length - 1 && (
62+
<hr className="mt-5 border-t border-gray-200 dark:border-gray-700" />
63+
)}
64+
</>
65+
)}
66+
</Disclosure>
67+
))}
68+
</div>
69+
</section>
70+
</div>
71+
)
72+
}

site/components/openmetadata/Hero.tsx

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import React from 'react';
2+
import ButtonLink from '../ButtonLink';
3+
import { useTheme } from 'next-themes';
4+
5+
export default function Hero() {
6+
const { theme } = useTheme();
7+
8+
return (
9+
<div
10+
className="overflow-hidden -mb-32 mt-[-4.5rem] pb-32 pt-[4.5rem] lg:mt-[-4.75rem] lg:pt-[4.75rem]"
11+
id="hero"
12+
>
13+
<div className="py-16 sm:px-2 lg:relative lg:py-20 lg:px-0">
14+
<div className="mx-auto max-w-2xl px-4 lg:max-w-8xl lg:px-8 xl:px-12">
15+
<div className="relative mb-10 lg:mb-0 text-center">
16+
<h1 className="inline bg-gradient-to-r from-blue-500 via-blue-300 to-blue-500 bg-clip-text text-5xl tracking-tight text-transparent">
17+
OpenMetadata & PortalJS
18+
</h1>
19+
<p className="mt-8 text-xl tracking-tight text-slate-400">
20+
Transform OpenMetadata's technical interface into user-friendly, customized data catalogs for business users.
21+
</p>
22+
23+
<div className="flex flex-col sm:flex-row items-center justify-center gap-4 mt-8">
24+
<ButtonLink
25+
href="https://calendar.app.google/sn2PU7ZvzjCPo1ok6"
26+
title="Book a Free Consultation"
27+
className="text-sm"
28+
>
29+
Book a Free Consultation
30+
</ButtonLink>
31+
</div>
32+
33+
<div className="mt-16 mb-12 flex flex-col md:flex-row items-center justify-center gap-8">
34+
<div className="bg-slate-800 dark:bg-slate-900 p-6 rounded-xl shadow-xl w-full md:w-1/2 relative">
35+
<div className="absolute -top-4 left-1/2 transform -translate-x-1/2 bg-red-500 text-white text-xs px-2 py-1 rounded-full">
36+
Without PortalJS
37+
</div>
38+
<h3 className="text-white text-lg mb-4">Technical OpenMetadata UI</h3>
39+
<ul className="text-left text-slate-300 text-sm space-y-2">
40+
<li className="flex items-start">
41+
<span className="mr-2"></span>
42+
<span>Complex, developer-oriented UI</span>
43+
</li>
44+
<li className="flex items-start">
45+
<span className="mr-2"></span>
46+
<span>Hard for business users to explore metadata</span>
47+
</li>
48+
<li className="flex items-start">
49+
<span className="mr-2"></span>
50+
<span>Limited frontend customization</span>
51+
</li>
52+
</ul>
53+
</div>
54+
55+
<div className="bg-slate-100 dark:bg-slate-800 p-6 rounded-xl shadow-xl w-full md:w-1/2 relative">
56+
<div className="absolute -top-4 left-1/2 transform -translate-x-1/2 bg-green-500 text-white text-xs px-2 py-1 rounded-full">
57+
With PortalJS
58+
</div>
59+
<h3 className="text-slate-800 dark:text-white text-lg mb-4">Business-Friendly UI</h3>
60+
<ul className="text-left text-slate-700 dark:text-slate-300 text-sm space-y-2">
61+
<li className="flex items-start">
62+
<span className="mr-2"></span>
63+
<span>Clean, user-friendly experience</span>
64+
</li>
65+
<li className="flex items-start">
66+
<span className="mr-2"></span>
67+
<span>Tailored portals for every department</span>
68+
</li>
69+
<li className="flex items-start">
70+
<span className="mr-2"></span>
71+
<span>Fully customizable interface & workflows</span>
72+
</li>
73+
</ul>
74+
</div>
75+
</div>
76+
77+
</div>
78+
</div>
79+
</div>
80+
</div>
81+
);
82+
}

0 commit comments

Comments
 (0)