mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2026-03-14 02:32:00 +08:00
Compare commits
10 Commits
fix/nodeid
...
fix/canoni
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a10b9d0d4 | ||
|
|
c481e8aa38 | ||
|
|
87ed33b330 | ||
|
|
6837330be1 | ||
|
|
b1d97db2d2 | ||
|
|
f20cf95592 | ||
|
|
6e5e77c86b | ||
|
|
2410c89bde | ||
|
|
b513a48c2a | ||
|
|
b4990ae3cd |
@@ -6,18 +6,66 @@
|
||||
},
|
||||
"GN6SnI7RXIeW8JeD-qORW": {
|
||||
"title": "What is an AI Engineer?",
|
||||
"description": "",
|
||||
"links": []
|
||||
"description": "AI engineers are professionals who specialize in designing, developing, and implementing artificial intelligence (AI) systems. Their work is essential in various industries, as they create applications that enable machines to perform tasks that typically require human intelligence, such as problem-solving, learning, and decision-making.\n\nVisit the following resources to learn more:",
|
||||
"links": [
|
||||
{
|
||||
"title": "AI For Everyone",
|
||||
"url": "https://www.coursera.org/learn/ai-for-everyone",
|
||||
"type": "course"
|
||||
},
|
||||
{
|
||||
"title": "How to Become an AI Engineer: Duties, Skills, and Salary",
|
||||
"url": "https://www.simplilearn.com/tutorials/artificial-intelligence-tutorial/how-to-become-an-ai-engineer",
|
||||
"type": "article"
|
||||
},
|
||||
{
|
||||
"title": "AI engineers: What they do and how to become one",
|
||||
"url": "https://www.techtarget.com/whatis/feature/How-to-become-an-artificial-intelligence-engineer",
|
||||
"type": "article"
|
||||
},
|
||||
{
|
||||
"title": "AI Engineers- What Do They Do?",
|
||||
"url": "https://www.youtube.com/watch?v=y8qRq9PMCh8&t=1s",
|
||||
"type": "video"
|
||||
}
|
||||
]
|
||||
},
|
||||
"jSZ1LhPdhlkW-9QJhIvFs": {
|
||||
"title": "AI Engineer vs ML Engineer",
|
||||
"description": "",
|
||||
"links": []
|
||||
"description": "An AI Engineer develops broad AI solutions, such as chatbots, NLP, and intelligent automation, focusing on integrating AI technologies into large applications. In contrast, an ML Engineer is more focused on building and deploying machine learning models, handling data processing, model training, and optimization in production environments.\n\nVisit the following resources to learn more:",
|
||||
"links": [
|
||||
{
|
||||
"title": "AI Engineer vs. ML Engineer: Duties, Skills, and Qualifications",
|
||||
"url": "https://www.upwork.com/resources/ai-engineer-vs-ml-engineer",
|
||||
"type": "article"
|
||||
},
|
||||
{
|
||||
"title": "AI Developer vs ML Engineer: What’s the difference?",
|
||||
"url": "https://www.youtube.com/watch?v=yU87V2-XisA&t=2s",
|
||||
"type": "video"
|
||||
}
|
||||
]
|
||||
},
|
||||
"wf2BSyUekr1S1q6l8kyq6": {
|
||||
"title": "LLMs",
|
||||
"description": "",
|
||||
"links": []
|
||||
"description": "Large Language Models (LLMs) are advanced artificial intelligence programs designed to comprehend and generate human language text.\n\nVisit the following resources to learn more:",
|
||||
"links": [
|
||||
{
|
||||
"title": "What is a large language model (LLM)?",
|
||||
"url": "https://www.cloudflare.com/learning/ai/what-is-large-language-model/",
|
||||
"type": "article"
|
||||
},
|
||||
{
|
||||
"title": "Large language model",
|
||||
"url": "https://en.wikipedia.org/wiki/Large_language_model",
|
||||
"type": "article"
|
||||
},
|
||||
{
|
||||
"title": "How Large Language Models Work",
|
||||
"url": "https://www.youtube.com/watch?v=5sLYAQS9sWQ&t=1s",
|
||||
"type": "video"
|
||||
}
|
||||
]
|
||||
},
|
||||
"KWjD4xEPhOOYS51dvRLd2": {
|
||||
"title": "Inference",
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
"type": "article"
|
||||
},
|
||||
{
|
||||
"title": "Libra Office",
|
||||
"title": "LibreOffice",
|
||||
"url": "https://www.libreoffice.org/",
|
||||
"type": "article"
|
||||
}
|
||||
|
||||
@@ -463,6 +463,11 @@
|
||||
"title": "Node.js Errors - Official Docs",
|
||||
"url": "https://nodejs.org/api/errors.html#errors_class_systemerror",
|
||||
"type": "article"
|
||||
},
|
||||
{
|
||||
"title": "@Article@16 Common Errors in Node.js and How to Fix Them",
|
||||
"url": "https://betterstack.com/community/guides/scaling-nodejs/nodejs-errors/",
|
||||
"type": "article"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -4,6 +4,7 @@ import Cookies from 'js-cookie';
|
||||
import { TOKEN_COOKIE_NAME, setAuthToken } from '../../lib/jwt';
|
||||
import { httpGet } from '../../lib/http';
|
||||
import { Spinner } from '../ReactIcons/Spinner.tsx';
|
||||
import { triggerUtmRegistration } from '../../lib/browser.ts';
|
||||
|
||||
type GitHubButtonProps = {
|
||||
isDisabled?: boolean;
|
||||
@@ -46,6 +47,8 @@ export function GitHubButton(props: GitHubButtonProps) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerUtmRegistration();
|
||||
|
||||
let redirectUrl = '/';
|
||||
const gitHubRedirectAt = localStorage.getItem(GITHUB_REDIRECT_AT);
|
||||
const lastPageBeforeGithub = localStorage.getItem(GITHUB_LAST_PAGE);
|
||||
|
||||
@@ -4,6 +4,10 @@ import { TOKEN_COOKIE_NAME, setAuthToken } from '../../lib/jwt';
|
||||
import { httpGet } from '../../lib/http';
|
||||
import { Spinner } from '../ReactIcons/Spinner.tsx';
|
||||
import { GoogleIcon } from '../ReactIcons/GoogleIcon.tsx';
|
||||
import {
|
||||
getStoredUtmParams,
|
||||
triggerUtmRegistration,
|
||||
} from '../../lib/browser.ts';
|
||||
|
||||
type GoogleButtonProps = {
|
||||
isDisabled?: boolean;
|
||||
@@ -37,6 +41,8 @@ export function GoogleButton(props: GoogleButtonProps) {
|
||||
}`,
|
||||
)
|
||||
.then(({ response, error }) => {
|
||||
const utmParams = getStoredUtmParams();
|
||||
|
||||
if (!response?.token) {
|
||||
setError(error?.message || 'Something went wrong.');
|
||||
setIsLoading(false);
|
||||
@@ -45,6 +51,8 @@ export function GoogleButton(props: GoogleButtonProps) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerUtmRegistration();
|
||||
|
||||
let redirectUrl = '/';
|
||||
const googleRedirectAt = localStorage.getItem(GOOGLE_REDIRECT_AT);
|
||||
const lastPageBeforeGoogle = localStorage.getItem(GOOGLE_LAST_PAGE);
|
||||
@@ -97,9 +105,12 @@ export function GoogleButton(props: GoogleButtonProps) {
|
||||
// For non authentication pages, we want to redirect back to the page
|
||||
// the user was on before they clicked the social login button
|
||||
if (!['/login', '/signup'].includes(window.location.pathname)) {
|
||||
const pagePath = ['/respond-invite', '/befriend', '/r', '/ai'].includes(
|
||||
window.location.pathname,
|
||||
)
|
||||
const pagePath = [
|
||||
'/respond-invite',
|
||||
'/befriend',
|
||||
'/r',
|
||||
'/ai',
|
||||
].includes(window.location.pathname)
|
||||
? window.location.pathname + window.location.search
|
||||
: window.location.pathname;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { TOKEN_COOKIE_NAME, setAuthToken } from '../../lib/jwt';
|
||||
import { httpGet } from '../../lib/http';
|
||||
import { Spinner } from '../ReactIcons/Spinner.tsx';
|
||||
import { LinkedInIcon } from '../ReactIcons/LinkedInIcon.tsx';
|
||||
import { triggerUtmRegistration } from '../../lib/browser.ts';
|
||||
|
||||
type LinkedInButtonProps = {
|
||||
isDisabled?: boolean;
|
||||
@@ -45,6 +46,8 @@ export function LinkedInButton(props: LinkedInButtonProps) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerUtmRegistration();
|
||||
|
||||
let redirectUrl = '/';
|
||||
const linkedInRedirectAt = localStorage.getItem(LINKEDIN_REDIRECT_AT);
|
||||
const lastPageBeforeLinkedIn = localStorage.getItem(LINKEDIN_LAST_PAGE);
|
||||
@@ -97,9 +100,12 @@ export function LinkedInButton(props: LinkedInButtonProps) {
|
||||
// For non authentication pages, we want to redirect back to the page
|
||||
// the user was on before they clicked the social login button
|
||||
if (!['/login', '/signup'].includes(window.location.pathname)) {
|
||||
const pagePath = ['/respond-invite', '/befriend', '/r', '/ai'].includes(
|
||||
window.location.pathname,
|
||||
)
|
||||
const pagePath = [
|
||||
'/respond-invite',
|
||||
'/befriend',
|
||||
'/r',
|
||||
'/ai',
|
||||
].includes(window.location.pathname)
|
||||
? window.location.pathname + window.location.search
|
||||
: window.location.pathname;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { httpPost } from '../../lib/http';
|
||||
import { TOKEN_COOKIE_NAME, setAuthToken } from '../../lib/jwt';
|
||||
import { Spinner } from '../ReactIcons/Spinner';
|
||||
import { ErrorIcon2 } from '../ReactIcons/ErrorIcon2';
|
||||
import { triggerUtmRegistration } from '../../lib/browser.ts';
|
||||
|
||||
export function TriggerVerifyAccount() {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
@@ -26,6 +27,8 @@ export function TriggerVerifyAccount() {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerUtmRegistration();
|
||||
|
||||
setAuthToken(response.token);
|
||||
window.location.href = '/';
|
||||
})
|
||||
|
||||
@@ -6,6 +6,7 @@ import { X } from 'lucide-react';
|
||||
import { setViewSponsorCookie } from '../lib/jwt';
|
||||
import { isMobile } from '../lib/is-mobile';
|
||||
import Cookies from 'js-cookie';
|
||||
import { getUrlUtmParams } from '../lib/browser.ts';
|
||||
|
||||
export type PageSponsorType = {
|
||||
company: string;
|
||||
@@ -50,6 +51,16 @@ export function PageSponsor(props: PageSponsorProps) {
|
||||
const [sponsorId, setSponsorId] = useState<string | null>(null);
|
||||
const [sponsor, setSponsor] = useState<PageSponsorType>();
|
||||
|
||||
useEffect(() => {
|
||||
const foundUtmParams = getUrlUtmParams();
|
||||
|
||||
if (!foundUtmParams.utmSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
localStorage.setItem('utm_params', JSON.stringify(foundUtmParams));
|
||||
}, []);
|
||||
|
||||
const loadSponsor = async () => {
|
||||
const currentPath = window.location.pathname;
|
||||
if (
|
||||
|
||||
22
src/data/changelogs/devops-project-ideas.md
Normal file
22
src/data/changelogs/devops-project-ideas.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
title: 'DevOps Project Ideas, Team Dashboard, Redis Content'
|
||||
description: 'New Project Ideas for DevOps, Team Dashboard, Redis Content'
|
||||
images:
|
||||
"DevOps Project Ideas": "https://assets.roadmap.sh/guest/devops-project-ideas.png"
|
||||
"Redis Resources": "https://assets.roadmap.sh/guest/redis-resources.png"
|
||||
"Team Dashboard": "https://assets.roadmap.sh/guest/team-dashboard.png"
|
||||
seo:
|
||||
title: 'DevOps Project Ideas, Team Dashboard, Redis Content'
|
||||
description: ''
|
||||
date: 2024-10-16
|
||||
---
|
||||
|
||||
We have added 21 new project ideas to our DevOps roadmap, added content to Redis roadmap and introduced a new team dashboard for teams
|
||||
|
||||
- Practice your skills with [21 newly added DevOps Project Ideas](https://roadmap.sh/devops)
|
||||
- We have a new [Dashboard for teams](https://roadmap.sh/teams) to track their team activity.
|
||||
- [Redis roadmap](https://roadmap.sh/redis) now comes with learning resources.
|
||||
- Watch us [interview Bruno Simon](https://www.youtube.com/watch?v=IQK9T05BsOw) about his journey as a creative developer.
|
||||
- Bug fixes and performance improvements
|
||||
|
||||
ML Engineer roadmap and team dashboards are coming up next. Stay tuned!
|
||||
@@ -6,7 +6,6 @@ seo:
|
||||
title: 'Consistency Patterns - roadmap.sh'
|
||||
description: 'Everything you need to know about Week, Strong and Eventual Consistency'
|
||||
isNew: false
|
||||
canonicalUrl: 'https://cs.fyi/guide/consistency-patterns-week-strong-eventual/'
|
||||
type: 'textual'
|
||||
date: 2023-01-18
|
||||
sitemap:
|
||||
|
||||
@@ -7,7 +7,7 @@ seo:
|
||||
title: 'How to become a Front-End Developer in 7 Steps'
|
||||
description: 'Learn how to become a front-end developer in 7 clear steps. Start your coding journey with practical tips and resources today!'
|
||||
ogImageUrl: 'https://assets.roadmap.sh/guest/how-to-become-frontend-developer-i23nx.jpg'
|
||||
isNew: true
|
||||
isNew: false
|
||||
type: 'textual'
|
||||
date: 2024-08-15
|
||||
sitemap:
|
||||
|
||||
@@ -22,6 +22,7 @@ roadmapIds:
|
||||
- 'java'
|
||||
- 'golang'
|
||||
- 'spring-boot'
|
||||
- 'cpp'
|
||||
---
|
||||
|
||||
You are required to build a CLI tool that starts a caching proxy server, it will forward requests to the actual server and cache the responses. If the same request is made again, it will return the cached response instead of forwarding the request to the server.
|
||||
|
||||
@@ -22,6 +22,7 @@ roadmapIds:
|
||||
- 'java'
|
||||
- 'golang'
|
||||
- 'spring-boot'
|
||||
- 'cpp'
|
||||
---
|
||||
|
||||
You are required to build a command-line interface (CLI) utility for backing up any type of database. The utility will support various database management systems (DBMS) such as MySQL, PostgreSQL, MongoDB, SQLite, and others. The tool will feature automatic backup scheduling, compression of backup files, storage options (local and cloud), and logging of backup activities.
|
||||
|
||||
@@ -23,6 +23,7 @@ roadmapIds:
|
||||
- 'java'
|
||||
- 'golang'
|
||||
- 'spring-boot'
|
||||
- 'cpp'
|
||||
---
|
||||
|
||||
Build a simple expense tracker application to manage your finances. The application should allow users to add, delete, and view their expenses. The application should also provide a summary of the expenses.
|
||||
|
||||
@@ -22,6 +22,7 @@ roadmapIds:
|
||||
- 'java'
|
||||
- 'golang'
|
||||
- 'spring-boot'
|
||||
- 'cpp'
|
||||
---
|
||||
|
||||
In this project, you will build a simple command line interface (CLI) to fetch the recent activity of a GitHub user and display it in the terminal. This project will help you practice your programming skills, including working with APIs, handling JSON data, and building a simple CLI application.
|
||||
|
||||
@@ -22,6 +22,7 @@ roadmapIds:
|
||||
- 'java'
|
||||
- 'golang'
|
||||
- 'spring-boot'
|
||||
- 'cpp'
|
||||
---
|
||||
|
||||
You are required to build a simple number guessing game where the computer randomly selects a number and the user has to guess it. The user will be given a limited number of chances to guess the number. If the user guesses the number correctly, the game will end, and the user will win. Otherwise, the game will continue until the user runs out of chances.
|
||||
|
||||
@@ -22,6 +22,7 @@ roadmapIds:
|
||||
- 'java'
|
||||
- 'golang'
|
||||
- 'spring-boot'
|
||||
- 'cpp'
|
||||
---
|
||||
|
||||
Task tracker is a project used to track and manage your tasks. In this task, you will build a simple command line interface (CLI) to track what you need to do, what you have done, and what you are currently working on. This project will help you practice your programming skills, including working with the filesystem, handling user inputs, and building a simple CLI application.
|
||||
|
||||
@@ -1 +1,8 @@
|
||||
# Hugging Face Hub
|
||||
# Hugging Face Hub
|
||||
|
||||
The Hugging Face Hub is a comprehensive platform that hosts over 900,000 machine learning models, 200,000 datasets, and 300,000 demo applications, facilitating collaboration and sharing within the AI community. It serves as a central repository where users can discover, upload, and experiment with various models and datasets across multiple domains, including natural language processing, computer vision, and audio tasks. It also supports version control.
|
||||
|
||||
Learn more from the following resources:
|
||||
|
||||
- [@official@Documentation](https://huggingface.co/docs/hub/en/index)
|
||||
- [@course@nlp-official](https://huggingface.co/learn/nlp-course/en/chapter4/1)
|
||||
|
||||
@@ -1 +1,9 @@
|
||||
# Hugging Face Tasks
|
||||
# Hugging Face Tasks
|
||||
|
||||
Hugging Face supports text classification, named entity recognition, question answering, summarization, and translation. It also extends to multimodal tasks that involve both text and images, such as visual question answering (VQA) and image-text matching. Each task is done by various pre-trained models that can be easily accessed and fine-tuned through the Hugging Face library.
|
||||
|
||||
Learn more from the following resources:
|
||||
|
||||
- [@official@Task and Model](https://huggingface.co/learn/computer-vision-course/en/unit4/multimodal-models/tasks-models-part1)
|
||||
- [@official@Task Summary](https://huggingface.co/docs/transformers/v4.14.1/en/task_summary)
|
||||
- [@official@Task Manager](https://huggingface.co/docs/optimum/en/exporters/task_manager)
|
||||
|
||||
@@ -1 +1,8 @@
|
||||
# Hugging Face
|
||||
# Hugging Face
|
||||
|
||||
Hugging Face is often called the GitHub of machine learning because it lets developers share and test their work openly. Hugging Face is known for its `Transformers Python library`, which simplifies the process of `downloading and training ML models`. It promotes collaboration within the AI community by enabling users to `share models` and `datasets`, thus advancing the democratization of artificial intelligence through open-source practices.
|
||||
|
||||
Learn more from the following resources:
|
||||
|
||||
- [@official@Hugging Face](https://huggingface.co/)
|
||||
- [@official@Github](https://github.com/huggingface)
|
||||
|
||||
@@ -1 +1,8 @@
|
||||
# Inference SDK
|
||||
# Inference SDK
|
||||
|
||||
The Hugging Face Inference SDK is a powerful tool that allows developers to easily integrate and run inference on large language models hosted on the Hugging Face Hub. By using the `InferenceClient`, users can make API calls to various models for tasks such as text generation, image creation, and more. The SDK supports both synchronous and asynchronous operations thus compatible with existing workflows.
|
||||
|
||||
Learn more from the following resources:
|
||||
|
||||
- [@official@Inference](https://huggingface.co/docs/huggingface_hub/en/package_reference/inference_client)
|
||||
- [@article@Endpoint Setup](https://www.npmjs.com/package/@huggingface/inference)
|
||||
|
||||
@@ -1 +1,8 @@
|
||||
# Ollama Models
|
||||
# Ollama Models
|
||||
|
||||
Ollama includes popular options like `Llama 2, Mistral, and Code Llama`. It simplifies the deployment process by bundling model weights, configurations, and datasets into a single package managed by a `Modelfile`, allowing users to easily manage and interact with these models. The platform's extensive library allows users to choose models tailored to their specific needs, and reduces reliance in cloud. Ollama Models could be of `text/base`, `chat/instruct` or `multi modal`.
|
||||
|
||||
Learn more from the following resources:
|
||||
|
||||
- [@official@Ollama Model Library](https://ollama.com/library)
|
||||
- [@course@Ollama Free Course](https://youtu.be/f4tXwCNP1Ac?si=0RRKIfw2XAsWNNBo)
|
||||
|
||||
@@ -1 +1,9 @@
|
||||
# Ollama SDK
|
||||
# Ollama SDK
|
||||
|
||||
The Ollama SDK is a community-driven tool that allows developers to integrate and run large language models (LLMs) locally through a simple API. Enabling users to easily import the Ollama provider and create customized instances for various models, such as Llama 2 and Mistral. The SDK supports functionalities like `text generation` and `embeddings`, making it versatile for applications ranging from `chatbots` to `content generation`. Also Ollama SDK enhances privacy and control over data while offering seamless integration with existing workflows.
|
||||
|
||||
Learn more from the following resources:
|
||||
|
||||
- [@article@SDK Provider](https://sdk.vercel.ai/providers/community-providers/ollama)
|
||||
- [@article@Beginner's Guide](https://dev.to/jayantaadhikary/using-the-ollama-api-to-run-llms-and-generate-responses-locally-18b7)
|
||||
- [@article@Setup](https://klu.ai/glossary/ollama)
|
||||
|
||||
@@ -1 +1,8 @@
|
||||
# Ollama
|
||||
# Ollama
|
||||
|
||||
Ollama is a powerful open-source tool designed to run large language models (LLMs) locally on users' machines, It exposes a `local API`, allowing developers to seamlessly integrate LLMs into their applications and workflows. This API facilitates efficient communication between your application and the LLM, enabling you to send prompts, receive responses, and leverage the full potential of these **powerful AI models**.
|
||||
|
||||
Learn more from the following resources:
|
||||
|
||||
- [@official@Ollama](https://ollama.com/)
|
||||
- [@article@Ollama Explained](https://www.geeksforgeeks.org/ollama-explained-transforming-ai-accessibility-and-language-processing/)
|
||||
|
||||
@@ -1 +1,7 @@
|
||||
# Transformers.js
|
||||
# Transformers.js
|
||||
|
||||
Hugging Face Transformers.js is a JavaScript library that enables developers to run transformer models directly in the browser without requiring a server. It offers a similar API to the original Python library, allowing tasks like sentiment analysis, text generation, and image processing using pre-trained models. By supporting the `pipeline API`, it simplifies the integration of models with preprocessing and postprocessing functionalities.
|
||||
|
||||
Learn more from the following resources:
|
||||
|
||||
- [@official@Transformers.js](https://huggingface.co/docs/hub/en/transformers-js)
|
||||
|
||||
@@ -3550,7 +3550,7 @@
|
||||
"selectable": true
|
||||
},
|
||||
{
|
||||
"id": "Wwd-0PjrtViMFWxRGaQey",
|
||||
"id": "1DrqtOwxCuFtWQXQ6ZALp",
|
||||
"type": "subtopic",
|
||||
"position": {
|
||||
"x": -198.46804969796983,
|
||||
|
||||
@@ -1,3 +1,65 @@
|
||||
type UtmParams = Partial<{
|
||||
utmSource: string;
|
||||
utmMedium: string;
|
||||
utmCampaign: string;
|
||||
utmContent: string;
|
||||
utmTerm: string;
|
||||
}>;
|
||||
|
||||
export function getUrlUtmParams(): UtmParams {
|
||||
if (typeof window === 'undefined') {
|
||||
return {};
|
||||
}
|
||||
|
||||
const utmParams = new URLSearchParams(window.location.search);
|
||||
const utmSource = utmParams.get('utm_source') ?? undefined;
|
||||
const utmMedium = utmParams.get('utm_medium') ?? undefined;
|
||||
const utmCampaign = utmParams.get('utm_campaign') ?? undefined;
|
||||
const utmContent = utmParams.get('utm_content') ?? undefined;
|
||||
const utmTerm = utmParams.get('utm_term') ?? undefined;
|
||||
|
||||
if (!utmSource || !utmCampaign) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
utmSource: utmCampaign ? utmSource.toLowerCase() : undefined,
|
||||
utmMedium: utmMedium ? utmMedium.toLowerCase() : undefined,
|
||||
utmCampaign: utmCampaign ? utmCampaign.toLowerCase() : undefined,
|
||||
utmContent: utmContent ? utmContent.toLowerCase() : undefined,
|
||||
utmTerm: utmTerm ? utmTerm.toLowerCase() : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export function triggerUtmRegistration() {
|
||||
const utmParams = getStoredUtmParams();
|
||||
console.log(utmParams);
|
||||
if (!utmParams.utmSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
localStorage.removeItem('utm_params');
|
||||
|
||||
window.fireEvent({
|
||||
category: 'UserRegistration',
|
||||
action: `Registration: ${utmParams.utmSource || 'unknown'}-${utmParams.utmCampaign || 'unknown'}`,
|
||||
label: `Registration: ${utmParams.utmSource || 'unknown'}-${utmParams.utmCampaign || 'unknown'}`,
|
||||
});
|
||||
}
|
||||
|
||||
export function getStoredUtmParams(): UtmParams {
|
||||
if (typeof window === 'undefined') {
|
||||
return {};
|
||||
}
|
||||
|
||||
const utmParams = localStorage.getItem('utm_params');
|
||||
if (!utmParams) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return JSON.parse(utmParams);
|
||||
}
|
||||
|
||||
export function getUrlParams() {
|
||||
if (typeof window === 'undefined') {
|
||||
return {};
|
||||
|
||||
@@ -60,7 +60,7 @@ const { response: userCounts } =
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
permalink={`/${roadmapId}`}
|
||||
permalink={`/${roadmapId}/projects`}
|
||||
title={seoTitle}
|
||||
description={seoDescription}
|
||||
briefTitle={roadmapData.briefTitle}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { FriendsPage } from '../../components/Friends/FriendsPage';
|
||||
title='Friends'
|
||||
noIndex={true}
|
||||
initialLoadingMessage='Loading friends'
|
||||
permalink="/account/friends"
|
||||
>
|
||||
<AccountSidebar activePageId='friends' activePageTitle='Friends'>
|
||||
<FriendsPage client:only="react" />
|
||||
|
||||
@@ -8,6 +8,7 @@ import AccountLayout from '../../layouts/AccountLayout.astro';
|
||||
title='Activity'
|
||||
noIndex={true}
|
||||
initialLoadingMessage={'Loading activity'}
|
||||
permalink="/account"
|
||||
>
|
||||
<AccountSidebar activePageId='activity' activePageTitle='Activity'>
|
||||
<ActivityPage client:only='react' />
|
||||
|
||||
@@ -8,6 +8,7 @@ import { RoadCardPage } from '../../components/RoadCard/RoadCardPage';
|
||||
title='Road Card'
|
||||
noIndex={true}
|
||||
initialLoadingMessage='Preparing card'
|
||||
permalink="/account/road-card"
|
||||
>
|
||||
<AccountSidebar activePageId='road-card' activePageTitle='Road Card'>
|
||||
<RoadCardPage client:only="react" />
|
||||
|
||||
@@ -8,6 +8,7 @@ import { RoadmapListPage } from '../../components/CustomRoadmap/RoadmapListPage'
|
||||
title='Roadmaps'
|
||||
noIndex={true}
|
||||
initialLoadingMessage='Loading roadmaps'
|
||||
permalink="/account/roadmaps"
|
||||
>
|
||||
<AccountSidebar activePageId='roadmaps' activePageTitle='Roadmaps'>
|
||||
<RoadmapListPage client:only='react' />
|
||||
|
||||
@@ -10,6 +10,7 @@ import { ProfileSettingsPage } from '../../components/ProfileSettings/ProfileSet
|
||||
description=''
|
||||
noIndex={true}
|
||||
initialLoadingMessage={'Loading settings'}
|
||||
permalink="/account/settings"
|
||||
>
|
||||
<AccountSidebar activePageId='settings' activePageTitle='Settings'>
|
||||
<ProfileSettingsPage client:load />
|
||||
|
||||
@@ -8,6 +8,7 @@ import AccountLayout from '../../layouts/AccountLayout.astro';
|
||||
title='Update Profile'
|
||||
noIndex={true}
|
||||
initialLoadingMessage={'Loading profile'}
|
||||
permalink="/account/update-profile"
|
||||
>
|
||||
<AccountSidebar activePageId='profile' activePageTitle='Profile'>
|
||||
<UpdatePublicProfileForm client:load />
|
||||
|
||||
@@ -3,6 +3,6 @@ import { ExploreAIRoadmap } from '../../components/ExploreAIRoadmap/ExploreAIRoa
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
---
|
||||
|
||||
<BaseLayout title='Explore AI Generated Roadmaps'>
|
||||
<BaseLayout title='Explore AI Generated Roadmaps' permalink="/ai/explore">
|
||||
<ExploreAIRoadmap client:load />
|
||||
</BaseLayout>
|
||||
|
||||
@@ -3,6 +3,6 @@ import { GenerateRoadmap } from '../../components/GenerateRoadmap/GenerateRoadma
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
---
|
||||
|
||||
<BaseLayout title='Roadmap AI'>
|
||||
<BaseLayout title='Roadmap AI' permalink="/ai">
|
||||
<GenerateRoadmap client:load />
|
||||
</BaseLayout>
|
||||
|
||||
@@ -25,7 +25,7 @@ const ogImageUrl =
|
||||
<BaseLayout
|
||||
title={replaceVariables(guideData.seo.title)}
|
||||
description={replaceVariables(guideData.seo.description)}
|
||||
permalink={`/backend/languages`}
|
||||
permalink={`/backend/frameworks`}
|
||||
canonicalUrl={guideData.canonicalUrl}
|
||||
ogImageUrl={ogImageUrl}
|
||||
>
|
||||
|
||||
@@ -11,7 +11,7 @@ const allChangelogs = await getAllChangelogs();
|
||||
<BaseLayout
|
||||
title='Changelogs'
|
||||
description='Changelogs for the updates and changes to roadmap.sh'
|
||||
permalink='/changelogs'
|
||||
permalink='/changelog'
|
||||
noIndex={true}
|
||||
>
|
||||
<div class='bg-gray-100 px-4'>
|
||||
|
||||
@@ -7,6 +7,6 @@ const description =
|
||||
'Explore the community-created roadmaps to learn new skills, tools, and technologies. You can also create your own roadmap and share it with the world.';
|
||||
---
|
||||
|
||||
<BaseLayout title={title} description={description}>
|
||||
<BaseLayout title={title} description={description} permalink="/community">
|
||||
<DiscoverRoadmaps client:load />
|
||||
</BaseLayout>
|
||||
|
||||
@@ -56,7 +56,7 @@ const enrichedBestPractices = bestPractices.map((bestPractice) => {
|
||||
});
|
||||
---
|
||||
|
||||
<BaseLayout title='Dashboard' noIndex={true}>
|
||||
<BaseLayout title='Dashboard' noIndex={true} permalink="/dashboard">
|
||||
<DashboardPage
|
||||
builtInRoleRoadmaps={enrichedRoleRoadmaps}
|
||||
builtInSkillRoadmaps={enrichedSkillRoadmaps}
|
||||
|
||||
@@ -4,7 +4,7 @@ import AccountLayout from '../layouts/AccountLayout.astro';
|
||||
import {AccountTerms} from "../components/AccountTerms";
|
||||
---
|
||||
|
||||
<AccountLayout title='Forgot Password' noIndex={true}>
|
||||
<AccountLayout title='Forgot Password' noIndex={true} permalink="/forgot-password">
|
||||
<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'
|
||||
|
||||
@@ -37,7 +37,7 @@ 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'}
|
||||
permalink={'/get-started'}
|
||||
>
|
||||
<div class='bg-gradient-to-b from-gray-200 to-white py-4 sm:py-8 md:py-12'>
|
||||
<div class='container'>
|
||||
|
||||
@@ -11,7 +11,7 @@ const { response: leaderboardStats, error: leaderboardError } =
|
||||
await leaderboardClient.listLeaderboardStats();
|
||||
---
|
||||
|
||||
<BaseLayout title='Leaderboard'>
|
||||
<BaseLayout title='Leaderboard' permalink="/leaderboard">
|
||||
{leaderboardError && <ErrorPage error={leaderboardError} />}
|
||||
{
|
||||
leaderboardStats && (
|
||||
|
||||
@@ -7,7 +7,7 @@ import AccountLayout from '../layouts/AccountLayout.astro';
|
||||
<AccountLayout
|
||||
title='Login - roadmap.sh'
|
||||
description='Register yourself to receive occasional emails about new roadmaps, updates, guides and videos'
|
||||
permalink={'/signup'}
|
||||
permalink={'/login'}
|
||||
noIndex={true}
|
||||
>
|
||||
<div class='container'>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
layout: ../layouts/MarkdownLayout.astro
|
||||
title: Privacy Policy - roadmap.sh
|
||||
noIndex: true
|
||||
permalink: /privacy
|
||||
---
|
||||
|
||||
# Privacy Policy
|
||||
|
||||
@@ -37,7 +37,7 @@ const githubUrl = `https://github.com/kamranahmedse/developer-roadmap/tree/maste
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
permalink={`/projects/${projectId}`}
|
||||
permalink={`/projects/${projectId}/solutions`}
|
||||
title={projectData?.seo?.title}
|
||||
briefTitle={projectData.title}
|
||||
ogImageUrl={ogImageUrl}
|
||||
|
||||
@@ -10,7 +10,7 @@ const questionGroups = await getAllQuestionGroups();
|
||||
<BaseLayout
|
||||
title='Questions'
|
||||
description={'Step by step guides and paths to learn different tools or technologies'}
|
||||
permalink={'/roadmaps'}
|
||||
permalink={'/questions'}
|
||||
>
|
||||
<SimplePageHeader
|
||||
title='Questions'
|
||||
|
||||
@@ -56,7 +56,7 @@ const enrichedBestPractices = bestPractices.map((bestPractice) => {
|
||||
});
|
||||
---
|
||||
|
||||
<BaseLayout title='Dashboard' noIndex={true}>
|
||||
<BaseLayout title='Team' noIndex={true} permalink="/team">
|
||||
<DashboardPage
|
||||
builtInRoleRoadmaps={enrichedRoleRoadmaps}
|
||||
builtInSkillRoadmaps={enrichedSkillRoadmaps}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
layout: ../layouts/MarkdownLayout.astro
|
||||
title: Terms and Conditions - roadmap.sh
|
||||
noIndex: true
|
||||
permalink: /terms
|
||||
---
|
||||
|
||||
# Terms of Service
|
||||
|
||||
Reference in New Issue
Block a user