That's a rather unusual question from you. I mean typically beginners ask that, and you have proven that you are capable of dealing with OS dev.
Anyway, here are my answers:
First I read the documentation. One or maybe more times, to get the big picture. Once I got that, I start experimenting, doing smaller or bigger PoCs. Time after time I pick up the documentation again and I check the details.
About in which order: I think there's no common answer here. I have seen a lot of systems doing things differently. I suggest just to start it, and when you got a dependency, work on that, and then return. Sometimes (in microkernel's world more often than one would anticipate) you'll face chicken-and-egg scenarios. In those cases you'll have to find a workaround, there'll be no "optimal order" at all. For example you'll need to allocate memory to store the free memory list, but you cannot do that until you have a list of free memory to allocate from... If you choose a different path there's a chance you'll never face that problem at all. It's up to you. No-one can foresee which problems to solve in YOUR design. It's only up to you. Another example: you can develop storage driver before you develop filesystems (common for monolithic kernels). With microkernels, most probably you'll first implement filesystems in order to load the storage driver from ramdisk.
For you, a logical step would be to implement filesystems, but that's just a suggestion, at the end of the day it's totally up to you.
The path I've chosen (I have to stress that it's my personal preference, you don't have to follow it, it's nothing more than an example):
1. milestone: build environment, bootloader, mkfstool (to create initrd), hello world kernel, bootloader tests (here mkfs preceeds kernel because in my design kernel is located inside the initrd)
2. milestone: kprintf, early filesystem support, load services, parse executable format (as I have a microkernel), tasks, cooperative multitasking.
3. milestone: panic screen, interrupts (as ISR stubs call panic), pmm, timer, scheduler, preemtion, messaging.
Here I faced the lack of mmap (to map initrd in FS service's and video buffer in video driver's memory)
4. milestone: vmm (mapping), input/output devices: PS2 keyboard, mouse, lfb driver, UI service, libc.
Here I found that further UI development depends of malloc (to allocate window buffers and block cache) and filesystems (to load icons)
5. milestone: malloc implementation in libc, mounting file systems
Here I went back and finished the initialization sequence of my OS (using cooperative multitasking during init, and switch to preemtion when the idle task first scheduled. I've also modified my design which originally had one task for drivers into a separate task for every driver as I could route IRQs more effectively).
Now I've found file operations depend on cache, which in turn lazily depend on storage drivers (I had to take into consideration that I want an async mechanism to load blocks from disk into cache, but for now I'm fine with reading blocks only from initrd eliminating a layer in the first implementation). Further roadmap: file and directory operations, window management, rescue shell, storage drivers, first beta release. As you can see, I have a basic plan, but I often change it as dependencies show up along the way. It's also possible to partially fulfill a dependency (like I did with ramdisk/storage devices). Although I try to do it the right way for the first time, it's not possible all the time. Therefore I sometimes end up with a quick-and-dirty-but-works solution, and later go back to correct it. To keep track of those things, I use comments in my code, and I use a script to create a
TODO list. When I'm in a doubt what to do, I pick one from that list.