mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2026-03-15 19:31:48 +08:00
Compare commits
1 Commits
fix/authen
...
feat/visit
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab2327d539 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -30,4 +30,4 @@ tests-examples
|
||||
*.csv
|
||||
|
||||
/editor/*
|
||||
!/editor/readonly-editor.tsx
|
||||
!/editor/readonly-editor.tsx
|
||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 288 KiB |
@@ -1,15 +0,0 @@
|
||||
import { PartyPopper } from 'lucide-react';
|
||||
|
||||
export function AppChecklist() {
|
||||
return (
|
||||
<div className="fixed bottom-6 right-3">
|
||||
<a
|
||||
href="/get-started"
|
||||
className="flex items-center gap-2 rounded-full border border-slate-900 bg-white py-2 pl-3 pr-4 text-sm font-medium hover:bg-zinc-200"
|
||||
>
|
||||
<PartyPopper className="relative -top-[2px] h-[20px] w-[20px] text-purple-600" />
|
||||
Welcome! Start here
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
import { GitHubButton } from './GitHubButton';
|
||||
import { GoogleButton } from './GoogleButton';
|
||||
import { LinkedInButton } from './LinkedInButton';
|
||||
import { EmailLoginForm } from './EmailLoginForm';
|
||||
import { EmailSignupForm } from './EmailSignupForm';
|
||||
|
||||
type AuthenticationFormProps = {
|
||||
type?: 'login' | 'signup';
|
||||
};
|
||||
|
||||
export function AuthenticationForm(props: AuthenticationFormProps) {
|
||||
const { type = 'login' } = props;
|
||||
|
||||
const [isDisabled, setIsDisabled] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex w-full flex-col gap-2">
|
||||
<GitHubButton isDisabled={isDisabled} setIsDisabled={setIsDisabled} />
|
||||
<GoogleButton isDisabled={isDisabled} setIsDisabled={setIsDisabled} />
|
||||
<LinkedInButton isDisabled={isDisabled} setIsDisabled={setIsDisabled} />
|
||||
</div>
|
||||
|
||||
<div className="flex w-full items-center gap-2 py-6 text-sm text-slate-600">
|
||||
<div className="h-px w-full bg-slate-200" />
|
||||
OR
|
||||
<div className="h-px w-full bg-slate-200" />
|
||||
</div>
|
||||
|
||||
{type === 'login' ? (
|
||||
<EmailLoginForm isDisabled={isDisabled} setIsDisabled={setIsDisabled} />
|
||||
) : (
|
||||
<EmailSignupForm
|
||||
isDisabled={isDisabled}
|
||||
setIsDisabled={setIsDisabled}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -4,14 +4,7 @@ import { useState } from 'react';
|
||||
import { httpPost } from '../../lib/http';
|
||||
import { TOKEN_COOKIE_NAME } from '../../lib/jwt';
|
||||
|
||||
type EmailLoginFormProps = {
|
||||
isDisabled?: boolean;
|
||||
setIsDisabled?: (isDisabled: boolean) => void;
|
||||
};
|
||||
|
||||
export function EmailLoginForm(props: EmailLoginFormProps) {
|
||||
const { isDisabled, setIsDisabled } = props;
|
||||
|
||||
export function EmailLoginForm() {
|
||||
const [email, setEmail] = useState<string>('');
|
||||
const [password, setPassword] = useState<string>('');
|
||||
const [error, setError] = useState('');
|
||||
@@ -21,7 +14,6 @@ export function EmailLoginForm(props: EmailLoginFormProps) {
|
||||
const handleFormSubmit = async (e: FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
setIsLoading(true);
|
||||
setIsDisabled?.(true);
|
||||
setError('');
|
||||
|
||||
const { response, error } = await httpPost<{ token: string }>(
|
||||
@@ -53,7 +45,6 @@ export function EmailLoginForm(props: EmailLoginFormProps) {
|
||||
}
|
||||
|
||||
setIsLoading(false);
|
||||
setIsDisabled?.(false);
|
||||
setError(error?.message || 'Something went wrong. Please try again later.');
|
||||
};
|
||||
|
||||
@@ -101,7 +92,7 @@ export function EmailLoginForm(props: EmailLoginFormProps) {
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isLoading || isDisabled}
|
||||
disabled={isLoading}
|
||||
className="inline-flex w-full items-center justify-center rounded-lg bg-black p-2 py-3 text-sm font-medium text-white outline-none focus:ring-2 focus:ring-black focus:ring-offset-1 disabled:bg-gray-400"
|
||||
>
|
||||
{isLoading ? 'Please wait...' : 'Continue'}
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
import { type FormEvent, useState } from 'react';
|
||||
import { httpPost } from '../../lib/http';
|
||||
|
||||
type EmailSignupFormProps = {
|
||||
isDisabled?: boolean;
|
||||
setIsDisabled?: (isDisabled: boolean) => void;
|
||||
};
|
||||
|
||||
export function EmailSignupForm(props: EmailSignupFormProps) {
|
||||
const { isDisabled, setIsDisabled } = props;
|
||||
|
||||
export function EmailSignupForm() {
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [name, setName] = useState('');
|
||||
@@ -20,7 +13,6 @@ export function EmailSignupForm(props: EmailSignupFormProps) {
|
||||
e.preventDefault();
|
||||
|
||||
setIsLoading(true);
|
||||
setIsDisabled?.(true);
|
||||
setError('');
|
||||
|
||||
const { response, error } = await httpPost<{ status: 'ok' }>(
|
||||
@@ -29,21 +21,20 @@ export function EmailSignupForm(props: EmailSignupFormProps) {
|
||||
email,
|
||||
password,
|
||||
name,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (error || response?.status !== 'ok') {
|
||||
setIsLoading(false);
|
||||
setIsDisabled?.(false);
|
||||
setError(
|
||||
error?.message || 'Something went wrong. Please try again later.',
|
||||
error?.message || 'Something went wrong. Please try again later.'
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
window.location.href = `/verification-pending?email=${encodeURIComponent(
|
||||
email,
|
||||
email
|
||||
)}`;
|
||||
};
|
||||
|
||||
@@ -99,7 +90,7 @@ export function EmailSignupForm(props: EmailSignupFormProps) {
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isLoading || isDisabled}
|
||||
disabled={isLoading}
|
||||
className="inline-flex w-full items-center justify-center rounded-lg bg-black p-2 py-3 text-sm font-medium text-white outline-none focus:ring-2 focus:ring-black focus:ring-offset-1 disabled:bg-gray-400"
|
||||
>
|
||||
{isLoading ? 'Please wait...' : 'Continue to Verify Email'}
|
||||
|
||||
@@ -5,17 +5,12 @@ import { TOKEN_COOKIE_NAME } from '../../lib/jwt';
|
||||
import { httpGet } from '../../lib/http';
|
||||
import { Spinner } from '../ReactIcons/Spinner.tsx';
|
||||
|
||||
type GitHubButtonProps = {
|
||||
isDisabled?: boolean;
|
||||
setIsDisabled?: (isDisabled: boolean) => void;
|
||||
};
|
||||
type GitHubButtonProps = {};
|
||||
|
||||
const GITHUB_REDIRECT_AT = 'githubRedirectAt';
|
||||
const GITHUB_LAST_PAGE = 'githubLastPage';
|
||||
|
||||
export function GitHubButton(props: GitHubButtonProps) {
|
||||
const { isDisabled, setIsDisabled } = props;
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
|
||||
@@ -30,7 +25,6 @@ export function GitHubButton(props: GitHubButtonProps) {
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
setIsDisabled?.(true);
|
||||
httpGet<{ token: string }>(
|
||||
`${import.meta.env.PUBLIC_API_URL}/v1-github-callback${
|
||||
window.location.search
|
||||
@@ -41,7 +35,6 @@ export function GitHubButton(props: GitHubButtonProps) {
|
||||
const errMessage = error?.message || 'Something went wrong.';
|
||||
setError(errMessage);
|
||||
setIsLoading(false);
|
||||
setIsDisabled?.(false);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -80,13 +73,11 @@ export function GitHubButton(props: GitHubButtonProps) {
|
||||
.catch((err) => {
|
||||
setError('Something went wrong. Please try again later.');
|
||||
setIsLoading(false);
|
||||
setIsDisabled?.(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleClick = async () => {
|
||||
setIsLoading(true);
|
||||
setIsDisabled?.(true);
|
||||
|
||||
const { response, error } = await httpGet<{ loginUrl: string }>(
|
||||
`${import.meta.env.PUBLIC_API_URL}/v1-github-login`,
|
||||
@@ -98,7 +89,6 @@ export function GitHubButton(props: GitHubButtonProps) {
|
||||
);
|
||||
|
||||
setIsLoading(false);
|
||||
setIsDisabled?.(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -122,7 +112,7 @@ export function GitHubButton(props: GitHubButtonProps) {
|
||||
<>
|
||||
<button
|
||||
className="inline-flex h-10 w-full items-center justify-center gap-2 rounded border border-slate-300 bg-white p-2 text-sm font-medium text-black outline-none focus:ring-2 focus:ring-[#333] focus:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-60"
|
||||
disabled={isLoading || isDisabled}
|
||||
disabled={isLoading}
|
||||
onClick={handleClick}
|
||||
>
|
||||
{isLoading ? (
|
||||
|
||||
@@ -5,17 +5,12 @@ import { httpGet } from '../../lib/http';
|
||||
import { Spinner } from '../ReactIcons/Spinner.tsx';
|
||||
import { GoogleIcon } from '../ReactIcons/GoogleIcon.tsx';
|
||||
|
||||
type GoogleButtonProps = {
|
||||
isDisabled?: boolean;
|
||||
setIsDisabled?: (isDisabled: boolean) => void;
|
||||
};
|
||||
type GoogleButtonProps = {};
|
||||
|
||||
const GOOGLE_REDIRECT_AT = 'googleRedirectAt';
|
||||
const GOOGLE_LAST_PAGE = 'googleLastPage';
|
||||
|
||||
export function GoogleButton(props: GoogleButtonProps) {
|
||||
const { isDisabled, setIsDisabled } = props;
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
|
||||
@@ -30,7 +25,6 @@ export function GoogleButton(props: GoogleButtonProps) {
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
setIsDisabled?.(true);
|
||||
httpGet<{ token: string }>(
|
||||
`${import.meta.env.PUBLIC_API_URL}/v1-google-callback${
|
||||
window.location.search
|
||||
@@ -40,7 +34,6 @@ export function GoogleButton(props: GoogleButtonProps) {
|
||||
if (!response?.token) {
|
||||
setError(error?.message || 'Something went wrong.');
|
||||
setIsLoading(false);
|
||||
setIsDisabled?.(false);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -79,13 +72,11 @@ export function GoogleButton(props: GoogleButtonProps) {
|
||||
.catch((err) => {
|
||||
setError('Something went wrong. Please try again later.');
|
||||
setIsLoading(false);
|
||||
setIsDisabled?.(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleClick = () => {
|
||||
setIsLoading(true);
|
||||
setIsDisabled?.(true);
|
||||
httpGet<{ loginUrl: string }>(
|
||||
`${import.meta.env.PUBLIC_API_URL}/v1-google-login`,
|
||||
)
|
||||
@@ -93,7 +84,6 @@ export function GoogleButton(props: GoogleButtonProps) {
|
||||
if (!response?.loginUrl) {
|
||||
setError(error?.message || 'Something went wrong.');
|
||||
setIsLoading(false);
|
||||
setIsDisabled?.(false);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -116,7 +106,6 @@ export function GoogleButton(props: GoogleButtonProps) {
|
||||
.catch((err) => {
|
||||
setError('Something went wrong. Please try again later.');
|
||||
setIsLoading(false);
|
||||
setIsDisabled?.(false);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -124,7 +113,7 @@ export function GoogleButton(props: GoogleButtonProps) {
|
||||
<>
|
||||
<button
|
||||
className="inline-flex h-10 w-full items-center justify-center gap-2 rounded border border-slate-300 bg-white p-2 text-sm font-medium text-black outline-none focus:ring-2 focus:ring-[#333] focus:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-60"
|
||||
disabled={isLoading || isDisabled}
|
||||
disabled={isLoading}
|
||||
onClick={handleClick}
|
||||
>
|
||||
{isLoading ? (
|
||||
|
||||
@@ -5,17 +5,12 @@ import { httpGet } from '../../lib/http';
|
||||
import { Spinner } from '../ReactIcons/Spinner.tsx';
|
||||
import { LinkedInIcon } from '../ReactIcons/LinkedInIcon.tsx';
|
||||
|
||||
type LinkedInButtonProps = {
|
||||
isDisabled?: boolean;
|
||||
setIsDisabled?: (isDisabled: boolean) => void;
|
||||
};
|
||||
type LinkedInButtonProps = {};
|
||||
|
||||
const LINKEDIN_REDIRECT_AT = 'linkedInRedirectAt';
|
||||
const LINKEDIN_LAST_PAGE = 'linkedInLastPage';
|
||||
|
||||
export function LinkedInButton(props: LinkedInButtonProps) {
|
||||
const { isDisabled, setIsDisabled } = props;
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
|
||||
@@ -30,7 +25,6 @@ export function LinkedInButton(props: LinkedInButtonProps) {
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
setIsDisabled?.(true);
|
||||
httpGet<{ token: string }>(
|
||||
`${import.meta.env.PUBLIC_API_URL}/v1-linkedin-callback${
|
||||
window.location.search
|
||||
@@ -40,7 +34,6 @@ export function LinkedInButton(props: LinkedInButtonProps) {
|
||||
if (!response?.token) {
|
||||
setError(error?.message || 'Something went wrong.');
|
||||
setIsLoading(false);
|
||||
setIsDisabled?.(false);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -79,13 +72,11 @@ export function LinkedInButton(props: LinkedInButtonProps) {
|
||||
.catch((err) => {
|
||||
setError('Something went wrong. Please try again later.');
|
||||
setIsLoading(false);
|
||||
setIsDisabled?.(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleClick = () => {
|
||||
setIsLoading(true);
|
||||
setIsDisabled?.(true);
|
||||
httpGet<{ loginUrl: string }>(
|
||||
`${import.meta.env.PUBLIC_API_URL}/v1-linkedin-login`,
|
||||
)
|
||||
@@ -93,7 +84,6 @@ export function LinkedInButton(props: LinkedInButtonProps) {
|
||||
if (!response?.loginUrl) {
|
||||
setError(error?.message || 'Something went wrong.');
|
||||
setIsLoading(false);
|
||||
setIsDisabled?.(false);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -116,7 +106,6 @@ export function LinkedInButton(props: LinkedInButtonProps) {
|
||||
.catch((err) => {
|
||||
setError('Something went wrong. Please try again later.');
|
||||
setIsLoading(false);
|
||||
setIsDisabled?.(false);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -124,7 +113,7 @@ export function LinkedInButton(props: LinkedInButtonProps) {
|
||||
<>
|
||||
<button
|
||||
className="inline-flex h-10 w-full items-center justify-center gap-2 rounded border border-slate-300 bg-white p-2 text-sm font-medium text-black outline-none focus:ring-2 focus:ring-[#333] focus:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-60"
|
||||
disabled={isLoading || isDisabled}
|
||||
disabled={isLoading}
|
||||
onClick={handleClick}
|
||||
>
|
||||
{isLoading ? (
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
---
|
||||
import Popup from '../Popup/Popup.astro';
|
||||
import { AuthenticationForm } from './AuthenticationForm';
|
||||
import { EmailLoginForm } from './EmailLoginForm';
|
||||
import Divider from './Divider.astro';
|
||||
import { GitHubButton } from './GitHubButton';
|
||||
import { GoogleButton } from './GoogleButton';
|
||||
import { LinkedInButton } from './LinkedInButton';
|
||||
---
|
||||
|
||||
<Popup id='login-popup' title='' subtitle=''>
|
||||
<div class='mb-7 text-center'>
|
||||
<div class='text-center'>
|
||||
<p class='mb-3 text-2xl font-semibold leading-5 text-slate-900'>
|
||||
Login to your account
|
||||
</p>
|
||||
@@ -12,9 +16,19 @@ import { AuthenticationForm } from './AuthenticationForm';
|
||||
You must be logged in to perform this action.
|
||||
</p>
|
||||
</div>
|
||||
<AuthenticationForm client:load />
|
||||
|
||||
<div class='mt-7 flex flex-col gap-2'>
|
||||
<GitHubButton client:load />
|
||||
<GoogleButton client:load />
|
||||
<LinkedInButton client:load />
|
||||
</div>
|
||||
|
||||
<Divider />
|
||||
|
||||
<EmailLoginForm client:load />
|
||||
|
||||
<div class='mt-6 text-center text-sm text-slate-600'>
|
||||
Don't have an account?{' '}
|
||||
<a href='/signup' class='font-medium text-[#4285f4]'> Sign up</a>
|
||||
<a href='/signup' class='font-medium text-[#4285f4]'>Sign up</a>
|
||||
</div>
|
||||
</Popup>
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
import { ExternalLink, Globe2, type LucideIcon } from 'lucide-react';
|
||||
|
||||
type RoadmapCardProps = {
|
||||
title: string;
|
||||
description: string;
|
||||
icon: LucideIcon;
|
||||
icon2?: LucideIcon;
|
||||
link: string;
|
||||
isUpcoming?: boolean;
|
||||
};
|
||||
export function RoadmapCard(props: RoadmapCardProps) {
|
||||
const {
|
||||
isUpcoming,
|
||||
link,
|
||||
title,
|
||||
description,
|
||||
icon: Icon,
|
||||
icon2: Icon2,
|
||||
} = props;
|
||||
|
||||
if (isUpcoming) {
|
||||
return (
|
||||
<div className="group relative block rounded-xl border border-gray-300 bg-gradient-to-br from-gray-100 to-gray-50 p-5 overflow-hidden">
|
||||
<div className="mb-2 sm:mb-5 flex flex-row items-center">
|
||||
<div className="flex h-7 w-7 sm:h-9 sm:w-9 items-center justify-center rounded-full bg-gray-900 text-white">
|
||||
<Icon className="h-3 sm:h-5" />
|
||||
</div>
|
||||
{Icon2 && (
|
||||
<>
|
||||
<span className="mx-2 text-gray-400">+</span>
|
||||
<div className="flex h-7 w-7 sm:h-9 sm:w-9 items-center justify-center rounded-full bg-gray-900 text-white">
|
||||
<Icon2 className="h-3 sm:h-5" />
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<span className="mb-0.5 block text-lg sm:text-xl font-semibold sm:mb-2">
|
||||
{title}
|
||||
</span>
|
||||
<span className="text-sm text-gray-500">{description}</span>
|
||||
|
||||
<div className="absolute inset-0 flex flex-col items-center justify-center bg-gray-100/70">
|
||||
<span className="text-sm bg-black rounded-lg text-white font-semibold py-1 px-2 -rotate-45 transform">
|
||||
Coming soon
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<a
|
||||
href={link}
|
||||
target={'_blank'}
|
||||
className="group relative block rounded-xl border border-gray-300 bg-gradient-to-br from-gray-100 to-gray-50
|
||||
p-3.5 sm:p-5 transition-colors duration-200 ease-in-out hover:cursor-pointer hover:border-black/30 hover:bg-gray-50/70 hover:shadow-sm"
|
||||
>
|
||||
<div className="mb-2 sm:mb-5 flex flex-row items-center">
|
||||
<div className="flex h-7 w-7 sm:h-9 sm:w-9 items-center justify-center rounded-full bg-gray-900 text-white">
|
||||
<Icon className="h-4 sm:h-5" />
|
||||
</div>
|
||||
{Icon2 && (
|
||||
<>
|
||||
<span className="mx-2 text-gray-400">+</span>
|
||||
<div className="flex h-7 w-7 sm:h-9 sm:w-9 items-center justify-center rounded-full bg-gray-900 text-white">
|
||||
<Icon2 className="h-4 sm:h-5" />
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<ExternalLink className="lucide lucide-external-link absolute right-2 top-2 h-4 text-gray-300 transition group-hover:text-gray-700" />
|
||||
<span className="mb-0 block text-lg sm:text-xl font-semibold sm:mb-2">
|
||||
{title}
|
||||
</span>
|
||||
<span className="text-sm text-gray-500">{description}</span>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
import { ExternalLink } from 'lucide-react';
|
||||
|
||||
type RoadmapMultiCardProps = {
|
||||
roadmaps: {
|
||||
title: string;
|
||||
link: string;
|
||||
}[];
|
||||
description: string;
|
||||
secondaryRoadmaps?: {
|
||||
title: string;
|
||||
link: string;
|
||||
}[];
|
||||
secondaryDescription?: string;
|
||||
};
|
||||
export function RoadmapMultiCard(props: RoadmapMultiCardProps) {
|
||||
const { roadmaps, description, secondaryRoadmaps, secondaryDescription } = props;
|
||||
return (
|
||||
<div
|
||||
className="relative flex flex-col overflow-hidden rounded-xl border border-gray-300 bg-gradient-to-br from-gray-100
|
||||
to-gray-50 ease-in-out"
|
||||
>
|
||||
<div className="flex flex-col divide-y">
|
||||
{roadmaps.map((roadmap, index) => (
|
||||
<a
|
||||
target={'_blank'}
|
||||
key={index}
|
||||
href={roadmap.link}
|
||||
className="group text-sm sm:text-base flex w-full items-center justify-between gap-2 bg-gradient-to-br from-gray-100 to-gray-50 px-4 sm:px-5 py-2 transition-colors duration-200"
|
||||
>
|
||||
{roadmap.title}
|
||||
<ExternalLink className="lucide lucide-external-link h-4 text-gray-300 transition group-hover:text-gray-700" />
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<p className="flex-grow bg-gray-200/70 p-4 sm:p-5 text-sm text-gray-500">
|
||||
{description}
|
||||
</p>
|
||||
|
||||
{secondaryRoadmaps && (
|
||||
<div className="flex flex-col divide-y">
|
||||
{secondaryRoadmaps.map((roadmap, index) => (
|
||||
<a
|
||||
target={'_blank'}
|
||||
key={index}
|
||||
href={roadmap.link}
|
||||
className="group text-sm sm:text-base flex w-full items-center justify-between gap-2 bg-gradient-to-br from-gray-100 to-gray-50 px-5 py-2 transition-colors duration-200"
|
||||
>
|
||||
{roadmap.title}
|
||||
<ExternalLink className="lucide lucide-external-link h-4 text-gray-300 transition group-hover:text-gray-700" />
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{secondaryDescription && (
|
||||
<p className="flex-grow bg-gray-200/70 p-4 sm:p-5 text-sm text-gray-500">
|
||||
{secondaryDescription}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import { type ReactNode } from 'react';
|
||||
import { SectionBadge } from './SectionBadge.tsx';
|
||||
|
||||
type RoleRoadmapsProps = {
|
||||
badge: string;
|
||||
title: string;
|
||||
description: string;
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
export function RoleRoadmaps(props: RoleRoadmapsProps) {
|
||||
const { badge, title, description, children } = props;
|
||||
|
||||
return (
|
||||
<div className="bg-gradient-to-b from-gray-100 to-white py-5 sm:py-8 md:py-12">
|
||||
<div className="container">
|
||||
<div className="text-left">
|
||||
<SectionBadge title={badge} />
|
||||
</div>
|
||||
<div className="my-4 sm:my-7 text-left">
|
||||
<h2 className="mb-1 text-xl sm:text-3xl font-semibold">{title}</h2>
|
||||
<p className="text-sm sm:text-base text-gray-500">{description}</p>
|
||||
|
||||
<div className="mt-4 sm:mt-7 grid sm:grid-cols-2 md:grid-cols-3 gap-3">{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
type SectionBadgeProps = {
|
||||
title: string;
|
||||
};
|
||||
export function SectionBadge(props: SectionBadgeProps) {
|
||||
const { title } = props;
|
||||
|
||||
return (
|
||||
<span className="rounded-full bg-black px-3 py-1 text-sm text-white">
|
||||
{title}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
type TipItemProps = {
|
||||
title: string;
|
||||
description: string;
|
||||
};
|
||||
export function TipItem(props: TipItemProps) {
|
||||
const { title, description } = props;
|
||||
|
||||
const [isToggled, setIsToggled] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
{!isToggled && (
|
||||
<div
|
||||
onClick={() => setIsToggled(true)}
|
||||
className="cursor-pointer rounded-lg sm:rounded-xl bg-black px-3 py-2 text-sm sm:text-base text-white"
|
||||
>
|
||||
{title}
|
||||
</div>
|
||||
)}
|
||||
{isToggled && (
|
||||
<p
|
||||
className="rounded-lg sm:rounded-xl bg-gray-200 px-3 py-2 text-black text-sm sm:text-base"
|
||||
>
|
||||
{description}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,38 +1,61 @@
|
||||
---
|
||||
import { Menu } from 'lucide-react';
|
||||
import Icon from '../AstroIcon.astro';
|
||||
import { NavigationDropdown } from '../NavigationDropdown';
|
||||
import { AccountDropdown } from './AccountDropdown';
|
||||
---
|
||||
|
||||
<div class='bg-slate-900 py-5 text-white sm:py-8'>
|
||||
<nav class='container flex items-center justify-between'>
|
||||
<div class='flex items-center gap-5'>
|
||||
<a
|
||||
class='flex items-center text-lg font-medium text-white'
|
||||
href='/'
|
||||
aria-label='roadmap.sh'
|
||||
>
|
||||
<Icon icon='logo' />
|
||||
</a>
|
||||
<a
|
||||
class='flex items-center text-lg font-medium text-white'
|
||||
href='/'
|
||||
aria-label='roadmap.sh'
|
||||
>
|
||||
<Icon icon='logo' />
|
||||
</a>
|
||||
|
||||
<!-- Desktop navigation items -->
|
||||
<div class='hidden space-x-5 sm:flex sm:items-center'>
|
||||
<NavigationDropdown client:load />
|
||||
<a href='/get-started' class='text-gray-400 hover:text-white'>
|
||||
Start Here
|
||||
</a>
|
||||
<a href='/teams' class='text-gray-400 hover:text-white'> Teams</a>
|
||||
<button
|
||||
data-command-menu
|
||||
class='hidden items-center rounded-md border border-gray-800 px-2.5 py-1.5 text-sm text-gray-400 hover:cursor-pointer hover:bg-gray-800 sm:flex'
|
||||
<!-- Desktop navigation items -->
|
||||
<ul class='hidden space-x-5 sm:flex sm:items-center'>
|
||||
<li>
|
||||
<a href='/roadmaps' class='text-gray-400 hover:text-white'>Roadmaps</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href='/best-practices' class='text-gray-400 hover:text-white'
|
||||
>Best Practices</a
|
||||
>
|
||||
<Icon icon='search' class='h-3 w-3' />
|
||||
<span class='ml-2'>Search</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class='hidden xl:inline'>
|
||||
<a href='/questions' class='text-gray-400 hover:text-white'>Questions</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href='/teams' class='group relative text-blue-300 hover:text-white'>
|
||||
Teams
|
||||
<span
|
||||
class='ml-0.5 hidden rounded-sm border-black bg-blue-300 px-1 py-0.5 text-xs font-semibold uppercase text-black group-hover:bg-white md:inline'
|
||||
>
|
||||
New
|
||||
</span>
|
||||
|
||||
<span class='inline md:hidden absolute -right-[11px] top-0'>
|
||||
<span class='relative flex h-2 w-2'>
|
||||
<span
|
||||
class='absolute inline-flex h-full w-full animate-ping rounded-full bg-sky-400 opacity-75'
|
||||
></span>
|
||||
<span class='relative inline-flex h-2 w-2 rounded-full bg-sky-500'
|
||||
></span>
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<kbd
|
||||
data-command-menu
|
||||
class='hidden items-center rounded-md border border-gray-800 px-2.5 py-1 text-sm text-gray-400 hover:cursor-pointer hover:bg-gray-800 sm:flex'
|
||||
>
|
||||
<Icon icon='search' class='mr-2 h-3 w-3' />
|
||||
<kbd class='mr-1 font-sans'>⌘</kbd><kbd class='font-sans'>K</kbd>
|
||||
</kbd>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class='hidden h-8 w-[172px] items-center justify-end gap-5 sm:flex'>
|
||||
<li data-guest-required class='hidden'>
|
||||
<a href='/login' class='text-gray-400 hover:text-white'>Login</a>
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
import {
|
||||
BookOpen,
|
||||
BookOpenText,
|
||||
CheckSquare,
|
||||
FileQuestion,
|
||||
Menu,
|
||||
Shirt,
|
||||
Video,
|
||||
Waypoints,
|
||||
} from 'lucide-react';
|
||||
import { useRef, useState } from 'react';
|
||||
import { cn } from '../lib/classname.ts';
|
||||
import { useOutsideClick } from '../hooks/use-outside-click.ts';
|
||||
|
||||
const links = [
|
||||
{
|
||||
link: '/roadmaps',
|
||||
label: 'Roadmaps',
|
||||
description: 'Step by step learning paths',
|
||||
Icon: Waypoints,
|
||||
},
|
||||
{
|
||||
link: '/best-practices',
|
||||
label: 'Best Practices',
|
||||
description: "Do's and don'ts",
|
||||
Icon: CheckSquare,
|
||||
},
|
||||
{
|
||||
link: '/questions',
|
||||
label: 'Questions',
|
||||
description: 'Test and Practice your knowledge',
|
||||
Icon: FileQuestion,
|
||||
},
|
||||
{
|
||||
link: '/guides',
|
||||
label: 'Guides',
|
||||
description: 'In-depth articles and tutorials',
|
||||
Icon: BookOpenText,
|
||||
},
|
||||
{
|
||||
link: 'https://youtube.com/@roadmapsh',
|
||||
label: 'Videos',
|
||||
description: 'Animated and interactive content',
|
||||
Icon: Video,
|
||||
isExternal: true,
|
||||
},
|
||||
{
|
||||
link: 'https://cottonbureau.com/people/roadmapsh',
|
||||
label: 'Shop',
|
||||
description: 'Get some cool swag',
|
||||
Icon: Shirt,
|
||||
isExternal: true,
|
||||
},
|
||||
];
|
||||
|
||||
export function NavigationDropdown() {
|
||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
useOutsideClick(dropdownRef, () => {
|
||||
setIsOpen(false);
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="relative flex items-center" ref={dropdownRef}>
|
||||
<button
|
||||
className={cn('text-gray-400 hover:text-white', {
|
||||
'text-white': isOpen,
|
||||
})}
|
||||
onClick={() => setIsOpen(true)}
|
||||
onMouseOver={() => setIsOpen(true)}
|
||||
>
|
||||
<Menu className="h-5 w-5" />
|
||||
</button>
|
||||
<div
|
||||
className={cn(
|
||||
'absolute pointer-events-none left-0 top-full z-[999] mt-2 w-48 min-w-[320px] -translate-y-1 rounded-lg bg-slate-800 py-2 opacity-0 shadow-xl transition-all duration-100',
|
||||
{
|
||||
'pointer-events-auto translate-y-2.5 opacity-100': isOpen,
|
||||
},
|
||||
)}
|
||||
>
|
||||
{links.map((link) => (
|
||||
<a
|
||||
href={link.link}
|
||||
target={link.isExternal ? '_blank' : undefined}
|
||||
rel={link.isExternal ? 'noopener noreferrer' : undefined}
|
||||
key={link.link}
|
||||
className="group flex items-center gap-3 px-4 py-2.5 text-gray-400 transition-colors hover:bg-slate-700"
|
||||
>
|
||||
<span className="flex h-[40px] w-[40px] items-center justify-center rounded-full bg-slate-600 transition-colors group-hover:bg-slate-500 group-hover:text-slate-100">
|
||||
<link.Icon className="inline-block h-5 w-5" />
|
||||
</span>
|
||||
<span className="flex flex-col">
|
||||
<span className="font-medium text-slate-300 transition-colors group-hover:text-slate-100">
|
||||
{link.label}
|
||||
</span>
|
||||
<span className="text-sm">{link.description}</span>
|
||||
</span>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,33 +1,31 @@
|
||||
import {AlertTriangle, Barcode, BookOpenIcon, PieChart, Shrub, SquareIcon, UserRoundPlus} from "lucide-react";
|
||||
|
||||
const toolsList = [
|
||||
{
|
||||
icon: Shrub,
|
||||
imageUrl: '/images/team-promo/growth-plans.png',
|
||||
title: 'Growth plans',
|
||||
description: 'Prepare shared or individual growth plans for members.',
|
||||
},
|
||||
{
|
||||
icon: Barcode,
|
||||
imageUrl: '/images/team-promo/progress-tracking.png',
|
||||
title: 'Progress tracking',
|
||||
description: 'Track and compare the progress of team members.',
|
||||
},
|
||||
{
|
||||
icon: UserRoundPlus,
|
||||
imageUrl: '/images/team-promo/onboarding.png',
|
||||
title: 'Onboarding',
|
||||
description: 'Prepare onboarding plans for new team members.',
|
||||
},
|
||||
{
|
||||
icon: PieChart,
|
||||
imageUrl: '/images/team-promo/team-insights.png',
|
||||
title: 'Team insights',
|
||||
description: 'Get insights about your team skills, progress and more.',
|
||||
},
|
||||
{
|
||||
icon: AlertTriangle,
|
||||
imageUrl: '/images/team-promo/skill-gap.png',
|
||||
title: 'Skill gap analysis',
|
||||
description: 'Understand the skills of your team and identify gaps.',
|
||||
},
|
||||
{
|
||||
icon: BookOpenIcon,
|
||||
imageUrl: '/images/team-promo/documentation.png',
|
||||
title: 'Documentation',
|
||||
description: 'Create and share visual team documentation.',
|
||||
},
|
||||
@@ -46,9 +44,11 @@ export function TeamTools() {
|
||||
{toolsList.map((tool) => {
|
||||
return (
|
||||
<div className="rounded-md sm:rounded-xl border p-2 sm:p-5 text-left sm:text-center md:text-left">
|
||||
<div className='mb-5 flex h-9 w-9 items-center justify-center rounded-full bg-gray-900 text-white'>
|
||||
{tool.icon ? <tool.icon size={23} /> : <SquareIcon size={24} /> }
|
||||
</div>
|
||||
<img
|
||||
alt={tool.title}
|
||||
src={tool.imageUrl}
|
||||
className="mb-5 h-48 hidden sm:block mx-auto md:mx-0"
|
||||
/>
|
||||
<h3 className="mb-0.5 sm:mb-2 text-lg sm:text-2xl font-bold">{tool.title}</h3>
|
||||
<p className='text-sm sm:text-base'>{tool.description}</p>
|
||||
</div>
|
||||
|
||||
@@ -8137,7 +8137,7 @@
|
||||
"x": "426",
|
||||
"y": "1521",
|
||||
"properties": {
|
||||
"controlName": "103-smart-contract-frameworks:foundry"
|
||||
"controlName": "103-smart-contract-frameworks:dapp-tools"
|
||||
},
|
||||
"children": {
|
||||
"controls": {
|
||||
|
||||
@@ -8,5 +8,5 @@ Argo CD is designed to be a simple and efficient way to manage cloud-native appl
|
||||
|
||||
Visit the following resources to learn more:
|
||||
|
||||
- [Argo CD - Argo Project](https://argo-cd.readthedocs.io/en/stable/)
|
||||
- [Argo CD - Argo Project](https://argoproj.github.io/docs/argo-cd/)
|
||||
- [ArgoCD Tutorial for Beginners](https://www.youtube.com/watch?v=MeU5_k9ssrs)
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
# Python
|
||||
|
||||
Python is an interpreted high-level general-purpose programming language. Its design philosophy emphasizes code readability with its significant use of indentation. Its language constructs as well as its object-oriented approach aim to help programmers write clear, logical code for small and large-scale projects. Python is dynamically-typed and garbage-collected. It supports multiple programming paradigms, including structured (particularly, procedural), object-oriented and functional programming. Python is often described as a "batteries included" language due to its comprehensive standard library.
|
||||
|
||||
To start learning Python, here are some useful resources:
|
||||
|
||||
- [Python.org](https://www.python.org/) - The official website offers extensive documentation and tutorials for beginners as well as advanced users.
|
||||
- [Codecademy's Python Course](https://www.codecademy.com/learn/learn-python) - A comprehensive, interactive course covering a wide range of Python topics.
|
||||
- [Real Python](https://realpython.com/) - Offers a variety of Python tutorials, articles, and courses that cater to different experience levels.
|
||||
- [Automate the Boring Stuff with Python](https://automatetheboringstuff.com/) - A beginner-friendly book that teaches Python by guiding you through practical tasks and automation examples.
|
||||
|
||||
Remember, practice is key, and the more you work with Python, the more you'll appreciate its utility in the world of cyber security.
|
||||
@@ -1,6 +0,0 @@
|
||||
# Bash
|
||||
|
||||
Understanding bash is essential for MLOps tasks.
|
||||
|
||||
- **Book Suggestion:** _The Linux Command Line, 2nd Edition_ by William E. Shotts
|
||||
- [Bash Scripting Tutorial](https://www.freecodecamp.org/news/bash-scripting-tutorial-linux-shell-script-and-command-line-for-beginners/)
|
||||
@@ -1,3 +0,0 @@
|
||||
# Programming Fundamentals
|
||||
|
||||
Programming is the key requirement for MLOps. You need to be proficient in atleast one programming language. Python is the most popular language for MLOps.
|
||||
@@ -1,9 +0,0 @@
|
||||
# Git
|
||||
|
||||
[Git](https://git-scm.com/) is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.
|
||||
|
||||
Visit the following resources to learn more:
|
||||
|
||||
- [Git & GitHub Crash Course For Beginners](https://www.youtube.com/watch?v=SWYqp7iY_Tc)
|
||||
- [Learn Git with Tutorials, News and Tips - Atlassian](https://www.atlassian.com/git)
|
||||
- [Git Cheat Sheet](https://cs.fyi/guide/git-cheatsheet)
|
||||
@@ -1,14 +0,0 @@
|
||||
# GitHub
|
||||
|
||||
GitHub is a provider of Internet hosting for software development and version control using Git. It offers the distributed version control and source code management functionality of Git, plus its own features.
|
||||
|
||||
Visit the following resources to learn more:
|
||||
|
||||
- [GitHub Website](https://github.com)
|
||||
- [GitHub Documentation](https://docs.github.com/en/get-started/quickstart)
|
||||
- [How to Use Git in a Professional Dev Team](https://ooloo.io/project/github-flow)
|
||||
- [What is GitHub?](https://www.youtube.com/watch?v=w3jLJU7DT5E)
|
||||
- [Git vs. GitHub: Whats the difference?](https://www.youtube.com/watch?v=wpISo9TNjfU)
|
||||
- [Git and GitHub for Beginners](https://www.youtube.com/watch?v=RGOj5yH7evk)
|
||||
- [Git and GitHub - CS50 Beyond 2019](https://www.youtube.com/watch?v=eulnSXkhE7I)
|
||||
- [Learn Git Branching](https://learngitbranching.js.org/?locale=en_us)
|
||||
@@ -1,8 +0,0 @@
|
||||
# Version Control Systems
|
||||
|
||||
Version control/source control systems allow developers to track and control changes to code over time. These services often include the ability to make atomic revisions to code, branch/fork off of specific points, and to compare versions of code. They are useful in determining the who, what, when, and why code changes were made.
|
||||
|
||||
Visit the following resources to learn more:
|
||||
|
||||
- [Git](https://git-scm.com/)
|
||||
- [What is Version Control?](https://www.atlassian.com/git/tutorials/what-is-version-control)
|
||||
@@ -1,9 +0,0 @@
|
||||
# AWS / Azure / GCP
|
||||
|
||||
AWS (Amazon Web Services) Azure and GCP (Google Cloud Platform) are three leading providers of cloud computing services. AWS by Amazon is the oldest and the most established among the three, providing a breadth and depth of solutions ranging from infrastructure services like compute, storage, and databases to the machine and deep learning. Azure, by Microsoft, has integrated tools for DevOps, supports a large number of programming languages, and offers seamless integration with on-prem servers and Microsoft’s software. Google's GCP has strength in cost-effectiveness, live migration of virtual machines, and flexible computing options. All three have introduced various MLOps tools and services to boost capabilities for machine learning development and operations.
|
||||
|
||||
Visit the following resources to learn more about AWS, Azure, and GCP:
|
||||
|
||||
- [AWS Roadmap](https://roadmap.sh/aws)
|
||||
- [Azure Tutorials](https://docs.microsoft.com/en-us/learn/azure/)
|
||||
- [GCP Learning Resources](https://cloud.google.com/training)
|
||||
@@ -1,9 +0,0 @@
|
||||
# Cloud-native ML Services
|
||||
|
||||
Most of the cloud providers offer managed services for machine learning. These services are designed to help data scientists and machine learning engineers to build, train, and deploy machine learning models at scale. These services are designed to be cloud-native, meaning they are designed to work with other cloud services and are optimized for the cloud environment.
|
||||
|
||||
Here are the services offered by the major cloud providers:
|
||||
|
||||
- **Amazon Web Services (AWS)**: SageMaker
|
||||
- **Google Cloud Platform (GCP)**: AI Platform
|
||||
- **Microsoft Azure**: Azure Machine Learning
|
||||
@@ -1,3 +0,0 @@
|
||||
# Cloud Computing
|
||||
|
||||
**Cloud Computing** refers to the delivery of computing services over the internet rather than using local servers or personal devices. These services include servers, storage, databases, networking, software, analytics, and intelligence. Cloud Computing enables faster innovation, flexible resources, and economies of scale. There are various types of cloud computing such as public clouds, private clouds, and hybrids clouds. Furthermore, it's divided into different services like Infrastructure as a Service (IaaS), Platform as a Service (PaaS), and Software as a Service (SaaS). These services differ mainly in the level of control an organization has over their data and infrastructures.
|
||||
@@ -1,9 +0,0 @@
|
||||
# Docker
|
||||
|
||||
Docker is a platform for working with containerized applications. Among its features are a daemon and client for managing and interacting with containers, registries for storing images, and a desktop application to package all these features together.
|
||||
|
||||
Visit the following resources to learn more:
|
||||
|
||||
- [Docker Documentation](https://docs.docker.com/)
|
||||
- [Docker Tutorial](https://www.youtube.com/watch?v=RqTEHSBrYFw)
|
||||
- [Docker simplified in 55 seconds](https://youtu.be/vP_4DlOH1G4)
|
||||
@@ -1,13 +0,0 @@
|
||||
# Kubernetes
|
||||
|
||||
Kubernetes is an [open source](https://github.com/kubernetes/kubernetes) container management platform, and the dominant product in this space. Using Kubernetes, teams can deploy images across multiple underlying hosts, defining their desired availability, deployment logic, and scaling logic in YAML. Kubernetes evolved from Borg, an internal Google platform used to provision and allocate compute resources (similar to the Autopilot and Aquaman systems of Microsoft Azure).
|
||||
|
||||
The popularity of Kubernetes has made it an increasingly important skill for the DevOps Engineer and has triggered the creation of Platform teams across the industry. These Platform engineering teams often exist with the sole purpose of making Kubernetes approachable and usable for their product development colleagues.
|
||||
|
||||
Visit the following resources to learn more:
|
||||
|
||||
- [Kubernetes Website](https://kubernetes.io/)
|
||||
- [Kubernetes Documentation](https://kubernetes.io/docs/home/)
|
||||
- [Kubernetes Crash Course for Absolute Beginners](https://www.youtube.com/watch?v=s_o8dwzRlu4)
|
||||
- [Primer: How Kubernetes Came to Be, What It Is, and Why You Should Care](https://thenewstack.io/primer-how-kubernetes-came-to-be-what-it-is-and-why-you-should-care/)
|
||||
- [Kubernetes: An Overview](https://thenewstack.io/kubernetes-an-overview/)
|
||||
@@ -1,12 +0,0 @@
|
||||
# Containers
|
||||
|
||||
Containers are a construct in which [cgroups](https://en.wikipedia.org/wiki/Cgroups), [namespaces](https://en.wikipedia.org/wiki/Linux_namespaces), and [chroot](https://en.wikipedia.org/wiki/Chroot) are used to fully encapsulate and isolate a process. This encapsulated process, called a container image, shares the kernel of the host with other containers, allowing containers to be significantly smaller and faster than virtual machines.
|
||||
|
||||
These images are designed for portability, allowing for full local testing of a static image, and easy deployment to a container management platform.
|
||||
|
||||
Visit the following resources to learn more:
|
||||
|
||||
- [What are Containers?](https://cloud.google.com/learn/what-are-containers)
|
||||
- [What is a Container?](https://www.docker.com/resources/what-container/)
|
||||
- [What are Containers?](https://www.youtube.com/playlist?list=PLawsLZMfND4nz-WDBZIj8-nbzGFD4S9oz)
|
||||
- [Articles about Containers - The New Stack](https://thenewstack.io/category/containers/)
|
||||
@@ -1,6 +0,0 @@
|
||||
# Machine Learning Fundamentals
|
||||
|
||||
An MLOps engineer should have a basic understanding of machine learning models.
|
||||
|
||||
- **Courses:** [MLCourse.ai](https://mlcourse.ai/), [Fast.ai](https://course.fast.ai)
|
||||
- **Book Suggestion:** _Applied Machine Learning and AI for Engineers_ by Jeff Prosise
|
||||
@@ -1,3 +0,0 @@
|
||||
# Data Pipelines
|
||||
|
||||
Data pipelines refer to a set of processes that involve moving data from one system to another, for purposes such as data integration, data migration, data transformation, or data synchronization. These processes can involve a variety of data sources and destinations, and may often require data to be cleaned, enriched, or otherwise transformed along the way. It's a key concept in data engineering to ensure that data is appropriately processed from its source to the location where it will be used, typically a data warehouse, data mart, or a data lake. As such, data pipelines play a crucial part in building an effective and efficient data analytics setup, enabling the flow of data to be processed for insights.
|
||||
@@ -1,3 +0,0 @@
|
||||
# Data lakes & Warehouses
|
||||
|
||||
"**Data Lakes** are large-scale data repository systems that store raw, untransformed data, in various formats, from multiple sources. They're often used for big data and real-time analytics requirements. Data lakes preserve the original data format and schema which can be modified as necessary. On the other hand, **Data Warehouses** are data storage systems which are designed for analyzing, reporting and integrating with transactional systems. The data in a warehouse is clean, consistent, and often transformed to meet wide-range of business requirements. Hence, data warehouses provide structured data but require more processing and management compared to data lakes."
|
||||
@@ -1,3 +0,0 @@
|
||||
# Spark / Airflow / Kafka
|
||||
|
||||
Apache Spark is an open-source distributed computing system used for big data processing and analytics. It provides an interface for programming entire clusters with implicit data parallelism and fault tolerance. On the other hand, Apache Airflow is an open-source platform to programmatically author, schedule and monitor workflows. The primary use case of Airflow is to define workflows of tasks that run at specific times or in response to specific events. Apache Kafka is a distributed event streaming platform that lets you publish, subscribe to, store, and process streams of records in real time. It is often used in situations where JMS (Java Messaging Service), RabbitMQ, and other messaging systems are found to be necessary but not powerful or flexible enough.
|
||||
@@ -1,3 +0,0 @@
|
||||
# Data Engineering Fundamentals
|
||||
|
||||
Data Engineering is essentially dealing with the collection, validation, storage, transformation, and processing of data. The objective is to provide reliable, efficient, and scalable data pipelines and infrastructure that allow data scientists to convert data into actionable insights. It involves steps like data ingestion, data storage, data processing, and data provisioning. Important concepts include designing, building, and maintaining data architecture, databases, processing systems, and large-scale processing systems. It is crucial to have extensive technical knowledge in various tools and programming languages like SQL, Python, Hadoop, and more.
|
||||
@@ -1,9 +0,0 @@
|
||||
# MLOps Principles
|
||||
|
||||
Awareness of MLOps principles and maturity factors is required.
|
||||
|
||||
- **Books:**
|
||||
- _Designing Machine Learning Systems_ by Chip Huyen
|
||||
- _Introducing MLOps_ by Mark Treveil and Dataiku
|
||||
- **Assessment:** [MLOps maturity assessment](https://marvelousmlops.substack.com/p/mlops-maturity-assessment)
|
||||
- **Great resource on MLOps:** [ml-ops.org](https://ml-ops.org)
|
||||
@@ -1,8 +0,0 @@
|
||||
# Version Control Systems
|
||||
|
||||
Version control/source control systems allow developers to track and control changes to code over time. These services often include the ability to make atomic revisions to code, branch/fork off of specific points, and to compare versions of code. They are useful in determining the who, what, when, and why code changes were made.
|
||||
|
||||
Visit the following resources to learn more:
|
||||
|
||||
- [Git](https://git-scm.com/)
|
||||
- [What is Version Control?](https://www.atlassian.com/git/tutorials/what-is-version-control)
|
||||
@@ -1,9 +0,0 @@
|
||||
# CI / CD
|
||||
|
||||
Critical for traceable and reproducible ML model deployments.
|
||||
|
||||
- **Books:**
|
||||
- _Learning GitHub Actions_ by Brent Laster
|
||||
- _Learning Git_ by Anna Skoulikari
|
||||
- **Tutorials & Courses:** [Git & GitHub for beginners](https://www.youtube.com/watch?v=RGOj5yH7evk), [Python to Production guide](https://www.udemy.com/course/setting-up-the-linux-terminal-for-software-development/), [Version Control Missing Semester](https://missing.csail.mit.edu/2020/version-control/), https://learngitbranching.js.org/
|
||||
- **Tool:** [Pre-commit hooks](https://marvelousmlops.substack.com/p/welcome-to-pre-commit-heaven)
|
||||
@@ -1,4 +0,0 @@
|
||||
Systems like Airflow and Mage are important in ML engineering.
|
||||
|
||||
- **Course:** [Introduction to Airflow in Python](https://app.datacamp.com/learn/courses/introduction-to-airflow-in-python)
|
||||
- **Note:** Airflow is also featured in the _ML Engineering with Python_ book and [_The Full Stack 7-Steps MLOps Framework_](https://www.pauliusztin.me/courses/the-full-stack-7-steps-mlops-framework).
|
||||
@@ -1,8 +0,0 @@
|
||||
# Experiment Tracking and Model Registry
|
||||
|
||||
**Experiment Tracking** is an essential part of MLOps, providing a system to monitor and record the different experiments conducted during the machine learning model development process. This involves capturing, organizing and visualizing the metadata associated with each experiment, such as hyperparameters used, models produced, metrics like accuracy or loss, and other information about the computational environment. This tracking allows for reproducibility of experiments, comparison across different experiment runs, and helps in identifying the best models.
|
||||
|
||||
Logging metadata, parameters, and artifacts of training runs.
|
||||
|
||||
- **Tool:** MLflow
|
||||
- **Courses:** [MLflow Udemy course](https://www.udemy.com/course/mlflow-course/), [End-to-end machine learning (MLflow piece)](https://www.udemy.com/course/sustainable-and-scalable-machine-learning-project-development/)
|
||||
@@ -1,9 +0,0 @@
|
||||
# Data Lineage and Feature Stores
|
||||
|
||||
**Data Lineage** refers to the life-cycle of data, including its origins, movements, characteristics and quality. It's a critical component in MLOps for tracking the journey of data through every process in a pipeline, from raw input to model output. Data lineage helps in maintaining transparency, ensuring compliance, and facilitating data debugging or tracing data related bugs. It provides a clear representation of data sources, transformations, and dependencies thereby aiding in audits, governance, or reproduction of machine learning models.
|
||||
|
||||
Feature stores are a crucial component of MLOps infrastructure.
|
||||
|
||||
- **Tutorial:** Creating a feature store with Feast [Part 1](https://kedion.medium.com/creating-a-feature-store-with-feast-part-1-37c380223e2f) [Part 2](https://kedion.medium.com/feature-storage-for-ml-with-feast-part-2-34df1971a8d3) [Part 3](https://kedion.medium.com/feature-storage-for-ml-with-feast-a061899fc4a2)
|
||||
- **Tool:** DVC for data tracking
|
||||
- **Course:** [End-to-end machine learning (DVC piece)](https://www.udemy.com/course/sustainable-and-scalable-machine-learning-project-development/)
|
||||
@@ -1,8 +0,0 @@
|
||||
# Model Training and Serving
|
||||
|
||||
"Model Training" refers to the phase in the Machine Learning (ML) pipeline where we teach a machine learning model how to make predictions by providing it with data. This process begins with feeding the model a training dataset, which it uses to learn and understand patterns or perform computations. The model's performance is then evaluated by comparing its prediction outputs with the actual results. Various algorithms can be used in the model training process. The choice of algorithm usually depends on the task, the data available, and the requirements of the project. It is worth noting that the model training stage can be computationally expensive particularly when dealing with large datasets or complex models.
|
||||
|
||||
Decisions depend on the organization's infrastructure.
|
||||
|
||||
- **Repository Suggestion:** [ML Deployment k8s Fast API](https://github.com/sayakpaul/ml-deployment-k8s-fastapi/tree/main)
|
||||
- **Tutorial Suggestions:** [ML deployment with k8s FastAPI, Building an ML app with FastAPI](https://dev.to/bravinsimiyu/beginner-guide-on-how-to-build-a-machine-learning-app-with-fastapi-part-ii-deploying-the-fastapi-application-to-kubernetes-4j6g), [Basic Kubeflow pipeline](https://towardsdatascience.com/tutorial-basic-kubeflow-pipeline-from-scratch-5f0350dc1905), [Building and deploying ML pipelines](https://www.datacamp.com/tutorial/kubeflow-tutorial-building-and-deploying-machine-learning-pipelines?utm_source=google&utm_medium=paid_search&utm_campaignid=19589720818&utm_adgroupid=157156373991&utm_device=c&utm_keyword=&utm_matchtype=&utm_network=g&utm_adpostion=&utm_creative=683184494153&utm_targetid=dsa-2218886984380&utm_loc_interest_ms=&utm_loc_physical_ms=9064564&utm_content=&utm_campaign=230119_1-sea~dsa~tofu_2-b2c_3-eu_4-prc_5-na_6-na_7-le_8-pdsh-go_9-na_10-na_11-na-dec23&gad_source=1&gclid=Cj0KCQiA4Y-sBhC6ARIsAGXF1g7iSih9h2RGL27LwWY6dlPLhEss-e5Af8pnaBvdDynRh7IHIKi8sGgaApD-EALw_wcB), [KServe tutorial](https://towardsdatascience.com/kserve-highly-scalable-machine-learning-deployment-with-kubernetes-aa7af0b71202)
|
||||
@@ -1,7 +0,0 @@
|
||||
# Monitoring and Observability
|
||||
|
||||
**Monitoring** in MLOps primarily involves tracking the performance of machine learning (ML) models in production to ensure that they continually deliver accurate and reliable results. Such monitoring is necessary because the real-world data that these models handle may change over time, a scenario known as data drift. These changes can adversely affect model performance. Monitoring helps to detect any anomalies in the model’s behaviour or performance and such alerts can trigger the retraining of models with new data. From a broader perspective, monitoring also involves tracking resources and workflows to detect and rectify any operational issues in the MLOps pipeline.
|
||||
|
||||
- [**ML Monitoring vs Observability article**](https://marvelousmlops.substack.com/p/ml-monitoring-vs-ml-observability)
|
||||
- **Course:** [Machine learning monitoring concepts](https://app.datacamp.com/learn/courses/machine-learning-monitoring-concepts), [Monitoring ML in Python](https://app.datacamp.com/learn/courses/monitoring-machine-learning-in-python)
|
||||
- **Tools:** [Prometheus, Grafana](https://www.udemy.com/course/mastering-prometheus-and-grafana/)
|
||||
@@ -1,3 +0,0 @@
|
||||
# MLOps Components
|
||||
|
||||
MLOps components can be broadly classified into three major categories: Development, Operations and Governance. The **Development** components include everything involved in the creation of machine learning models, such as data extraction, data analysis, feature engineering, and machine learning model training. The **Operations** category includes components involved in deploying, monitoring, and maintaining machine learning models in production. This may include release management, model serving, and performance monitoring. Lastly, the **Governance** category encompasses the policies and regulations related to machine learning models. This includes model audit and tracking, model explainability, and security & compliance regulations.
|
||||
@@ -1,7 +0,0 @@
|
||||
# Infrastructure as Code
|
||||
|
||||
Essential for a reproducible MLOps framework.
|
||||
|
||||
- **Course:** [Terraform course for beginners](https://www.youtube.com/watch?v=SLB_c_ayRMo)
|
||||
- **Video:** [8 Terraform best practices by Techworld by Nana](https://www.youtube.com/watch?v=gxPykhPxRW0)
|
||||
- **Book Suggestion:** _Terraform: Up and Running, 3rd Edition_ by Yevgeniy Brikman
|
||||
@@ -1 +0,0 @@
|
||||
#
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,38 +0,0 @@
|
||||
---
|
||||
jsonUrl: '/jsons/roadmaps/mlops.json'
|
||||
pdfUrl: '/pdfs/roadmaps/mlops.pdf'
|
||||
order: 18
|
||||
briefTitle: 'MLOps'
|
||||
briefDescription: 'Step by step guide to learn MLOps in 2024'
|
||||
title: 'MLOps Roadmap'
|
||||
description: 'Step by step guide to learn MLOps in 2024'
|
||||
hasTopics: true
|
||||
isNew: true
|
||||
dimensions:
|
||||
width: 968
|
||||
height: 1256.63
|
||||
schema:
|
||||
headline: 'MLOps Roadmap'
|
||||
description: 'Learn about MLOps with this interactive step by step guide in 2023. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'
|
||||
imageUrl: 'https://roadmap.sh/roadmaps/mlops.png'
|
||||
datePublished: '2024-02-12'
|
||||
dateModified: '2024-02-12'
|
||||
seo:
|
||||
title: 'MLOps Roadmap'
|
||||
description: 'Learn about MLOps using this roadmap. Community driven, articles, resources, guides, interview questions, quizzes for modern backend development.'
|
||||
keywords:
|
||||
- 'mlops roadmap 2024'
|
||||
- 'mlops engineer'
|
||||
- 'machine learning engineer'
|
||||
- 'ai ops engineer'
|
||||
relatedRoadmaps:
|
||||
- 'ai-data-scientist'
|
||||
- 'python'
|
||||
sitemap:
|
||||
priority: 1
|
||||
changefreq: 'monthly'
|
||||
tags:
|
||||
- 'roadmap'
|
||||
- 'main-sitemap'
|
||||
- 'role-roadmap'
|
||||
---
|
||||
@@ -1,414 +0,0 @@
|
||||
---
|
||||
import GridItem from '../components/GridItem.astro';
|
||||
import SimplePageHeader from '../components/SimplePageHeader.astro';
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
import { RoadmapCard } from '../components/GetStarted/RoadmapCard';
|
||||
import { getRoadmapsByTag } from '../lib/roadmap';
|
||||
import { RoadmapMultiCard } from '../components/GetStarted/RoadmapMultiCard';
|
||||
import { RoleRoadmaps } from '../components/GetStarted/RoleRoadmaps';
|
||||
import {
|
||||
Blocks,
|
||||
Code,
|
||||
ExternalLink,
|
||||
Globe2,
|
||||
GraduationCap,
|
||||
MousePointerSquare,
|
||||
ServerCog,
|
||||
ServerCogIcon,
|
||||
ArrowRight,
|
||||
Server,
|
||||
Cloud,
|
||||
Smartphone,
|
||||
Bot,
|
||||
MessageCircleCode,
|
||||
Shield,
|
||||
ShieldHalf,
|
||||
Workflow,
|
||||
Gamepad2,
|
||||
PenSquare,
|
||||
Component,
|
||||
Waypoints,
|
||||
CheckSquare,
|
||||
} from 'lucide-react';
|
||||
import { SectionBadge } from '../components/GetStarted/SectionBadge';
|
||||
import { TipItem } from '../components/GetStarted/TipItem';
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title='Developer Roadmaps'
|
||||
description={'Step by step guides and paths to learn different tools or technologies'}
|
||||
permalink={'/roadmaps'}
|
||||
>
|
||||
<div class='bg-gradient-to-b from-gray-200 to-white py-4 sm:py-8 md:py-12'>
|
||||
<div class='container'>
|
||||
<div class='text-left'>
|
||||
<SectionBadge title='Beginner Roadmaps' />
|
||||
</div>
|
||||
<div class='my-3 md:my-5 text-left'>
|
||||
<h2 class='mb-0 sm:mb-1 text-xl sm:text-3xl font-semibold'>
|
||||
Are you an Absolute beginner?
|
||||
</h2>
|
||||
<p class='text-sm sm:text-base text-gray-500'>
|
||||
Here are some beginner friendly roadmaps you should start with.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class='grid sm:grid-cols-2 md:grid-cols-3 gap-3'>
|
||||
<RoadmapCard
|
||||
icon={Globe2}
|
||||
title='Frontend Developer'
|
||||
link='/frontend?r=frontend-beginner'
|
||||
description='Develop the part of web apps that users interact with i.e. things rendered in the browser.'
|
||||
/>
|
||||
<RoadmapCard
|
||||
icon={ServerCog}
|
||||
title='Backend Developer'
|
||||
link='/backend?r=backend-beginner'
|
||||
description='Develop the part hidden from the user e.g. things like APIs, databases, search engines etc.'
|
||||
/>
|
||||
|
||||
<RoadmapCard
|
||||
icon={Globe2}
|
||||
icon2={ServerCog}
|
||||
title='Full Stack Developer'
|
||||
link='/full-stack'
|
||||
description='Develop both the frontend and backend side of the web apps i.e. the whole development stack.'
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p class="my-4 sm:my-7 text-sm sm:text-base">
|
||||
There is also a <a
|
||||
target='_blank'
|
||||
class='font-medium underline underline-offset-2'
|
||||
href='/devops?r=devops-beginner'>beginner DevOps roadmap</a
|
||||
> which requires you to have some backend knowledge and entails a lot of
|
||||
operations work i.e. deploying, scaling, monitoring, and maintaining
|
||||
applications.
|
||||
</p>
|
||||
|
||||
<div class='rounded-xl border bg-white p-3 sm:p-4'>
|
||||
<h2 class='mb-0 sm:mb-1 text-lg sm:text-xl font-semibold'>Tips for Beginners</h2>
|
||||
<p class="text-sm sm:text-base">
|
||||
Learning to code can be overwhelming, here are some tips to help you
|
||||
get started:
|
||||
</p>
|
||||
|
||||
<div class='mt-3 flex flex-col gap-1'>
|
||||
<TipItem
|
||||
title='Avoid Tutorial Hell'
|
||||
description="Don't get stuck in tutorial hell. It's easy to get caught up in tutorials and never actually build anything. Tutorials are great for learning, but the best way to learn is by doing. An example of this is to watch a project-based tutorial, code along with the instructor. After finishing the tutorial, try to build the same project from scratch without the tutorial (if you can't, it's okay to go back to the tutorial). Repeat this process until you can build the project without the tutorial. After that, try to add new features to the project or build something similar from scratch."
|
||||
client:load
|
||||
/>
|
||||
|
||||
<TipItem
|
||||
title='Consistent study habits'
|
||||
description="Commit to regular, consistent study sessions. It's better to study for 30 minutes every day than to cram for 10 hours once a week."
|
||||
client:load
|
||||
/>
|
||||
|
||||
<TipItem
|
||||
title='Set a clear goal'
|
||||
description='Establish a clear, significant goal that motivates you. It could be building a company, an app, a website, or anything that personally resonates with you.'
|
||||
client:load
|
||||
/>
|
||||
|
||||
<TipItem
|
||||
title='Embrace the marathon mindset'
|
||||
description="You will feel lost in the beginning. Avoid comparing yourself to others; everyone progresses at their own pace. Understand that challenges are part of the journey, and it's okay to take your time."
|
||||
client:load
|
||||
/>
|
||||
|
||||
<TipItem
|
||||
title='Build projects'
|
||||
description="The best way to learn is by doing. Start building projects as soon as possible. It's okay if they're simple at first; the goal is to learn and improve. Build upon code-alongs and tutorials to create your projects and learn through hands-on experience"
|
||||
client:load
|
||||
/>
|
||||
<TipItem
|
||||
title='Learn to get unstuck'
|
||||
description="Once you start learning to code, you're going to run into problems that you don't know how to solve. This is normal and part of the process. You don't really learn unless you struggle through it. That said, you won't always be able to move forward without some help. So how do you find that help? First off, forget books. They aren't a great place to start here, because the number and types of errors they can cover is so small. Online is the easiest place to find help. Most devs look for solutions on StackOverflow or just google the error message (if they have one). Other solutions are to find newsgroups or forums dedicated to the language you're using."
|
||||
client:load
|
||||
/>
|
||||
|
||||
<TipItem
|
||||
title='Join a community'
|
||||
description="Join a community of learners, such as a local coding group, a Discord server, or a subreddit. It's a great way to get help, share your progress, and learn from others."
|
||||
client:load
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<RoleRoadmaps
|
||||
badge='Self-taught Developer'
|
||||
title='Are you a self-taught developer?'
|
||||
description='How about taking a peek at the Computer Science roadmap aimed at self-taught developers?'
|
||||
>
|
||||
<RoadmapCard
|
||||
icon={GraduationCap}
|
||||
title='Computer Science'
|
||||
link='/computer-science'
|
||||
description='Learn the fundamental concepts of computer science and programming.'
|
||||
/>
|
||||
<RoadmapCard
|
||||
icon={Blocks}
|
||||
title='System Design'
|
||||
link='/system-design'
|
||||
description='Learn how to design large scale systems and prepare for system design interviews.'
|
||||
/>
|
||||
<RoadmapCard
|
||||
icon={Blocks}
|
||||
title='Software Design and Architecture'
|
||||
link='/software-design-architecture'
|
||||
description='Learn how to design and architect software systems.'
|
||||
/>
|
||||
</RoleRoadmaps>
|
||||
|
||||
<RoleRoadmaps
|
||||
badge='Frontend Developer'
|
||||
title='Are you a Frontend Developer?'
|
||||
description='How about skimming through the frontend or JavaScript roadmaps to see if there is anything you missed? TypeScript is all the rage these days, maybe it is time to learn it?'
|
||||
>
|
||||
<RoadmapCard
|
||||
icon={Globe2}
|
||||
title='Frontend'
|
||||
link='/frontend'
|
||||
description='Learn all you need to know to become a frontend developer.'
|
||||
/>
|
||||
|
||||
<RoadmapMultiCard
|
||||
roadmaps={[
|
||||
{ title: 'JavaScript', link: '/javascript' },
|
||||
{ title: 'TypeScript', link: '/typescript' },
|
||||
]}
|
||||
description='How about mastering the language of the web: JavaScript? or maybe TypeScript?'
|
||||
secondaryRoadmaps={[
|
||||
{
|
||||
title: 'Frontend Performance',
|
||||
link: '/best-practices/frontend-performance',
|
||||
},
|
||||
]}
|
||||
secondaryDescription='Or learn how to improve the performance of your web apps?'
|
||||
/>
|
||||
<RoadmapMultiCard
|
||||
roadmaps={[
|
||||
{ title: 'React', link: '/react' },
|
||||
{ title: 'Vue', link: '/vue' },
|
||||
{ title: 'Angular', link: '/angular' },
|
||||
]}
|
||||
description='Or learn a framework?'
|
||||
secondaryRoadmaps={[{ title: 'Design Systems', link: '/design-system' }]}
|
||||
secondaryDescription='or learn about design systems?'
|
||||
/>
|
||||
</RoleRoadmaps>
|
||||
|
||||
<RoleRoadmaps
|
||||
badge='Backend Developer'
|
||||
title='Are you a Backend Developer?'
|
||||
description='Explore the general backend roadmap or dive into a specific technology like Node.js, Python, Java etc'
|
||||
>
|
||||
<RoadmapCard
|
||||
icon={ServerCog}
|
||||
title='Backend'
|
||||
link='/backend'
|
||||
description='Learn all you need to know to become a backend developer.'
|
||||
/>
|
||||
|
||||
<RoadmapMultiCard
|
||||
roadmaps={[
|
||||
{ title: 'Node.js', link: '/nodejs' },
|
||||
{ title: 'Rust', link: '/rust' },
|
||||
{ title: 'Go', link: '/golang' },
|
||||
{ title: 'Python', link: '/python' },
|
||||
{ title: 'Java', link: '/java' },
|
||||
{ title: 'ASP.NET Core', link: '/aspnet-core' },
|
||||
{ title: 'C++', link: '/cpp' },
|
||||
]}
|
||||
description='Or learn a specific technology?'
|
||||
/>
|
||||
|
||||
<RoadmapMultiCard
|
||||
roadmaps={[
|
||||
{ title: 'System Design', link: '/system-design' },
|
||||
{
|
||||
title: 'Design and Architecture',
|
||||
link: '/software-design-architecture',
|
||||
},
|
||||
]}
|
||||
description='How about improving your System Design skills?'
|
||||
secondaryRoadmaps={[
|
||||
{ title: 'SQL', link: '/sql' },
|
||||
{ title: 'PostgreSQL', link: '/postgresql-dba' },
|
||||
{ title: 'MongoDB', link: '/mongodb' },
|
||||
]}
|
||||
secondaryDescription='Or perhaps improve your database skills?'
|
||||
/>
|
||||
</RoleRoadmaps>
|
||||
|
||||
<RoleRoadmaps
|
||||
badge='DevOps Engineer'
|
||||
title='DevOps or a Wanna-be DevOps Engineer?'
|
||||
description='Explore the general DevOps roadmap or dive into a specific technology like Docker, Kubernetes etc'
|
||||
>
|
||||
<RoadmapCard
|
||||
icon={Server}
|
||||
title='DevOps'
|
||||
link='/devops'
|
||||
description='Learn all you need to know to become a DevOps Engineer.'
|
||||
/>
|
||||
|
||||
<RoadmapCard
|
||||
icon={Cloud}
|
||||
title='AWS'
|
||||
link='/aws'
|
||||
description='Learn all you need to know to become an AWS Engineer.'
|
||||
/>
|
||||
|
||||
<RoadmapMultiCard
|
||||
roadmaps={[
|
||||
{ title: 'Docker', link: '/docker' },
|
||||
{ title: 'Kubernetes', link: '/kubernetes' },
|
||||
]}
|
||||
description='or perhaps you want to learn Docker or Kubernetes?'
|
||||
secondaryRoadmaps={[
|
||||
{ title: 'Python', link: '/python' },
|
||||
{ title: 'Go', link: '/golang' },
|
||||
{ title: 'Rust', link: '/rust' },
|
||||
]}
|
||||
secondaryDescription='Or maybe improve your automation skills?'
|
||||
/>
|
||||
</RoleRoadmaps>
|
||||
|
||||
<RoleRoadmaps
|
||||
badge='Mobile Developer'
|
||||
title='Are you a Mobile Developer?'
|
||||
description='How about beefing up your mobile development skills?'
|
||||
>
|
||||
<RoadmapCard
|
||||
icon={Smartphone}
|
||||
title='Android'
|
||||
link='/android'
|
||||
description='Learn all you need to know to become an Android Developer.'
|
||||
/>
|
||||
|
||||
<RoadmapMultiCard
|
||||
roadmaps={[
|
||||
{ title: 'React Native', link: '/react-native' },
|
||||
{ title: 'Flutter', link: '/flutter' },
|
||||
]}
|
||||
description='Or learn a cross-platform framework?'
|
||||
/>
|
||||
|
||||
<RoadmapCard
|
||||
icon={Smartphone}
|
||||
title='iOS'
|
||||
link='/ios'
|
||||
isUpcoming={true}
|
||||
description='We will be adding an iOS roadmap soon.'
|
||||
/>
|
||||
</RoleRoadmaps>
|
||||
<RoleRoadmaps
|
||||
badge='AI and Machine Learning'
|
||||
title='Are you an AI or Machine Learning enthusiast?'
|
||||
description='How about diving into the AI or Machine Learning roadmaps?'
|
||||
>
|
||||
<RoadmapCard
|
||||
icon={Bot}
|
||||
title='AI and Data Science'
|
||||
link='/ai-data-scientist'
|
||||
description='Learn all you need to know to become an AI or Data Scientist.'
|
||||
/>
|
||||
|
||||
<RoadmapCard
|
||||
icon={MessageCircleCode}
|
||||
title='Prompt Engineering'
|
||||
link='/prompt-engineering'
|
||||
description='Learn how to write better prompts for GPT-3 and other language models.'
|
||||
/>
|
||||
|
||||
<RoadmapCard
|
||||
icon={Bot}
|
||||
icon2={ServerCog}
|
||||
title='MLOps'
|
||||
link='/mlops'
|
||||
description='Learn how to deploy and manage machine learning models.'
|
||||
isUpcoming={true}
|
||||
/>
|
||||
</RoleRoadmaps>
|
||||
<RoleRoadmaps
|
||||
badge='More Roles'
|
||||
title='Fancy something else?'
|
||||
description='Explore the following roadmaps about UX, Game Development, Software Architect and more'
|
||||
>
|
||||
<div class='flex flex-col justify-center gap-3'>
|
||||
<RoadmapCard
|
||||
icon={ShieldHalf}
|
||||
title='Cyber Security'
|
||||
link='/cyber-security'
|
||||
description='Learn to become a Cyber Security Expert.'
|
||||
/>
|
||||
<RoadmapCard
|
||||
icon={Workflow}
|
||||
title='UX Designer'
|
||||
link='/ux-design'
|
||||
description='Learn all you need to know to become a UX Designer.'
|
||||
/>
|
||||
</div>
|
||||
<div class='flex flex-col justify-center gap-3'>
|
||||
<RoadmapCard
|
||||
icon={Gamepad2}
|
||||
title='Game Development'
|
||||
link='/game-developer'
|
||||
description='Learn all you need to know to become a Game Developer.'
|
||||
/>
|
||||
<RoadmapCard
|
||||
icon={PenSquare}
|
||||
title='Technical Writer'
|
||||
link='/technical-writer'
|
||||
description='Learn all you need to know to become a Technical Writer.'
|
||||
/>
|
||||
</div>
|
||||
<div class='flex flex-col justify-center gap-3'>
|
||||
<RoadmapCard
|
||||
icon={PenSquare}
|
||||
title='Blockchain'
|
||||
link='/blockchain'
|
||||
description='Learn all you need to know to become a Technical Writer.'
|
||||
/>
|
||||
<RoadmapCard
|
||||
icon={Component}
|
||||
title='Software Architect'
|
||||
link='/software-architect'
|
||||
description='Learn all you need to know to become a Software Architect.'
|
||||
/>
|
||||
</div>
|
||||
</RoleRoadmaps>
|
||||
|
||||
<div class='container'>
|
||||
<div class='-mt-5 mb-12 rounded-3xl bg-black p-5'>
|
||||
<h2 class='mb-0.5 sm:mb-1 text-xl sm:text-2xl font-semibold text-white'>There is more!</h2>
|
||||
<p class='text-gray-400 text-sm sm:text-base'>
|
||||
We have a lot more content for you to explore.
|
||||
</p>
|
||||
|
||||
<div class='my-4 sm:my-5 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-2 sm:gap-3'>
|
||||
<a href='/roadmaps' class='text-sm sm:text-base rounded-lg bg-gradient-to-br from-gray-800 to-gray-700 p-4 text-white flex-grow hover:from-gray-700 hover:to-gray-700 transition-all'>
|
||||
<Waypoints className="h-5 w-5 mb-3 sm:mb-2 text-gray-500" />
|
||||
Explore all Roadmaps
|
||||
</a>
|
||||
<a href='/best-practices' class='text-sm sm:text-base rounded-lg bg-gradient-to-br from-gray-800 to-gray-700 p-4 text-white flex-grow hover:from-gray-700 hover:to-gray-700 transition-all'>
|
||||
<CheckSquare className="h-5 w-5 mb-3 sm:mb-2 text-gray-500" />
|
||||
Explore Best Practices
|
||||
</a>
|
||||
<a href='/questions' class='text-sm sm:text-base rounded-lg bg-gradient-to-br from-gray-800 to-gray-700 p-4 text-white flex-grow hover:from-gray-700 hover:to-gray-700 transition-all'>
|
||||
<CheckSquare className="h-5 w-5 mb-3 sm:mb-2 text-gray-500" />
|
||||
Explore Questions
|
||||
</a>
|
||||
</div>
|
||||
<p class="text-gray-400 sm:text-base text-sm">
|
||||
Or visit our <a href="/guides" class="rounded-lg hover:bg-gray-600 transition-colors hover:text-white bg-gray-700 text-gray-300 py-1 px-2">guides</a> and <a href="/videos" class="rounded-lg hover:bg-gray-600 transition-colors hover:text-white bg-gray-700 text-gray-300 py-1 px-2">videos</a> for long-form content.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</BaseLayout>
|
||||
@@ -1,5 +1,9 @@
|
||||
---
|
||||
import { AuthenticationForm } from '../components/AuthenticationFlow/AuthenticationForm';
|
||||
import Divider from '../components/AuthenticationFlow/Divider.astro';
|
||||
import { EmailLoginForm } from '../components/AuthenticationFlow/EmailLoginForm';
|
||||
import { GitHubButton } from '../components/AuthenticationFlow/GitHubButton';
|
||||
import { GoogleButton } from '../components/AuthenticationFlow/GoogleButton';
|
||||
import { LinkedInButton } from '../components/AuthenticationFlow/LinkedInButton';
|
||||
import AccountLayout from '../layouts/AccountLayout.astro';
|
||||
---
|
||||
|
||||
@@ -10,17 +14,23 @@ import AccountLayout from '../layouts/AccountLayout.astro';
|
||||
noIndex={true}
|
||||
>
|
||||
<div class='container'>
|
||||
<div
|
||||
class='mx-auto flex flex-col items-start justify-start pb-28 pt-10 sm:max-w-[400px] sm:items-center sm:justify-center sm:pt-20'
|
||||
>
|
||||
<div class='mx-auto flex flex-col items-start justify-start pb-28 pt-10 sm:max-w-[400px] sm:items-center sm:justify-center sm:pt-20'>
|
||||
<div class='mb-2 text-left sm:mb-5 sm:text-center'>
|
||||
<h1 class='mb-2 text-3xl font-semibold sm:mb-5 sm:text-5xl'>Login</h1>
|
||||
<p class='mb-3 text-base leading-6 text-gray-600'>
|
||||
<p class='text-base text-gray-600 leading-6 mb-3'>
|
||||
Welcome back! Let's take you to your account.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<AuthenticationForm client:load />
|
||||
<div class='flex w-full flex-col gap-2'>
|
||||
<GitHubButton client:load />
|
||||
<GoogleButton client:load />
|
||||
<LinkedInButton client:load />
|
||||
</div>
|
||||
|
||||
<Divider />
|
||||
|
||||
<EmailLoginForm client:load />
|
||||
|
||||
<div class='mt-6 text-center text-sm text-slate-600'>
|
||||
Don't have an account?{' '}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
---
|
||||
import { AuthenticationForm } from '../components/AuthenticationFlow/AuthenticationForm';
|
||||
import Divider from '../components/AuthenticationFlow/Divider.astro';
|
||||
import { EmailSignupForm } from '../components/AuthenticationFlow/EmailSignupForm';
|
||||
import { GitHubButton } from '../components/AuthenticationFlow/GitHubButton';
|
||||
import { GoogleButton } from '../components/AuthenticationFlow/GoogleButton';
|
||||
import { LinkedInButton } from '../components/AuthenticationFlow/LinkedInButton';
|
||||
import AccountLayout from '../layouts/AccountLayout.astro';
|
||||
---
|
||||
|
||||
@@ -25,7 +29,15 @@ import AccountLayout from '../layouts/AccountLayout.astro';
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<AuthenticationForm type='signup' client:load />
|
||||
<div class='flex w-full flex-col items-stretch gap-2'>
|
||||
<GitHubButton client:load />
|
||||
<GoogleButton client:load />
|
||||
<LinkedInButton client:load />
|
||||
</div>
|
||||
|
||||
<Divider />
|
||||
|
||||
<EmailSignupForm client:load />
|
||||
|
||||
<div class='mt-6 text-center text-sm text-slate-600'>
|
||||
Already have an account? <a
|
||||
|
||||
Reference in New Issue
Block a user