├── .eslintrc.json
├── .gitignore
├── LICENSE.md
├── README.md
├── next.config.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── prettier.config.js
├── public
└── og-image.jpg
├── src
├── app
│ ├── favicon.ico
│ ├── layout.tsx
│ ├── not-found.tsx
│ └── page.tsx
├── components
│ ├── Author.tsx
│ ├── Button.tsx
│ ├── CheckIcon.tsx
│ ├── Container.tsx
│ ├── Expandable.tsx
│ ├── Footer.tsx
│ ├── FreeChapters.tsx
│ ├── Friends.tsx
│ ├── GridPattern.tsx
│ ├── Hero.tsx
│ ├── Introduction.tsx
│ ├── NavBar.tsx
│ ├── Pattern.tsx
│ ├── Pricing.tsx
│ ├── Resources.tsx
│ ├── Screencasts.tsx
│ ├── SectionHeading.tsx
│ ├── StarRating.tsx
│ ├── TableOfContents.tsx
│ ├── Testimonial.tsx
│ └── Testimonials.tsx
├── fonts
│ ├── CalSans-SemiBold.ttf
│ └── CalSans-SemiBold.woff2
├── images
│ ├── avatars
│ │ ├── author.jpg
│ │ ├── author.png
│ │ ├── avatar-1.png
│ │ ├── avatar-10.png
│ │ ├── avatar-11.png
│ │ ├── avatar-12.png
│ │ ├── avatar-13.png
│ │ ├── avatar-14.png
│ │ ├── avatar-15.png
│ │ ├── avatar-16.png
│ │ ├── avatar-17.png
│ │ ├── avatar-18.png
│ │ ├── avatar-2.png
│ │ ├── avatar-3.png
│ │ ├── avatar-4.png
│ │ ├── avatar-5.png
│ │ ├── avatar-6.png
│ │ ├── avatar-7.png
│ │ ├── avatar-8.png
│ │ └── avatar-9.png
│ ├── cover.png
│ ├── resources
│ │ ├── abstract-background.png
│ │ ├── discord.svg
│ │ ├── figma.svg
│ │ └── video-player.svg
│ └── screencasts
│ │ ├── duotone.svg
│ │ ├── grids.svg
│ │ ├── setup.svg
│ │ └── strokes.svg
└── styles
│ └── tailwind.css
├── tailwind.config.ts
└── tsconfig.json
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "next/core-web-vitals"
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | *.pem
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 |
27 | # local env files
28 | .env*.local
29 |
30 | # vercel
31 | .vercel
32 |
33 | # typescript
34 | *.tsbuildinfo
35 | next-env.d.ts
36 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) oss/acc. Built with TailwindUI.com
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # oss/acc
2 |
3 | ossacc.com has been built with Primer, a [Tailwind UI](https://tailwindui.com) site template built using [Tailwind CSS](https://tailwindcss.com) and [Next.js](https://nextjs.org).
4 |
5 | ## Getting started
6 |
7 | To get started with this template, first install the npm dependencies:
8 |
9 | ```bash
10 | npm install
11 | ```
12 |
13 | Next, run the development server:
14 |
15 | ```bash
16 | npm run dev
17 | ```
18 |
19 | Finally, open [http://localhost:3000](http://localhost:3000) in your browser to view the website.
20 |
21 | ## Customizing
22 |
23 | You can start editing this template by modifying the files in the `/src` folder. The site will auto-update as you edit these files.
24 |
25 | ## Learn more
26 |
27 | To learn more about the technologies used in this site template, see the following resources:
28 |
29 | - [Tailwind CSS](https://tailwindcss.com/docs) - the official Tailwind CSS documentation
30 | - [Next.js](https://nextjs.org/docs) - the official Next.js documentation
31 | - [Headless UI](https://headlessui.dev) - the official Headless UI documentation
32 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {}
3 |
4 | module.exports = nextConfig
5 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tailwindui-primer",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "browserslist": "defaults, not ie <= 11",
12 | "dependencies": {
13 | "@headlessui/react": "^1.7.13",
14 | "@types/node": "20.4.5",
15 | "@types/react": "18.2.17",
16 | "@types/react-dom": "18.2.7",
17 | "autoprefixer": "^10.4.12",
18 | "clsx": "^1.2.1",
19 | "next": "13.4.16",
20 | "react": "18.2.0",
21 | "react-dom": "18.2.0",
22 | "tailwindcss": "^3.3.3",
23 | "typescript": "5.1.6"
24 | },
25 | "devDependencies": {
26 | "eslint": "8.45.0",
27 | "eslint-config-next": "13.4.16",
28 | "prettier": "^3.0.1",
29 | "prettier-plugin-tailwindcss": "^0.5.2",
30 | "sharp": "^0.32.0"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/prettier.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('prettier').Options} */
2 | module.exports = {
3 | singleQuote: true,
4 | semi: false,
5 | plugins: ['prettier-plugin-tailwindcss'],
6 | }
7 |
--------------------------------------------------------------------------------
/public/og-image.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/public/og-image.jpg
--------------------------------------------------------------------------------
/src/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/app/favicon.ico
--------------------------------------------------------------------------------
/src/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import { type Metadata } from 'next'
2 | import { Inter } from 'next/font/google'
3 | import clsx from 'clsx'
4 | import localFont from 'next/font/local'
5 |
6 | import '@/styles/tailwind.css'
7 |
8 | const inter = Inter({
9 | subsets: ['latin'],
10 | display: 'swap',
11 | variable: '--font-inter',
12 | })
13 |
14 | const calSans = localFont({
15 | src: '../fonts/CalSans-SemiBold.woff2',
16 | variable: '--font-cal',
17 | })
18 |
19 | export const metadata: Metadata = {
20 | title: 'oss/acc',
21 | description:
22 | 'Everything is build with Open Source. The modern world we live in today would simply not exist.',
23 | }
24 |
25 | export default function RootLayout({
26 | children,
27 | }: {
28 | children: React.ReactNode
29 | }) {
30 | return (
31 |
39 |
40 |
41 |
42 |
47 |
52 |
56 |
57 | {children}
58 |
59 | )
60 | }
61 |
--------------------------------------------------------------------------------
/src/app/not-found.tsx:
--------------------------------------------------------------------------------
1 | import Link from 'next/link'
2 |
3 | import { Container } from '@/components/Container'
4 | import { GridPattern } from '@/components/GridPattern'
5 |
6 | export default function NotFound() {
7 | return (
8 |
9 |
10 |
11 |
12 |
13 |
14 | 404
15 |
16 |
17 | Page not found
18 |
19 |
20 | Sorry, we couldn’t find the page you’re looking for.
21 |
22 |
26 | Go back home →
27 |
28 |
29 |
30 | )
31 | }
32 |
--------------------------------------------------------------------------------
/src/app/page.tsx:
--------------------------------------------------------------------------------
1 | import { Author } from '@/components/Author'
2 | import { Footer } from '@/components/Footer'
3 | import { Introduction } from '@/components/Introduction'
4 |
5 | export default function Home() {
6 | return (
7 | <>
8 |
9 |
10 |
11 | >
12 | )
13 | }
14 |
--------------------------------------------------------------------------------
/src/components/Author.tsx:
--------------------------------------------------------------------------------
1 | import Image from 'next/image'
2 | import Link from 'next/link'
3 |
4 | import { GridPattern } from '@/components/GridPattern'
5 | import { SectionHeading } from '@/components/SectionHeading'
6 | import authorImage from '@/images/avatars/author.jpg'
7 |
8 | function TwitterIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
9 | return (
10 |
11 |
12 |
13 | )
14 | }
15 |
16 | export function Author() {
17 | return (
18 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
35 |
36 |
37 |
38 | Author
39 |
40 |
41 | Peer Richelsen – open
42 | source, open heart, open mind.
43 |
44 |
45 | I’ve started my career in Open Source back in 2013 with Wordpress
46 | and I’ll do everything in my power to create an Open Future with
47 | Cal.com and all other Open Source ventures that I am involved in.
48 |
49 |
50 |
54 |
59 |
60 |
61 |
62 |
63 | Follow on X.com
64 |
65 |
66 |
67 |
68 |
69 |
70 | )
71 | }
72 |
--------------------------------------------------------------------------------
/src/components/Button.tsx:
--------------------------------------------------------------------------------
1 | import Link from 'next/link'
2 | import clsx from 'clsx'
3 |
4 | const baseStyles = {
5 | solid:
6 | 'inline-flex justify-center rounded-md py-1 px-4 text-base font-semibold tracking-tight shadow-sm focus:outline-none',
7 | outline:
8 | 'inline-flex justify-center rounded-md border py-[calc(theme(spacing.1)-1px)] px-[calc(theme(spacing.4)-1px)] text-base font-semibold tracking-tight focus:outline-none',
9 | }
10 |
11 | const variantStyles = {
12 | solid: {
13 | slate:
14 | 'bg-slate-900 text-white hover:bg-slate-700 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-slate-900 active:bg-slate-700 active:text-white/80 disabled:opacity-30 disabled:hover:bg-slate-900',
15 | blue: 'bg-blue-600 text-white hover:bg-blue-500 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600 active:bg-blue-700 active:text-white/80 disabled:opacity-30 disabled:hover:bg-blue-600',
16 | white:
17 | 'bg-white text-blue-600 hover:text-blue-700 focus-visible:text-blue-900 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white active:bg-blue-50 active:text-blue-900/80 disabled:opacity-40 disabled:hover:text-blue-600',
18 | },
19 | outline: {
20 | slate:
21 | 'border-slate-200 text-slate-900 hover:border-slate-300 hover:bg-slate-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-slate-600 active:border-slate-200 active:bg-slate-50 active:text-slate-900/70 disabled:opacity-40 disabled:hover:border-slate-200 disabled:hover:bg-transparent',
22 | blue: 'border-blue-300 text-blue-600 hover:border-blue-400 hover:bg-blue-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600 active:text-blue-600/70 disabled:opacity-40 disabled:hover:border-blue-300 disabled:hover:bg-transparent',
23 | },
24 | }
25 |
26 | type VariantKey = keyof typeof variantStyles
27 | type ColorKey =
28 | keyof (typeof variantStyles)[Variant]
29 |
30 | type ButtonProps<
31 | Variant extends VariantKey,
32 | Color extends ColorKey,
33 | > = {
34 | variant?: Variant
35 | color?: Color
36 | } & (
37 | | Omit, 'color'>
38 | | (Omit, 'color'> & {
39 | href?: undefined
40 | })
41 | )
42 |
43 | export function Button<
44 | Color extends ColorKey,
45 | Variant extends VariantKey = 'solid',
46 | >({ variant, color, className, ...props }: ButtonProps) {
47 | variant = variant ?? ('solid' as Variant)
48 | color = color ?? ('slate' as Color)
49 |
50 | className = clsx(
51 | baseStyles[variant],
52 | variantStyles[variant][color],
53 | className,
54 | )
55 |
56 | return typeof props.href === 'undefined' ? (
57 |
58 | ) : (
59 |
60 | )
61 | }
62 |
--------------------------------------------------------------------------------
/src/components/CheckIcon.tsx:
--------------------------------------------------------------------------------
1 | export function CheckIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
2 | return (
3 |
4 |
5 |
6 | )
7 | }
8 |
--------------------------------------------------------------------------------
/src/components/Container.tsx:
--------------------------------------------------------------------------------
1 | import clsx from 'clsx'
2 |
3 | const styles = {
4 | xs: 'mx-auto px-4 sm:px-6 md:max-w-2xl md:px-4 lg:px-2',
5 | sm: 'mx-auto px-4 sm:px-6 md:max-w-2xl md:px-4 lg:max-w-4xl lg:px-12',
6 | md: 'mx-auto px-4 sm:px-6 md:max-w-2xl md:px-4 lg:max-w-5xl lg:px-8',
7 | lg: 'mx-auto px-4 sm:px-6 md:max-w-2xl md:px-4 lg:max-w-7xl lg:px-8',
8 | }
9 |
10 | export function Container({
11 | size = 'sm',
12 | className,
13 | ...props
14 | }: React.ComponentPropsWithoutRef<'div'> & { size?: keyof typeof styles }) {
15 | return
16 | }
17 |
--------------------------------------------------------------------------------
/src/components/Expandable.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import { Children, createContext, useContext, useState } from 'react'
4 |
5 | function ArrowDownIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
6 | return (
7 |
8 |
16 |
17 | )
18 | }
19 |
20 | const ExpandableContext = createContext({
21 | isExpanded: false,
22 | expand: () => {},
23 | })
24 |
25 | export function Expandable(props: React.ComponentPropsWithoutRef<'div'>) {
26 | let [isExpanded, setIsExpanded] = useState(false)
27 |
28 | return (
29 | {
33 | setIsExpanded(true)
34 | },
35 | }}
36 | >
37 |
38 |
39 | )
40 | }
41 |
42 | export function ExpandableItems({
43 | children,
44 | limit = 2,
45 | }: {
46 | children: React.ReactNode
47 | limit?: number
48 | }) {
49 | let { isExpanded } = useContext(ExpandableContext)
50 |
51 | return Children.toArray(children).slice(0, isExpanded ? undefined : limit)
52 | }
53 |
54 | export function ExpandableButton({ children }: { children: React.ReactNode }) {
55 | let { isExpanded, expand } = useContext(ExpandableContext)
56 |
57 | return (
58 | !isExpanded && (
59 |
60 |
65 | {children}
66 |
67 |
68 |
69 | )
70 | )
71 | }
72 |
--------------------------------------------------------------------------------
/src/components/Footer.tsx:
--------------------------------------------------------------------------------
1 | import { GridPattern } from '@/components/GridPattern'
2 |
3 | export function Footer() {
4 | return (
5 |
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/src/components/FreeChapters.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from '@/components/Button'
2 | import { Container } from '@/components/Container'
3 | import { Pattern } from '@/components/Pattern'
4 |
5 | export function FreeChapters() {
6 | return (
7 |
12 |
13 |
17 |
18 |
19 |
20 | Get the free sample chapters
21 |
22 |
23 | Enter your email address and I’ll send you a sample from the book
24 | containing two of my favorite chapters.
25 |
26 |
27 |
53 |
54 |
55 |
56 | )
57 | }
58 |
--------------------------------------------------------------------------------
/src/components/Friends.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from './Button'
2 |
3 | export default async function Friends() {
4 | const res = await fetch('https://formbricks.com/api/oss-friends')
5 | const resJson = await res.json()
6 | const friends = resJson.data.filter((item: any) => item.name !== 'Cal.com')
7 | return (
8 | <>
9 |
13 |
14 | Our Open Source Friends
15 |
16 |
17 | Meet other projects whose code and culture is open
18 |
19 |
20 |
21 | {friends.map((friend: any, index: number) => (
22 |
34 | ))}
35 |
36 | >
37 | )
38 | }
39 |
--------------------------------------------------------------------------------
/src/components/GridPattern.tsx:
--------------------------------------------------------------------------------
1 | import { useId } from 'react'
2 |
3 | export function GridPattern(
4 | props: Omit, 'id'>,
5 | ) {
6 | let patternId = useId()
7 |
8 | return (
9 |
10 |
11 |
18 |
19 |
20 |
21 |
22 |
23 | )
24 | }
25 |
--------------------------------------------------------------------------------
/src/components/Hero.tsx:
--------------------------------------------------------------------------------
1 | import Image from 'next/image'
2 |
3 | import { Button } from '@/components/Button'
4 | import { GridPattern } from '@/components/GridPattern'
5 | import { StarRating } from '@/components/StarRating'
6 | import coverImage from '@/images/cover.png'
7 |
8 | function Testimonial() {
9 | return (
10 |
11 |
12 |
13 |
14 |
15 |
16 | “This method of designing icons is genius. I wish I had known this
17 | method a lot sooner.”
18 |
19 |
20 |
21 |
22 | Stacey Solomon
23 |
24 | , Founder at Retail Park
25 |
26 |
27 | )
28 | }
29 |
30 | export function Hero() {
31 | return (
32 |
33 |
34 |
35 |
36 |
41 |
42 |
43 |
44 |
45 |
46 |
50 |
51 |
52 |
53 | Get lost in the world of icon design.
54 |
55 |
56 | A book and video course that teaches you how to design your own
57 | icons from scratch.
58 |
59 |
60 |
61 | Get sample chapter
62 |
63 |
64 | Buy book
65 |
66 |
67 |
68 |
69 |
70 |
71 | )
72 | }
73 |
--------------------------------------------------------------------------------
/src/components/Introduction.tsx:
--------------------------------------------------------------------------------
1 | import Link from 'next/link'
2 |
3 | import { CheckIcon } from '@/components/CheckIcon'
4 | import { Container } from '@/components/Container'
5 |
6 | export function Introduction() {
7 | return (
8 |
13 |
14 |
15 | Everything is built with Open Source. The modern world we live in
16 | today would simply not exist.
17 |
18 |
19 | As we accelerate into the future, we need to make sure that we
20 | continue building open systems that impact our day to day lives,
21 | especially when it comes to advanced AI and AGI.
22 |
23 | We need oss/acc.
24 |
25 |
26 | {[
27 | 'Transparency and Trust',
28 | 'Security and Reliability',
29 | 'Innovation and Progress',
30 | 'Accessibility and Inclusivity',
31 | 'Customizability and Flexibility',
32 | 'Longevity and Sustainability',
33 | 'Ethical and Social Responsibility',
34 | 'Global Collaboration and Cooperation',
35 | ].map((feature) => (
36 |
37 |
38 | {feature}
39 |
40 | ))}
41 |
42 |
43 |
44 |
45 |
46 | Transparency and Trust: Open source
47 | software's code is accessible to everyone, allowing users
48 | to review, modify, and enhance it. This transparency fosters
49 | trust as it ensures there are no hidden functionalities or
50 | vulnerabilities that could compromise security.
51 |
52 |
53 |
54 |
55 | Security and Reliability: With a global
56 | community continuously examining the code, issues and
57 | vulnerabilities are quickly identified and fixed. This
58 | collaborative approach leads to more secure and reliable
59 | software, reducing the risk of cyber attacks and ensuring robust
60 | systems for critical infrastructure.
61 |
62 |
63 |
64 |
65 | Innovation and Progress: Open source encourages
66 | innovation by enabling developers worldwide to build upon
67 | existing solutions. This collaborative environment sparks
68 | creativity and accelerates technological progress, leading to
69 | better tools, applications, and systems that benefit society.
70 |
71 |
72 |
73 |
74 | Accessibility and Inclusivity: Open source
75 | software is often free or available at minimal cost, breaking
76 | down financial barriers to technology. It empowers individuals
77 | and communities, particularly in underserved regions, to access
78 | and use advanced tools, fostering digital inclusivity.
79 |
80 |
81 |
82 |
83 | Customizability and Flexibility: Users can
84 | tailor open source software to suit their specific needs. This
85 | flexibility allows for customization, adaptation, and
86 | integration into diverse environments, ensuring solutions that
87 | fit a wide array of contexts and requirements.
88 |
89 |
90 |
91 |
92 | Longevity and Sustainability: Open source
93 | projects are not dependent on the fate of a single entity.
94 | Communities sustain these projects, ensuring their longevity
95 | even if a particular organization or company fades away,
96 | providing continuity and stability.
97 |
98 |
99 |
100 |
101 | Ethical and Social Responsibility: Open source
102 | software embodies principles of collaboration, sharing, and
103 | knowledge dissemination. It aligns with ethical values by
104 | promoting the democratization of technology and fostering a
105 | culture of giving back to the community.
106 |
107 |
108 |
109 |
110 | Global Collaboration and Cooperation: Open
111 | source transcends borders and encourages collaboration among
112 | diverse communities worldwide. It harnesses the collective
113 | intelligence of individuals irrespective of their geographical
114 | location, fostering a global spirit of cooperation and shared
115 | advancement.
116 |
117 |
118 |
119 |
120 |
121 | A future built upon open source software cultivates an environment
122 | where technology serves humanity, empowers individuals, and creates a
123 | more secure, equitable, and prosperous world for all.
124 |
125 |
126 | Join the open source movement and sign the manifesto or{' '}
127 |
133 | see who already has signed it
134 |
135 | .
136 |
137 |
138 |
142 | Sign and share on x.com
143 | →
144 |
145 |
146 |
147 |
148 | )
149 | }
150 |
--------------------------------------------------------------------------------
/src/components/NavBar.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import { useEffect, useRef, useState } from 'react'
4 | import { Popover } from '@headlessui/react'
5 | import clsx from 'clsx'
6 |
7 | const sections = [
8 | {
9 | id: 'table-of-contents',
10 | title: (
11 | <>
12 | Table of contents
13 | Contents
14 | >
15 | ),
16 | },
17 | { id: 'screencasts', title: 'Screencasts' },
18 | { id: 'resources', title: 'Resources' },
19 | { id: 'pricing', title: 'Pricing' },
20 | { id: 'author', title: 'Author' },
21 | ]
22 |
23 | function MenuIcon({
24 | open,
25 | ...props
26 | }: React.ComponentPropsWithoutRef<'svg'> & {
27 | open: boolean
28 | }) {
29 | return (
30 |
39 |
42 |
43 | )
44 | }
45 |
46 | export function NavBar() {
47 | let navBarRef = useRef>(null)
48 | let [activeIndex, setActiveIndex] = useState(null)
49 | let mobileActiveIndex = activeIndex === null ? 0 : activeIndex
50 |
51 | useEffect(() => {
52 | function updateActiveIndex() {
53 | if (!navBarRef.current) {
54 | return
55 | }
56 |
57 | let newActiveIndex = null
58 | let elements = sections
59 | .map(({ id }) => document.getElementById(id))
60 | .filter((el): el is HTMLElement => el !== null)
61 | let bodyRect = document.body.getBoundingClientRect()
62 | let offset = bodyRect.top + navBarRef.current.offsetHeight + 1
63 |
64 | if (window.scrollY >= Math.floor(bodyRect.height) - window.innerHeight) {
65 | setActiveIndex(sections.length - 1)
66 | return
67 | }
68 |
69 | for (let index = 0; index < elements.length; index++) {
70 | if (
71 | window.scrollY >=
72 | elements[index].getBoundingClientRect().top - offset
73 | ) {
74 | newActiveIndex = index
75 | } else {
76 | break
77 | }
78 | }
79 |
80 | setActiveIndex(newActiveIndex)
81 | }
82 |
83 | updateActiveIndex()
84 |
85 | window.addEventListener('resize', updateActiveIndex)
86 | window.addEventListener('scroll', updateActiveIndex, { passive: true })
87 |
88 | return () => {
89 | window.removeEventListener('resize', updateActiveIndex)
90 | window.removeEventListener('scroll', updateActiveIndex)
91 | }
92 | }, [])
93 |
94 | return (
95 |
96 |
97 | {({ open }) => (
98 | <>
99 |
106 | {!open && (
107 | <>
108 |
112 | {(mobileActiveIndex + 1).toString().padStart(2, '0')}
113 |
114 |
115 | {sections[mobileActiveIndex].title}
116 |
117 | >
118 | )}
119 |
126 | {!open && (
127 | <>
128 | {/* Increase hit area */}
129 |
130 | >
131 | )}
132 |
133 |
134 |
135 |
136 | {sections.map((section, sectionIndex) => (
137 |
143 |
147 | {(sectionIndex + 1).toString().padStart(2, '0')}
148 |
149 |
150 | {section.title}
151 |
152 |
153 | ))}
154 |
155 |
156 | >
157 | )}
158 |
159 |
181 |
182 | )
183 | }
184 |
--------------------------------------------------------------------------------
/src/components/Pattern.tsx:
--------------------------------------------------------------------------------
1 | import { useId } from 'react'
2 |
3 | export function Pattern({
4 | size = 40,
5 | gapX = 16,
6 | gapY = 8,
7 | pattern = [
8 | [0, 1, 0, 1, 1, 0, 1, 0],
9 | [1, 0, 1, 1, 0, 0, 0, 1],
10 | [0, 1, 0, 1, 1, 0, 1, 0],
11 | [1, 0, 1, 1, 0, 0, 0, 1],
12 | ],
13 | ...props
14 | }: React.ComponentPropsWithoutRef<'svg'> & {
15 | size?: number
16 | gapX?: number
17 | gapY?: number
18 | pattern?: Array>
19 | }) {
20 | let id = useId()
21 | let width = pattern[0].length * size + (pattern[0].length - 1) * gapX
22 | let height = pattern.length * size + (pattern.length - 1) * gapY
23 |
24 | return (
25 |
26 |
27 |
28 |
29 |
35 |
36 |
37 |
43 |
50 |
51 |
52 | {pattern.map((row, rowIndex) =>
53 | row.map((shape, columnIndex) => (
54 |
60 | )),
61 | )}
62 |
63 | )
64 | }
65 |
--------------------------------------------------------------------------------
/src/components/Pricing.tsx:
--------------------------------------------------------------------------------
1 | import clsx from 'clsx'
2 |
3 | import { Button } from '@/components/Button'
4 | import { CheckIcon } from '@/components/CheckIcon'
5 | import { Container } from '@/components/Container'
6 | import { GridPattern } from '@/components/GridPattern'
7 | import { SectionHeading } from '@/components/SectionHeading'
8 |
9 | function Plan({
10 | name,
11 | description,
12 | price,
13 | features,
14 | href,
15 | featured = false,
16 | }: {
17 | name: string
18 | description: string
19 | price: string
20 | features: Array
21 | href: string
22 | featured?: boolean
23 | }) {
24 | return (
25 |
31 | {featured && (
32 |
33 |
34 |
35 | )}
36 |
37 |
43 | {name}
44 |
45 |
51 | {description}
52 |
53 |
54 |
60 | $
61 |
62 |
68 | {price}
69 |
70 |
71 |
72 |
81 | {features.map((feature) => (
82 |
83 |
89 | {feature}
90 |
91 | ))}
92 |
93 |
94 |
100 | Get started
101 |
102 |
103 |
104 | )
105 | }
106 |
107 | export function Pricing() {
108 | return (
109 |
114 |
115 |
116 | Pricing
117 |
118 |
119 | Pick your package
120 |
121 |
122 | “Everything Starts as a Square” is available in two different packages
123 | so you can pick the one that’s right for you.
124 |
125 |
126 |
155 |
156 | )
157 | }
158 |
--------------------------------------------------------------------------------
/src/components/Resources.tsx:
--------------------------------------------------------------------------------
1 | import Image from 'next/image'
2 |
3 | import { Container } from '@/components/Container'
4 | import { SectionHeading } from '@/components/SectionHeading'
5 | import abstractBackgroundImage from '@/images/resources/abstract-background.png'
6 | import discordImage from '@/images/resources/discord.svg'
7 | import figmaImage from '@/images/resources/figma.svg'
8 | import videoPlayerImage from '@/images/resources/video-player.svg'
9 | import { Button } from './Button'
10 |
11 | const resources = [
12 | {
13 | title: 'Explore and Contribute',
14 | description:
15 | 'Discover exciting open source projects, contribute or apply for a job!',
16 | button: (
17 |
18 | Discover Open Source
19 |
20 | ),
21 | image: function FigmaImage() {
22 | return (
23 |
24 |
25 |
26 | )
27 | },
28 | },
29 | {
30 | title: 'Start a COSS',
31 | description:
32 | 'COSS stands for commercial open source software. If you want to build a company to sustain your project',
33 | button: (
34 |
35 | Apply for Funding
36 |
37 | ),
38 | image: function VideoPlayerImage() {
39 | return (
40 |
41 |
47 |
53 |
54 | )
55 | },
56 | },
57 | {
58 | title: 'Participate in OSSHack',
59 | description:
60 | 'OSSHack.com is the largest in-person and remote Open Source-first hackathon.',
61 | button: (
62 |
63 | Visit OSSHack.com
64 |
65 | ),
66 | image: function DiscordImage() {
67 | return (
68 |
69 |
70 |
71 | )
72 | },
73 | },
74 | {
75 | title: 'Join a Community',
76 | description:
77 | 'Join our Discord server that promote oss/acc, COSS and Open Source',
78 | button: (
79 |
80 | Join Discord
81 |
82 | ),
83 | image: function DiscordImage() {
84 | return (
85 |
86 |
87 |
88 | )
89 | },
90 | },
91 | ]
92 |
93 | export function Resources() {
94 | return (
95 |
100 |
101 |
102 | Get Involved
103 |
104 |
105 | If you want to do more than just signing a pledge, here is how you can
106 | promote the mission
107 |
108 |
109 | Design assets, icon teardowns, and a community of fellow icon
110 | designers where you can ask questions, get feedback, and accelerate
111 | your learning.
112 |
113 |
114 |
115 |
119 | {resources.map((resource) => (
120 |
124 |
125 |
126 |
127 |
128 |
129 | {resource.title}
130 |
131 |
132 | {resource.description}
133 |
134 | {resource.button && resource.button}
135 |
136 |
137 | ))}
138 |
139 |
140 |
141 | )
142 | }
143 |
--------------------------------------------------------------------------------
/src/components/Screencasts.tsx:
--------------------------------------------------------------------------------
1 | import Image from 'next/image'
2 |
3 | import { Container } from '@/components/Container'
4 | import { SectionHeading } from '@/components/SectionHeading'
5 | import duotoneImage from '@/images/screencasts/duotone.svg'
6 | import gridsImage from '@/images/screencasts/grids.svg'
7 | import setupImage from '@/images/screencasts/setup.svg'
8 | import strokesImage from '@/images/screencasts/strokes.svg'
9 |
10 | const videos = [
11 | {
12 | title: 'Getting started with Figma',
13 | description:
14 | 'Get familiar with the Figma UI, the different tools it offers, and the most important features.',
15 | image: setupImage,
16 | runtime: { minutes: 16, seconds: 54 },
17 | },
18 | {
19 | title: 'Setting up your artboard',
20 | description:
21 | 'Learn how to create a new artboard and configure your grid and rulers for designing icons.',
22 | image: gridsImage,
23 | runtime: { minutes: 9, seconds: 12 },
24 | },
25 | {
26 | title: 'Designing your first icon',
27 | description:
28 | 'Using basic shapes and boolean operations, learn how to design your own notification icon from scratch.',
29 | image: strokesImage,
30 | runtime: { minutes: 23, seconds: 25 },
31 | },
32 | {
33 | title: 'Advanced design techniques',
34 | description:
35 | 'Learn the techniques you need to know to adapt your original icon to a modern duotone style.',
36 | image: duotoneImage,
37 | runtime: { minutes: 28, seconds: 44 },
38 | },
39 | ]
40 |
41 | function PlayIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
42 | return (
43 |
51 |
52 |
53 |
54 | )
55 | }
56 |
57 | export function Screencasts() {
58 | return (
59 |
64 |
65 |
66 | Screencasts
67 |
68 |
69 | Over an hour of high quality, step-by-step video content to sharpen
70 | your icon design workflow.
71 |
72 |
73 | Learn how to design your very first icons in a series of screencasts
74 | that will teach you everything you need to know to go from beginner to
75 | pro in just over an hour.
76 |
77 |
78 |
79 |
83 | {videos.map((video) => (
84 |
85 |
92 |
93 |
94 |
95 |
96 |
97 |
101 | {`${video.runtime.minutes}:${video.runtime.seconds
102 | .toString()
103 | .padStart(2, '0')}`}
104 |
105 |
106 |
107 |
108 | {video.title}
109 |
110 | {video.description}
111 |
112 | ))}
113 |
114 |
115 |
116 | )
117 | }
118 |
--------------------------------------------------------------------------------
/src/components/SectionHeading.tsx:
--------------------------------------------------------------------------------
1 | import clsx from 'clsx'
2 |
3 | export function SectionHeading({
4 | children,
5 | className,
6 | ...props
7 | }: React.ComponentPropsWithoutRef<'h2'> & { number: string }) {
8 | return (
9 |
16 | {children}
17 |
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/src/components/StarRating.tsx:
--------------------------------------------------------------------------------
1 | function StarIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
2 | return (
3 |
4 |
5 |
6 | )
7 | }
8 |
9 | export function StarRating({ rating = 5 }: { rating?: 1 | 2 | 3 | 4 | 5 }) {
10 | return (
11 |
12 | {[...Array(rating).keys()].map((index) => (
13 |
14 | ))}
15 |
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/src/components/TableOfContents.tsx:
--------------------------------------------------------------------------------
1 | import { Container } from '@/components/Container'
2 | import {
3 | Expandable,
4 | ExpandableButton,
5 | ExpandableItems,
6 | } from '@/components/Expandable'
7 | import { SectionHeading } from '@/components/SectionHeading'
8 |
9 | const tableOfContents = {
10 | 'Getting started': {
11 | 'Getting started': 1,
12 | 'Intro to Figma': 15,
13 | 'Setting up your first artboard': 20,
14 | },
15 | Fundamentals: {
16 | 'Strokes and fills': 21,
17 | 'End points': 22,
18 | 'Bezier curves': 26,
19 | 'Designing on a grid': 31,
20 | 'Vector shapes': 45,
21 | },
22 | 'Boolean operations': {
23 | 'Combining shapes': 50,
24 | 'Subtracting shapes': 57,
25 | 'Intersecting shapes': 66,
26 | Flattening: 78,
27 | },
28 | 'Optimizing for production': {
29 | 'Preparing for SVG': 82,
30 | 'Configuring your export settings': 88,
31 | 'Minifying and removing metadata': 95,
32 | },
33 | }
34 |
35 | export function TableOfContents() {
36 | return (
37 |
42 |
43 |
44 | Table of contents
45 |
46 |
47 | Get a look at all of the content covered in the book. Everything you
48 | need to know is inside.
49 |
50 |
51 | “Everything Starts as a Square” is comprised of 240 tightly edited,
52 | highly visual pages designed to teach you everything you need to know
53 | about icon design with no unnecessary filler.
54 |
55 |
56 |
57 |
58 | {Object.entries(tableOfContents).map(([title, pages]) => (
59 |
60 |
61 | {title}
62 |
63 |
67 | {Object.entries(pages).map(([title, pageNumber]) => (
68 |
73 |
77 | {title}
78 |
79 |
83 | {pageNumber}
84 |
85 |
86 | ))}
87 |
88 |
89 | ))}
90 |
91 |
92 | See more
93 |
94 |
95 |
96 | )
97 | }
98 |
--------------------------------------------------------------------------------
/src/components/Testimonial.tsx:
--------------------------------------------------------------------------------
1 | import Image, { type ImageProps } from 'next/image'
2 |
3 | import { Container } from '@/components/Container'
4 | import { GridPattern } from '@/components/GridPattern'
5 | import { StarRating } from '@/components/StarRating'
6 |
7 | export function Testimonial({
8 | id,
9 | author,
10 | children,
11 | }: {
12 | id: string
13 | author: { name: string; role: string; image: ImageProps['src'] }
14 | children: React.ReactNode
15 | }) {
16 | return (
17 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | {children}
32 |
33 |
34 |
35 |
42 |
43 |
44 |
45 | {author.name}
46 |
47 |
{author.role}
48 |
49 |
50 |
51 |
52 |
53 | )
54 | }
55 |
--------------------------------------------------------------------------------
/src/components/Testimonials.tsx:
--------------------------------------------------------------------------------
1 | import Image, { type ImageProps } from 'next/image'
2 | import clsx from 'clsx'
3 |
4 | import { Container } from '@/components/Container'
5 | import {
6 | Expandable,
7 | ExpandableButton,
8 | ExpandableItems,
9 | } from '@/components/Expandable'
10 | import avatarImage3 from '@/images/avatars/avatar-3.png'
11 | import avatarImage4 from '@/images/avatars/avatar-4.png'
12 | import avatarImage5 from '@/images/avatars/avatar-5.png'
13 | import avatarImage6 from '@/images/avatars/avatar-6.png'
14 | import avatarImage7 from '@/images/avatars/avatar-7.png'
15 | import avatarImage8 from '@/images/avatars/avatar-8.png'
16 | import avatarImage9 from '@/images/avatars/avatar-9.png'
17 | import avatarImage10 from '@/images/avatars/avatar-10.png'
18 | import avatarImage11 from '@/images/avatars/avatar-11.png'
19 |
20 | const testimonials = [
21 | [
22 | {
23 | content: 'Heck yea! A movement I can 100% stand for.',
24 | author: {
25 | name: 'Carlos Virreira — oss/acc',
26 | role: 'Frontend Developer',
27 | image: avatarImage3,
28 | },
29 | },
30 | {
31 | content:
32 | 'Even though I was excited to learn, I was pessimistic that I wouldn’t actually ever get good enough to design my own icons. I was wrong — this book is all I needed.',
33 | author: {
34 | name: 'Lynn Nolan',
35 | role: 'Growth Marketer',
36 | image: avatarImage4,
37 | },
38 | },
39 | {
40 | content:
41 | 'I’ve been employed as a professional icon designer for years and still learned tons of new tricks that have made my work even better',
42 | author: {
43 | name: 'Krista Prosacco',
44 | role: 'Professional Designer',
45 | image: avatarImage9,
46 | },
47 | },
48 | ],
49 | [
50 | {
51 | content:
52 | 'I run an ecommerce store selling rare vintage gummy bears and could never find a good gummy bear icon. Now I can design my own in minutes.',
53 | author: {
54 | name: 'Cameron Considine',
55 | role: 'Entrepreneur',
56 | image: avatarImage7,
57 | },
58 | },
59 | {
60 | content:
61 | 'The complete package is worth it for the weekly teardown videos alone. I’ve learned so much watching Mira take apart other icons and recreate them from scratch.',
62 | author: {
63 | name: 'Regina Wisoky',
64 | role: 'Design Student',
65 | image: avatarImage11,
66 | },
67 | },
68 | {
69 | content:
70 | 'I didn’t expect to find a lot of value in the community but now I’m in there for at least an hour every day picking up tips from other designers.',
71 | author: {
72 | name: 'Vernon Cummerata',
73 | role: 'UI Engineer',
74 | image: avatarImage8,
75 | },
76 | },
77 | ],
78 | [
79 | {
80 | content:
81 | 'I couldn’t believe how fast Mira moved in Figma compared to my own workflow. I’m designing icons more accurately in half the time with the shortcuts I learned from her videos.',
82 | author: {
83 | name: 'Steven Hackett',
84 | role: 'Bootcamp Instructor',
85 | image: avatarImage5,
86 | },
87 | },
88 | {
89 | content:
90 | 'I never thought I would enjoy designing icons but using the ideas in this book, it’s become a great way for me to relax while still being creative.',
91 | author: {
92 | name: 'Carla Schoen',
93 | role: 'Startup Founder',
94 | image: avatarImage10,
95 | },
96 | },
97 | {
98 | content:
99 | 'All I can say is wow — this is easily the best icon design resource I’ve ever encountered.',
100 | author: {
101 | name: 'Leah Kiehn',
102 | role: 'Creative Director',
103 | image: avatarImage6,
104 | },
105 | },
106 | ],
107 | ]
108 |
109 | function Testimonial({
110 | author,
111 | children,
112 | }: {
113 | author: { name: string; role: string; image: ImageProps['src'] }
114 | children: React.ReactNode
115 | }) {
116 | return (
117 |
118 |
119 |
120 | {children}
121 |
122 |
123 |
124 |
125 |
132 |
133 |
134 |
135 | {author.name}
136 |
137 |
{author.role}
138 |
139 |
140 |
141 | )
142 | }
143 |
144 | export function Testimonials() {
145 | return (
146 |
147 |
148 |
152 | {testimonials
153 | .map((column) => column[0])
154 | .map((testimonial, testimonialIndex) => (
155 |
156 |
157 | {testimonial.content}
158 |
159 |
160 | ))}
161 | {testimonials.map((column, columnIndex) => (
162 |
166 |
167 |
168 | {column.map((testimonial, testimonialIndex) => (
169 | 1 && 'mt-8',
175 | )}
176 | >
177 |
178 | {testimonial.content}
179 |
180 |
181 | ))}
182 |
183 |
184 |
185 | ))}
186 |
187 | Read more testimonials
188 |
189 |
190 | )
191 | }
192 |
--------------------------------------------------------------------------------
/src/fonts/CalSans-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/fonts/CalSans-SemiBold.ttf
--------------------------------------------------------------------------------
/src/fonts/CalSans-SemiBold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/fonts/CalSans-SemiBold.woff2
--------------------------------------------------------------------------------
/src/images/avatars/author.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/avatars/author.jpg
--------------------------------------------------------------------------------
/src/images/avatars/author.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/avatars/author.png
--------------------------------------------------------------------------------
/src/images/avatars/avatar-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/avatars/avatar-1.png
--------------------------------------------------------------------------------
/src/images/avatars/avatar-10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/avatars/avatar-10.png
--------------------------------------------------------------------------------
/src/images/avatars/avatar-11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/avatars/avatar-11.png
--------------------------------------------------------------------------------
/src/images/avatars/avatar-12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/avatars/avatar-12.png
--------------------------------------------------------------------------------
/src/images/avatars/avatar-13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/avatars/avatar-13.png
--------------------------------------------------------------------------------
/src/images/avatars/avatar-14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/avatars/avatar-14.png
--------------------------------------------------------------------------------
/src/images/avatars/avatar-15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/avatars/avatar-15.png
--------------------------------------------------------------------------------
/src/images/avatars/avatar-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/avatars/avatar-16.png
--------------------------------------------------------------------------------
/src/images/avatars/avatar-17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/avatars/avatar-17.png
--------------------------------------------------------------------------------
/src/images/avatars/avatar-18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/avatars/avatar-18.png
--------------------------------------------------------------------------------
/src/images/avatars/avatar-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/avatars/avatar-2.png
--------------------------------------------------------------------------------
/src/images/avatars/avatar-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/avatars/avatar-3.png
--------------------------------------------------------------------------------
/src/images/avatars/avatar-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/avatars/avatar-4.png
--------------------------------------------------------------------------------
/src/images/avatars/avatar-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/avatars/avatar-5.png
--------------------------------------------------------------------------------
/src/images/avatars/avatar-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/avatars/avatar-6.png
--------------------------------------------------------------------------------
/src/images/avatars/avatar-7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/avatars/avatar-7.png
--------------------------------------------------------------------------------
/src/images/avatars/avatar-8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/avatars/avatar-8.png
--------------------------------------------------------------------------------
/src/images/avatars/avatar-9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/avatars/avatar-9.png
--------------------------------------------------------------------------------
/src/images/cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/cover.png
--------------------------------------------------------------------------------
/src/images/resources/abstract-background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PeerRich/ossacc/ad0af5758d95b77f573c5d3cbf8f0d92229846d3/src/images/resources/abstract-background.png
--------------------------------------------------------------------------------
/src/images/resources/discord.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/images/resources/figma.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
15 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/images/resources/video-player.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
20 |
22 |
23 |
25 |
28 |
29 |
30 |
31 |
33 |
34 |
35 |
36 |
37 |
38 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/src/images/screencasts/duotone.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
17 |
20 |
23 |
24 |
26 |
27 |
28 |
29 |
32 |
34 |
37 |
38 |
39 |
40 |
41 |
42 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/src/images/screencasts/grids.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
17 |
20 |
23 |
24 |
26 |
27 |
28 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/src/images/screencasts/setup.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
19 |
20 |
22 |
23 |
24 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/src/images/screencasts/strokes.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
17 |
20 |
23 |
24 |
26 |
27 |
28 |
29 |
32 |
34 |
37 |
38 |
39 |
40 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/src/styles/tailwind.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
--------------------------------------------------------------------------------
/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | import { type Config } from 'tailwindcss'
2 | import defaultTheme from 'tailwindcss/defaultTheme'
3 |
4 | export default {
5 | content: ['./src/**/*.{js,jsx,ts,tsx}'],
6 | theme: {
7 | boxShadow: {
8 | sm: '0 2px 6px rgb(15 23 42 / 0.08)',
9 | md: '0 8px 8px rgb(15 23 42 / 0.05), 0 3px 6px rgb(15 23 42 / 0.05)',
10 | lg: '0 8px 15px rgb(15 23 42 / 0.08), 0 3px 6px rgb(15 23 42 / 0.08)',
11 | xl: '2px 11px 16px rgb(15 23 42 / 0.17), 0 1px 6px rgb(15 23 42 / 0.17), 3px 23px 24px rgb(15 23 42 / 0.17)',
12 | },
13 | fontSize: {
14 | xs: ['0.75rem', { lineHeight: '1rem' }],
15 | sm: ['0.875rem', { lineHeight: '1.5rem' }],
16 | base: ['1rem', { lineHeight: '2rem' }],
17 | lg: ['1.125rem', { lineHeight: '2rem' }],
18 | xl: ['1.25rem', { lineHeight: '2rem' }],
19 | '2xl': ['1.375rem', { lineHeight: '2rem' }],
20 | '3xl': ['1.5rem', { lineHeight: '2rem' }],
21 | '4xl': ['2rem', { lineHeight: '2.5rem' }],
22 | '5xl': ['3.5rem', { lineHeight: '1' }],
23 | '6xl': ['4rem', { lineHeight: '1' }],
24 | '7xl': ['4.5rem', { lineHeight: '1' }],
25 | '8xl': ['6rem', { lineHeight: '1' }],
26 | '9xl': ['8rem', { lineHeight: '1' }],
27 | },
28 | extend: {
29 | borderRadius: {
30 | '4xl': '2rem',
31 | '5xl': '3rem',
32 | '6xl': '5rem',
33 | },
34 | fontFamily: {
35 | sans: 'var(--font-inter)',
36 | display: ['var(--font-cal)'],
37 | },
38 | },
39 | },
40 | plugins: [],
41 | } satisfies Config
42 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es6",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "bundler",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "incremental": true,
17 | "plugins": [
18 | {
19 | "name": "next"
20 | }
21 | ],
22 | "paths": {
23 | "@/*": ["./src/*"]
24 | }
25 | },
26 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
27 | "exclude": ["node_modules"]
28 | }
29 |
--------------------------------------------------------------------------------