This repository documents the stage where I built my core web development foundation from the ground up, starting with semantic HTML and CSS, moving through JavaScript and problem solving, then going deeper into asynchronous programming, TypeScript, and responsive UI development with Tailwind CSS.
I built this repository because I wanted a strong foundation before going deeper into frontend development.
I did not want to know only how to make something work. I wanted to understand what the browser is doing, how JavaScript behaves, how layouts respond, how asynchronous code is scheduled, how APIs communicate, and how TypeScript can make code safer.
That is why this repository contains both simple examples and much deeper learning tracks.
Some folders focus on one small concept at a time.
Others go much further into problem solving, async behavior, type systems, responsive UI, and real application patterns.
This repository is the record of that entire process.
|
6 Core Learning Tracks |
145 JavaScript Practice Tasks |
27 TypeScript Practice Tasks |
44 Tailwind Topic Labs |
HTML
↓
CSS
↓
JavaScript
↓
Problem Solving
↓
Asynchronous JavaScript
↓
TypeScript
↓
Tailwind CSS
↓
Stronger Frontend Foundation
This progression reflects the order in which I built the foundation.
Each stage gave me a better understanding of the next one.
| Track | Focus |
|---|---|
| HTML | Semantic markup, forms, media, metadata, and document structure |
| CSS | Styling, Flexbox, Grid, responsive design, animation, and layout systems |
| JavaScript | Language fundamentals, DOM, events, OOP, browser programming, and problem solving |
| Asynchronous JavaScript | Event loop, Promises, async await, Fetch, concurrency, cancellation, caching, and advanced async patterns |
| TypeScript | Type system, generics, narrowing, OOP, advanced types, compiler configuration, and application typing |
| Tailwind CSS | Utility based styling, responsive systems, advanced layouts, interaction states, and reusable UI patterns |
My first goal was to understand how a web document should be structured before thinking about styling or JavaScript.
The HTML track contains 13 structured modules.
- HTML boilerplate and document structure
- Headings and paragraphs
- Text formatting
- Links and navigation
- Lists
- Images
- Tables
- Forms
- Semantic elements
- Audio
- Video
- Iframes
- Meta tags
- Favicons
- HTML entities
The track finishes with a complete HTML portfolio exercise where several concepts come together in one document.
HTML itself was not difficult to write.
The useful part was learning to think about structure.
I started paying more attention to document hierarchy, semantic elements, forms, content relationships, and the way good markup makes later styling and interaction easier.
After learning document structure, I moved into visual layout and responsive interface design.
The CSS track covers 29 core topics, followed by dedicated Flexbox and Grid practice projects.
- Selectors
- Colors
- CSS units
- Typography
- Backgrounds
- Borders
- Outlines
- Margin
- Padding
- Box model
- Display
- Overflow
- Visibility
- Cursor
- Z index
- Positioning
- Float and clear
- Flexbox
- CSS Grid
- Object fit
- Object position
- Transforms
- Transitions
- Keyframe animations
- Pseudo classes
- Pseudo elements
- Attribute selectors
- Shadows
- Filters
- Backdrop filters
- CSS functions
- CSS variables
- Responsive layout fundamentals
- Breakpoints
- Flexible sizing
- Layout adaptation
- Mobile friendly interfaces
I also worked on focused layout exercises instead of learning properties only in isolation.
- Navigation
- Pricing cards
- Team layouts
- Gallery sections
- Alignment exercises
- Magazine layout
- Dashboard structure
- Image gallery
- Holy Grail layout
- Responsive card grids
Content
↓
Box Model
↓
Available Space
↓
Layout System
↓
Alignment
↓
Responsive Behavior
This stage helped me stop fixing layouts with random values and start thinking about how elements actually relate to each other.
JavaScript became the largest part of my early foundation.
I worked through the language itself first, then used it for browser interaction, structured data, object oriented programming, asynchronous behavior, and problem solving.
- Variables and declarations
- Primitive values
- Reference values
- Type conversion
- Operators
- Equality
- Truthy and falsy values
- Conditionals
- Loops
- Control flow
- Function declarations
- Function expressions
- Arrow functions
- Default parameters
- Rest parameters
- Arguments
- Function scope
- Block scope
- Higher order functions
- Callback functions
- IIFEs
- Recursion
- Arrays
- Array methods
- Objects
- Object operations
- Strings
- String methods
- Sets
- Maps
- JSON
- Destructuring
- Spread syntax
- Scope
- Closures
- Hoisting
- Error handling
- Custom errors
- DOM selection
- DOM manipulation
- Element creation
- Class manipulation
- Events
- Event objects
- Keyboard events
- Input events
- Event delegation
- Listener cleanup
- Classes
- Instances
- Constructors
- Methods
- Inheritance
- Method overriding
super- Getters
- Setters
- Static methods
- Static properties
I did not want JavaScript to become a subject where I knew the syntax but struggled when I had to solve something without a ready made example.
That is why problem solving became a major part of this repository.
The repository contains 145 dedicated JavaScript practice tasks.
The exercises cover:
- Conditions and decision making
- Loops
- Arrays
- Strings
- Objects
- Functions
- Data transformation
- Searching
- Sorting
- Validation
- Debugging
- Closures
- Mutation and copying
- Small application problems
There are also separate sections for:
- Basic JavaScript problem solving
- ES6 problem solving
- Advanced ES6 problem solving
These include practice with:
letandconst- Template strings
- Default parameters
- Spread syntax
- Rest parameters
- Arrow functions
- Destructuring
- Object methods
- Optional chaining
mapfilterfindreduce- Method chaining
- Closures
- Custom sorting
- Product data
- Cart data
- Object transformations
Understand the Input
↓
Define the Output
↓
Break the Problem Down
↓
Choose the Right Data Structure
↓
Implement
↓
Test Different Cases
↓
Refactor
This part of the repository matters a lot to me because knowing JavaScript and being able to solve problems with JavaScript are two different things.
After learning the basics of Promises and async await, I created a separate track to understand asynchronous JavaScript more deeply.
It became an 8 module progression.
- Synchronous execution
- Blocking code
- Asynchronous execution
- JavaScript runtime
- Call stack
- Web APIs
- Callback queue
- Event loop
- Timers
- Execution order
- Callback functions
- Synchronous callbacks
- Asynchronous callbacks
- Timer callbacks
- Event callbacks
- Error first callback patterns
- Nested callbacks
- Callback hell
- Promise creation
- Promise states
- Resolve and reject
.then().catch().finally()- Promise chaining
- Returning values
- Error propagation
- Returning Promises
- Converting callback patterns
- Async functions
await- Promise returns
- Sequential asynchronous work
try...catchfinally- Throwing errors
- Custom errors
- Multiple awaits
- Async composition
- Common async mistakes
The next step was using asynchronous JavaScript for network communication.
- API fundamentals
- HTTP requests
- HTTP responses
- Fetch API
- Response objects
- JSON
- GET
- POST
- PUT
- PATCH
- DELETE
- Request headers
- HTTP status codes
- Fetch error handling
AbortController- Reusable API functions
This was where async JavaScript started to feel much more practical.
It was no longer only about timers and Promises. It became about handling real data and real requests.
I also spent time understanding the difference between running independent async tasks one after another and starting them together.
Sequential
Task A
↓
Task B
↓
Task C
Concurrent
Task A ─┐
Task B ─┼→ Results
Task C ─┘
Promise.allPromise.allSettledPromise.racePromise.any- Parallel API requests
- Failure behavior
- Timeout patterns
- Batch processing
The later modules move into problems that appear once multiple requests and changing application state are involved.
- Retry patterns
- Retry with delay
- Exponential backoff
- Timeouts
- Polling
- Cancellation
- Race conditions
- Preventing stale responses
- Debouncing
- Throttling
- Async caching
- Request deduplication
- Concurrency control
This part made asynchronous code much easier for me to reason about.
I started thinking beyond whether a request simply succeeds or fails.
I also started thinking about timing, overlapping requests, stale results, retries, cancellation, and what happens when multiple async operations interact.
The final async stage goes deeper into scheduling.
- Microtask queue
- Macrotask queue
- Promise execution order
- Timer execution order
queueMicrotask- Event loop behavior
- Async iteration
for await...of- Async generators
- Top level
await - Integrated async flows
JavaScript
↓
Call Stack
↓
External Async Work
↓
Task Queues
↓
Event Loop
↓
Call Stack
Understanding this was more useful than memorizing the order of a few examples.
It gave me a clearer way to reason about async behavior when something did not run in the order I expected.
TypeScript became one of the deepest tracks in this repository.
The main learning path contains 13 structured modules, plus 27 separate practice tasks.
I started with basic annotations and inference, then moved into narrowing, generics, object oriented programming, advanced type manipulation, compiler configuration, and practical application typing.
- Type annotations
- Type inference
- Primitive types
anyunknown- Union types
- Literal types
- Object types
- Optional properties
- Readonly properties
- Nested objects
- Arrays
- Arrays of objects
- Tuples
- Type aliases
- Parameter types
- Return types
- Arrow function typing
- Optional parameters
- Default parameters
- Function types
- Callback types
voidnever- Rest parameters
- Destructured parameters
- Function overloads
- Interfaces
- Optional interface properties
- Readonly interface properties
- Function interfaces
- Array interfaces
- Interface extension
- Multiple inheritance
- Type aliases
- Intersection types
- Interface vs type alias
This was where TypeScript started feeling less like annotations and more like a way to describe the shape of an application.
A big part of TypeScript is proving what a value actually is before using it.
- Type assertions
- Non null assertions
- Type guards
- Custom type guards
- Discriminated unions
keyoftypeof- Indexed access types
never- Exhaustive checking
Possible State
│
├── Idle
├── Loading
├── Success
└── Error
Discriminated unions were especially useful because they showed me how types can prevent invalid state combinations instead of only describing data.
- Generic functions
- Multiple generics
- Generic constraints
keyofwith generics- Generic interfaces
PartialRequiredPickOmitReadonlyRecordReturnType
Generics changed the way I thought about reusable code.
Instead of making a function broad with any, I could keep useful relationships between the input and output types.
A dedicated module covers:
- Classes
- Constructors
- Properties
- Methods
publicprivateprotected- Readonly members
- Getters
- Setters
- Static members
- Inheritance
- Method overriding
- Encapsulation
- Polymorphism
- Abstraction
The later modules go deeper into the type system.
- Mapped types
- Mapped type modifiers
- Conditional types
inferExcludeExtractParametersAwaited- Template literal types
as constsatisfies
These topics helped me understand how types can be derived and transformed instead of being rewritten manually every time.
I also spent time learning what TypeScript is doing outside individual files.
- TypeScript compiler
tsconfig.json- Target
- Lib
- Module configuration
- Strict mode
rootDiroutDir- Include and exclude
noEmit- Named imports and exports
- Default imports and exports
- Type only imports and exports
- Declaration files
- Project structure
This made TypeScript feel more complete.
I was not only writing types anymore. I had a much better idea of how the project itself is compiled and organized.
The later modules focus on using types in application style code.
- Async TypeScript
- Promise types
- API response typing
- Type imports
- Type exports
- Error handling with
unknown - Reusable application types
- Props style object types
- Event types
- Form data
- Nullable data
- Generic API responses
- Request states
- Exhaustive state handling
The final integration work brings several of these ideas together instead of keeping every concept isolated.
Alongside the structured modules, the repository includes 27 dedicated TypeScript practice tasks.
- Functions
- Typed objects
- Tuples
- Arrays
- Unknown values
- Nested objects
- Interfaces
- Union types
- Type assertions
- Generics
- Generic constraints
- Enums
- Utility types
as const- Derived union types
JavaScript Runtime Behavior
+
Static Type Information
↓
Clearer Contracts
↓
Earlier Feedback
↓
Safer Refactoring
The biggest value I found in TypeScript was not writing more syntax.
It was being forced to think more clearly about the data a function receives, what it returns, and what states are actually possible.
I learned Tailwind after spending time with regular CSS first.
That order helped a lot.
Flexbox, Grid, spacing, responsive behavior, positioning, and layout decisions were already familiar, so Tailwind became a faster way to express those ideas rather than a replacement for understanding CSS.
The track contains 44 focused topic labs across two intensive modules.
- Utility first mindset
- Spacing system
- Width and height
- Sizing
- Colors
- Backgrounds
- Typography
- Borders
- Radius
- Shadows
- Display
- Visibility
- Overflow
- Positioning
- Z index
- Flexbox
- Grid
- Responsive design
- Mobile first strategy
- Breakpoint ranges
- Responsive sizing
- Responsive spacing
- Responsive Flexbox
- Responsive Grid
- Complex responsive layout strategy
- Hover states
- Focus states
- Active states
- Disabled states
focus-visible- Group variants
- Peer variants
- Data variants
- ARIA variants
- Dark mode
- Transitions
- Transforms
- Animations
- Gradients
- Visual effects
- Arbitrary values
- Arbitrary properties
- Arbitrary variants
- Theme customization
- Design tokens
- Container queries
- Advanced responsive patterns
- Responsive design systems
- Dashboard layouts
- Complex grids
- Navbar strategy
- Sidebar strategy
- Responsive cards
- Responsive forms
- Responsive tables
- Reusable component styling
- Conditional classes
- Dynamic class pitfalls
- Tailwind best practices
- Accessibility
- Reduced motion
Design Requirement
↓
Layout Decision
↓
Responsive Strategy
↓
Utility Composition
↓
Reusable UI Pattern
Tailwind changed how I write styles, but the CSS knowledge underneath it is still what makes the classes make sense.
Across all of these tracks, a few habits kept repeating.
When something felt difficult, I learned to separate the input, conditions, transformations, and output before trying to write the full solution.
A lot of the JavaScript and TypeScript practice comes back to understanding the shape of the data before trying to manipulate it.
That includes:
- Arrays
- Objects
- Nested structures
- API responses
- Form values
- Application states
A lot of progress came from code that did not behave the way I expected.
I worked through problems involving:
- Incorrect conditions
- Loop mistakes
- Mutation bugs
- Async ordering
- Promise errors
- Stale responses
- Type mismatches
- Layout problems
Debugging became part of the learning process rather than something separate from it.
The repository also helped me become more comfortable with the actual environment where frontend code runs.
That includes:
- DOM
- Events
- Timers
- Web APIs
- HTTP
- Fetch
- Event loop
- Responsive layout
- Accessibility states
HTML
↓
Structure
CSS
↓
Presentation & Layout
JavaScript
↓
Behavior & Interaction
Values
↓
Control Flow
↓
Functions
↓
Data Structures
↓
Abstraction
↓
Problem Solving
Start Work
↓
External Async Operation
↓
Result Becomes Ready
↓
Scheduler
↓
JavaScript Continues
Data Shape
↓
Type Contract
↓
Functions & APIs
↓
Compiler Feedback
↓
Safer Application Code
Content
↓
Layout
↓
Responsive Behavior
↓
Interaction
↓
Usable Interface
One thing I like about keeping all of this work together is that the progression is visible.
The earlier folders are small and focused.
One topic, one example, one problem.
Later folders start combining multiple concepts and require more reasoning.
Single Concept
↓
Small Exercise
↓
More Practice
↓
Combined Concepts
↓
Larger Problems
↓
Better Structure
That progression is especially visible in the JavaScript problem solving work, the async modules, the later TypeScript modules, and the responsive Tailwind sections.
Web Engineering Foundations
│
├── HTML
│ └── 13 structured modules
│
├── CSS
│ ├── 29 core topics
│ ├── Flexbox project
│ └── Grid project
│
├── Java Script
│ ├── 19 core modules
│ ├── 145 practice tasks
│ ├── Basic problem solving
│ ├── ES6 problem solving
│ └── Advanced ES6 problem solving
│
├── Asynchronous Javascript Mastery
│ └── 8 deep dive modules
│
├── Type Script
│ ├── 13 structured modules
│ └── 27 practice tasks
│
└── Tailwind CSS
├── Foundation & responsive layouts
└── Advanced production design
The pattern across this repository was simple.
Learn
↓
Write Code
↓
Practice
↓
Break Something
↓
Debug
↓
Understand Why
↓
Try Again
That worked much better for me than trying to memorize a long list of methods or APIs first.
A lot of concepts only became clear after I used them, made mistakes with them, and then used them again in another problem.
By the end of this repository, I was much more comfortable working with the parts of frontend development that sit underneath frameworks and libraries.
I became comfortable with:
- Structuring web documents properly
- Building responsive layouts
- Working with Flexbox and Grid
- Writing JavaScript without framework abstractions
- Manipulating arrays and objects
- Solving programming problems
- Working with the DOM and browser events
- Understanding scope and closures
- Reasoning about asynchronous execution
- Working with Promises and async await
- Making HTTP requests
- Handling request failures
- Managing concurrency
- Preventing stale async work
- Designing reusable TypeScript types
- Working with generics
- Narrowing uncertain data
- Using advanced TypeScript utilities
- Configuring TypeScript projects
- Building responsive interfaces with Tailwind
- Thinking more carefully about accessibility and interaction states
More importantly, I became much more comfortable figuring things out when the answer is not immediately obvious.
That is one of the biggest things I wanted from this repository.
HTML ✓ Complete
CSS ✓ Complete
JavaScript ✓ Complete
JavaScript Problem Solving ✓ Complete
Asynchronous JavaScript ✓ Complete
TypeScript ✓ Complete
Tailwind CSS ✓ Complete
Web Engineering Foundations ✓ COMPLETE
This repository started with basic HTML.
By the end, I was working with event loop behavior, race conditions, request cancellation, generic types, mapped types, compiler configuration, container queries, responsive systems, and much larger problem solving exercises.
That progression matters to me more than any single topic in this repository.
Syntax can always be looked up.
What I wanted was enough understanding that when something does not behave the way I expect, I know how to start thinking about the problem.
Questions like:
What is the browser doing here?
What does this data actually look like?
What changes when this function runs?
Am I changing the original data or creating a new value?
Is this work sequential or concurrent?
Can an older request overwrite a newer result?
What does this type actually guarantee?
What happens if the data is not what I expected?
Will this layout still work on a smaller screen?
Am I solving the real problem or only making this one example work?
Those are the kinds of questions I became much more comfortable asking while building this repository.