The design you're suggesting doesn't work because it would cause server/client waterfalls everywhere, which goes against the entire purpose of the architecture.
The data flows in one direction: from the server to the client. It's just physics — your server is where the data is. You're trying to move it to the client. So the code that needs to run first is the server code.
This is why the data flow starts at the server. You can't fix this by changing how opting in works, or some other API design workaround. What you're fighting with is the arrow of time.
There's nothing about it "that doesn't work": it simply isn't as effective at getting people moving to the mental model you're prescribing. People would have mostly trucked as they have.
Except people not wanting to do that mental shift was largely why they chose Next.js over a framework like Remix.
Choosing a default that breaks things (forcing npm packages to label their components...) was way too heavy handed considering the tenuous nature of RSC as a whole with its single implementation at this point.
Making client components default (as they have been since the dawn of React) and saying something like "server only" would have done the trick.
But with the directive "use client" you hit the mental pathway that people have around SSR. It adds just enough friction to feel like you're missing out even though it's almost orthogonal to the concept of SSR.
The problem with the approach you’re suggesting is that it creates client-server waterfalls. Avoiding those is the entire point of the design — otherwise it’s dead on arrival.
Suppose that, as you say, client is default, and marking a component as server is opt-in. This means that in any given tree, a server component can appear in the middle and be rendered by a client component. That, in turn, means that any time that client component re-renders, the server component rendered by it need to refetch. But that server component may render another client component under it, which may render another server component (under the design you’re proposing). As a consequence, a simple state update in a client component somewhere can trigger an entire chain of repeated client/server waterfalls just to resolve the resulting tree. This is not a feasible design.
The way RSC solves this problem is by (1) starting the data flow from the server, and (2) ensuring that during rendering, the data always flows in one direction — from server to client. This restriction avoids the client/server network waterfalls I’ve described in the previous paragraph. But it does require that client is opt-in rather than server.
Let's be clear, the design I'm proposing makes no changes to which boundaries are allowed. It simply switches the default from shared to client. Nothing stops a given bundler from requiring a shared component where one is expected now.
What that compromise would have done however is caused significantly less adoption, because "out of sight, out of mind". Most people would not opt into shared/server since RSC is not providing enough value for them: They don't mind the waterfalls, they're stuck in their ways, and above all they highly value reactivity bring sprinkled everywhere since that's what they were all running away from in template based frameworks.
I think where we likely won't see eye to eye is if that was a fair decision to make. I think especially given the singular implementor, the React time should have left RSC as a default disabled and left the uphill battle to Vercel to convince developers to opt into RSC in their own bundler.
Forcing NPM packages to need to think about appending "use client" to be is the smoking gun that this was the wrong move.
The default is client components. You need to opt-in to server components by running a server that serves up your root component as a server component.
No, the default is shared. It's literally in the RFC.
That's why using any interactivity in a component default breaks until you add "use client". The alternative would have been to have state, a core concept of React, work correctly by default, and make server/shared components explicitly marked.
The data flows in one direction: from the server to the client. It's just physics — your server is where the data is. You're trying to move it to the client. So the code that needs to run first is the server code.
This is why the data flow starts at the server. You can't fix this by changing how opting in works, or some other API design workaround. What you're fighting with is the arrow of time.
As for the terminology, I agree it is confusing, but I have not seen a better suggestion yet. I shared our reasoning here (https://github.com/reactwg/server-components/discussions/4), hope it's helpful.