feature(public,docs): new public website and docs

This commit is contained in:
Carl-Gerhard Lindesvärd
2024-11-13 21:15:46 +01:00
parent fc2a019e1d
commit a022cb4831
234 changed files with 9341 additions and 6154 deletions

View File

@@ -1,20 +0,0 @@
import { Navbar } from '../navbar';
interface Props {
children: React.ReactNode;
}
export default function Layout({ children }: Props) {
return (
<>
<Navbar darkText />
<div
className="absolute left-0 right-0 top-0 z-0 h-screen w-full bg-[radial-gradient(circle_at_2px_2px,#D9DEF6_2px,transparent_0)] text-blue-950 opacity-50"
style={{
backgroundSize: '70px 70px',
}}
/>
<div className="relative">{children}</div>
</>
);
}

View File

@@ -1,525 +0,0 @@
import { Heading1 } from '../../copy';
export const dynamic = 'force-dynamic';
export const revalidate = 3600;
export default function Page() {
return (
<div className="container mt-[150px] max-w-2xl">
<article className="prose">
<Heading1>Privacy Policy</Heading1>
<p>Last updated: February 22, 2024</p>
<p>
This Privacy Policy describes Our policies and procedures on the
collection, use and disclosure of Your information when You use the
Service and tells You about Your privacy rights and how the law
protects You.
</p>
<p>
We use Your Personal data to provide and improve the Service. By using
the Service, You agree to the collection and use of information in
accordance with this Privacy Policy.
</p>
<h2>Interpretation and Definitions</h2>
<h3>Interpretation</h3>
<p>
The words of which the initial letter is capitalized have meanings
defined under the following conditions. The following definitions
shall have the same meaning regardless of whether they appear in
singular or in plural.
</p>
<h3>Definitions</h3>
<p>For the purposes of this Privacy Policy:</p>
<ul>
<li>
<p>
<strong>Account</strong> means a unique account created for You to
access our Service or parts of our Service.
</p>
</li>
<li>
<p>
<strong>Affiliate</strong> means an entity that controls, is
controlled by or is under common control with a party, where
&quot;control&quot; means ownership of 50% or more of the shares,
equity interest or other securities entitled to vote for election
of directors or other managing authority.
</p>
</li>
<li>
<p>
<strong>Application</strong> refers to Openpanel, the software
program provided by the Company.
</p>
</li>
<li>
<p>
<strong>Company</strong> (referred to as either &quot;the
Company&quot;, &quot;We&quot;, &quot;Us&quot; or &quot;Our&quot;
in this Agreement) refers to Coderax AB, Sankt Eriksgatan 100, 113
31, Stockholm.
</p>
</li>
<li>
<p>
<strong>Cookies</strong> are small files that are placed on Your
computer, mobile device or any other device by a website,
containing the details of Your browsing history on that website
among its many uses.
</p>
</li>
<li>
<p>
<strong>Country</strong> refers to: Sweden
</p>
</li>
<li>
<p>
<strong>Device</strong> means any device that can access the
Service such as a computer, a cellphone or a digital tablet.
</p>
</li>
<li>
<p>
<strong>Personal Data</strong> is any information that relates to
an identified or identifiable individual.
</p>
</li>
<li>
<p>
<strong>Service</strong> refers to the Application or the Website
or both.
</p>
</li>
<li>
<p>
<strong>Service Provider</strong> means any natural or legal
person who processes the data on behalf of the Company. It refers
to third-party companies or individuals employed by the Company to
facilitate the Service, to provide the Service on behalf of the
Company, to perform services related to the Service or to assist
the Company in analyzing how the Service is used.
</p>
</li>
<li>
<p>
<strong>Usage Data</strong> refers to data collected
automatically, either generated by the use of the Service or from
the Service infrastructure itself (for example, the duration of a
page visit).
</p>
</li>
<li>
<p>
<strong>Website</strong> refers to Openpanel, accessible from{' '}
<a
href="https://openpanel.dev"
rel="noreferrer external nofollow noopener"
target="_blank"
>
https://openpanel.dev
</a>
</p>
</li>
<li>
<p>
<strong>You</strong> means the individual accessing or using the
Service, or the company, or other legal entity on behalf of which
such individual is accessing or using the Service, as applicable.
</p>
</li>
</ul>
<h2>Collecting and Using Your Personal Data</h2>
<h3>Types of Data Collected</h3>
<h4>Personal Data</h4>
<p>
While using Our Service, We may ask You to provide Us with certain
personally identifiable information that can be used to contact or
identify You. Personally identifiable information may include, but is
not limited to:
</p>
<ul>
<li>
<p>Email address</p>
</li>
<li>
<p>First name and last name</p>
</li>
<li>
<p>Usage Data</p>
</li>
</ul>
<h4>Usage Data</h4>
<p>Usage Data is collected automatically when using the Service.</p>
<p>
Usage Data may include information such as Your Device&apos;s Internet
Protocol address (e.g. IP address), browser type, browser version, the
pages of our Service that You visit, the time and date of Your visit,
the time spent on those pages, unique device identifiers and other
diagnostic data.
</p>
<p>
When You access the Service by or through a mobile device, We may
collect certain information automatically, including, but not limited
to, the type of mobile device You use, Your mobile device unique ID,
the IP address of Your mobile device, Your mobile operating system,
the type of mobile Internet browser You use, unique device identifiers
and other diagnostic data.
</p>
<p>
We may also collect information that Your browser sends whenever You
visit our Service or when You access the Service by or through a
mobile device.
</p>
<h4>Tracking Technologies and Cookies</h4>
<p>
We use Cookies and similar tracking technologies to track the activity
on Our Service and store certain information. Tracking technologies
used are beacons, tags, and scripts to collect and track information
and to improve and analyze Our Service. The technologies We use may
include:
</p>
<ul>
<li>
<strong>Cookies or Browser Cookies.</strong> A cookie is a small
file placed on Your Device. You can instruct Your browser to refuse
all Cookies or to indicate when a Cookie is being sent. However, if
You do not accept Cookies, You may not be able to use some parts of
our Service. Unless you have adjusted Your browser setting so that
it will refuse Cookies, our Service may use Cookies.
</li>
<li>
<strong>Web Beacons.</strong> Certain sections of our Service and
our emails may contain small electronic files known as web beacons
(also referred to as clear gifs, pixel tags, and single-pixel gifs)
that permit the Company, for example, to count users who have
visited those pages or opened an email and for other related website
statistics (for example, recording the popularity of a certain
section and verifying system and server integrity).
</li>
</ul>
<p>
Cookies can be &quot;Persistent&quot; or &quot;Session&quot; Cookies.
Persistent Cookies remain on Your personal computer or mobile device
when You go offline, while Session Cookies are deleted as soon as You
close Your web browser. You can learn more about cookies{' '}
<a
href="https://www.termsfeed.com/blog/cookies/#What_Are_Cookies"
target="_blank"
rel="noreferrer nofollow"
>
here
</a>
.
</p>
<p>
We use both Session and Persistent Cookies for the purposes set out
below:
</p>
<ul>
<li>
<p>
<strong>Necessary / Essential Cookies</strong>
</p>
<p>Type: Session Cookies</p>
<p>Administered by: Us</p>
<p>
Purpose: These Cookies are essential to provide You with services
available through the Website and to enable You to use some of its
features. They help to authenticate users and prevent fraudulent
use of user accounts. Without these Cookies, the services that You
have asked for cannot be provided, and We only use these Cookies
to provide You with those services.
</p>
</li>
<li>
<p>
<strong>Cookies Policy / Notice Acceptance Cookies</strong>
</p>
<p>Type: Persistent Cookies</p>
<p>Administered by: Us</p>
<p>
Purpose: These Cookies identify if users have accepted the use of
cookies on the Website.
</p>
</li>
<li>
<p>
<strong>Functionality Cookies</strong>
</p>
<p>Type: Persistent Cookies</p>
<p>Administered by: Us</p>
<p>
Purpose: These Cookies allow us to remember choices You make when
You use the Website, such as remembering your login details or
language preference. The purpose of these Cookies is to provide
You with a more personal experience and to avoid You having to
re-enter your preferences every time You use the Website.
</p>
</li>
</ul>
<p>
For more information about the cookies we use and your choices
regarding cookies, please visit our Cookies Policy or the Cookies
section of our Privacy Policy.
</p>
<h3>Use of Your Personal Data</h3>
<p>The Company may use Personal Data for the following purposes:</p>
<ul>
<li>
<p>
<strong>To provide and maintain our Service</strong>, including to
monitor the usage of our Service.
</p>
</li>
<li>
<p>
<strong>To manage Your Account:</strong> to manage Your
registration as a user of the Service. The Personal Data You
provide can give You access to different functionalities of the
Service that are available to You as a registered user.
</p>
</li>
<li>
<p>
<strong>For the performance of a contract:</strong> the
development, compliance and undertaking of the purchase contract
for the products, items or services You have purchased or of any
other contract with Us through the Service.
</p>
</li>
<li>
<p>
<strong>To contact You:</strong> To contact You by email,
telephone calls, SMS, or other equivalent forms of electronic
communication, such as a mobile application&apos;s push
notifications regarding updates or informative communications
related to the functionalities, products or contracted services,
including the security updates, when necessary or reasonable for
their implementation.
</p>
</li>
<li>
<p>
<strong>To provide You</strong> with news, special offers and
general information about other goods, services and events which
we offer that are similar to those that you have already purchased
or enquired about unless You have opted not to receive such
information.
</p>
</li>
<li>
<p>
<strong>To manage Your requests:</strong> To attend and manage
Your requests to Us.
</p>
</li>
<li>
<p>
<strong>For business transfers:</strong> We may use Your
information to evaluate or conduct a merger, divestiture,
restructuring, reorganization, dissolution, or other sale or
transfer of some or all of Our assets, whether as a going concern
or as part of bankruptcy, liquidation, or similar proceeding, in
which Personal Data held by Us about our Service users is among
the assets transferred.
</p>
</li>
<li>
<p>
<strong>For other purposes</strong>: We may use Your information
for other purposes, such as data analysis, identifying usage
trends, determining the effectiveness of our promotional campaigns
and to evaluate and improve our Service, products, services,
marketing and your experience.
</p>
</li>
</ul>
<p>
We may share Your personal information in the following situations:
</p>
<ul>
<li>
<strong>With Service Providers:</strong> We may share Your personal
information with Service Providers to monitor and analyze the use of
our Service, to contact You.
</li>
<li>
<strong>For business transfers:</strong> We may share or transfer
Your personal information in connection with, or during negotiations
of, any merger, sale of Company assets, financing, or acquisition of
all or a portion of Our business to another company.
</li>
<li>
<strong>With Affiliates:</strong> We may share Your information with
Our affiliates, in which case we will require those affiliates to
honor this Privacy Policy. Affiliates include Our parent company and
any other subsidiaries, joint venture partners or other companies
that We control or that are under common control with Us.
</li>
<li>
<strong>With business partners:</strong> We may share Your
information with Our business partners to offer You certain
products, services or promotions.
</li>
<li>
<strong>With other users:</strong> when You share personal
information or otherwise interact in the public areas with other
users, such information may be viewed by all users and may be
publicly distributed outside.
</li>
<li>
<strong>With Your consent</strong>: We may disclose Your personal
information for any other purpose with Your consent.
</li>
</ul>
<h3>Retention of Your Personal Data</h3>
<p>
The Company will retain Your Personal Data only for as long as is
necessary for the purposes set out in this Privacy Policy. We will
retain and use Your Personal Data to the extent necessary to comply
with our legal obligations (for example, if we are required to retain
your data to comply with applicable laws), resolve disputes, and
enforce our legal agreements and policies.
</p>
<p>
The Company will also retain Usage Data for internal analysis
purposes. Usage Data is generally retained for a shorter period of
time, except when this data is used to strengthen the security or to
improve the functionality of Our Service, or We are legally obligated
to retain this data for longer time periods.
</p>
<h3>Transfer of Your Personal Data</h3>
<p>
Your information, including Personal Data, is processed at the
Company&apos;s operating offices and in any other places where the
parties involved in the processing are located. It means that this
information may be transferred to and maintained on computers
located outside of Your state, province, country or other governmental
jurisdiction where the data protection laws may differ than those from
Your jurisdiction.
</p>
<p>
Your consent to this Privacy Policy followed by Your submission of
such information represents Your agreement to that transfer.
</p>
<p>
The Company will take all steps reasonably necessary to ensure that
Your data is treated securely and in accordance with this Privacy
Policy and no transfer of Your Personal Data will take place to an
organization or a country unless there are adequate controls in place
including the security of Your data and other personal information.
</p>
<h3>Delete Your Personal Data</h3>
<p>
You have the right to delete or request that We assist in deleting the
Personal Data that We have collected about You.
</p>
<p>
Our Service may give You the ability to delete certain information
about You from within the Service.
</p>
<p>
You may update, amend, or delete Your information at any time by
signing in to Your Account, if you have one, and visiting the account
settings section that allows you to manage Your personal information.
You may also contact Us to request access to, correct, or delete any
personal information that You have provided to Us.
</p>
<p>
Please note, however, that We may need to retain certain information
when we have a legal obligation or lawful basis to do so.
</p>
<h3>Disclosure of Your Personal Data</h3>
<h4>Business Transactions</h4>
<p>
If the Company is involved in a merger, acquisition or asset sale,
Your Personal Data may be transferred. We will provide notice before
Your Personal Data is transferred and becomes subject to a different
Privacy Policy.
</p>
<h4>Law enforcement</h4>
<p>
Under certain circumstances, the Company may be required to disclose
Your Personal Data if required to do so by law or in response to valid
requests by public authorities (e.g. a court or a government agency).
</p>
<h4>Other legal requirements</h4>
<p>
The Company may disclose Your Personal Data in the good faith belief
that such action is necessary to:
</p>
<ul>
<li>Comply with a legal obligation</li>
<li>Protect and defend the rights or property of the Company</li>
<li>
Prevent or investigate possible wrongdoing in connection with the
Service
</li>
<li>
Protect the personal safety of Users of the Service or the public
</li>
<li>Protect against legal liability</li>
</ul>
<h3>Security of Your Personal Data</h3>
<p>
The security of Your Personal Data is important to Us, but remember
that no method of transmission over the Internet, or method of
electronic storage is 100% secure. While We strive to use commercially
acceptable means to protect Your Personal Data, We cannot guarantee
its absolute security.
</p>
<h2>Children&apos;s Privacy</h2>
<p>
Our Service does not address anyone under the age of 13. We do not
knowingly collect personally identifiable information from anyone
under the age of 13. If You are a parent or guardian and You are aware
that Your child has provided Us with Personal Data, please contact Us.
If We become aware that We have collected Personal Data from anyone
under the age of 13 without verification of parental consent, We take
steps to remove that information from Our servers.
</p>
<p>
If We need to rely on consent as a legal basis for processing Your
information and Your country requires consent from a parent, We may
require Your parent&apos;s consent before We collect and use that
information.
</p>
<h2>Links to Other Websites</h2>
<p>
Our Service may contain links to other websites that are not operated
by Us. If You click on a third party link, You will be directed to
that third party&apos;s site. We strongly advise You to review the
Privacy Policy of every site You visit.
</p>
<p>
We have no control over and assume no responsibility for the content,
privacy policies or practices of any third party sites or services.
</p>
<h2>Changes to this Privacy Policy</h2>
<p>
We may update Our Privacy Policy from time to time. We will notify You
of any changes by posting the new Privacy Policy on this page.
</p>
<p>
We will let You know via email and/or a prominent notice on Our
Service, prior to the change becoming effective and update the
&quot;Last updated&quot; date at the top of this Privacy Policy.
</p>
<p>
You are advised to review this Privacy Policy periodically for any
changes. Changes to this Privacy Policy are effective when they are
posted on this page.
</p>
<h2>Contact Us</h2>
<p>
If you have any questions about this Privacy Policy, You can contact
us:
</p>
<ul>
<li>By email: hello@openpanel.dev</li>
</ul>
</article>
</div>
);
}

View File

@@ -1,458 +0,0 @@
import { Heading1 } from '../../copy';
export const dynamic = 'force-dynamic';
export const revalidate = 3600;
export default function Page() {
return (
<div className="container mt-[150px] max-w-2xl">
<article className="prose">
<Heading1>Terms and Conditions</Heading1>
<p>Last updated: February 22, 2024</p>
<p>
Please read these terms and conditions carefully before using Our
Service.
</p>
<h2>Interpretation and Definitions</h2>
<h3>Interpretation</h3>
<p>
The words of which the initial letter is capitalized have meanings
defined under the following conditions. The following definitions
shall have the same meaning regardless of whether they appear in
singular or in plural.
</p>
<h3>Definitions</h3>
<p>For the purposes of these Terms and Conditions:</p>
<ul>
<li>
<p>
<strong>Application</strong> means the software program provided
by the Company downloaded by You on any electronic device, named
Openpanel
</p>
</li>
<li>
<p>
<strong>Application Store</strong> means the digital distribution
service operated and developed by Apple Inc. (Apple App Store) or
Google Inc. (Google Play Store) in which the Application has been
downloaded.
</p>
</li>
<li>
<p>
<strong>Affiliate</strong> means an entity that controls, is
controlled by or is under common control with a party, where
&quot;control&quot; means ownership of 50% or more of the shares,
equity interest or other securities entitled to vote for election
of directors or other managing authority.
</p>
</li>
<li>
<p>
<strong>Account</strong> means a unique account created for You to
access our Service or parts of our Service.
</p>
</li>
<li>
<p>
<strong>Country</strong> refers to: Sweden
</p>
</li>
<li>
<p>
<strong>Company</strong> (referred to as either &quot;the
Company&quot;, &quot;We&quot;, &quot;Us&quot; or &quot;Our&quot;
in this Agreement) refers to Coderax AB, Sankt Eriksgatan 100, 113
31, Stockholm.
</p>
</li>
<li>
<p>
<strong>Device</strong> means any device that can access the
Service such as a computer, a cellphone or a digital tablet.
</p>
</li>
<li>
<p>
<strong>Free Trial</strong> refers to a limited period of time
that may be free when purchasing a Subscription.
</p>
</li>
<li>
<p>
<strong>Service</strong> refers to the Application or the Website
or both.
</p>
</li>
<li>
<p>
<strong>Subscriptions</strong> refer to the services or access to
the Service offered on a subscription basis by the Company to You.
</p>
</li>
<li>
<p>
<strong>Terms and Conditions</strong> (also referred as
&quot;Terms&quot;) mean these Terms and Conditions that form the
entire agreement between You and the Company regarding the use of
the Service.
</p>
</li>
<li>
<p>
<strong>Third-party Social Media Service</strong> means any
services or content (including data, information, products or
services) provided by a third-party that may be displayed,
included or made available by the Service.
</p>
</li>
<li>
<p>
<strong>Website</strong> refers to Openpanel, accessible from{' '}
<a
href="https://openpanel.dev"
rel="noreferrer external nofollow noopener"
target="_blank"
>
https://openpanel.dev
</a>
</p>
</li>
<li>
<p>
<strong>You</strong> means the individual accessing or using the
Service, or the company, or other legal entity on behalf of which
such individual is accessing or using the Service, as applicable.
</p>
</li>
</ul>
<h2>Acknowledgment</h2>
<p>
These are the Terms and Conditions governing the use of this Service
and the agreement that operates between You and the Company. These
Terms and Conditions set out the rights and obligations of all users
regarding the use of the Service.
</p>
<p>
Your access to and use of the Service is conditioned on Your
acceptance of and compliance with these Terms and Conditions. These
Terms and Conditions apply to all visitors, users and others who
access or use the Service.
</p>
<p>
By accessing or using the Service You agree to be bound by these Terms
and Conditions. If You disagree with any part of these Terms and
Conditions then You may not access the Service.
</p>
<p>
You represent that you are over the age of 18. The Company does not
permit those under 18 to use the Service.
</p>
<p>
Your access to and use of the Service is also conditioned on Your
acceptance of and compliance with the Privacy Policy of the Company.
Our Privacy Policy describes Our policies and procedures on the
collection, use and disclosure of Your personal information when You
use the Application or the Website and tells You about Your privacy
rights and how the law protects You. Please read Our Privacy Policy
carefully before using Our Service.
</p>
<h2>Subscriptions</h2>
<h3>Subscription period</h3>
<p>
The Service or some parts of the Service are available only with a
paid Subscription. You will be billed in advance on a recurring and
periodic basis (such as daily, weekly, monthly or annually), depending
on the type of Subscription plan you select when purchasing the
Subscription.
</p>
<p>
At the end of each period, Your Subscription will automatically renew
under the exact same conditions unless You cancel it or the Company
cancels it.
</p>
<h3>Subscription cancellations</h3>
<p>
You may cancel Your Subscription renewal either through Your Account
settings page or by contacting the Company. You will not receive a
refund for the fees You already paid for Your current Subscription
period and You will be able to access the Service until the end of
Your current Subscription period.
</p>
<h3>Billing</h3>
<p>
You shall provide the Company with accurate and complete billing
information including full name, address, state, zip code, telephone
number, and a valid payment method information.
</p>
<p>
Should automatic billing fail to occur for any reason, the Company
will issue an electronic invoice indicating that you must proceed
manually, within a certain deadline date, with the full payment
corresponding to the billing period as indicated on the invoice.
</p>
<h3>Fee Changes</h3>
<p>
The Company, in its sole discretion and at any time, may modify the
Subscription fees. Any Subscription fee change will become effective
at the end of the then-current Subscription period.
</p>
<p>
The Company will provide You with reasonable prior notice of any
change in Subscription fees to give You an opportunity to terminate
Your Subscription before such change becomes effective.
</p>
<p>
Your continued use of the Service after the Subscription fee change
comes into effect constitutes Your agreement to pay the modified
Subscription fee amount.
</p>
<h3>Refunds</h3>
<p>
Except when required by law, paid Subscription fees are
non-refundable.
</p>
<p>
Certain refund requests for Subscriptions may be considered by the
Company on a case-by-case basis and granted at the sole discretion of
the Company.
</p>
<h3>Free Trial</h3>
<p>
The Company may, at its sole discretion, offer a Subscription with a
Free Trial for a limited period of time.
</p>
<p>
You may be required to enter Your billing information in order to sign
up for the Free Trial.
</p>
<p>
If You do enter Your billing information when signing up for a Free
Trial, You will not be charged by the Company until the Free Trial has
expired. On the last day of the Free Trial period, unless You canceled
Your Subscription, You will be automatically charged the applicable
Subscription fees for the type of Subscription You have selected.
</p>
<p>
At any time and without notice, the Company reserves the right to (i)
modify the terms and conditions of the Free Trial offer, or (ii)
cancel such Free Trial offer.
</p>
<h2>User Accounts</h2>
<p>
When You create an account with Us, You must provide Us information
that is accurate, complete, and current at all times. Failure to do so
constitutes a breach of the Terms, which may result in immediate
termination of Your account on Our Service.
</p>
<p>
You are responsible for safeguarding the password that You use to
access the Service and for any activities or actions under Your
password, whether Your password is with Our Service or a Third-Party
Social Media Service.
</p>
<p>
You agree not to disclose Your password to any third party. You must
notify Us immediately upon becoming aware of any breach of security or
unauthorized use of Your account.
</p>
<p>
You may not use as a username the name of another person or entity or
that is not lawfully available for use, a name or trademark that is
subject to any rights of another person or entity other than You
without appropriate authorization, or a name that is otherwise
offensive, vulgar or obscene.
</p>
<h2>Intellectual Property</h2>
<p>
The Service and its original content (excluding Content provided by
You or other users), features and functionality are and will remain
the exclusive property of the Company and its licensors.
</p>
<p>
The Service is protected by copyright, trademark, and other laws of
both the Country and foreign countries.
</p>
<p>
Our trademarks and trade dress may not be used in connection with any
product or service without the prior written consent of the Company.
</p>
<h2>Links to Other Websites</h2>
<p>
Our Service may contain links to third-party web sites or services
that are not owned or controlled by the Company.
</p>
<p>
The Company has no control over, and assumes no responsibility for,
the content, privacy policies, or practices of any third party web
sites or services. You further acknowledge and agree that the Company
shall not be responsible or liable, directly or indirectly, for any
damage or loss caused or alleged to be caused by or in connection with
the use of or reliance on any such content, goods or services
available on or through any such web sites or services.
</p>
<p>
We strongly advise You to read the terms and conditions and privacy
policies of any third-party web sites or services that You visit.
</p>
<h2>Termination</h2>
<p>
We may terminate or suspend Your Account immediately, without prior
notice or liability, for any reason whatsoever, including without
limitation if You breach these Terms and Conditions.
</p>
<p>
Upon termination, Your right to use the Service will cease
immediately. If You wish to terminate Your Account, You may simply
discontinue using the Service.
</p>
<h2>Limitation of Liability</h2>
<p>
Notwithstanding any damages that You might incur, the entire liability
of the Company and any of its suppliers under any provision of this
Terms and Your exclusive remedy for all of the foregoing shall be
limited to the amount actually paid by You through the Service or 100
USD if You haven&apos;t purchased anything through the Service.
</p>
<p>
To the maximum extent permitted by applicable law, in no event shall
the Company or its suppliers be liable for any special, incidental,
indirect, or consequential damages whatsoever (including, but not
limited to, damages for loss of profits, loss of data or other
information, for business interruption, for personal injury, loss of
privacy arising out of or in any way related to the use of or
inability to use the Service, third-party software and/or third-party
hardware used with the Service, or otherwise in connection with any
provision of this Terms), even if the Company or any supplier has been
advised of the possibility of such damages and even if the remedy
fails of its essential purpose.
</p>
<p>
Some states do not allow the exclusion of implied warranties or
limitation of liability for incidental or consequential damages, which
means that some of the above limitations may not apply. In these
states, each party&apos;s liability will be limited to the greatest
extent permitted by law.
</p>
<h2>&quot;AS IS&quot; and &quot;AS AVAILABLE&quot; Disclaimer</h2>
<p>
The Service is provided to You &quot;AS IS&quot; and &quot;AS
AVAILABLE&quot; and with all faults and defects without warranty of
any kind. To the maximum extent permitted under applicable law, the
Company, on its own behalf and on behalf of its Affiliates and its and
their respective licensors and service providers, expressly disclaims
all warranties, whether express, implied, statutory or otherwise, with
respect to the Service, including all implied warranties of
merchantability, fitness for a particular purpose, title and
non-infringement, and warranties that may arise out of course of
dealing, course of performance, usage or trade practice. Without
limitation to the foregoing, the Company provides no warranty or
undertaking, and makes no representation of any kind that the Service
will meet Your requirements, achieve any intended results, be
compatible or work with any other software, applications, systems or
services, operate without interruption, meet any performance or
reliability standards or be error free or that any errors or defects
can or will be corrected.
</p>
<p>
Without limiting the foregoing, neither the Company nor any of the
company&apos;s provider makes any representation or warranty of any
kind, express or implied: (i) as to the operation or availability of
the Service, or the information, content, and materials or products
included thereon; (ii) that the Service will be uninterrupted or
error-free; (iii) as to the accuracy, reliability, or currency of any
information or content provided through the Service; or (iv) that the
Service, its servers, the content, or e-mails sent from or on behalf
of the Company are free of viruses, scripts, trojan horses, worms,
malware, timebombs or other harmful components.
</p>
<p>
Some jurisdictions do not allow the exclusion of certain types of
warranties or limitations on applicable statutory rights of a
consumer, so some or all of the above exclusions and limitations may
not apply to You. But in such a case the exclusions and limitations
set forth in this section shall be applied to the greatest extent
enforceable under applicable law.
</p>
<h2>Governing Law</h2>
<p>
The laws of the Country, excluding its conflicts of law rules, shall
govern this Terms and Your use of the Service. Your use of the
Application may also be subject to other local, state, national, or
international laws.
</p>
<h2>Disputes Resolution</h2>
<p>
If You have any concern or dispute about the Service, You agree to
first try to resolve the dispute informally by contacting the Company.
</p>
<h2>For European Union (EU) Users</h2>
<p>
If You are a European Union consumer, you will benefit from any
mandatory provisions of the law of the country in which You are
resident.
</p>
<h2>United States Federal Government End Use Provisions</h2>
<p>
If You are a U.S. federal government end user, our Service is a
&quot;Commercial Item&quot; as that term is defined at 48 C.F.R.
§2.101.
</p>
<h2>United States Legal Compliance</h2>
<p>
You represent and warrant that (i) You are not located in a country
that is subject to the United States government embargo, or that has
been designated by the United States government as a &quot;terrorist
supporting&quot; country, and (ii) You are not listed on any United
States government list of prohibited or restricted parties.
</p>
<h2>Severability and Waiver</h2>
<h3>Severability</h3>
<p>
If any provision of these Terms is held to be unenforceable or
invalid, such provision will be changed and interpreted to accomplish
the objectives of such provision to the greatest extent possible under
applicable law and the remaining provisions will continue in full
force and effect.
</p>
<h3>Waiver</h3>
<p>
Except as provided herein, the failure to exercise a right or to
require performance of an obligation under these Terms shall not
affect a party&apos;s ability to exercise such right or require such
performance at any time thereafter nor shall the waiver of a breach
constitute a waiver of any subsequent breach.
</p>
<h2>Translation Interpretation</h2>
<p>
These Terms and Conditions may have been translated if We have made
them available to You on our Service. You agree that the original
English text shall prevail in the case of a dispute.
</p>
<h2>Changes to These Terms and Conditions</h2>
<p>
We reserve the right, at Our sole discretion, to modify or replace
these Terms at any time. If a revision is material We will make
reasonable efforts to provide at least 30 days&apos; notice prior to
any new terms taking effect. What constitutes a material change will
be determined at Our sole discretion.
</p>
<p>
By continuing to access or use Our Service after those revisions
become effective, You agree to be bound by the revised terms. If You
do not agree to the new terms, in whole or in part, please stop using
the website and the Service.
</p>
<h2>Contact Us</h2>
<p>
If you have any questions about these Terms and Conditions, You can
contact us:
</p>
<ul>
<li>By email: hello@openpanel.dev</li>
</ul>
</article>
</div>
);
}

View File

@@ -1,45 +0,0 @@
'use client';
import { useMemo, useState } from 'react';
import { TypeAnimation } from 'react-type-animation';
type Props = {
className?: string;
texts: { text: string; color: string }[];
};
const AnimatedText = ({ texts }: Props) => {
const [currIndex, setCurrIndex] = useState(0);
const sequence = useMemo(() => {
return texts.reduce((acc, { text }, index) => {
return [
...acc,
() => setCurrIndex(index),
text,
index === 0 ? 3000 : 2000,
];
}, [] as any[]);
}, []);
return (
<span
style={{
color: texts[currIndex]?.color,
height: 60,
display: 'block',
whiteSpace: 'nowrap',
}}
>
<TypeAnimation
cursor={false}
preRenderFirstString={true}
sequence={sequence}
wrapper="span"
repeat={Number.POSITIVE_INFINITY}
omitDeletionAnimation
/>
</span>
);
};
export default AnimatedText;

View File

@@ -1,26 +0,0 @@
import * as EmailValidator from 'email-validator';
import { NextResponse } from 'next/server';
import { db } from '@openpanel/db';
export const dynamic = 'force-dynamic';
export async function POST(req: Request) {
const body = await req.json();
if (!body.email) {
return NextResponse.json({ error: 'Email is required' }, { status: 400 });
}
if (!EmailValidator.validate(body.email)) {
return NextResponse.json({ error: 'Email is not valid' }, { status: 400 });
}
await db.waitlist.create({
data: {
email: String(body.email).toLowerCase(),
},
});
return NextResponse.json(body);
}

View File

@@ -1,76 +0,0 @@
import { cn } from '@/utils/cn';
interface Props {
children: React.ReactNode;
className?: string;
}
export function Lead({ children, className }: Props) {
return (
<p className={cn('text-xl font-light md:text-2xl', className)}>
{children}
</p>
);
}
export function Lead2({ children, className }: Props) {
return (
<p className={cn('text-lg font-light md:text-xl', className)}>{children}</p>
);
}
export function Paragraph({ children, className }: Props) {
return <p className={cn('text-lg', className)}>{children}</p>;
}
export function Heading1({ children, className }: Props) {
return (
<h1
className={cn(
'font-serif text-4xl font-bold !leading-tight text-slate-900 md:text-5xl',
className,
)}
>
{children}
</h1>
);
}
export function Heading2({ children, className }: Props) {
return (
<h2
className={cn(
'font-serif text-4xl font-bold text-slate-900 md:text-5xl',
className,
)}
>
{children}
</h2>
);
}
export function Heading3({ children, className }: Props) {
return (
<h3
className={cn(
'font-serif text-2xl font-bold text-slate-900 md:text-3xl',
className,
)}
>
{children}
</h3>
);
}
export function Heading4({ children, className }: Props) {
return (
<h3
className={cn(
'font-serif text-xl font-bold text-slate-900 md:text-2xl',
className,
)}
>
{children}
</h3>
);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -1,145 +0,0 @@
'use client';
import { cn } from '@/utils/cn';
import Image from 'next/image';
import { Heading3 } from './copy';
interface FeatureItem {
title: string;
description: string | React.ReactNode;
className: string;
image: string;
}
const features: FeatureItem[] = [
{
title: 'Visualize Your Data',
description: (
<p>
Gain a deep understanding of your data with our visualization tools.
</p>
),
className: '',
image: '/demo-3/img-1.png',
},
{
title: 'Get a good overview',
description: (
<p>
Even though we want to provide advanced charts and graphs, we also want
you to understand your data at a glance.
</p>
),
className: 'bg-slate-100',
image: '/demo-3/img-2.png',
},
{
title: 'Real-Time Data Access',
description: (
<>
<p>
Access all your events in real-time. No delays or waiting for data to
be accessible.
</p>
<p>
Mark events as conversions to highlight and get notifications with our
iOS/Android app (app coming soon!)
</p>
</>
),
className: '',
image: '/demo-3/img-3.png',
},
{
title: 'Unlimited dashboards with charts',
description: (
<>
<p>
Create beautiful charts and graphs to visualize your data and share
them with your team.
</p>
<div className="flex flex-wrap gap-2">
<div className="rounded border border-border px-3 py-1">
Linear
</div>
<div className="rounded border border-border px-3 py-1"> Area</div>
<div className="rounded border border-border px-3 py-1"> Bar</div>
<div className="rounded border border-border px-3 py-1"> Map</div>
<div className="rounded border border-border px-3 py-1"> Pie</div>
<div className="rounded border border-border px-3 py-1">
Funnels
</div>
<div className="rounded border border-border px-3 py-1">
Histogram
</div>
<div className="rounded border border-border px-3 py-1">
Metrics
</div>
</div>
</>
),
className: 'bg-slate-100',
image: '/demo-3/img-4.png',
},
{
title: 'Understand your users',
description: (
<>
<p>
Deep dive into your user&apos;s behavior and understand how they
interact with your app/website.
</p>
</>
),
className: '',
image: '/demo-3/img-5.png',
},
];
export function Features() {
return (
<div className="flex flex-col">
{features.map((feature, i) => {
return (
<Feature key={feature.title} {...feature} even={i % 2 === 0}>
{feature.description}
</Feature>
);
})}
</div>
);
}
export function Feature({
title,
children,
className,
image,
even,
}: FeatureItem & { even: boolean; children: React.ReactNode }) {
return (
<section className={cn('group py-16', className)}>
<div
className={cn(
'container flex min-h-[300px] items-center justify-between gap-16 max-md:flex-col-reverse',
!even && 'md:flex-row-reverse',
)}
>
<div className="flex w-full flex-col">
<Heading3 className="mb-2">{title}</Heading3>
<div className="prose-xl">{children}</div>
</div>
<div className="w-full">
<Image
src={image}
alt={title}
width={600}
height={400}
className="w-full max-w-xl rounded-xl border-8 border-black/5 transition-transform duration-500 group-hover:rotate-1 group-hover:scale-[101%]"
/>
</div>
</div>
</section>
);
}

View File

@@ -1,70 +0,0 @@
import { Logo } from '@/components/Logo';
import { ALink } from '@/components/ui/button';
import Image from 'next/image';
import Link from 'next/link';
import { Heading2, Lead2 } from './copy';
export default function Footer() {
return (
<footer className="bg-blue-darker relative mt-40 text-white">
<div className="absolute inset-0 h-full w-full bg-[radial-gradient(circle,rgba(255,255,255,0.2)_0%,rgba(255,255,255,0)_100%)]" />
<div className="container relative flex flex-col items-center text-center">
<div className="my-24">
<Heading2 className="mb-2 text-white">Get early access</Heading2>
<Lead2>
Ready to set your analytics free? Create your account today!
</Lead2>
<div className="mt-8">
<ALink
className="font-semibold"
size="lg"
href="https://dashboard.openpanel.dev"
>
Create your account
</ALink>
</div>
</div>
<div className="overflow-hidden rounded-xl">
<div className="bg-white/20 p-2">
<Image
src="/demo-2/1.png"
width={1080}
height={608}
alt="Openpanel overview page"
className="w-full rounded-lg"
/>
</div>
</div>
</div>
<div className="relative z-10 -mt-8">
<div className="h-px w-full bg-[radial-gradient(circle,rgba(255,255,255,0.7)_0%,rgba(255,255,255,0.7)_50%,rgba(255,255,255,0)_100%)]" />
<div className="bg-blue-darker p-4">
<div className="container">
<div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
<Logo />
<div className="flex flex-col gap-4 md:flex-row">
<Link className="hover:underline" href="/terms">
Terms and Conditions
</Link>
<Link className="hover:underline" href="/privacy">
Privacy Policy
</Link>
<a
className="hover:underline"
href="https://x.com/OpenPanelDev"
target="_blank"
rel="noreferrer nofollow"
>
Follow on X
</a>
</div>
</div>
</div>
</div>
</div>
</footer>
);
}

View File

@@ -1,105 +0,0 @@
import { ALink } from '@/components/ui/button';
import { TABLE_NAMES, chQuery } from '@openpanel/db';
import { cacheable } from '../../../../packages/redis';
import AnimatedText from './animated-text';
import { Heading1, Lead2 } from './copy';
function shortNumber(num: number) {
if (num < 1e3) return num;
if (num >= 1e3 && num < 1e6) return `${+(num / 1e3).toFixed(1)}K`;
if (num >= 1e6 && num < 1e9) return `${+(num / 1e6).toFixed(1)}M`;
if (num >= 1e9 && num < 1e12) return `${+(num / 1e9).toFixed(1)}B`;
if (num >= 1e12) return `${+(num / 1e12).toFixed(1)}T`;
}
const getProjectsWithCount = cacheable(async function getProjectsWithCount() {
const projects = await chQuery<{ project_id: string; count: number }>(
`SELECT project_id, count(*) as count from ${TABLE_NAMES.events} GROUP by project_id order by count()`,
);
return projects;
}, 60 * 60);
export async function Hero() {
const projects = await getProjectsWithCount();
const projectCount = projects.length;
const eventCount = projects.reduce((acc, { count }) => acc + count, 0);
return (
<div className="relative overflow-hidden">
{/* <div className="bg-blue-50 w-2/5 h-full absolute top-0 right-0"/> */}
<div className="container relative flex sm:h-[800px] flex-col items-center gap-4 max-md:pt-32 md:flex-row md:gap-8">
<div className="flex-1 max-md:text-center sm:min-w-[350px] lg:min-w-[400px]">
<div className="mb-4 flex justify-center md:justify-start">
<div className="rounded-md border border-border p-1.5 px-4 font-medium">
FREE DURING BETA
</div>
</div>
<Heading1 className="mb-4 text-slate-950">
An open-source
<br />
alternative to{' '}
<AnimatedText
texts={[
{
text: 'Mixpanel',
color: '#5028C0',
},
{
text: 'Google Analytics',
color: '#FAAE17',
},
{
text: 'Plausible',
color: '#5850EC',
},
]}
/>
</Heading1>
<Lead2 className="mb-12">
The power of Mixpanel, the ease of Plausible and nothing from Google
Analytics 😉
</Lead2>
<div className="flex justify-center gap-2 md:justify-start">
<ALink
className="font-semibold"
size="lg"
href="https://dashboard.openpanel.dev/register"
>
Get started
</ALink>
</div>
<div className="mt-8 flex justify-center gap-8 md:justify-start">
<div>
<div className=" uppercase text-muted-foreground">
Collected events
</div>
<div className="font-serif text-3xl font-semibold">
{shortNumber(eventCount)}
</div>
</div>
<div>
<div className=" uppercase text-muted-foreground">
Active projects
</div>
<div className="font-serif text-3xl font-semibold">
{projectCount}
</div>
</div>
</div>
</div>
<div className="relative mt-12 h-[700px] w-full md:mt-36">
<div className="absolute inset-0 flex rounded-2xl ring-8 ring-slate-300">
<div className="absolute inset-0 w-full animate-pulse overflow-hidden rounded-2xl bg-slate-100" />
<iframe
src="https://dashboard.openpanel.dev/share/overview/zef2XC?header=0&range=30d"
className="relative z-10 h-[700px] w-full rounded-2xl"
title="Openpanel Dashboard"
scrolling="no"
/>
</div>
</div>
</div>
</div>
);
}

View File

@@ -1,81 +0,0 @@
'use client';
import { Button } from '@/components/ui/button';
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
import { cn } from '@/utils/cn';
import { useEffect, useState } from 'react';
interface JoinWaitlistProps {
className?: string;
}
export function JoinWaitlistHero({ className }: JoinWaitlistProps) {
const [value, setValue] = useState('');
const [open, setOpen] = useState(false);
useEffect(() => {
if (open) {
// @ts-ignore
window.op('event', 'waitlist_success');
}
}, [open]);
return (
<>
<Dialog open={open} onOpenChange={setOpen}>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Thanks so much!</DialogTitle>
<DialogDescription>
You&apos;re now on the waiting list. We&apos;ll let you know when
we&apos;re ready. Should be within a month or two 🚀
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button onClick={() => setOpen(false)}>Got it!</Button>
</DialogFooter>
</DialogContent>
</Dialog>
<form
className="w-full max-w-md"
onSubmit={(e) => {
e.preventDefault();
fetch('/api/waitlist', {
method: 'POST',
body: JSON.stringify({ email: value }),
headers: {
'Content-Type': 'application/json',
},
}).then((res) => {
if (res.ok) {
setOpen(true);
}
});
}}
>
<div className="relative w-full">
<input
placeholder="Enter your email"
className={cn(
'text-blue-darker h-12 w-full rounded-md border border-slate-100 bg-white px-4 shadow-sm outline-none ring-black focus:ring-1',
className,
)}
value={value}
onChange={(e) => setValue(e.target.value)}
/>
<Button type="submit" className="absolute right-1 top-1">
Join waitlist
</Button>
</div>
</form>
</>
);
}

View File

@@ -1,81 +0,0 @@
'use client';
import { Button } from '@/components/ui/button';
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
import { cn } from '@/utils/cn';
import { useEffect, useState } from 'react';
interface JoinWaitlistProps {
className?: string;
}
export function JoinWaitlist({ className }: JoinWaitlistProps) {
const [value, setValue] = useState('');
const [open, setOpen] = useState(false);
useEffect(() => {
if (open) {
// @ts-ignore
window.op('event', 'waitlist_success');
}
}, [open]);
return (
<>
<Dialog open={open} onOpenChange={setOpen}>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Thanks so much!</DialogTitle>
<DialogDescription>
You&apos;re now on the waiting list. We&apos;ll let you know when
we&apos;re ready. Should be within a month or two 🚀
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button onClick={() => setOpen(false)}>Got it!</Button>
</DialogFooter>
</DialogContent>
</Dialog>
<form
className="w-full max-w-md"
onSubmit={(e) => {
e.preventDefault();
fetch('/api/waitlist', {
method: 'POST',
body: JSON.stringify({ email: value }),
headers: {
'Content-Type': 'application/json',
},
}).then((res) => {
if (res.ok) {
setOpen(true);
}
});
}}
>
<div className="relative w-full">
<input
placeholder="Enter your email"
className={cn(
'text-blue-darker h-12 w-full rounded-md border border-slate-100 bg-white px-4 shadow-sm outline-none ring-black focus:ring-1',
className,
)}
value={value}
onChange={(e) => setValue(e.target.value)}
/>
<Button type="submit" className="absolute right-1 top-1">
Join waitlist
</Button>
</div>
</form>
</>
);
}

View File

@@ -1,61 +0,0 @@
import { cn } from '@/utils/cn';
import type { Metadata } from 'next';
import { Bricolage_Grotesque, Inter } from 'next/font/google';
import { OpenPanelComponent } from '@openpanel/nextjs';
import Footer from './footer';
import { defaultMeta } from './meta';
import '@/styles/globals.css';
import { Navbar } from './navbar';
export const metadata: Metadata = {
...defaultMeta,
alternates: {
canonical: 'https://openpanel.dev',
},
};
const head = Bricolage_Grotesque({
display: 'swap',
subsets: ['latin'],
weight: ['400', '700'],
variable: '--font-serif',
});
const body = Inter({
display: 'swap',
subsets: ['latin'],
weight: ['400', '700'],
variable: '--font-sans',
});
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en" className="light bg-white">
<body
className={cn(
'grainy min-h-screen font-sans text-slate-900 antialiased',
head.variable,
body.variable,
)}
>
<Navbar darkText />
{children}
<Footer />
</body>
<OpenPanelComponent
clientId="301c6dc1-424c-4bc3-9886-a8beab09b615"
trackAttributes
trackScreenViews
trackOutgoingLinks
/>
</html>
);
}

View File

@@ -1,22 +0,0 @@
import type { MetadataRoute } from 'next';
import { defaultMeta } from './meta';
export default function manifest(): MetadataRoute.Manifest {
return {
name: defaultMeta.title as string,
short_name: 'Openpanel.dev',
description: defaultMeta.description!,
start_url: '/',
display: 'standalone',
background_color: '#fff',
theme_color: '#fff',
icons: [
{
src: '/favicon.ico',
sizes: 'any',
type: 'image/x-icon',
},
],
};
}

View File

@@ -1,23 +0,0 @@
import type { Metadata } from 'next';
const title = 'An open-source alternative to Mixpanel | Openpanel.dev';
const description =
'Unlock actionable insights effortlessly with Insightful, the open-source analytics library that combines the power of Mixpanel with the simplicity of Plausible. Enjoy a unified overview, predictable pricing, and a vibrant community. Join us in democratizing analytics today!';
export const defaultMeta: Metadata = {
title,
description,
openGraph: {
title,
url: 'https://openpanel.dev',
type: 'website',
images: [
{
url: 'https://openpanel.dev/ogimage.png',
width: 2011,
height: 1339,
alt: title,
},
],
},
};

View File

@@ -1,48 +0,0 @@
'use client';
import { Logo } from '@/components/Logo';
import { cn } from '@/utils/cn';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
interface Props {
darkText?: boolean;
className?: string;
}
export function Navbar({ darkText = false, className }: Props) {
const pathname = usePathname();
const textColor = darkText ? 'text-blue-dark' : 'text-white';
return (
<div
className={cn(
'fixed left-0 right-0 top-0 z-10 z-50 flex h-20 items-center border-b border-border bg-white',
textColor,
className,
)}
>
<div className="container flex items-center justify-between py-4">
<Logo className="max-sm:[&_span]:hidden" />
<nav className="flex gap-4 ">
{pathname !== '/' && <Link href="/">Home</Link>}
<Link href="/#pricing" data-event="click_pricing">
Pricing
</Link>
<a href="https://docs.openpanel.dev" target="_blank" rel="noreferrer">
Docs
</a>
<a href="https://git.new/openpanel" target="_blank" rel="noreferrer">
Github
</a>
<a
href="https://dashboard.openpanel.dev"
target="_blank"
rel="noreferrer"
>
Sign in
</a>
</nav>
</div>
</div>
);
}

View File

@@ -1,125 +0,0 @@
import { ALink } from '@/components/ui/button';
import { ExternalLinkIcon } from 'lucide-react';
import { Heading2, Lead2, Paragraph } from './copy';
import { Features } from './features';
import { Hero } from './hero';
import { Pricing } from './pricing';
import { PunchLines } from './punch-lines';
export const dynamic = 'force-dynamic';
export const revalidate = 3600;
export default function Page() {
return (
<div>
<Hero />
<div className="bg-gradient-to-bl from-blue-600 to-blue-800 py-24">
<div className="container">
<Heading2 className="mb-2 leading-none text-white md:text-5xl">
Analytics should be easy
<br />
and powerful
</Heading2>
<Lead2 className="text-white/80">
The power of Mixpanel, the ease of Plausible and nothing from Google
Analytics 😉 Curious how it looks?
</Lead2>
<ALink
href="https://dashboard.openpanel.dev/share/overview/zef2XC"
target="_blank"
className="mt-8"
variant={'outline'}
>
Check out the demo
<ExternalLinkIcon className="ml-2 h-4 w-4" />
</ALink>
</div>
</div>
<Features />
<PunchLines />
<Pricing />
<div className="container mt-40">
<div className="flex flex-col gap-8 md:flex-row">
<div className="relative mb-4 flex-shrink-0 md:w-1/2">
<Heading2>Another analytic tool? Really?</Heading2>
{/* <SirenIcon
strokeWidth={0.5}
size={300}
className="opacity-10 absolute -rotate-12 -left-20 -top-10"
/> */}
</div>
<div className="flex max-w-3xl flex-col gap-4">
<h3 className="text-blue-dark text-lg font-bold">TL;DR</h3>
<Paragraph>
Our open-source analytic library fills a crucial gap by combining
the strengths of Mixpanel&apos;s powerful features with
Plausible&apos;s clear overview page. Motivated by the lack of an
open-source alternative to Mixpanel and inspired by
Plausible&apos;s simplicity, we aim to create an intuitive
platform with predictable pricing. With a single-tier pricing
model and limits only on monthly event counts, our goal is to
democratize analytics, offering unrestricted access to all
features while ensuring affordability and transparency for users
of all project sizes.
</Paragraph>
<h3 className="text-blue-dark mt-12 text-lg font-bold">The why</h3>
<Paragraph>
Our open-source analytic library emerged from a clear need within
the analytics community. While platforms like Mixpanel offer
powerful and user-friendly features, they lack a comprehensive
overview page akin to Plausible&apos;s, which succinctly
summarizes essential metrics. Recognizing this gap, we saw an
opportunity to combine the strengths of both platforms while
addressing their respective shortcomings.
</Paragraph>
<Paragraph>
One significant motivation behind our endeavor was the absence of
an open-source alternative to Mixpanel. We believe in the
importance of accessibility and transparency in analytics, which
led us to embark on creating a solution that anyone can freely use
and contribute to.
</Paragraph>
<Paragraph>
Inspired by Plausible&apos;s exemplary approach to simplicity and
clarity, we aim to build upon their foundation and further refine
the user experience. By harnessing the best practices demonstrated
by Plausible, we aspire to create an intuitive and streamlined
analytics platform that empowers users to derive actionable
insights effortlessly.
</Paragraph>
<Paragraph>
Our own experiences with traditional analytics platforms like
Mixpanel underscored another critical aspect driving our project:
the need for predictable pricing. As project owners ourselves, we
encountered the frustration of escalating costs as our user base
grew. Therefore, we are committed to offering a single-tier
pricing model that provides unlimited access to all features
without the fear of unexpected expenses.
</Paragraph>
<Paragraph>
In line with our commitment to fairness and accessibility, our
pricing model will only impose limits on the number of events
users can send each month. This approach, akin to
Plausible&apos;s, ensures that users have the freedom to explore
and utilize our platform to its fullest potential without
arbitrary restrictions on reports or user counts. Ultimately, our
goal is to democratize analytics by offering a reliable,
transparent, and cost-effective solution for projects of all
sizes.
</Paragraph>
</div>
</div>
</div>
</div>
);
}

View File

@@ -1,76 +0,0 @@
import { CheckIcon, StarIcon } from 'lucide-react';
import { Heading2, Lead2 } from './copy';
const pricing = [
{ price: 'Free', events: 5000, hint: 'Try it' },
{ price: '$5', events: 10_000 },
{ price: '$10', events: 100_000 },
{ price: '$20', events: 200_000, hint: 'Great value' },
{ price: '$40', events: 500_000 },
{ price: '$60', events: 1_000_000 },
{ price: '$80', events: 2_000_000 },
{ price: '$120', events: 5_000_000 },
{ price: '$150', events: 10_000_000 },
];
export function Pricing() {
return (
<div className="bg-slate-100 py-32" id="pricing">
<div className="mx-auto px-4 sm:max-w-xl md:max-w-3xl">
<section className="flex flex-col gap-6">
<div className="flex w-full flex-col gap-4 md:max-w-[58rem]">
<Heading2>Simple, transparent pricing</Heading2>
<Lead2 className="max-w-[85%] leading-normal text-muted-foreground sm:text-lg sm:leading-7">
Everything is included, just decide how many events you want to
track each month.
</Lead2>
</div>
<ul className="grid gap-3 text-muted-foreground sm:grid-cols-2 md:grid-cols-3">
<li className="flex items-center">
<CheckIcon className="mr-2 h-4 w-4" /> Unlimited websites/apps
</li>
<li className="flex items-center">
<CheckIcon className="mr-2 h-4 w-4" /> Unlimited users
</li>
<li className="flex items-center">
<CheckIcon className="mr-2 h-4 w-4" /> Unlimted dashboards
</li>
<li className="flex items-center">
<CheckIcon className="mr-2 h-4 w-4" /> Unlimted charts
</li>
<li className="flex items-center">
<CheckIcon className="mr-2 h-4 w-4" /> Unlimted tracked profiles
</li>
<li className="flex items-center font-bold text-slate-900">
<CheckIcon className="mr-2 h-4 w-4" /> Yes, its that simple
</li>
</ul>
<div className="grid gap-6 md:grid-cols-2">
{pricing.map((item) => (
<div
key={item.price}
className="border-blue-dark relative flex flex-col gap-1 rounded-lg border bg-white p-6"
>
{item.hint && (
<div className="absolute right-2 top-2 flex items-center gap-2 rounded bg-blue-600 px-2 py-1 text-sm text-white">
<StarIcon size={12} />
{item.hint}
</div>
)}
<div className="text-3xl font-bold">{item.price}</div>
<div className="flex justify-between text-lg">
<span>
{new Intl.NumberFormat('en').format(item.events)} events
</span>
<span className="text-muted-foreground">per month</span>
</div>
</div>
))}
</div>
<p className="font-bold">Everything is free during beta period!</p>
</section>
</div>
</div>
);
}

View File

@@ -1,166 +0,0 @@
import { cn } from '@/utils/cn';
import type { LucideIcon, LucideProps } from 'lucide-react';
import {
ClockIcon,
CloudIcon,
CookieIcon,
DollarSignIcon,
HandshakeIcon,
KeyIcon,
ShieldIcon,
WebhookIcon,
} from 'lucide-react';
import Image from 'next/image';
import { Heading2, Heading4 } from './copy';
const items = [
{
title: 'Own Your Own Data',
description: (
<p>
We believe that you should own your own data. That&apos;s why we
don&apos;t sell your data to third parties.{' '}
<strong>Ever. Period.</strong>
</p>
),
icon: KeyIcon,
color: '#2563EB',
className: 'bg-blue-light',
},
{
title: 'GDPR Compliant',
description: (
<p>
All our serveres are hosted in EU (Stockholm) and we are fully GDPR
compliant.
</p>
),
icon: ShieldIcon,
color: '#b051d3',
className: 'bg-[#b051d3]',
},
{
title: 'Cloud or Self-Hosting',
description: (
<p>
Choose between the flexibility of cloud-based hosting or the autonomy of
self-hosting to tailor your analytics infrastructure to your needs.
</p>
),
icon: CloudIcon,
color: '#ff7557',
className: '', // 'bg-[#ff7557]',
},
{
title: 'Real-Time Events',
description: (
<p>
Stay up-to-date with real-time event tracking, enabling instant insights
into user actions as they happen.
</p>
),
icon: ClockIcon,
color: '#7fe1d8',
className: '', // bg-[#7fe1d8]
},
{
title: 'No cookies!',
description: (
<p>
Our trackers are cookie-free, skip that annyoing cookie consent banner!
</p>
),
icon: CookieIcon,
color: '#f8bc3c',
className: 'bg-blue-dark', //'bg-[#f8bc3c]',
},
{
title: 'Cost-Effective',
description: (
<p>
We have combined the best from Mixpanel and Plausible. Cut the costs and
keep the features.
</p>
),
icon: DollarSignIcon,
color: '#0f7ea0',
className: 'bg-[#3ba974]',
},
{
title: 'Predictable pricing',
description: (
<p>You only pay for events, everything else is included. No surprises.</p>
),
icon: HandshakeIcon,
color: '#0f7ea0',
className: 'bg-[#3ba974]',
},
{
title: 'First Class React Native Support',
description: (
<p>
Our SDK is built with React Native in mind, making it easy to integrate
with your mobile apps.
</p>
),
icon: (({ className }: LucideProps) => {
return (
<Image
src="/react-native.svg"
alt="React Native"
className={cn(className, 'p-3')}
width={50}
height={50}
/>
);
}) as unknown as LucideIcon,
color: '#3ba974',
className: 'bg-[#e19900]',
},
{
title: 'Powerful Export API',
description: <p>Use our powerful export API to access your data.</p>,
icon: WebhookIcon,
color: '#3ba974',
className: 'bg-[#e93838]',
},
];
export function PunchLines() {
return (
<div className="bg-blue-darker relative py-32">
<div className="absolute inset-0 h-full w-full bg-[radial-gradient(circle,rgba(255,255,255,0.2)_0%,rgba(255,255,255,0)_100%)]" />
<div className="relative">
<Heading2 className="mb-16 text-center text-white">
Not convinced?
</Heading2>
<div className="container">
<div className="grid gap-8 md:grid-cols-2 lg:grid-cols-3">
{items.map((item) => {
const Icon = item.icon;
return (
<div
className="rounded-xl border border-border bg-white p-6"
key={item.title}
>
<div
className={cn(
'mb-4 flex h-14 w-14 items-center justify-center rounded-full',
item.color,
)}
style={{ background: item.color }}
>
<Icon color="#fff" />
</div>
<Heading4>{item.title}</Heading4>
<div className="prose">{item.description}</div>
</div>
);
})}
</div>
</div>
</div>
</div>
);
}

View File

@@ -1,17 +0,0 @@
import { TooltipProvider } from '@/components/ui/tooltip';
import { db } from '@openpanel/db';
import { SocialProof } from './social-proof';
interface Props {
className?: string;
}
export async function SocialProofServer(props: Props) {
const waitlistCount = await db.waitlist.count();
return (
<TooltipProvider>
<SocialProof count={waitlistCount} {...props} />
</TooltipProvider>
);
}

View File

@@ -1,73 +0,0 @@
'use client';
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from '@/components/ui/tooltip';
import { cn } from '@/utils/cn';
// import { StarIcon } from 'lucide-react';
import Image from 'next/image';
interface JoinWaitlistProps {
className?: string;
count: number;
}
export function SocialProof({ className, count }: JoinWaitlistProps) {
return (
<div className={cn('flex items-center gap-2', className)}>
<div className="flex">
<Tooltip>
<TooltipTrigger>
<Image
className="rounded-full"
src="/clickhouse.png"
width={40}
height={40}
alt="Clickhouse"
/>
</TooltipTrigger>
<TooltipContent>Clickhouse is here</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger className="-mx-3">
<Image
className="rounded-full"
src="/getdreams.png"
width={40}
height={40}
alt="GetDreams"
/>
</TooltipTrigger>
<TooltipContent>GetDreams is here</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger>
<Image
className="rounded-full"
src="/kiddokitchen.png"
width={40}
height={40}
alt="KiddoKitchen"
/>
</TooltipTrigger>
<TooltipContent>KiddoKitchen is here</TooltipContent>
</Tooltip>
</div>
<div>
<p className="text-left">{count} early birds have signed up! 🚀</p>
{/* <div className="flex gap-0.5">
<StarIcon size={16} color="#F5C962" fill="#F5C962" />
<StarIcon size={16} color="#F5C962" fill="#F5C962" />
<StarIcon size={16} color="#F5C962" fill="#F5C962" />
<StarIcon size={16} color="#F5C962" fill="#F5C962" />
<StarIcon size={16} color="#F5C962" fill="#F5C962" />
</div> */}
</div>
</div>
);
}
// <div class="flex flex-col gap-y-2 mt-5 lg:mt-3"><p class="text-gray-700 dark:text-gray-100 text-sm w-24 text-start font-semibold whitespace-nowrap">What users think</p><div class="flex flex-row w-full gap-x-2 items-start"><div class="w-5 shrink-0"/><img class="w-5 h-5 rounded-full " src="https://pbs.twimg.com/profile_images/1744063824431370240/BbVtyCiy_normal.png" alt="feedback_0"><span class="flex-wrap text-sm text-gray-600 dark:text-gray-200 text-start font-normal">“ Been a long time Mixpanel user and without a doubt there's a bunch of room to innovate. I'm confident Openpanel is on the right path! ”</span/><div class="flex flex-row w-full gap-x-2 items-start"><div class="w-5 shrink-0"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-flame w-5 h-5 text-red-600 fill-orange-400 animate-pulse"><path d="M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5z"></path></svg/><img class="w-5 h-5 rounded-full border border-2 border-red-500" src="https://pbs.twimg.com/profile_images/1751607056316944384/8E4F88FL_normal.jpg" alt="feedback_1"><span class="flex-wrap text-sm text-gray-600 dark:text-gray-200 text-start font-normal">“ I have used Openpanel for the last 6 months (since Im the creator) for 3 different sites/apps. Its a great analytics product that has everything you need. Still lacking a native app but will work hard to make that a reality! ”</span/><div class="flex flex-row w-full gap-x-2 items-start"><div class="w-5 shrink-0"/><img class="w-5 h-5 rounded-full " src="https://pbs.twimg.com/profile_images/1701887174042324992/g2GBIQay_normal.jpg" alt="feedback_2"><span class="flex-wrap text-sm text-gray-600 dark:text-gray-200 text-start font-normal">“ would be cool if it was easier to edit text after image is generated ”</span/><div class="flex flex-row w-full gap-x-2 items-start"><div class="w-5 shrink-0"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-flame w-5 h-5 text-red-600 fill-orange-400 animate-pulse"><path d="M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5z"></path></svg/><img class="w-5 h-5 rounded-full border border-2 border-red-500" src="https://pbs.twimg.com/profile_images/1194368464946974728/1D2biimN_normal.jpg" alt="feedback_3"><span class="flex-wrap text-sm text-gray-600 dark:text-gray-200 text-start font-normal">“ Awesome product, very easy to use and understand. I miss a native app and the documentation could be improved. Otherwise I love it. ”</span/><div class="flex flex-row w-full gap-x-2 items-start"><div class="w-5 shrink-0"/><img class="w-5 h-5 rounded-full " src="https://lh3.googleusercontent.com/a/ACg8ocIWiGTd3nWE5etp-CFhxrTKFvSLSJJd7pPmiM9SNJ9sAg=s96-c" alt="feedback_4"><span class="flex-wrap text-sm text-gray-600 dark:text-gray-200 text-start font-normal">“ I have used Open panel since the private beta and i'm super impressed by the product already, the speed after you give feedback to actually get the features is truly amazing! Can't wait to see where Openpanel are in 6 months! ”</span/><div class="flex flex-row w-full gap-x-2 items-start"><div class="w-5 shrink-0"/><img class="w-5 h-5 rounded-full " src="https://lh3.googleusercontent.com/a/ACg8ocKymAw_YoIrfoGp-bWMlDsXgM6St0dzaVJ7m_lGNXDtrA=s96-c" alt="feedback_5"><span class="flex-wrap text-sm text-gray-600 dark:text-gray-200 text-start font-normal">“ Impressively fast UI and easy to integrate! Added it alongside my current analytics tool for my native app in less than an hour. ”</span/><div class="flex flex-row w-full gap-x-2 items-start"><div class="w-5 shrink-0"/><img class="w-5 h-5 rounded-full " src="https://pbs.twimg.com/profile_images/1735771119980879872/Mx5MlB9e_normal.jpg" alt="feedback_6"><span class="flex-wrap text-sm text-gray-600 dark:text-gray-200 text-start font-normal">“ Im using plausible and find it pleasing but limited.
// Im looking forward to trying out Openpanel, the demo pictures and the page look professional. The listed features seem to be broader then plausible. :) ”</span/><div class="flex flex-row w-full gap-x-2 items-start"><div class="w-5 shrink-0"/><img class="w-5 h-5 rounded-full " src="https://pbs.twimg.com/profile_images/1767459527006334976/unbMENPG_normal.jpg" alt="feedback_7"><span class="flex-wrap text-sm text-gray-600 dark:text-gray-200 text-start font-normal">“ Incredibly easy to implement and a joy to use. 5/5 would recommend. ”</span/></div>