Edit May 3, 2023 (most recent)
The latest version of this function is being developed (for some definition of the word "developed") here. The main function is FancyGeoFrame[ticksX, ticksY, opts]
.
SetDirectory[NotebookDirectory[]];
<<FancyGeoFrame`
(*
The frame will have four black corners can therefore look slightly nicer if there
are an even number of X and Y ticks, but it isn't required.
*)
ticksX={110,115,120,125,130,135,140};
ticksY={20,23,26,29,32,35};
{frame,newrange} = FancyGeoFrame[ticksX, ticksY,
FancyBoxesSize->{{0.5,0.5},{0.45,0.45}},
FancyTicksPadding->{2,3},
FancyTicksMag->2.5,
FancyTicksAngle->{0,-5}*Pi/180,
FancyTicksYDelta->0.2];
world={
GeoStyling[Opacity[1]],
FaceForm[LightGray],
EdgeForm[None],
CountryData["World", "Polygon"]
};
GeoGraphics[
Join[world,frame],
GeoRange->Reverse[newrange],
GeoRangePadding->{None,None},
GeoBackground->None,
GeoGridLines->None,
ImageSize->1100
]

The following options are available
FancyBoxesSize -> {{left, right}, {bottom, top}}
specifies the width of the boxes on each side.
FancyTicksPadding->{bottom, left}
specifies how far away the tick labels are from the frame.
FancyTicksMag->mag
specifies how large the tick labels are.
FancyGridlinesOpacity->op
specifies the opacity of the gridlines.
FancyTicksAngle->{bottom, left}
specifies the rotation of the labels. On the y axis, the labels are rotated uniformly and on the x axis they are rotated concentrically. This can make the labels look nicer if their angle roughly matches the angle of the gridlines.
FancyTicksYDelta->delta
specifies the "slope" of the labels on the y axis. This can make the labels look nicer if the lower labels are too far away from the y axis.
Original Answer
I have written the following function to create the frame and axes labels. This function does not "just work" by any stretch of the imagination, it requires a lot of parameter tweaking to get it to look right and I'm truly sorry if you have to use this. Note that I'm using MaTeX to get a professional font.
ConstructFrame[georange_, nx_, ny_, deltax_, deltay_, paddingsizex_,
paddingsizey_, axesmag_, textmag_, angle_, slope_] :=
Module[{xrng, yrng, bw, labelerx, labelery, boxes = {},
paddingboxes = {}, gridlines = {}, xlabels = {}, ylabels = {},
world},
xrng =
Range[georange[[2, 1]], georange[[2, 2]],
Ceiling[(georange[[2, 2]] - georange[[2, 1]])/nx]];
yrng =
Range[georange[[1, 1]], georange[[1, 2]],
Ceiling[(georange[[1, 2]] - georange[[1, 1]])/ny]];
If[xrng[[-1]] != georange[[2, 2]], AppendTo[xrng, georange[[2, 2]]]];
If[yrng[[-1]] != georange[[1, 2]], AppendTo[yrng, georange[[1, 2]]]];
bw[i_] := If[OddQ[i], Black, White];
(*Constructing x boxes*);
Do[
AppendTo[boxes,
{GeoStyling[Opacity[1]], FaceForm[bw[i]], EdgeForm[Black],
GeoBoundsRegion[{{georange[[1, 1]],
georange[[1, 1]] + deltax}, {xrng[[i]], xrng[[i + 1]]}}]}
];
AppendTo[boxes,
{GeoStyling[Opacity[1]], FaceForm[bw[i]], EdgeForm[Black],
GeoBoundsRegion[{{georange[[1, 2]],
georange[[1, 2]] - deltax}, {xrng[[i]], xrng[[i + 1]]}}]}
],
{i, 1, Length[xrng] - 1}
];
(*Constructing y boxes*);
Do[
AppendTo[boxes,
{GeoStyling[Opacity[1]], FaceForm[bw[i]], EdgeForm[Black],
GeoBoundsRegion[{{yrng[[i]], yrng[[i + 1]]}, {georange[[2, 1]],
georange[[2, 1]] + deltay}}]}
];
AppendTo[boxes,
{GeoStyling[Opacity[1]], FaceForm[bw[i]], EdgeForm[Black],
GeoBoundsRegion[{{yrng[[i]],
yrng[[i + 1]]}, {georange[[2, 2]] - deltay,
georange[[2, 2]]}}]}
],
{i, 1, Length[yrng] - 1}
];
(*Constructing x padding boxes*);
AppendTo[paddingboxes,
{GeoStyling[Opacity[1]], FaceForm[White], EdgeForm[White],
GeoBoundsRegion[{{georange[[1, 1]] - 0.07,
georange[[1, 1]] - paddingsizex - 1}, {-179.9, 179.9}}]}
];
(*Constructing y padding boxes*);
AppendTo[paddingboxes,
{GeoStyling[Opacity[1]], FaceForm[White], EdgeForm[White],
GeoBoundsRegion[{{-89.9, 89.9}, {georange[[2, 1]] - paddingsizey,
georange[[2, 1]] - 0.03}}]}
];
(*Constructing x gridlines*);
Do[AppendTo[gridlines,
{Opacity[0.2], Black,
GeoPath[{{georange[[1, 1]], xrng[[i]]}, {georange[[1, 2]],
xrng[[i]]}}]}], {i, 1, Length[xrng]}];
(*Constructing y gridlines*);
Do[AppendTo[gridlines,
{Opacity[0.2], Black,
GeoPath[{{yrng[[i]], georange[[2, 1]]}, {yrng[[i]],
georange[[2, 2]]}}, "Rhumb"]}], {i, 1, Length[yrng]}];
(*Constructing x labels*);
labelerx[xval_] :=
If[xval == 0, MaTeX["0^\\circ", Magnification -> textmag],
If[xval < 0,
MaTeX[ToString[Abs[xval]] <> "^\\circ \\, \\text{W}",
Magnification -> textmag],
MaTeX[ToString[xval] <> "^\\circ \\, \\text{E}",
Magnification -> textmag]]];
Do[AppendTo[xlabels,
{GeoMarker[{georange[[1, 1]] - paddingsizex/4, xrng[[i]]},
Text[labelerx[xrng[[i]]]], "Alignment" -> Center,
"Scale" -> axesmag]}], {i, 2, Length[xrng] - 1}];
(*Constructing y labels*);
labelery[yval_] :=
If[yval == 0, MaTeX["0^\\circ", Magnification -> textmag],
If[yval < 0,
MaTeX[ToString[Abs[yval]] <> "^\\circ \\, \\text{S}",
Magnification -> textmag],
MaTeX[ToString[yval] <> "^\\circ \\, \\text{N}",
Magnification -> textmag]]];
Do[AppendTo[ylabels,
{GeoMarker[{yrng[[i]],
georange[[2, 1]] - paddingsizey/1.1 -
slope*(i - Length[yrng/2])},
Rotate[ Text[labelery[yrng[[i]]]], angle],
"Alignment" -> Center, "Scale" -> axesmag]}], {i, 1,
Length[yrng] - 1}];
(*world shapes*);
world = {GeoStyling[Opacity[0.5]],
FaceForm[RGBColor[0.65, 0.65, 0.65]],
EntityValue[Entity["GeographicRegion", "World"],
EntityProperty["GeographicRegion", "Polygon"]]};
Join[{world, boxes, gridlines, paddingboxes, xlabels, ylabels}]
]
Now we can make the plot.
RANGE = {{20, 35}, {110, 140}};
XLines = 8;
YLines = 5;
FrameX = 0.2;
FrameY = 0.3;
PaddingX = 2.5;
PaddingY = 1.5;
MarkerScale = 1;
AxesLabelScale = 2;
Angle = (\[Pi]/180)*(-10);
Slope = 0.07;
frame = ConstructFrame[RANGE, XLines, YLines, FrameX, FrameY,
PaddingX, PaddingY, MarkerScale, AxesLabelScale, Angle, Slope];
RANGE = RANGE - {{PaddingX, 0}, {PaddingY, 0}};
GeoGraphics[frame,
GeoRange -> RANGE,
GeoRangePadding -> None,
GeoBackground -> White,
GeoGridLines -> None,
ImageSize -> 1100]

Frame -> True
, but this only works for well for equirectangular projection. See also this question. $\endgroup$